make_flow
make_flow

Reputation: 13

Converting regular color image to a blurred version

I'm trying to create code for converting an image into a blurred version of itself. The below code does generate a blurrier version but in my assignment's check tool I'm getting the following errors:

Since the numbers are off by so much, it doesn't seem to be a rounding issue but something completely different. Any ideas? Am I missing something basic?


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

for (int i = 1; i < height - 1; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
                int sumred = 0;
                int sumgreen = 0;
                int sumblue = 0;

                for (int a = i - 1; a <= i + 1; a++)
                {
                    for (int b = j - 1; b <= j + 1; b++)
                    {
                        sumred = image[a][b].rgbtRed + sumred;
                        sumblue = image[a][b].rgbtBlue + sumblue;
                        sumgreen = image[a][b].rgbtGreen + sumgreen;
                    }
                }

                int x = round((float)sumred / 9);
                int y = round((float)sumgreen / 9);
                int z = round((float)sumblue / 9);

                image[i][j].rgbtRed = x;
                image[i][j].rgbtGreen = y;
                image[i][j].rgbtBlue = z;
        }

}
 return;
}

Upvotes: 1

Views: 425

Answers (2)

Draft25
Draft25

Reputation: 52

The problem with the posted code is probably, that it does not handle the border pixels of the input image. Take a look at the for loop:

for (int i = 1; i < height - 1; i++)
    {
        for (int j = 1; j < width - 1; j++)
        {
        //...

What about the pixels for i=0 or j=0? There are different ways for handeling border pixels. The most simple way is to just consider existing pixels, e.g., for a corner pixel only consider the three neighboring pixels and divide by 4. To complete the assignment you have to know the way border pixels shall be treated.

In addition, you should create a new image. In the posted code you average averaged values. See the source code down below:

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    // Make a copy first
    RGBTRIPLE copy_image[height][width];
    for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                copy_image[i][j] = image[i][j];
            }
        }

    for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                    float sumred = 0;
                    float sumgreen = 0;
                    float sumblue = 0;
                    int count = 0;

                    for (int a = i - 1; a <= i + 1; a++)
                    {
                        if(a > -1 && a < height) {
                            for (int b = j - 1; b <= j + 1; b++)
                            {
                                if(b > -1 && b < width) {
                                    sumred += image[a][b].rgbtRed;
                                    sumblue += image[a][b].rgbtBlue;
                                    sumgreen += image[a][b].rgbtGreen;
                                    ++count;
                                }
                            }
                        }
                    }

                    copy_image[i][j].rgbtRed = round((sumred) / ((float) count));
                    copy_image[i][j].rgbtGreen = round((sumgreen) / ((float) count));
                    copy_image[i][j].rgbtBlue= round((sumblue) / ((float) count));
            }
    }

    // Save the result
    for (int i = 0; i < height; i++)
        {
            for (int j = 0; j < width; j++)
            {
                image[i][j] = copy_image[i][j];
            }
        }
}

Upvotes: 0

Weather Vane
Weather Vane

Reputation: 34585

You are missing some basic things.

"Does not blur the edges" is because the loops exclude all the edge pixels. Instead, iterate every pixel, testing for and counting the pixels that are adjacent, ignoring neighbours that are "off the map." So at the corners you will average 4 pixels, dividing their sum by 4.

Besides that, you should be creating a new image, not modifying the previous one – which will give incorrect results by averaging values from those which were already averaged.

For example:

void blur(int height, int width, RGBTRIPLE newim[height][width], RGBTRIPLE image[height][width])
{
    for (int i = 0; i < height; i++) {
        for (int j = 0; j < width; j++) {   
            int sumred = 0;
            int sumgreen = 0;
            int sumblue = 0;
            int count = 0;

            for (int a = i - 1; a <= i + 1; a++) {
                if(a >= 0 && a < height) {
                    for (int b = j - 1; b <= j + 1; b++) {
                        if(b >= 0 && b < width) {
                            sumred   += image[a][b].rgbtRed;
                            sumblue  += image[a][b].rgbtBlue;
                            sumgreen += image[a][b].rgbtGreen;
                            count++;
                        }
                    }
                }
            }
            newim[i][j].rgbtRed   = round((float)sumred   / count);
            newim[i][j].rgbtGreen = round((float)sumgreen / count);
            newim[i][j].rgbtBlue  = round((float)sumblue  / count);
        }
    }
}

There could be an argument that you should "weight" the target pixels at the edges to compensate for the ones off the map, so that if there are, say, 3 pixels off the map and so can't be considered, you total 4 * the current pixel's components and still divide by 9. But that depends on the definition of "blurring."

Upvotes: 1

Related Questions