'CS50 pset4 blur function doesn't calculate edges and corners correctly

Hey, so I been stuck on the cs50 pst4 for a while now, specifically on blur. The goal is to create a filter which blurs the image by changing each pixel to the average of the ones surrounding it.

What I did first is create a copy of the image so that I wouldn't use the changed pixels when calculating the average.

To calculate the sides and the corners i made the colors of pixels outside of the picture to 0. Then I could blindly add it and divide by however many pixels are there for ex. corners have 4 pixels surrounding it so i divide by 4, edges by 6 etc.

To get the positions I looped around image[i][j] from [i - 1][j - 1] to [i + 1][j + 1] However it seems that the right and bottom right side aren't being calculated correctly.

#include "helpers.h"
#include <stdio.h>
#include <math.h>
#include <stdbool.h>

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            for(int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            bool corner = false;
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            for(int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if(n < 0 || n > height || k < 0 || k > width)
                    {
                        copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
                    }
                rgbtRed += copy[n][k].rgbtRed;
                rgbtGreen += copy[n][k].rgbtGreen;
                rgbtBlue += copy[n][k].rgbtBlue;
                }
            }
            if ((i == 0 && (j == 0 || j == width)) || (i == height && (j == 0 || j == width)))
            {
                image[i][j].rgbtRed = (rgbtRed / 4);
                image[i][j].rgbtGreen = (rgbtGreen / 4);
                image[i][j].rgbtBlue = (rgbtBlue / 4);
                corner = true;
            }
            else if (!corner && (i == 0 || i == height || j == 0 || j == width))
            {
                image[i][j].rgbtRed = (rgbtRed / 6);
                image[i][j].rgbtGreen = (rgbtGreen / 6);
                image[i][j].rgbtBlue = (rgbtBlue / 6);
            }
            else
            {
                image[i][j].rgbtRed = (rgbtRed / 9);
                image[i][j].rgbtGreen = (rgbtGreen / 9);
                image[i][j].rgbtBlue = (rgbtBlue / 9);
            }
        }
    }

Thankful for anyhelp provided



Solution 1:[1]

From the question it is not clear how the right and bottom right side aren't being calculated correctly. I run the your code and the output is decent from my point of view. Though it gives some runtime error.

Here are some suggestions.

if (n < 0 || n > height || k < 0 || k > width)
{
    copy[n][k].rgbtRed = copy[n][k].rgbtGreen = copy[n][k].rgbtBlue = 0;
}
rgbtRed += copy[n][k].rgbtRed;
rgbtGreen += copy[n][k].rgbtGreen;
rgbtBlue += copy[n][k].rgbtBlue;

I think you are trying to setup a special handling for the boundary case. For the upper limit, isn't it should be n >= height, since it is zero-based index? Moreover, you don't have to explicitly set the pixel to black. Just ignore it and don't add them to the average value is fine. But you didn't stop there and followed by rgbtRed += copy[n][k].rgbtRed. n could be -1 or > height, it could hit array index out of bound.

Also, you setup a if statement with 3 conditions for edge, corner, and inbound case. You don't need that. You only need to know how many pixel are inbound. Take that number as the divisor for the average formula. Below is my example.

void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE copy[height][width];
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            for (int n = 0; n < 9; n++)
            {
                copy[i][j].rgbtRed = image[i][j].rgbtRed;
                copy[i][j].rgbtGreen = image[i][j].rgbtGreen;
                copy[i][j].rgbtBlue = image[i][j].rgbtBlue;
            }
        }
    }
    int rgbtRed, rgbtGreen, rgbtBlue;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            rgbtRed = rgbtGreen = rgbtBlue = 0;
            // number of pixel is within boundary
            int inbound = 0;
            for (int n = i - 1; n <= i + 1; n++)
            {
                for (int k = j - 1; k <= j + 1; k++)
                {
                    if (n >= 0 && n < height && k >= 0 && k < width)
                    {
                        rgbtRed += copy[n][k].rgbtRed;
                        rgbtGreen += copy[n][k].rgbtGreen;
                        rgbtBlue += copy[n][k].rgbtBlue;
                        inbound++;
                    }

                }
            }
            image[i][j].rgbtRed = (rgbtRed / inbound);
            image[i][j].rgbtGreen = (rgbtGreen / inbound);
            image[i][j].rgbtBlue = (rgbtBlue / inbound);
        }
    }
}

$ ./filter -b ./images/courtyard.bmp outfile.bmp

Result

enter image description here

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1