Próbuję narysować ramkę na obrazie z maską squircle za pomocą Picassa Transformation. Maska squircle to VectorDrawable.

Myślę, że najłatwiejszym i najbardziej elastycznym sposobem, aby to zrobić, jest najpierw narysowanie większej wiewiórki o pożądanym kolorze obramowania za pomocą canvas.drawPaint. Następnie narysuj mniejszą wiewiórkę za pomocą mapy bitowej zdjęcia za pomocą canvas.drawBitmap. Mogę narysować je osobno, mogę przeskalować bitmapę i pomyślnie narysować ją z maską, ale za każdym razem, gdy próbuję połączyć oba, traci maskę przy wywołaniu canvas.drawBitmap. Jakieś pomysły na to, co mogę zrobić źle?

Próbowałem wielu opcji trybu mieszania, ale nie sądzę, że to jest problem.

override fun transform(source: Bitmap): Bitmap {
    val width = source.width
    val height = source.height
    val borderWidth = 100

    val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(output)

    //Draw a full size, red squircle
    val paint = Paint()
    paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    paint.color = Color.RED
    val mask = context.getDrawable(maskID)
    mask.setBounds(0, 0, width, height)
    mask.draw(canvas)
    canvas.drawPaint(paint)

    //Draw a masked, scaled down bitmap of the photo on top
    val bitmapPaint = Paint()
    bitmapPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
    val bitmapMask = context.getDrawable(maskID)
    bitmapMask.setBounds(borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2)
    bitmapMask.draw(canvas)

    val sourceDrawable = source.toDrawable(context.resources)
    sourceDrawable.setBounds(borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2)
    canvas.drawBitmap(sourceDrawable.bitmap, null,
           Rect(borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2),
           bitmapPaint)

    source.recycle()

    return output
}

Wynik:

Squircle with unmasked bitmap

Jeśli skomentuję połączenie do drawBitmap, otrzymuję ten wynik (który jest prawie na miejscu!):

Squircle with mask only

2
Daniel Wilson 23 listopad 2018, 03:32

1 odpowiedź

Najlepsza odpowiedź

ZAKTUALIZOWANO 27/11/2018

Rozwiązałem ten problem, rysując obraz na tymczasowym płótnie z żądaną maską, a następnie rysując wynikową bitmapę na głównym płótnie. Kod źródłowy i wynik wizualny są zawarte tutaj:

MaskaTransformation.kt

import android.content.Context
import android.graphics.*
import android.graphics.drawable.BitmapDrawable
import android.support.annotation.DrawableRes
import android.support.v4.content.ContextCompat
import com.squareup.picasso.Transformation


class MaskTransformation(
    private val context: Context,
    @DrawableRes private val maskID: Int
) : Transformation {

    override fun key(): String {
        return "mask"
    }

    override fun transform(source: Bitmap): Bitmap {
        val width = source.width
        val height = source.height
        val borderWidth = 400

        val output = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(output)

        //Draw a full size, red squircle
        val paint = Paint()
        paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        paint.color = Color.RED
        val mask = ContextCompat.getDrawable(context, maskID)!!
        mask.setBounds(0, 0, width, height)
        mask.draw(canvas)
        canvas.drawPaint(paint)

        //Draw a masked, scaled down bitmap of the photo on top
        val maskingPaint = Paint()
        maskingPaint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
        val maskDrawable = ContextCompat.getDrawable(context, maskID)!!
        maskDrawable.setBounds(borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2)

        val overlayBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
        val overlayCanvas = Canvas(overlayBitmap)
        maskDrawable.draw(overlayCanvas)

        val pictureBitmap = Bitmap.createBitmap(width - borderWidth, height - borderWidth, Bitmap.Config.ARGB_8888)
        val pictureCanvas = Canvas(pictureBitmap)

        val sourceDrawable = BitmapDrawable(context.resources, source)
        sourceDrawable.setBounds(borderWidth / 2, borderWidth / 2, width - borderWidth / 2, height - borderWidth / 2)
        pictureCanvas.drawBitmap(
            sourceDrawable.bitmap,
            null,
            Rect(0, 0, width - borderWidth, height - borderWidth),
            Paint()
        )

        overlayCanvas.drawBitmap(pictureBitmap, (borderWidth / 2).toFloat(), (borderWidth / 2).toFloat(), maskingPaint)

        canvas.drawBitmap(overlayBitmap, 0f, 0f, Paint())

        source.recycle()

        return output
    }

}

MainActivity.kt

import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import com.squareup.picasso.Picasso
import kotlinx.android.synthetic.main.activity_main.*

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        Picasso.get()
            .load(R.drawable.img_aminography)
            .transform(MaskTransformation(this, R.drawable.ic_squircle))
            .into(imageView)

    }
}

ic_squircle.xml

<vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="24dp"
        android:height="24dp"
        android:viewportWidth="32"
        android:viewportHeight="32">

    <path android:fillColor="#000000"
          android:pathData="M31.2,14.3v3.5c0,9.8,-5.9,13.5,-13.4,13.5h-3.5c-7.7,0,-13.5,-3.4,-13.5,-13.5v-3.5c0,-10.8,6,-13.5,13.5,-13.5h3.5C25.2,0.8,31.2,4.1,31.2,14.3"/>

</vector>

.

Wynik wizualny

enter image description here

3
aminography 27 listopad 2018, 17:28