cimagealgorithmppm

Peculiar problem regarding convolution in PPM format


After debugging, trying different image softwares (xdg, gimp) I persist to have a bug which throws me off completely.

Problem is about convolution in PPM format, for images different in aspect ratio, I'm using 1500x1000px image, where mask of {0,0,0, 0,1,0, 0,0,0} works just fine (it's just copying image), however for mask where first or last row is different than 0 eg. {0,1,0, 0,0,0, 0,0,0} image is moved by 1/3 of its size rightwards. I find it peculiar, because as far as I know, I do not have an overflow or any pointer arithmetic that might cause this problem.

I've narrowed it down to the kernel of convolution. Afaik I do not have any problems saving, reading image, after running i_convolution it just moves image by predefined value?.

void i_convolution(unsigned int **in, unsigned int ***out,
                int y_max, int x_max, int kernel_size)
{
    int kernel_sum = 0;
    for(int i = 0; i < kernel_size; i++)
    {
        for(int j = 0; j < kernel_size; j++)
        {
            kernel_sum += kernel[i * kernel_size + j];
        }
    }

    printf("kernel sum = %d\n", kernel_sum);

    for (int i = 1; i < y_max - 1; i++)
    {
        for (int j = 1; j < x_max - 1; j++)
        {
            int r = 0;
            int g = 0;
            int b = 0;

            for (int y_conv = -1; y_conv <= 1; y_conv++)
            {
                for (int x_conv = -1; x_conv <= 1; x_conv++)
                {
                    int y_index = i + y_conv;
                    int x_index = j + x_conv;

                    unsigned char rval = (unsigned char)(in[y_index][x_index] & 0xff);
                    unsigned char gval = (unsigned char)((in[y_index][x_index] & 0xff00) >> 8);
                    unsigned char bval = (unsigned char)((in[y_index][x_index] & 0xff0000) >> 16);

                    int kernel_val = kernel[(y_conv + 1)*kernel_size + (x_conv + 1)];

                    r += (int)(rval * kernel_val);
                    g += (int)(gval * kernel_val);
                    b += (int)(bval * kernel_val);
                }
            }

            r /= kernel_sum;//median filtration
            g /= kernel_sum;//median filtration
            b /= kernel_sum;//median filtration
            // b = abs(b);

            if (r > 255) r = 255;
            else if(r < 0) r = 0;
            if (g > 255) g = 255;
            else if(g < 0) g = 0;
            if (b > 255) b = 255;
            else if(b < 0) b = 0;

            unsigned int val;
            val = 0;

            val |= b & 0xff;
            val <<= 8;

            val |= g & 0xff;
            val <<= 8;

            val |= r & 0xff;
            (*out)[i][j] = val;

        }
    }
}

let's take kernel {0, 1, 0, 0, 0, 0,
result are like this, with left being original, right after convolution https://i.sstatic.net/aIlA0.jpg

I will be thankful for any help. Best regards.


Solution

  • I mark it as solved, because there was a problem with me misinterpreting PPM format height and width, which caused this behaviour, swapping y with x (and allocating memory as such) solves it!