代码之家  ›  专栏  ›  技术社区  ›  Daniel Wilson

带边框的毕加索图像蒙版变换

  •  1
  • Daniel Wilson  · 技术社区  · 6 年前

    我正试图用毕加索的“代码>变换”在带有外圆掩模的图像上绘制边界。“环绕”遮罩是一种可矢量绘制的。

    我认为最简单和最灵活的方法是首先使用 canvas.drawpaint>绘制所需边框颜色的大圆环。然后使用照片位图使用 canvas.drawBitmap绘制较小的圆环。我可以分别绘制,我可以缩放位图并成功地使用遮罩绘制,但任何时候我尝试组合这两个位图时,它都会在 canvas.drawBitmap call上丢失遮罩。对我可能做错的事情有什么看法吗?

    我尝试了很多混合模式选项,但我不认为这是问题所在。

    覆盖fun变换(源:位图):位图{ VAL宽度=震源宽度 VAL高度=震源高度 val边框宽度=100 val output=bitmap.createBitmap(宽度、高度、bitmap.config.argb_8888) val canvas=画布(输出) //绘制一个全尺寸的红色圆环 val paint=油漆()) paint.xfermode=porterdufxfermode(porterduff.mode.src_-in) paint.color=颜色。红色 val mask=context.getDrawable(maskid) mask.setbounds(0,0,宽度,高度) 遮罩.绘图(画布) 帆布.绘画(绘画) //在顶部绘制一个蒙版、缩小的照片位图 Val Bitmappaint=绘制()。 bitmapaint.xfermode=porterdufxfermode(porterduff.mode.src_-in) val bitmapmask=context.getDrawable(maskid) bitmapmask.setbounds(borderwidth/2,borderwidth/2,width-borderwidth/2,height-borderwidth/2) BitmapMask.Draw(画布) val sourcedrawable=源.todrawable(context.resources) sourcedrawable.setbounds(borderwidth/2,borderwidth/2,width-borderwidth/2,height-borderwidth/2) canvas.drawBitmap(sourceDrawable.bitmap,空, 矩形(borderwidth/2,borderwidth/2,width-borderwidth/2,height-borderwidth/2) 位标记 源.recycle()) 返回输出 } < /代码>

    结果:

    如果我注释掉对 drawBitmap的调用,我会得到这个结果(几乎是这样!)

    . canvas.drawPaint . 然后使用照片位图绘制较小的圆环 canvas.drawBitmap . 我可以分别绘制,我可以缩放位图并成功地用遮罩绘制它,但是任何时候我试图组合这两个位图时,它都会丢失遮罩。 画布.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 我得到了这个结果(就快到了!):

    1 回复  |  直到 6 年前
        1
  •  1
  •   aminography    6 年前

    更新日期:2018年11月27日

    我已经解决了这个问题,在临时画布上用所需的遮罩绘制图片,然后在主画布上绘制结果位图。源代码和可视结果包含在以下内容中:

    maskTransformation.kt.

    导入android.content.context 导入android.graphics.* 导入android.graphics.drawable.bitmapdrawable 导入android.support.annotation.drawableres 导入android.support.v4.content.contextcompat 导入com.squreup.picasso.transformation 类掩码转换( 私有VAL上下文:上下文, @drawableres private val maskid:int ):转换{ override fun key():字符串{ 返回“面具” } 覆盖fun转换(源:位图):位图{ VAL宽度=震源宽度 VAL高度=震源高度 val边框宽度=400 val output=bitmap.createBitmap(宽度、高度、bitmap.config.argb_8888) val canvas=画布(输出) //绘制一个全尺寸的红色圆环 val paint=油漆()) paint.xfermode=porterdufxfermode(porterduff.mode.src_-in) paint.color=颜色。红色 val mask=contextcompat.getdrawable(context,maskid)!! mask.setbounds(0,0,宽度,高度) 遮罩.绘图(画布) 帆布.绘画(绘画) //在顶部绘制一个蒙版、缩小的照片位图 val maskingpaint=paint()。 maskingpaint.xfermode=porterdufxfermode(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(宽度、高度、bitmap.config.argb_8888) val overlayCanvas=画布(overlayBitmap) maskdrawable.draw(覆盖画布) val pictureBitmap=bitmap.createBitmap(width-borderwidth,height-borderwidth,bitmap.config.argb_8888) val PictureCanvas=画布(PictureBitmap) val sourcedrawable=bitmapdrawable(context.resources,source) sourcedrawable.setbounds(borderwidth/2,borderwidth/2,width-borderwidth/2,height-borderwidth/2) PictureCanvas.DrawBitmap( 源Drawable.bitmap, 无效的, rect(0,0,width-borderwidth,height-borderwidth) 油漆() ) overlayCanvas.drawBitmap(pictureBitmap,(borderwidth/2).tofloat(),(borderwidth/2).tofloat(),maskingpaint) canvas.drawBitmap(overlayBitmap,0f,0f,paint()) 源.recycle()) 返回输出 } } < /代码>

    mainactivity.kt

    导入android.os.bundle 导入android.support.v7.app.appcompatactivity 导入com.squreup.picasso.picasso 导入kotlinx.android.synthetic.main.activity_main.* 类MainActivity:AppCompatActivity()。{ 覆盖fun oncreate(savedinstancestate:bundle?){ super.oncreate(保存的状态) setContentView(r.layout.activity_-main) Picasso . GET() .负荷(R.Drawable.img_氨基造影术) .transform(masktransformation(this,r.drawable.ic_squircle))。 .into(图像视图) } } < /代码>

    ic squircle.xml

    矢量xmlns:android=“http://schemas.android.com/apk/res/android” 安卓:width=“24dp” 安卓:height=“24dp” android:viewportwidth=“32” android:viewportheight=“32”> <路径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”/>gt; &向量/gt; < /代码>

    视觉效果

    主画布。源代码和可视结果如下:

    蒙面变换.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
        }
    
    }
    

    主要活动

    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)
    
        }
    }
    

    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