cimage-processingsdlgaussiangaussianblur

Gaussian blur in C using SDL


I'm trying to create a Gaussian blur in C using SDL.

Here is my function:

We admit that the param surface is a grayscale image (that's why i only use the r).

SDL_Surface* gaussian_blur(SDL_Surface* surface) {
    int w = surface->w;
    int h = surface->h;

    SDL_Surface* res = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);

   
    for (int y = 0; y < h; y++) {
        for (int x = 0; x < w; x++) {
            Uint8 r = 0;

            for (int i = -2; i <= 2; i++) {
                for (int j = -2; j <= 2; j++) {
                    Uint32 pixel = get_pixel(surface, x+i, y+j);
                    double weight = core[i+2][j+2];

                    r += pixel*weight;
                }
            }

            Uint32 nPixel = SDL_MapRGB(res->format, r, r, r);
            put_pixel(res, x, y, nPixel); 
        }
    }

    free_surface(surface);
    return res;
}

My core is defined as it :

double core[KERNEL_SIZE][KERNEL_SIZE] = {
    {1.0/273.0, 4.0/273.0, 7.0/273.0, 4.0/273.0, 1.0/273.0},
    {4.0/273.0, 16.0/273.0, 26.0/273.0, 16.0/273.0, 4.0/273.0},
    {7.0/273.0, 26.0/273.0, 41.0/273.0, 26.0/273.0, 7.0/273.0},
    {4.0/273.0, 16.0/273.0, 26.0/273.0, 16.0/273.0, 4.0/273.0},
    {1.0/273.0, 4.0/273.0, 7.0/273.0, 4.0/273.0, 1.0/273.0}
};
Uint32 get_pixel(SDL_Surface* surface, int x, int y) {
    int w = surface->w;
    int h = surface->h;

    if (surface != NULL && x >= 0 && x < w && y >= 0 && y < h) {
        Uint32* pixels = (Uint32*)surface->pixels;
        return pixels[y * w + x];
    }
    return 0;
}

void put_pixel(SDL_Surface* surface, int x, int y, Uint32 pixel) {
    int w = surface->w;
    int h = surface->h;
    
    if (surface != NULL && x >= 0 && x < w && y >= 0 && y < h) {
        Uint32* pixels = (Uint32*)surface->pixels;
        pixels[y * w + x] = pixel;
    }
}

The picture is the result of the function : Result of the function

I've searched on different sites but I can't find anything that could help me.

I can't use MATHLAB or OpenCV. I'm only allowed to use SDL

If anyone has any ideas on how to go about it, I'd love to hear from you.


Solution

  • My get_pixel give me all the color (r, g and b). So i have just to apply a mask (& 0xFF) to have the right color.

    There is the correction :

    Uint8 pixel_color(SDL_Surface* surface, int w, int h, int x, int y) {
        Uint8 r = 0;
    
        for (int i = -2; i <= 2; i++) {
            for (int j = -2; j <= 2; j++) {
                Uint32 pixel = get_pixel(surface, x+i, y+j);
                Uint8 pixel_color = pixel & 0xFF; //HERE
                double weight = core[i+2][j+2];
    
                int nX = x+i, nY = y+j; 
    
                if (nX >= 0 && nX < w && nY >= 0 && nY < h)
                    r += pixel_color*weight;
                else
                    r += weight*255;
            }
        }
    
        return r;
    }
    
    SDL_Surface* gaussian_blur(SDL_Surface* surface) {
        int w = surface->w;
        int h = surface->h;
    
        SDL_Surface* res = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0);
    
       
        for (int y = 0; y < h; y++) {
            for (int x = 0; x < w; x++) {
                
                Uint8 color = pixel_color(surface, w, h, x, y);
    
                Uint32 nPixel = SDL_MapRGB(res->format, color, color, color);
                put_pixel(res, x, y, nPixel); 
            }
        }
    
        free_surface(surface);
        return res;
    }