Как залить растровое изображение с помощью Android Renderscript? - PullRequest
0 голосов
/ 13 сентября 2018

Я пытаюсь заливать растровое изображение, используя 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 метод вызывается для каждого пикселя. Как я могу оптимизировать этот код. И как я могу сравнить две uchar4 переменные в Renderscript? Как я могу улучшить свой метод same? Или Как я могу найти похожие соседние пиксели, используя пороговое значение? Я застрял. Пожалуйста, ребята, помогите мне. Я не очень хорошо знаю c99 язык программирования и Renderscript. Ребята, вы можете отладить мой код для рендеринга. и, пожалуйста, скажите мне, что не так в этом коде. Или я могу улучшить этот код отрисовки, чтобы заполнить растровое изображение. Любая помощь будет оценена и извините за мой плохой английский ;-). Спасибо

1 Ответ

0 голосов
/ 19 декабря 2018

Renderscript - это интерфейс Android к графическим инструкциям. И это очень хорошо, если вы хотите выполнять операции с каждым пикселем, потому что он использует широкие возможности GPU-параллелизма. Таким образом, вы можете запустить операцию для каждого пикселя. Для этого вы запускаете программу в Renderscript со строкой типа «для всех пикселей, выполните следующие действия».

Алгоритм заливки не может работать в такой параллельной среде, потому что вы знаете, какой пиксель нужно нарисовать после рисования другого пикселя перед ним. Это верно не только для Renderscript, но и для всех связанных с GPU библиотек, таких как CUDA или другие.

...