Android:动态创建一个掩码

时间:2017-06-23 11:54:59

标签: java android image-processing renderscript android-renderscript

在我的Android应用程序中,我有一辆车,用户可以从中点击并选择不同的面板。图像相对复杂(与此处粘贴的图像相反),因此难以将按钮叠加在正确的位置。此外还有很多不同的图像。 我想尝试的解决方案:

(第一个图像表示用于确定单击哪个面板的颜色,第二个图像表示生成的蒙版,最后一个图像表示结果')。

我遇到的唯一问题是:如何动态创建掩码?我想过使用Floodfill类型方法来创建一个带有'掩码的新画布。选定的面板。但是,我担心它可能计算量太大了。任何更简单的建议? [my representation of the car images[1]

更新:好的,我已经相当远了。正如预期的那样,掩模的创建时间太长(对于小图像为2-4秒)。但是,然后我发现了RenderScripts !!我想我仍然可以让这个工作。我现在唯一的小障碍是:如何传递已按下的颜色?

我目前的代码如下:

// create a bitmap for the mask.
ImageView img = (ImageView) findViewById (mask);
img.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(img.getDrawingCache());

// Create a tiny bitmap to store the colours of the panels that are 
//'selected'
Bitmap.Config conf = Bitmap.Config.ARGB_8888; // see other conf types
Bitmap myBitmap = Bitmap.createBitmap(pickedPanels.size(), 1, conf);
int [] myInts = new int[pickedPanels.size()];
for (int i = 0; i<pickedPanels.size(); i++){
    myInts[i] = pickedPanels.get(i).intValue();
}
myBitmap.setPixels(myInts, 0, myBitmap.getWidth(), 0, 0, 
myBitmap.getWidth(),0);

//Run thescript and set the output
final RenderScript rs = RenderScript.create(this);
final Allocation input = Allocation.createFromBitmap(rs, bitmap, 
Allocation.MipmapControl.MIPMAP_NONE,Allocation.USAGE_SCRIPT);
final Allocation output = Allocation.createTyped(rs, input.getType());
        final ScriptC_singlesource script = new 
ScriptC_singlesource(rs);
script.set_image(Allocation.createFromBitmap(rs, myBitmap, 
Allocation.MipmapControl.MIPMAP_NONE,Allocation.USAGE_SCRIPT));
script.set_imgWidth(pickedPanels.size());
script.forEach_root(input, output);
output.copyTo(bitmap);
img.setImageBitmap(bitmap);

ImageView destim = (ImageView) findViewById (dest);
destim.setDrawingCacheEnabled(true);
destim.setImageBitmap(bitmap);

这是脚本:

#pragma version(1)
#pragma rs java_package_name(za.co.overtake)

rs_allocation image;
int imgWidth;

uchar4 RS_KERNEL root(uchar4 in, uint32_t x, uint32_t y) {

for(int col = 0; col < imgWidth; col++){
    const uchar4 colour = *(const uchar4*)rsGetElementAt(image, col,0);
     if (in.r == colour.r && in.g == colour.g && in.b == colour.b){
        in.r = 255;
        in.g = 0;
        in.b = 0;
        break;
    } else {
       in.r = 0;
       in.g = 255;
       in.b = 0;
       rsDebug("HELLLLLP>>", colour);
    }

}
return in;
}

但是,当我尝试从myBitmap(或脚本中的图像)读取像素值时,RGB始终为0.

(抱歉命名错误等等。我一直在疯狂地试图解决这个问题)

1 个答案:

答案 0 :(得分:-1)

好的,终于搞清楚了。 在我的renderscript代码中,我有:

#pragma version(1)
#pragma rs java_package_name(za.co.overtake)

int*reds;
int*greens;    
int*blues;
int imgWidth;

uchar4 RS_KERNEL root(uchar4 in, uint32_t x, uint32_t y) {
   bool colourme = false;
   for(int col = 0; col < imgWidth; col++){

        const int red = reds[col];
        const int green = greens[col];
        const int blue = blues[col];

         if (in.r == red && in.g == green && in.b == blue){
            colourme = true;
        } 
    }
     if (colourme) {
        in.r = 255;
        in.g = 0;
        in.b = 0;
        in.a = 50;
     } else {
         in.r = 0;
         in.g = 0;
         in.b = 0;
         in.a = 0;
     }
    return in;
}

然后在Java

public void showDamagedPanels(int dest, int mask) {

    int noOfColours = pickedPanels.size();
    if (noOfColours > 0) {
        ImageView img = (ImageView) findViewById (mask);
        img.setDrawingCacheEnabled(true);
        Bitmap bitmap = Bitmap.createBitmap(img.getDrawingCache());
        img.setDrawingCacheEnabled(false);

        int [] reds = new int[noOfColours];
        int [] greens = new int[noOfColours];
        int [] blues = new int[noOfColours];

        for (int i = 0; i< noOfColours; i++){
            int colour = pickedPanels.get(i);
            reds[i] = (colour >> 16) & 0xFF;
            greens[i] = (colour >> 8) & 0xFF;
            blues[i] = (colour >> 0) & 0xFF;
        }

        final RenderScript rs = RenderScript.create(this);
        final Allocation input = Allocation.createFromBitmap(rs, bitmap, Allocation.MipmapControl.MIPMAP_NONE,
                Allocation.USAGE_SCRIPT);
        final Allocation output = Allocation.createTyped(rs, input.getType());
        final ScriptC_singlesource script = new ScriptC_singlesource(rs);

        Allocation red = Allocation.createSized(rs, Element.I32(rs), reds.length);
        red.copyFrom(reds);
        script.bind_reds(red);

        Allocation green = Allocation.createSized(rs, Element.I32(rs), greens.length);
        green.copyFrom(greens);
        script.bind_greens(green);

        Allocation blue = Allocation.createSized(rs, Element.I32(rs), blues.length);
        blue.copyFrom(blues);
        script.bind_blues(blue);

        script.set_imgWidth(pickedPanels.size());
        script.forEach_root(input, output);
        output.copyTo(bitmap);

        ImageView destim = (ImageView) findViewById (dest);
        destim.setDrawingCacheEnabled(true);
        destim.setImageBitmap(bitmap);
    } else {
        ImageView destim = (ImageView) findViewById (dest);
        destim.setImageBitmap(null);
    }


}

其中dest是叠加图像,并且图像中的蒙版充当蒙版。所以基本上,当单击一个面板时 - 将其颜色放在pickedPanels中。然后调用showPanels方法,该方法调用脚本。脚本检查颜色并将结果图像设置为红色或透明。