【问题标题】:How to Floodfill a bitmap using Android Renderscript?如何使用 Android Renderscript 填充位图?
【发布时间】:2018-09-13 12:32:15
【问题描述】:

我正在尝试使用Renderscript 填充位图。而我的渲染脚本文件progress.rs

#pragma version(1)
#pragma rs java_package_name(com.intel.sample.androidbasicrs)

rs_allocation input;

int width;
int height;
int xTouchApply;
int yTouchApply;

static int same(uchar4 pixel, uchar4 in);

uchar4 __attribute__((kernel)) root(const uchar4 in, uint32_t x, uint32_t y) {


    uchar4 out = in;

    rsDebug("Process.rs : image width: ", width);
    rsDebug("Process.rs : image height: ", height);
    rsDebug("Process.rs : image pointX: ", xTouchApply);
    rsDebug("Process.rs : image pointY: ", yTouchApply);

    if(xTouchApply >= 0 && xTouchApply < width && yTouchApply >=0 && yTouchApply < height){

        // getting touched pixel
        uchar4 pixel = rsGetElementAt_uchar4(input, xTouchApply, yTouchApply);
        rsDebug("Process.rs : getting touched pixel", 0);

        // resets the pixel stack
        int topOfStackIndex = 0;

        // creating pixel stack
        int pixelStack[width*height];

        // Pushes the touched pixel onto the stack
        pixelStack[topOfStackIndex] = xTouchApply;
        pixelStack[topOfStackIndex+1] = yTouchApply;
        topOfStackIndex += 2;

        //four way stack floodfill algorithm
        while(topOfStackIndex>0){
            rsDebug("Process.rs : looping while", 0);
            // Pops a pixel from the stack
            int x = pixelStack[topOfStackIndex - 2];
            int y1 = pixelStack[topOfStackIndex - 1];
            topOfStackIndex -= 2;

            while (y1 >= 0 && same(rsGetElementAt_uchar4(input, x, y1), pixel)) {
                y1--;
            }
            y1++;

            int spanLeft = 0;
            int spanRight = 0;

            while (y1 < height && same(rsGetElementAt_uchar4(input, x, y1), pixel)) {
                rsDebug("Process.rs : pointX: ", x);
                rsDebug("Process.rs : pointY: ", y1);
                float3 outPixel = dot(f4.rgb, channelWeights);
                out = rsPackColorTo8888(outPixel);
                // conditions to traverse skipPixels to check threshold color(Similar color)
                if (!spanLeft && x > 0 && same(rsGetElementAt_uchar4(input, x - 1, y1), pixel)) {
                    // Pixel to the left must also be changed, pushes it to the stack
                    pixelStack[topOfStackIndex] = x - 1;
                    pixelStack[topOfStackIndex + 1] = y1;
                    topOfStackIndex += 2;
                    spanLeft = 1;
                } else if (spanLeft && !same(rsGetElementAt_uchar4(input, x - 1, y1), pixel)) {
                    // Pixel to the left has already been changed
                    spanLeft = 0;
                }

                // conditions to traverse skipPixels to check threshold color(Similar color)
                if (!spanRight && x < width - 1 && same(rsGetElementAt_uchar4(input, x + 1, y1), pixel)) {
                    // Pixel to the right must also be changed, pushes it to the stack
                    pixelStack[topOfStackIndex] = x + 1;
                    pixelStack[topOfStackIndex + 1] = y1;
                    topOfStackIndex += 2;
                    spanRight = 1;
                } else if (spanRight && x < width - 1 && !same(rsGetElementAt_uchar4(input, x + 1, y1), pixel)) {
                    // Pixel to the right has already been changed
                    spanRight = 0;
                }
                y1++;
            }
        }
    }

    return out;
}

static int same(uchar4 px, uchar4 inPx){
    int isSame = 0;
    if((px.r == inPx.r) && (px.g == inPx.g) && (px.b == inPx.b) && (px.a == inPx.a)) {
        isSame = 1;
        // rsDebug("Process.rs : matching pixel: ", isSame);
    } else {
        isSame = 0;
    }

    // rsDebug("Process.rs : matching pixel: ", isSame);
    return isSame;
} 

我的活动代码是:

inputBitmap = Bitmap.createScaledBitmap(inputBitmap, displayWidth, displayHeight, false);

    // Create an allocation (which is memory abstraction in the RenderScript)
    // that corresponds to the inputBitmap.
    allocationIn = Allocation.createFromBitmap(
            rs,
            inputBitmap,
            Allocation.MipmapControl.MIPMAP_NONE,
            Allocation.USAGE_SCRIPT
    );

    allocationOut = Allocation.createTyped(rs, allocationIn.getType());

    int imageWidth = inputBitmap.getWidth();
    int imageHeight = inputBitmap.getHeight();

    script.set_width(imageWidth);
    script.set_height(imageHeight);
    script.set_input(allocationIn);
    //....
    //....

    // and my onTouchEvent Code is
    script.set_xTouchApply(xTouchApply);
    script.set_yTouchApply(yTouchApply);

    // Run the script.
    script.forEach_root(allocationIn, allocationOut);
    allocationOut.copyTo(outputBitmap);

当我触摸位图时,它显示应用程序没有响应。这是因为root 方法正在调用每个像素。如何优化此代码。以及如何比较 Renderscript 中的两个 uchar4 变量?如何改进我的same 方法?或者如何使用阈值找到相似的相邻像素?我被困。请大家帮帮我。 我对c99 编程语言和Renderscript 了解不多。你们能调试我的渲染脚本代码吗?请告诉我这段代码有什么问题。或者我可以改进这个渲染脚本代码来填充位图。任何帮助将不胜感激,并为我糟糕的英语感到抱歉;-)。谢谢

【问题讨论】:

    标签: android c99 renderscript flood-fill


    【解决方案1】:

    Renderscript 是 Android 的 GPU 指令前端。如果你想对每个像素执行操作,那是非常好的,因为它使用了大量的 GPU 并行能力。因此,您可以对每个像素运行一个操作。为此,您在 Renderscript 中启动一个程序,例如“对于所有像素,执行以下操作”。

    洪水填充算法虽然不能在这样的并行环境中运行,因为您只知道在绘制之前的另一个像素之后要绘制哪个像素。这不仅适用于渲染脚本,而且适用于所有与 GPU 相关的库,例如 CUDA 或其他库。

    【讨论】:

    • 感谢您的回答。我在 Renderscript 的帮助下解决了这个问题。
    • @JitendraSingh 您是如何实现 FloodFill 的并行版本的?你能在 gist 上向我们展示你的代码吗?
    猜你喜欢
    • 2010-10-29
    • 2011-10-20
    • 2010-12-15
    • 2011-03-17
    • 1970-01-01
    • 2013-08-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多