Обрезка изображения от руки - выбор пользовательского изображения и обрезка дает прозрачное растровое изображение - PullRequest
0 голосов
/ 23 января 2019

Используя приведенный ниже код, я могу нарисовать путь от руки и могу обрезать изображение, но я сталкиваюсь с проблемой, я всегда получаю растровое изображение с некоторой прозрачностью, которая мне не нужна.

вот мой класс для выбора части изображения, я перепробовал почти все решения, которые искал или нашел в своем решении, но не достиг своей цели

 class MyCanvasView(context: Context?, attributeSet: AttributeSet) : View(context, attributeSet) {


private var mCanvas: Canvas? = null
private var mPath: Path? = null
private var mPaint: Paint? = null
private val paths = ArrayList<Pair<Path, Paint>>()
private val undonePaths = ArrayList<Pair<Path, Paint>>()


var startingOfTouchX: Float? = null
var startingOfTouchY: Float? = null
var mBitmap: Bitmap? = null


var shader: Shader? = null
var shaderPaint: Paint? = null
var mMatrix: Matrix? = null
private var scaleGestureDetector: ScaleGestureDetector? = null
var scale: Float = 5.0f
var imageView: ImageView? = null
var stroke: Float = 6f

init {
    isFocusable = true
    isFocusableInTouchMode = true
    mPaint = Paint()
    mPaint?.isAntiAlias = true
    mPaint?.isDither = true

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        mPaint!!.color = context!!.getColor(R.color.colorPrimaryTranparent)
    else
        mPaint!!.color = -0x1

    mPaint?.style = Paint.Style.STROKE
    mPaint?.strokeJoin = Paint.Join.ROUND
    mPaint?.strokeCap = Paint.Cap.ROUND
    mPaint?.strokeWidth = stroke
    mCanvas = Canvas()
    mPath = Path()
    shaderPaint = Paint()
    mMatrix = Matrix()
    scaleGestureDetector = ScaleGestureDetector(context, ScaleListener())
}

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    mBitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
    mCanvas = Canvas(mBitmap!!)

    shader = BitmapShader(mBitmap!!, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)

    shaderPaint?.shader = shader
    mMatrix?.reset()
    mMatrix?.postScale(2f, 2f, mX, mY)
    shaderPaint?.shader?.setLocalMatrix(matrix)

}

override fun onDraw(canvas: Canvas?) {
    super.onDraw(canvas)

    for (p in paths) {
        canvas?.drawPath(p.first, p.second)
    }
}


var mX: Float = 0.toFloat()
var mY: Float = 0.toFloat()
private val TOUCH_TOLERANCE = 4f


private fun touchStart(x: Float, y: Float) {

    undonePaths.clear()
    mY = y
    startingOfTouchX = x
    startingOfTouchY = y


    val p = Paint()
    p.isAntiAlias = true
    p.isDither = true

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
        p.color = context.getColor(R.color.colorPrimaryTranparent)
    else
        p.color = -0x1

    p.style = Paint.Style.STROKE
    p.strokeJoin = Paint.Join.ROUND
    p.strokeCap = Paint.Cap.ROUND
    p.strokeWidth = stroke

    val pa = Path()
    pa.moveTo(x, y)

    paths.add(Pair(pa, p))

    shaderPaint?.shader = shader
    mMatrix?.reset()
    mMatrix?.postScale(20f, 20f, 100f, 100f)
    shaderPaint?.shader?.setLocalMatrix(matrix)

}

fun setSeekStroke(diameter: Float) {

    stroke = diameter
}

private fun touchMove(x: Float, y: Float) {
    val dx = Math.abs(x - mX)
    val dy = Math.abs(y - mY)
    if (dx >= TOUCH_TOLERANCE || dy >= TOUCH_TOLERANCE) {
        mX = x
        mY = y

        paths[paths.size - 1].first.quadTo(mX, mY, (x + mX) / 2, (y + mY) / 2)


    }
}

private fun touchUp() {

    paths[paths.size - 1].first.lineTo(mX, mY)
    paths[paths.size - 1].second.style = Paint.Style.FILL

}


override fun onTouchEvent(event: MotionEvent?): Boolean {


    var x = event!!.x
    var y = event.y

    x += stroke
    y += stroke
    // Invalidate() is inside the case statements because there are many
    // other types of motion events passed into this listener,
    // and we don't want to invalidate the view for those.
    when (event.action) {
        MotionEvent.ACTION_DOWN -> {
            touchStart(x, y)
            invalidate()
        }
        MotionEvent.ACTION_MOVE -> {
            touchMove(x, y)
            invalidate()
        }
        MotionEvent.ACTION_UP -> {
            touchUp()
            invalidate()
        }
    }

    scaleGestureDetector!!.onTouchEvent(event)

    return true
}

fun onClickUndo() {
    if (paths.size > 0) {
        undonePaths.add(paths.removeAt(paths.size - 1))
        invalidate()
    } else {
        Toast.makeText(context, "Nothing to undo !!!", Toast.LENGTH_SHORT).show()
    }
}


fun onClickRedo() {
    if (undonePaths.size > 0) {
        paths.add(undonePaths.removeAt(undonePaths.size - 1))
        invalidate()
    } else {
        Toast.makeText(context, "Nothing to redo !!!", Toast.LENGTH_SHORT).show()
    }
}


private inner class ScaleListener : ScaleGestureDetector.SimpleOnScaleGestureListener() {
    override fun onScale(detector: ScaleGestureDetector?): Boolean {
        scale *= detector!!.scaleFactor
        scale = Math.max(0.1f, Math.min(scale, 5f))
        mMatrix!!.setScale(scale, scale)

        imageView!!.imageMatrix = matrix

        return true
    }
}

}

Вот мой код для обрезки из выбранной части изображения

ib_selection_done.setOnClickListener {

        val bitmap = cropBitmap()
        Glide.with(this).load(BitmapHelper.getInstance().bitmap).into(iv_croped)
    }


     private fun cropBitmap(): Bitmap {

    val bmp2 = screenShot(iv_background_image)
    val bmOverlay = Bitmap.createBitmap(my_canvas_view.width, my_canvas_view.height, Bitmap.Config.ARGB_8888)

    val paint = Paint()
    val p = Paint()
    paint.color = resources.getColor(R.color.colorBlack)
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN)
    paint.isAntiAlias = true
    val canvas = Canvas(bmOverlay)
    canvas.drawBitmap(bmp2, 0f, 0f, p)
    val b = screenShot(my_canvas_view) // custom view for selection
    canvas.drawBitmap(b, 0f, 0f, paint)
    return bmOverlay

}

private fun screenShot(view: View): Bitmap {

    val bitmap = Bitmap.createBitmap(view.width, view.height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    view.draw(canvas)
    return bitmap
}

мой XML здесь,

<android.support.constraint.ConstraintLayout

xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">

   <photoblender.kotlin.thetamobile.com.photoblender.Classes.MyCanvasView
    android:id="@+id/my_canvas_view"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent" />

<ImageButton

    android:id="@+id/ib_selection_done"
    android:layout_width="40dp"
    android:layout_height="40dp"
    android:layout_margin="8dp"
    android:background="@drawable/btn_white_round_background"
    android:src="@drawable/next_arrow"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent" />

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...