Common

PorterDuff

날아갔나요 2020. 8. 18. 18:10

 

 

알파채널 개념을 개발한 토마스 포터와 톰 더프의 이름을 따서 만들었다.

 

대상(렌더링 대상의 콘텐츠)을 사용하여

소스(렌더 할 그래픽 개체)의 합성 결과 색상을 계산하는 방법으로

12개의 합성 연산자로 구성되어 있다.

 

 

 

 

 

구현해보기

 

        private fun drawPorterDuffSample(canvas: Canvas) {
            val sampleBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            val sampleCanvas = Canvas(sampleBitmap)
 
            sampleCanvas.drawBitmap(getCircleBitmap(), 0f, 0f, Paint())
            sampleCanvas.drawBitmap(getRectangleBitmap(), 0f, 0f, Paint().apply {
                xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
            })
 
            canvas.drawBitmap(sampleBitmap, 0f, 0f, Paint())
        }
cs

 

 

canvas의 drawRect, drawCircle과 같은 메소드에 적용하면 기대와 다른 결과가 나온다.

SRC, DST 모두 Bitmap으로 사용해야 기대한 결과를 볼 수 있었다.

 

위 코드에서 rectangleBitmap이 SRC, circleBitmap이 DST가 된다.

  

 

전체 코드

더보기
    class Renderer {
        private var width: Int = 0
        private var height: Int = 0
        private var centerX: Int = 0
        private var centerY: Int = 0
 
        fun setWidthAndHeight(width: Int, height: Int) {
            this.width = width
            this.height = height
            centerX = width/2
            centerY = height/2
        }
 
        fun onDraw(canvas: Canvas) {
            drawPorterDuffSample(canvas)
        }
 
        private fun drawPorterDuffSample(canvas: Canvas) {
            val sampleBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            val sampleCanvas = Canvas(sampleBitmap)
 
            sampleCanvas.drawBitmap(getCircleBitmap(), 0f, 0f, Paint())
            sampleCanvas.drawBitmap(getRectangleBitmap(), 0f, 0f, Paint().apply {
                xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC)
            })
 
            canvas.drawBitmap(sampleBitmap, 0f, 0f, Paint())
        }
 
        private fun getCircleBitmap() = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
            val canvas = Canvas(this)
            val paint = Paint().apply {
                flags = Paint.ANTI_ALIAS_FLAG
                color = Color.parseColor("#E9B639")
            }
            val radius = width*3.5f/10
 
            canvas.drawCircle(radius, radius, radius, paint)
        }
 
        private fun getRectangleBitmap() = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
            val canvas = Canvas(this)
            val paint = Paint().apply {
                flags = Paint.ANTI_ALIAS_FLAG
                color = Color.parseColor("#4899C5")
            }
            val startTop = width*3/10
            val endBottom = width*9/10
 
            canvas.drawRect(
                Rect(startTop, startTop, endBottom, endBottom),
                paint
            )
        }
 
    }
cs

 

 

 

 

 

 

결과

 

 

위에 코드를 안드로이드 커스텀뷰에서 그린 결과이다.

 

안드로이드 커스텀뷰 코드

더보기
class CustomView(context: Context, attrs: AttributeSet?, defStyle: Int) : View(context, attrs, defStyle) {
    constructor(context: Context) : this(context, null0)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
 
    private val renderer = Renderer()
 
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        renderer.setWidthAndHeight(measuredWidth, measuredHeight)
    }
 
    override fun onDraw(canvas: Canvas) {
        renderer.onDraw(canvas)
    }
 
    class Renderer {
        private var width: Int = 0
        private var height: Int = 0
        private var centerX: Int = 0
        private var centerY: Int = 0
 
        fun setWidthAndHeight(width: Int, height: Int) {
            this.width = width
            this.height = height
            centerX = width/2
            centerY = height/2
        }
 
        fun onDraw(canvas: Canvas) {
            drawPorterDuffSample(canvas)
        }
 
        private fun drawPorterDuffSample(canvas: Canvas) {
            val sampleBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            val sampleCanvas = Canvas(sampleBitmap)
 
            sampleCanvas.drawBitmap(getCircleBitmap(), 0f, 0f, Paint())
            sampleCanvas.drawBitmap(getRectangleBitmap(), 0f, 0f, Paint().apply {
                xfermode = PorterDuffXfermode(PorterDuff.Mode.SCREEN)
            })
 
            canvas.drawBitmap(sampleBitmap, 0f, 0f, Paint())
        }
 
        private fun getCircleBitmap() = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
            val canvas = Canvas(this)
            val paint = Paint().apply {
                flags = Paint.ANTI_ALIAS_FLAG
                color = Color.parseColor("#E9B639")
            }
            val radius = width*3.5f/10
 
            canvas.drawCircle(radius, radius, radius, paint)
        }
 
        private fun getRectangleBitmap() = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888).apply {
            val canvas = Canvas(this)
            val paint = Paint().apply {
                flags = Paint.ANTI_ALIAS_FLAG
                color = Color.parseColor("#4899C5")
            }
            val startTop = width*3/10
            val endBottom = width*9/10
 
            canvas.drawRect(
                Rect(startTop, startTop, endBottom, endBottom),
                paint
            )
        }
 
    }
 
}
cs

 

 

 

 

 

참고

 

https://ko.wikipedia.org/wiki/%EC%95%8C%ED%8C%8C_%EC%B1%84%EB%84%90

 

알파 채널 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전.

ko.wikipedia.org

 

https://developer.android.com/reference/android/graphics/PorterDuff.Mode

 

PorterDuff.Mode  |  Android 개발자  |  Android Developers

 

developer.android.com