Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现马赛克效果,Kotlin(3)
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.graphics.Canvas
import android.graphics.Matrix
import android.graphics.Paint
import android.graphics.Path
import android.graphics.PorterDuff
import android.graphics.PorterDuffXfermode
import android.util.AttributeSet
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageView
class MyView : AppCompatImageView {
private var WIDTH = 0
private var HEIGHT = 0
private var mPaint: Paint = Paint()
private var mBmpMosaic: Bitmap
private var mBmpDst: Bitmap
private var mBmpSrc: Bitmap
private var mPath: Path
private var mPreX = 0f
private var mPreY = 0f
private var mPorterDuffXfermode: PorterDuffXfermode
private val mResId = R.mipmap.p
private val mScaleFator = 20f
constructor(ctx: Context, attributeSet: AttributeSet) : super(ctx, attributeSet) {
mPaint.style = Paint.Style.STROKE
mPaint.strokeWidth = 30f
//和一张原图大小相同的马赛克图
mBmpMosaic = getMosaicBmp()
//原图。
mBmpSrc = BitmapFactory.decodeResource(resources, mResId, null)
WIDTH = mBmpSrc.width
HEIGHT = mBmpSrc.height
//空的Bitmap
mBmpDst = Bitmap.createBitmap(WIDTH, HEIGHT, Bitmap.Config.ARGB_8888)
mPath = Path()
/**
*
* SRC_OUT
*
* 当目标图像有图像时合成结果为空白像素;
* 当目标图像没有图像时,合成结果显示源图像;
* 如果把手指Path做为目标图像,在与源图像合成时,有手指轨迹的地方就变为空白像素,效果就是擦除。
*
*/
mPorterDuffXfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_OUT)
}
override fun onDraw(canvas: Canvas) {
//super.onDraw(canvas)
//第一层,一张固定的马赛克底图。
canvas.drawBitmap(mBmpMosaic, 0f, 0f, null)
val layerId = canvas.saveLayer(0f, 0f, WIDTH.toFloat(), HEIGHT.toFloat(), null)
//第二层,原图。
canvas.drawBitmap(mBmpSrc, 0f, 0f, null)
//第三层,绘制空的目标图像,和原图大小一致
canvas.drawBitmap(mBmpDst, 0f, 0f, null)
//合成图像
mPaint.setXfermode(mPorterDuffXfermode)
//空的mBmpDst绘制Path
canvas.drawPath(mPath, mPaint) //擦除第二层的原图,使得第一层的马赛克底图露出来。
mPaint.setXfermode(null)
canvas.restoreToCount(layerId)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
when (event.action) {
MotionEvent.ACTION_DOWN -> {
mPath.moveTo(event.x, event.y)
mPreX = event.x
mPreY = event.y
return true
}
MotionEvent.ACTION_MOVE -> {
val endX = (mPreX + event.x) / 2
val endY = (mPreY + event.y) / 2
mPath.quadTo(mPreX, mPreY, endX, endY)
mPreX = event.x
mPreY = event.y
}
MotionEvent.ACTION_UP -> {
}
}
postInvalidate()
return super.onTouchEvent(event)
}
private fun getMosaicBmp(): Bitmap {
val bmpSrc = BitmapFactory.decodeResource(resources, mResId, null)
val w = bmpSrc.width
val h = bmpSrc.height
//原Bitmap的1/mScaleFator
val smallBmp = Bitmap.createBitmap((w / mScaleFator).toInt(), (h / mScaleFator).toInt(), Bitmap.Config.ARGB_8888)
val cDst = Canvas(smallBmp)
val mtx = Matrix()
mtx.setScale(1 / mScaleFator, 1 / mScaleFator)
cDst.drawBitmap(bmpSrc, mtx, null)
mtx.reset()
val resultBmp = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
val canvas = Canvas(resultBmp)
mtx.setScale(mScaleFator, mScaleFator)
canvas.drawBitmap(smallBmp, mtx, null)
//此时的resultBmp为原图大小的马赛克图。
return resultBmp
}
}
当手指在图像上划过后,划过的轨迹变成马赛克。
Android使用PorterDuffXfermode模式PorterDuff.Mode.SRC_OUT橡皮擦实现“刮刮乐”效果,Kotlin(2)-CSDN博客文章浏览阅读589次,点赞21次,收藏12次。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。Android Bitmap保存成至手机图片文件,Kotlin_android bitmap保存图片-CSDN博客。Android拼接合并图片生成长图代码实现合并两张图片,以第一张图片的宽度为标准,如果被合并的第二张图片宽度和第一张不同,那么就以第一张图片的宽度为准线,对第二张图片进行缩放。https://blog.csdn.net/zhangphil/article/details/144536192