우선, Canvas vs Bitmap
Canvas : 2D graphic을 그리는 데 필요한 class
Bitmap: Canvas 클래스와 연결되어 있는 그림을 그리기 위한 공간
Activity는 화면에 view를 보여줌. setContentView()의 형식 인자로 view가 필요.
저번엔 View를 상속받은 custom view 객체를 만들었지만, 이번엔 ImageView를 사용할 것(ImageView도 View의 일종!)
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val myBitmap = Bitmap.createBitmap( // 비트맵 생성
800, 600, Bitmap.Config.ARGB_8888
)
val myCanvas = Canvas(myBitmap)
myCanvas.drawColor(Color.argb(255, 0, 0, 255))
val paint = Paint()
paint.textSize = 100f
paint.color = Color.argb(255, 255, 255, 255)
myCanvas.drawText("Hello World!!", 100f, 100f, paint)
paint.color = Color.argb(255, 100, 100, 100)
myCanvas.drawCircle(400f, 300f, 150f, paint)
val myImageView = ImageView(this)
myImageView.setImageBitmap(myBitmap)
setContentView(myImageView)
}
}
img를 Bitmap으로 변환
그리고 그려줄 것. 이떄 다음 drawBitmap사용
drawBitmap(Bitmap bitmap, Rect src, Rect dst, Paint paint)
- bitmap, dst는 null 되면 안됨
- src : bitmap의 subset
- dst : 원래 이미지보다 더 크게/작게 출력 가능
우선 img를 drawable에 넣어주고, MyView 클래스에 다음과 같이 써줌.
class MyView(context: Context): View(context) {
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
canvas.drawColor(Color.LTGRAY)
// img객체를 bitmap 객체로 변환
val b: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.harubang)
canvas.drawBitmap(b, 0f, 0f, null) // paint객체 필요 없음
}
}
MainActivity.kt에는 요렇고롬
setContentView(MyView(this))
화면과 이미지 크기 출력하고 싶으면 다음 코드 추가
val paint = Paint()
paint.textSize = 50f
var px = 500f
var py = 100f
// 화면에 대한 width, height
canvas.drawText(width.toString(), px, py, paint)
canvas.drawText(height.toString(), px + 150f, py, paint)
py += 100f
// 이미지에 대한 width, height
canvas.drawText(b.width.toString(), px, py, paint)
canvas.drawText(b.height.toString(), px + 150f, py, paint)
(화면에 따라서 이미지 크기가 실제랑 다를 수 있음)
bitmap 이미지 일부 확대/축소
위와 연결되는 내용.
위에서 이미지를 가져와 bitmap으로 바꾼 뒤 draw해주었음.
이번엔 그 bitmap 이미지의 일부만 출력하는 방법에 대해 할 것.
class MyView(context: Context): View(context) {
// img객체를 bitmap 객체로 변환
private val b:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.harubang)
private val w:Int = b.width
private val h:Int = b.height
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
canvas.drawColor(Color.LTGRAY)
canvas.drawBitmap(b, 0f, 0f, null) // paint객체 굳이 필요 없음
/**
* 사진 일부만 보이게
*/
val src = Rect(40, 40, 140, 140) // 하르방 왼쪽 눈
var pi = w + 50 // bitmap의 폭 + 50
val dst = Rect(pi, 0, pi + w, h)
canvas.drawBitmap(b, src, dst, null) // b의 src부분을 dst에 그린다.
var pj = h + 50 // bitmap의 높이 + 50
val dst2 = Rect(pi, pj, pi + w/2, pj + h/2)
canvas.drawBitmap(b, src, dst2, null) // b의 src부분을 dst2에 그린다.
}
}
bitmap 공간 만든 후 출력
위에서는 별도의 bitmap공간을 만들지 않았음. 이러면 전체 공간에 할당 됨.
그래서! 이번에는 bitmap 공간을 만들어 준 뒤, 거기에 bitmap 이미지를 출력해보자.
ver1. onDraw 메소드에서 createBitmap 실행 : Layout이 화면에 나타난 다음 메모리에 저장된 bitmap 이미지 출력
class MyView(context: Context): View(context) {
// img객체를 bitmap 객체로 변환
private val b:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.harubang)
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
canvas.drawColor(Color.LTGRAY)
/**
* bitmap 공간 생성 뒤 bitmap 이미지 출력
*/
val mbitmap = Bitmap.createBitmap(600, 600,
Bitmap.Config.ARGB_8888)
// canvas 안에 별도의 비트맵을 만들어 줌. mCanvas는 mbitmap 안에서만 사용가능
val mCanvas = Canvas(mbitmap)
mCanvas.drawColor(Color.YELLOW)
mCanvas.drawBitmap(b, 50f, 50f, null)
canvas.drawBitmap(mbitmap, 50f, 50f, null)
}
}
ver2. onSizeChanged 메소드에서 createBitmap 실행 : Layout 화면에 나타나기 전에 실행
(drawBitmap을 사용해 미리 메모리에 bitmap 이미지를 그림)
class MyView(context: Context): View(context) {
// img객체를 bitmap 객체로 변환
private val b:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.harubang)
private val mBitmap = Bitmap.createBitmap(600, 600,
Bitmap.Config.ARGB_8888)
/**
* bitmap 공간 생성 뒤 bitmap 이미지 출력 ver.2 [onSizeChanged] 메소드 사용
*/
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
canvas.drawColor(Color.LTGRAY)
canvas.drawBitmap(mBitmap, 50f, 50f, null)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
val mCanvas = Canvas(mBitmap)
mCanvas.drawColor(Color.YELLOW)
mCanvas.drawBitmap(b, 20f, 20f, null)
}
}
이미지 확대/축소
createScaledBitmap(Bitmap src, int dstWidth, int dstHeight, boolean filter) : src 비트맵을 dstWidth, dstHeight 크기로 조정해줌
확대할 때 filter를 true로 해주면 edges가 스무스 해짐.
class MyView(context: Context): View(context) {
lateinit var myBitmap:Bitmap
lateinit var myCanvas:Canvas
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
myBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
myCanvas = Canvas(myBitmap)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
myCanvas.drawColor(Color.BLUE)
drawEnlargedBitmap()
canvas.drawBitmap(myBitmap, 0f, 0f, null)
}
private fun drawEnlargedBitmap() {
var bobBitmap:Bitmap = BitmapFactory.decodeResource(resources, R.drawable.bob)
myCanvas.drawBitmap(bobBitmap, 25f, 25f, null)
// 300, 400 으로 bobBitmap 크기 조정
bobBitmap = Bitmap.createScaledBitmap(bobBitmap, 300, 400, false)
val w = bobBitmap.width
myCanvas.drawBitmap(bobBitmap, w + 25f, 25f, null)
}
}
요건 줄인 코드
bobBitmap = Bitmap.createScaledBitmap(bobBitmap, 50, 75, false)
이미지 회전
이미지 상하 반전 - matrix(변환행렬)사용
package com.example.graphicexample
import android.content.Context
import android.graphics.*
import android.view.View
class MyView(context: Context): View(context) {
lateinit var myBitmap:Bitmap
lateinit var myCanvas:Canvas
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
myBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
myCanvas = Canvas(myBitmap)
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
if (canvas == null) return
myCanvas.drawColor(Color.BLUE)
drawMirrorBitmap()
canvas.drawBitmap(myBitmap, 0f, 0f, null)
}
private fun drawMirrorBitmap() {
var bobBitmap: Bitmap = BitmapFactory.decodeResource(resources, R.drawable.bob)
myCanvas.drawBitmap(bobBitmap, 25f, 25f, null)
val matrix = Matrix()
matrix.preScale(1f, -1f) // y값 뒤집힘
val w = bobBitmap.width
val h = bobBitmap.height
var bobBitmap2 = Bitmap.createBitmap(bobBitmap, 0, 0, w, h, matrix, false)
myCanvas.drawBitmap(bobBitmap2, 25f, h + 50f, null)
matrix.preRotate(-90f) // 반시계 방향으로 90도 회전
var bobBitmap3 = Bitmap.createBitmap(bobBitmap, 0, 0, w, h, matrix, false)
myCanvas.drawBitmap(bobBitmap3, 25f, 2*h + 50f, null)
}
}
'APP > Kotlin' 카테고리의 다른 글
[2D Graphic - 4] Property animation (0) | 2021.12.05 |
---|---|
[2D Graphic - 3] xml에서 도형 객체 정의 (0) | 2021.12.05 |
[2D Graphic - 1] Custom View 방식, 간단한 도형 그리기, 속성, color, font (0) | 2021.12.05 |
댓글