Question

enter image description here

enter image description here

I want to implement convolution matrix algo in Android using JNI. I have tried my best to do so,but always getting lined image after applying the convolution using JNI. This is the Convolution Algo in Java:

private static final int MATRIX_SIZE = 3;
private static int cap(int color) {
if (color 255)
return 255;
else
return color;
}
public static Bitmap convolute(Bitmap bmp, Matrix mat, float factor, int offset) {
// get matrix values
float [] mxv = new float[MATRIX_SIZE * MATRIX_SIZE];
mat.getValues(mxv);
// cache source pixels
int width = bmp.getWidth();
int height = bmp.getHeight();
int [] scrPxs = new int[width * height];
bmp.getPixels(scrPxs, 0, width, 0, 0, width, height);
// clone source pixels in an array
// here we’ll store results
int [] rtPxs = scrPxs.clone();
int r, g, b;
int rSum, gSum, bSum;
int idx;    // current pixel index
int pix;    // current pixel
float mv;   // current matrix value
for(int x = 0, w = width – MATRIX_SIZE + 1; x < w; ++x) {
for(int y = 0, h = height – MATRIX_SIZE + 1; y < h; ++y) {
idx = (x + 1) + (y + 1) * width;
rSum = gSum = bSum = 0;
for(int mx = 0; mx < MATRIX_SIZE; ++mx) {
for(int my = 0; my < MATRIX_SIZE; ++my) {
pix = scrPxs[(x + mx) + (y + my) * width];
mv = mxv[mx + my * MATRIX_SIZE];
rSum += (Color.red(pix) * mv);
gSum += (Color.green(pix) * mv);
bSum += (Color.blue(pix) * mv);
}
}
r = cap((int)(rSum / factor + offset));
g = cap((int)(gSum / factor + offset));
b = cap((int)(bSum / factor + offset));
// store computed pixel
rtPxs[idx] = Color.argb(Color.alpha(scrPxs[idx]), r, g, b);
}
}
// return bitmap with transformed pixels
return Bitmap.createBitmap(rtPxs, width, height, bmp.getConfig());
}

This is the implementation in JNI:

extern "C" JNIEXPORT void JNICALL Java_com_example_filtertest_JniLoader_applyconvolution(JNIEnv * env, jobject  obj, jobject bitmap)
{
    LOGI("Applying convolution to the bitmap...");

    AndroidBitmapInfo  info;
    int ret;
    void* pixels;

    if ((ret = AndroidBitmap_getInfo(env, bitmap, &info)) < 0) {
        LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
        return;
    }
    if (info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
        LOGE("Bitmap format is not RGBA_8888 !");
        return;
    }

    if ((ret = AndroidBitmap_lockPixels(env, bitmap, &pixels)) < 0) {
        LOGE("AndroidBitmap_lockPixels() failed ! error=%d", ret);
    }


    convolute(&info, pixels);

    AndroidBitmap_unlockPixels(env, bitmap );

    LOGI("Bitmap is blurred successfully...");
}


void convolute(AndroidBitmapInfo* info, void* pixels)
{
    int width = info->width;
    int height = info->height;
    int r, g, b;
    int rSum, gSum, bSum , w , h;
    int idx;    // current pixel index
    int pix;    // current pixel
    float mv;   // current matrix value
    int factor = 1 , offset = 127;
    uint32_t naseeb;

    rgba* input = (rgba*) pixels;
    rgba p;
    uint32_t* line = (uint32_t*)pixels;

    w = width - SIZE + 1;
    h = height - SIZE + 1;


    for(int x = 0; x < w; ++x)
    {
        for(int y = 0; y < h; ++y)
        {
            idx = (x + 1) + (y + 1) * width;

            rSum = gSum = bSum = 0;

            for(int mx = 0; mx < SIZE; ++mx)
            {
                for(int my = 0; my < SIZE; ++my)
                {
                    naseeb = line[(x + mx) + (y + my) * width];

                    //extract the RGB values from the pixel
                    r = (int) ((naseeb & 0x00FF0000) >> 16);
                    g = (int)((naseeb & 0x0000FF00) >> 8);
                    b = (int) (naseeb & 0x00000FF );

                    mv = GaussianBlurConfig1[mx + my * SIZE];

                    rSum += (r * mv);
                    gSum += (g * mv);
                    bSum += (b * mv);
                }
            }

            r = rgb_clamp((int)(rSum / factor + offset));
            g = rgb_clamp((int)(gSum / factor + offset));
            b = rgb_clamp((int)(bSum / factor + offset));

            // set the new pixel back in
            line[idx] =
                    ((r << 16) & 0x00FF0000) |
                    ((g << 8) & 0x0000FF00) |
                    (b & 0x000000FF);
        }
    }
} 

Please help me.Thanks in advance.

Was it helpful?

Solution

Ok, it's not tested, but taking inspiration from this may help you. It strips the unpleasant int to RGBA conversions:

void convolute(AndroidBitmapInfo* info, void* pixels)
{
    int width = info->width;
    int height = info->height;
    int r, g, b;
    int rSum, gSum, bSum , w , h;
    int idx;    // current pixel index
    int pix;    // current pixel
    float mv;   // current matrix value
    int factor = 1 , offset = 127;

    char * line = (char *) pixels;

    w = width - SIZE + 1;
    h = height - SIZE + 1;


    for(int x = 0; x < w; ++x)
    {
        for(int y = 0; y < h; ++y)
        {
            idx = (x + 1) + (y + 1) * width;

            rSum = gSum = bSum = 0;

            for(int mx = 0; mx < SIZE; ++mx)
            {
                for(int my = 0; my < SIZE; ++my)
                {
                    r = line[(x+mx+(y+my)*width)*4    ];
                    g = line[(x+mx+(y+my)*width)*4 + 1];
                    b = line[(x+mx+(y+my)*width)*4 + 2];

                    mv = GaussianBlurConfig1[mx + my * SIZE];

                    rSum += (r * mv);
                    gSum += (g * mv);
                    bSum += (b * mv);
                }
            }

            r = rgb_clamp((int)(rSum / factor + offset));
            g = rgb_clamp((int)(gSum / factor + offset));
            b = rgb_clamp((int)(bSum / factor + offset));

            // set the new pixel back in
            line[4*idx    ] = r;
            line[4*idx + 1] = g;
            line[4*idx + 2] = b;
        }
    }
}

It may require some other changes in you code, but it does simplify the problem...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top