iraza-n
iraza-n

Reputation: 37

Blurring an Image in c pixel by pixel - special cases

I'm working on a program that will slightly blur an image in c.

Knowing that I need the average and rgb values of the 8 surrounding pixels and the selected pixel to change the color of that pixel, I've added them together and taken the average.

I know that the way I'm implementing this is not the most efficient way this can be done, so if there are any suggestions on how to simplify this, please let me know.

I plan on copy tempimage back to image in a third for-loop at the end.

The struct RGBTRIPLE contain the rgb values for a pixel.

    BYTE  rgbtBlue;
    BYTE  rgbtGreen;
    BYTE  rgbtRed;

My issue now is dealing with special cases, such as the edges of the image or the pixels on the side.

How can I get the values of the surrounding pixels when the selected pixel is not surrounded by 9 pixels?

Here is my code so far:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // copy all values to temporary image
    RGBTRIPLE tempimage[height][width];
    int avgRed = 0;
    int avgGreen = 0;
    int avgBlue = 0;
    //copy pixels to temp image
    for ( int x = 0; x < height; x++)
    {
        for (int y = 0; y < width; y++)
        {
            tempimage[x][y] = image[x][y];
        }
    }
    //get average of surrounding pixels
    for ( int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            //TODO: edge check
            //surrounding pixels
            avgRed = round(((float)(image[i][j].rgbtRed
            + image[i][j - 1].rgbtRed + image[i][j + 1].rgbtRed
            + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed
            + image[i - 1][j + 1].rgbtRed + image[i + 1][j].rgbtRed
            + image[i + 1][j - 1].rgbtRed + image[i + 1][j + 1].rgbtRed)) / 9);

            avgGreen = round(((float)(image[i][j].rgbtGreen
            + image[i][j - 1].rgbtGreen + image[i][j + 1].rgbtGreen
            + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen
            + image[i - 1][j + 1].rgbtGreen + image[i + 1][j].rgbtGreen
            + image[i + 1][j - 1].rgbtGreen + image[i + 1][j + 1].rgbtGreen)) / 9);

            avgBlue = round(((float)(image[i][j].rgbtBlue
            + image[i][j - 1].rgbtBlue + image[i][j + 1].rgbtBlue
            + image[i - 1][j].rgbtBlue + image[i - 1][j - 1].rgbtBlue
            + image[i - 1][j + 1].rgbtBlue + image[i + 1][j].rgbtBlue
            + image[i + 1][j - 1].rgbtBlue + image[i + 1][j + 1].rgbtBlue)) / 9);


            tempimage[i][j].rgbtRed = avgRed;
            tempimage[i][j].rgbtGreen = avgGreen;
            tempimage[i][j].rgbtBlue = avgBlue;

        }
    }

    //TODO: for loop to copy tempimage back to image here
    return;
}

Upvotes: 3

Views: 1703

Answers (2)

Adrian Mole
Adrian Mole

Reputation: 51874

There are various ways of handling 'edge' cases in an algorithm like yours. The code below uses the current 'row' or 'column' (instead of that above/below or left/right of it) if it's on the relevant edge:

for ( int i = 0; i < height; i++)
{
    // Edge check (A for 'above' index and B for 'below'):
    int A = i - 1; if (A < 0) A = 0;
    int B = i + 1; if (B > height - 1) B = height - 1;
    for (int j = 0; j < width; j++)
    {
        // Edge check (L = 'left of', R = 'right of'):
        int L = j - 1; if (L < 0) L = 0;
        int R = j + 1; if (R > width - 1) R = width - 1;
        // Then change all your 'i-1'|'i+i'|'j-i'|j+1' indexes to A|B|L|R:
        avgRed = round(((float)(image[i][j].rgbtRed
        + image[i][L].rgbtRed + image[i][R].rgbtRed
        + image[A][j].rgbtRed + image[A][L].rgbtRed
        + image[A][R].rgbtRed + image[B][j].rgbtRed
        + image[B][L].rgbtRed + image[B][R].rgbtRed)) / 9);
        // ... and similarly for green and blue ...

Incidentally, I notice you have your pixel indexes as image[column][row] (= column-major order). Conventionally, C and C++ 2D arrays are defined the other way round, as image[row][column] (= row-major order); however, as long as you're sure that's what you have, then no problem!

Upvotes: 2

abarna baskar
abarna baskar

Reputation: 1

This code in C works well when you consider blurring an image or n*n matxix using box blur. It considers top, bottom and middle rows and calculates the pixels RGB respectively.

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{

    int sumBlue;
    int sumGreen;
    int sumRed;
    //create a temporary table
    RGBTRIPLE temp[height][width];

    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            sumBlue = 0;
            sumGreen = 0;
            sumRed = 0;
            //Top row
            if (i == 0)
            {
                if (j == 0) //top row left corner
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i + 1][j + 1].rgbtBlue) / 4);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j + 1].rgbtGreen
                                          +  image[i + 1][j].rgbtGreen
                                          +  image[i + 1][j + 1].rgbtGreen) / 4);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j + 1].rgbtRed
                                        + image[i + 1][j].rgbtRed
                                        + image[i + 1][j + 1].rgbtRed) / 4);

                }

                else if (j == width - 1) //top row right corner
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i + 1][j - 1].rgbtBlue) / 4);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j - 1].rgbtGreen
                                          + image[i + 1][j].rgbtGreen
                                          + image[i + 1][j - 1].rgbtGreen) / 4);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j - 1].rgbtRed
                                        + image[i + 1][j].rgbtRed
                                        + image[i + 1][j - 1].rgbtRed) / 4);
                }

                else //top row middle pixel
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i + 1][j - 1].rgbtBlue
                                         + image[i + 1][j + 1].rgbtBlue) / 6);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j - 1].rgbtGreen
                                          + image[i][j + 1].rgbtGreen
                                          + image[i + 1][j].rgbtGreen
                                          + image[i + 1][j - 1].rgbtGreen
                                          + image[i + 1][j + 1].rgbtGreen) / 6);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j - 1].rgbtRed
                                        + image[i][j + 1].rgbtRed
                                        + image[i + 1][j].rgbtRed
                                        + image[i + 1][j - 1].rgbtRed
                                        + image[i + 1][j + 1].rgbtRed) / 6);
                }

            }
            //Bottom row of image
            else if (i == height - 1)
            {
                if (j == 0) //left side pixel of bottom row
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i - 1][j + 1].rgbtBlue) / 4);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j + 1].rgbtGreen
                                          + image[i - 1][j].rgbtGreen
                                          + image[i - 1][j + 1].rgbtGreen) / 4);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j + 1].rgbtRed
                                        + image[i - 1][j].rgbtRed
                                        + image[i - 1][j + 1].rgbtRed) / 4);
                }

                else if (j == width - 1) //right side pixel of last row
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i - 1][j - 1].rgbtBlue) / 4);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j - 1].rgbtGreen
                                          + image[i - 1][j].rgbtGreen
                                          + image[i - 1][j - 1].rgbtGreen) / 4);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j - 1].rgbtRed
                                        + image[i - 1][j].rgbtRed
                                        + image[i - 1][j - 1].rgbtRed) / 4);
                }

                else //middle pixels of last row
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i - 1][j - 1].rgbtBlue
                                         + image[i - 1][j + 1].rgbtBlue) / 6);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          + image[i][j - 1].rgbtGreen
                                          + image[i][j + 1].rgbtGreen
                                          + image[i - 1][j].rgbtGreen
                                          + image[i - 1][j - 1].rgbtGreen
                                          + image[i - 1][j + 1].rgbtGreen) / 6);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        + image[i][j - 1].rgbtRed
                                        + image[i][j + 1].rgbtRed
                                        + image[i - 1][j].rgbtRed
                                        + image[i - 1][j - 1].rgbtRed
                                        + image[i - 1][j + 1].rgbtRed) / 6);
                }

            }

            else
            {
                if (j == 0) //left side of image
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i - 1][j + 1].rgbtBlue
                                         + image[i + 1][j + 1].rgbtBlue) / 6); //6 pixels surrounding the left side of the image
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          +  image[i - 1][j].rgbtGreen
                                          +  image[i + 1][j].rgbtGreen
                                          +  image[i][j + 1].rgbtGreen
                                          +  image[i - 1][j + 1].rgbtGreen
                                          +  image[i + 1][j + 1].rgbtGreen) / 6);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        +  image[i - 1][j].rgbtRed
                                        +  image[i + 1][j].rgbtRed
                                        +  image[i][j + 1].rgbtRed
                                        +  image[i - 1][j + 1].rgbtRed
                                        +  image[i + 1][j + 1].rgbtRed) / 6);
                }

                //Right side of image
                else if (j == width - 1)
                {
                    sumBlue = round(ceil(image[i][j].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i - 1][j - 1].rgbtBlue
                                         + image[i + 1][j - 1].rgbtBlue) / 6);
                    sumGreen = round(ceil(image[i][j].rgbtGreen
                                          +  image[i - 1][j].rgbtGreen
                                          +  image[i + 1][j].rgbtGreen
                                          +  image[i][j - 1].rgbtGreen
                                          +  image[i - 1][j - 1].rgbtGreen
                                          +  image[i + 1][j - 1].rgbtGreen) / 6);
                    sumRed = round(ceil(image[i][j].rgbtRed
                                        +  image[i - 1][j].rgbtRed
                                        +  image[i + 1][j].rgbtRed
                                        +  image[i][j - 1].rgbtRed
                                        +  image[i - 1][j - 1].rgbtRed
                                        +  image[i + 1][j - 1].rgbtRed) / 6);
                }

                else //middle pixels of middle rows
                {
                    //calculate for blue pixels
                    sumBlue = round(ceil(image[i - 1][j - 1].rgbtBlue
                                         + image[i - 1][j].rgbtBlue
                                         + image[i - 1][j + 1].rgbtBlue
                                         + image[i][j - 1].rgbtBlue
                                         + image[i][j].rgbtBlue
                                         + image[i][j + 1].rgbtBlue
                                         + image[i + 1][j - 1].rgbtBlue
                                         + image[i + 1][j].rgbtBlue
                                         + image[i + 1][j + 1].rgbtBlue) / 9);
                    //calculate for green pixels
                    sumGreen = round(ceil(image[i - 1][j - 1].rgbtGreen
                                          + image[i - 1][j].rgbtGreen
                                          + image[i - 1][j + 1].rgbtGreen
                                          + image[i][j - 1].rgbtGreen
                                          + image[i][j].rgbtGreen
                                          + image[i][j + 1].rgbtGreen
                                          + image[i + 1][j - 1].rgbtGreen
                                          + image[i + 1][j].rgbtGreen
                                          + image[i + 1][j + 1].rgbtGreen) / 9); // 9 pixels surrounding the middle one
                    //calculate for red pixels
                    sumRed = round(ceil(image[i - 1][j - 1].rgbtRed
                                        + image[i - 1][j].rgbtRed
                                        + image[i - 1][j + 1].rgbtRed
                                        + image[i][j - 1].rgbtRed
                                        + image[i][j].rgbtRed
                                        + image[i][j + 1].rgbtRed
                                        + image[i + 1][j - 1].rgbtRed
                                        + image[i + 1][j].rgbtRed
                                        + image[i + 1][j + 1].rgbtRed) / 9);
                }
            }

            //assign temp values with the calculated values
            temp[i][j].rgbtBlue = round((sumBlue));
            temp[i][j].rgbtGreen = round((sumGreen));
            temp[i][j].rgbtRed = round((sumRed));

        }
    }

    //copies values from temporary table and assigns to original image
    for (int i = 0; i < width; i++)
    {
        for (int j = 0; j < height; j++)
        {
            //assiging temp value to original image
            image[j][i].rgbtBlue = temp[j][i].rgbtBlue;
            image[j][i].rgbtGreen = temp[j][i].rgbtGreen;
            image[j][i].rgbtRed = temp[j][i].rgbtRed;
        }
    }




}

Upvotes: 0

Related Questions