Преобразование маски изображения Пикассо с рамкой - PullRequest
0 голосов
/ 23 ноября 2018

Я пытаюсь нарисовать границу на изображении с помощью маски Squircle, используя Пикассо Transformation.Squircle mask представляет собой VectorDrawable.

Я думаю, что самый простой и гибкий способ сделать это - сначала нарисовать более крупную белку желаемого цвета границы, используя canvas.drawPaint.Затем нарисуйте небольшую белку, используя растровое изображение, используя canvas.drawBitmap.Я могу нарисовать их оба по отдельности, я могу масштабировать растровое изображение и успешно рисовать его с маской, но каждый раз, когда я пытаюсь объединить два, он теряет маску при вызове canvas.drawBitmap.Любые идеи о том, что я могу делать неправильно?

Я пробовал множество вариантов режима наложения, но я не думаю, что это проблема.

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
}

Результат:

Squircle with unmasked bitmap

Если я закомментирую вызов drawBitmap, я получу такой результат (который почти у цели!):

Squircle with mask only

1 Ответ

0 голосов
/ 26 ноября 2018

ОБНОВЛЕНО 27/11/2018

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

MaskTransformation.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>

.

Визуальный результат

enter image description here

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