Java Android-使用另一个位图屏蔽位图

Java Android-使用另一个位图屏蔽位图,java,android,filter,bitmap,mask,Java,Android,Filter,Bitmap,Mask,我有两张位图。下面是位图1: 这是位图2: 最终结果是什么: 我希望有一段代码,不过,我更希望能参考文档或教程。我想完全理解代码,我已经在developer.android.com上搜索了很长时间,但运气不好。谢谢。三年多没有回答?我可以解决这个问题 如评论所述,位图2在边缘和中间是透明的(只有轮廓在那里),所以第一步是用白色填充中心。有很多洪水填充算法可用。我用它是因为它很容易,虽然还有其他的当然更快。这是必要的,因为它支持下一步 第二步是使用组合填充位图2和位图1PorterDuff.

我有两张位图。下面是位图1:

这是位图2:

最终结果是什么:


我希望有一段代码,不过,我更希望能参考文档或教程。我想完全理解代码,我已经在developer.android.com上搜索了很长时间,但运气不好。谢谢。

三年多没有回答?我可以解决这个问题

如评论所述,位图2在边缘和中间是透明的(只有轮廓在那里),所以第一步是用白色填充中心。有很多洪水填充算法可用。我用它是因为它很容易,虽然还有其他的当然更快。这是必要的,因为它支持下一步

第二步是使用组合填充位图2和位图1
PorterDuff.Mode.SRC_top
将有效地将位图1绘制到位图2现在的白色区域,同时使轮廓外部的区域保持透明

代码如下:

package test.testapplication;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.graphics.Bitmap.Config;

import java.util.LinkedList;
import java.util.Queue;

public class MainActivity extends AppCompatActivity {

    Bitmap mask, background, filledMask, overlay;
    Canvas c;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mask = BitmapFactory.decodeResource(getResources(), R.drawable.mask);
        background = BitmapFactory.decodeResource(getResources(), R.drawable.background);

        // get the mask, copy it to filledMask and then flood from the center with CYAN
        filledMask = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Config.ARGB_8888);
        c = new Canvas(filledMask);
        c.drawBitmap(mask, 0, 0, new Paint());
        Point center = new Point(filledMask.getWidth() / 2, filledMask.getHeight() / 2);
        floodFill(filledMask, center, Color.TRANSPARENT, Color.WHITE);


        // create new overlay Bitmap, draw the filledMask and then add the background using PorterDuff
        overlay = Bitmap.createBitmap(filledMask.getWidth(), filledMask.getHeight(), Config.ARGB_8888);
        c = new Canvas(overlay);
        Paint p = new Paint();
        p.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_ATOP));
        c.drawBitmap(filledMask, 0, 0, new Paint());
        c.drawBitmap(background, 0, 0, p);

        DrawView drawView = new DrawView(this);
        // set background to light blue in order to see transparent areas
        drawView.setBackgroundColor(0xffd2d7fe);
        setContentView(drawView);
        drawView.requestFocus();
    }

    public class DrawView extends View {
        Paint p = new Paint();
        int top = 0;

        public DrawView(Context context) {
            super(context);
        }

        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            canvas.drawBitmap(mask, 0, 0, p);
            top += mask.getHeight();

            canvas.drawBitmap(filledMask, 0, top, p);
            top += filledMask.getHeight();

            canvas.drawBitmap(background, 0, top, p);
            top += background.getHeight();

            canvas.drawBitmap(overlay, 0, top, p);
        }
    }

    // method from https://stackoverflow.com/a/8925653/852795
    public void floodFill(Bitmap bmp, Point pt, int targetColor, int replacementColor) {

        Queue<Point> q = new LinkedList<>();
        q.add(pt);
        while (q.size() > 0) {
            Point n = q.poll();
            if (bmp.getPixel(n.x, n.y) != targetColor) continue;

            Point w = n, e = new Point(n.x + 1, n.y);
            while ((w.x > 0) && (bmp.getPixel(w.x, w.y) == targetColor)) {
                bmp.setPixel(w.x, w.y, replacementColor);
                if ((w.y > 0) && (bmp.getPixel(w.x, w.y - 1) == targetColor)) q.add(new Point(w.x, w.y - 1));
                if ((w.y < bmp.getHeight() - 1) && (bmp.getPixel(w.x, w.y + 1) == targetColor)) q.add(new Point(w.x, w.y + 1));
                w.x--;
            }
            while ((e.x < bmp.getWidth() - 1) && (bmp.getPixel(e.x, e.y) == targetColor)) {
                bmp.setPixel(e.x, e.y, replacementColor);

                if ((e.y > 0) && (bmp.getPixel(e.x, e.y - 1) == targetColor)) q.add(new Point(e.x, e.y - 1));
                if ((e.y < bmp.getHeight() - 1) && (bmp.getPixel(e.x, e.y + 1) == targetColor)) q.add(new Point(e.x, e.y + 1));
                e.x++;
            }
        }
    }
}
package test.testapplication;
导入android.content.Context;
导入android.graphics.Bitmap;
导入android.graphics.BitmapFactory;
导入android.graphics.Canvas;
导入android.graphics.Color;
导入android.graphics.Paint;
导入android.graphics.Point;
导入android.graphics.PorterDuff;
导入android.graphics.PorterDuffXfermode;
导入android.os.Bundle;
导入android.support.v7.app.AppActivity;
导入android.view.view;
导入android.graphics.Bitmap.Config;
导入java.util.LinkedList;
导入java.util.Queue;
公共类MainActivity扩展了AppCompatActivity{
位图掩码、背景、填充任务、覆盖;
帆布c;
@凌驾
创建时受保护的void(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
mask=BitmapFactory.decodeResource(getResources(),R.drawable.mask);
background=BitmapFactory.decodeResource(getResources(),R.drawable.background);
//获取遮罩,将其复制到filledMask,然后从中心注入青色
filledMask=Bitmap.createBitmap(mask.getWidth()、mask.getHeight()、Config.ARGB_8888);
c=新画布(填充任务);
c、 drawBitmap(掩码,0,0,新绘制());
点中心=新点(filledMask.getWidth()/2,filledMask.getHeight()/2);
泛光填充(填充表面、中心、彩色、透明、彩色、白色);
//创建新的覆盖位图,绘制填充任务,然后使用PorterDuff添加背景
overlay=Bitmap.createBitmap(filledMask.getWidth(),filledMask.getHeight(),Config.ARGB_8888);
c=新画布(覆盖);
油漆p=新油漆();
p、 setXfermode(新的PorterDuffXfermode(PorterDuff.Mode.SRC_));
c、 drawBitmap(Filled任务,0,0,new Paint());
c、 绘图位图(背景,0,0,p);
DrawView DrawView=新的DrawView(此);
//将背景设置为浅蓝色以查看透明区域
drawView.setBackgroundColor(0xffd2d7fe);
setContentView(drawView);
requestFocus();
}
公共类DrawView扩展视图{
油漆p=新油漆();
int-top=0;
公共绘图视图(上下文){
超级(上下文);
}
受保护的void onDraw(画布){
super.onDraw(帆布);
绘制位图(掩码,0,0,p);
top+=mask.getHeight();
画布.drawBitmap(填充任务,0,顶部,p);
top+=filledMask.getHeight();
画布.绘图位图(背景,0,顶部,p);
top+=background.getHeight();
画布.绘图位图(覆盖,0,顶部,p);
}
}
//方法自https://stackoverflow.com/a/8925653/852795
公共空白泛光填充(位图bmp、点pt、int targetColor、int REPLACENTCOLOR){
队列q=新的LinkedList();
q、 添加(pt);
而(q.size()>0){
n点=q.poll();
如果(bmp.getPixel(n.x,n.y)!=targetColor)继续;
点w=n,e=新点(n.x+1,n.y);
而((w.x>0)和&(bmp.getPixel(w.x,w.y)==targetColor)){
bmp.setPixel(w.x,w.y,replacementColor);
如果((w.y>0)和&(bmp.getPixel(w.x,w.y-1)==targetColor))q.add(新点(w.x,w.y-1));
如果((w.y0)&(bmp.getPixel(e.x,e.y-1)=targetColor))q.add(新点(e.x,e.y-1));
if((e.y
运行时,输出(为“查看”图像的透明区域向背景添加淡蓝色色调后)应如下所示,图像分别为位图2、位图2填充、位图1,最后是位图2填充和位图1的组合:


轮廓内部似乎有点“模糊”,但这可能是洪水填充的伪影,或者可能是原始位图2。这两个问题都可以解决。

这是可以做到的,我相信会有人带着一些见解来拜访。但是我能问你为什么不使用一个位图或.png作为你想要的最终结果吗?@JadeByfield也许这些是动态的输入和输出,在这种情况下,你不能这样做that@fge啊,好的观点:)正如@fge所说:)无论如何——看看PNG,你只有countour,其余的都是空的。。。我想如果伯爵的周围环境是别的东西(比如黑色?)会更容易些