简体   繁体   中英

RenderScript remove pixels with alpha at bitmap

I've got a bitmap and I need to remove all pixels that have alpha. Sounds easy, but I'm stuck with it. I've got this Java code:

 public static Bitmap overdrawAlphaBits(Bitmap image, int color) {
    Bitmap coloredBitmap = image.copy(Bitmap.Config.ARGB_8888, true);
    for (int y = 0; y < coloredBitmap.getHeight(); y++) {
        for (int x = 0; x < coloredBitmap.getWidth(); x++) {
            int pixel = coloredBitmap.getPixel(x, y);
            if (pixel != 0) {
                coloredBitmap.setPixel(x, y, color);
            }
        }
    }
    return coloredBitmap;
}

And it works fine, but slowly, processing of one bitmap takes around 2 second. I'my trying with RenderScript. It works fast, but not stable. here is my code:

public static Bitmap overdrawAlphaBits(Bitmap image, Context context) {
    Bitmap blackbitmap = Bitmap.createBitmap(image.getWidth(), image.getHeight(), image.getConfig());
    RenderScript mRS = RenderScript.create(context);
    ScriptC_replace_with_main_green_color script = new ScriptC_replace_with_main_green_color(mRS);

    Allocation allocationRaster0 = Allocation.createFromBitmap(mRS, image, Allocation.MipmapControl.MIPMAP_NONE, Allocation.USAGE_SCRIPT);
    Allocation allocationRaster1 = Allocation.createTyped(mRS, allocationRaster0.getType());
    script.forEach_root(allocationRaster0, allocationRaster1);
    allocationRaster1.copyTo(blackbitmap);
    allocationRaster0.destroy();
    allocationRaster1.destroy();
    script.destroy();
    mRS.destroy();
    return blackbitmap;
}

And my.rs file:

void root(const uchar4 *v_in, uchar4 *v_out) {
uint32_t rValue = v_in->r;
uint32_t gValue = v_in->g;
uint32_t bValue = v_in->b;
uint32_t aValue = v_in->a;
if(rValue!=0 || gValue!=0 || bValue!=0 || aValue!=0){
   v_out->r = 0x55;
   v_out->g = 0xED;
   v_out->b = 0x69;
}
}

So I use this method on multiple bitmaps - at first bitmap is works fine, but than I receive corrupted images. By the way when I apply this method again on first bitmap it also corrupts it. Looks like there is not closed memory allocation or shared resources, idk.

Any ideas, please? Maybe there is an easier solution? Thanks everyone in advance!

Actually you can use getPixels method to read all pixels in array and than manipulate them. It works fast enough. The problem is that getPixel works slow. So here is the code:

public static Bitmap overdrawAlphaBits(Bitmap image, int color) {
    int[] pixels = new int[image.getHeight() * image.getWidth()];
    image.getPixels(pixels, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight());
    for (int i = 0; i < image.getWidth() * image.getHeight(); i++) {
        if (pixels[i] != 0) {
            pixels[i] = color;
        }
    }
    image.setPixels(pixels, 0, image.getWidth(), 0, 0, image.getWidth(), image.getHeight());
    return image;
}

In your.rs file, I think the rValue, gValue, etc should be of type uchar, not uint32_t. Also the if-statement is missing an else-clause where the v_in values are copied to v_out, otherwise you get undefined output values. Note that in your Java code, the output bitmap is initialised as a copy. This is not the case in the renderscript code, where you create an output allocation of the same type as the input, but the values are not copied. Therefore you need to copy the input values in the kernel.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM