Peter B. Peter B. - 7 days ago 6
C Question

Wrong result for non square image

I am trying to implement dark (not exactly)emboss filter, my problem is when I use it on SQUARED Lena image 512x512 result is good.
But when I use it on image which has rectangular shape e.g. 1280x720 result is all messed up, why is it so? Format of images is RGB.

GOOD result with Lena 512x512 (original):
enter image description here

WRONG result with 1280x720 image (original not same size just for comparison):
enter image description here

Answer

For a 24bit image, if the width of the image is 682 then it needs padding. Because 682*3 is not a multiple of 4. Try changing the image width to 680 and try again.

To pad the image rows, use the following formula:

int pad = WIDTH % 4;
if(pad == 4) pad = 0;
WIDTH += pad;

Change the condition to fb_j < HEIGHT - 1 - FILTER_HEIGHT and fb_i < WIDTH - 1 - FILTER_WIDTH to avoid buffer overflow.

The bitmap is scanned from top to bottom. It works fine when I switched the dimension as follows (but I loaded the bitmap differently)

//Pixel frame_buffer[WIDTH][HEIGHT];
//Pixel temp_buffer[WIDTH][HEIGHT];

Pixel frame_buffer[HEIGHT][WIDTH]; 
Pixel temp_buffer[HEIGHT][WIDTH]; 
...
for(int fb_j = 1; fb_j < HEIGHT - 1 - FILTER_HEIGHT; fb_j++) {
    for(int fb_i = 1; fb_i < WIDTH - 1 - FILTER_WIDTH; fb_i++) {

        float r = 0, g = 0, b = 0;

        for(int ker_i = 0; ker_i < FILTER_WIDTH; ker_i++) {
            for(int ker_j = 0; ker_j < FILTER_HEIGHT; ker_j++) {
                r += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].r / 255.0) * emboss_kernel[ker_j][ker_i]);
                g += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].g / 255.0) * emboss_kernel[ker_j][ker_i]);
                b += ((float)(frame_buffer[fb_j + ker_j][fb_i + ker_i].b / 255.0) * emboss_kernel[ker_j][ker_i]);
            }
        }

        if(r > 1.0) r = 1.0;
        else if(r < 0) r = 0;

        if(g > 1.0) g = 1.0;
        else if(g < 0) g = 0;

        if(b > 1.0) b = 1.0;
        else if(b < 0) b = 0;

        // Output buffer which will be rendered after convolution
        temp_buffer[fb_j][fb_i].r = (GLubyte)(r*255.0);
        temp_buffer[fb_j][fb_i].g = (GLubyte)(g*255.0);
        temp_buffer[fb_j][fb_i].b = (GLubyte)(b*255.0);
    }
}

Also try running a direct copy for testing. Example:

temp_buffer[fb_j][fb_i].r = frame_buffer[fb_j][fb_i].r;
temp_buffer[fb_j][fb_i].g = frame_buffer[fb_j][fb_i].g;
temp_buffer[fb_j][fb_i].b = frame_buffer[fb_j][fb_i].b;
Comments