blur edges function in cs50 - c

i know the code looks ugly but cleaning is for later i want it to work first then i could work on the clean design
i run it on check50 and it says that it can't blur edges, i try applying the same technique in a test file with constant values of red, green, blue and it works well
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++)
{
blurcorner(i,j,height,width,image,copy);
bluredge(i,j,height,width,image,copy);
image[i][j] = copy[i][j];
}
}
return;
}
////////
void blurcorner (int i, int j, int height, int width, RGBTRIPLE image[height][width],RGBTRIPLE copy[height][width])
{
if (i == height - 1 && j == width - 1)
{
int redav = (image[i - 1][j].rgbtRed + image[i][j-1].rgbtRed + image[i-1][j-1].rgbtRed + image[i][j].rgbtRed) / 4;
copy[i][j].rgbtRed = redav;
int greenav = (image[i - 1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen + image[i][j].rgbtGreen) / 4;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i - 1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue + image[i][j].rgbtBlue) / 4;
copy[i][j].rgbtBlue = blueav;
}
else if (i == height - 1 && j == 0)
{
int redav = (image[i - 1][j].rgbtRed + image[i][j+1].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j].rgbtRed) / 4;
copy[i][j].rgbtRed = redav;
int greenav = (image[i - 1][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j].rgbtGreen) / 4;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i - 1][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j].rgbtBlue) / 4;
copy[i][j].rgbtBlue = blueav;
}
else if (i == 0 && j == 0)
{
int redav = (image[i + 1][j].rgbtRed + image[i][j+1].rgbtRed + image[i+1][j+1].rgbtRed + image[i][j].rgbtRed) / 4;
copy[i][j].rgbtRed = redav;
int greenav = (image[i + 1][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j].rgbtGreen) / 4;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i + 1][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j].rgbtBlue) / 4;
copy[i][j].rgbtBlue = blueav;
}
else if (i == 0 && j == width - 1)
{
int redav = (image[i - 1][j].rgbtRed + image[i][j-1].rgbtRed + image[i-1][j-1].rgbtRed + image[i][j].rgbtRed) / 4;
copy[i][j].rgbtRed = redav;
int greenav = (image[i - 1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen + image[i][j].rgbtGreen) / 4;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i - 1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue + image[i][j].rgbtBlue) / 4;
copy[i][j].rgbtBlue = blueav;
}
}
void bluredge (int i, int j, int height, int width, RGBTRIPLE image[height][width],RGBTRIPLE copy[height][width])
{
if (i == 0 && j > 0 && j < width - 1)
{
int redav = (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 + image[i][j+1].rgbtRed) / 6;
copy[i][j].rgbtRed = redav;
int greenav = (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 + image[i][j+1].rgbtGreen) / 6;
copy[i][j].rgbtGreen = greenav;
int blueav = (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 + image[i][j+1].rgbtBlue) / 6;
copy[i][j].rgbtBlue = blueav;
}
else if (i == height - 1 && j > 0 && j < width - 1)
{
int redav = (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 + image[i][j+1].rgbtRed) / 6;
copy[i][j].rgbtRed = redav;
int greenav = (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 + image[i][j+1].rgbtGreen) / 6;
copy[i][j].rgbtGreen = greenav;
int blueav = (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 + image[i][j+1].rgbtBlue) / 6;
copy[i][j].rgbtBlue = blueav;
}
else if (i > 0 && i < height - 1 && j == width - 1)
{
int redav = (image[i][j].rgbtRed + image[i-1][j].rgbtRed + image[i+1][j].rgbtRed + image[i+1][j-1].rgbtRed + image[i][j - 1].rgbtRed + image[i-1][j-1].rgbtRed) / 6;
copy[i][j].rgbtRed = redav;
int greenav = (image[i][j].rgbtGreen + image[i-1][j].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i][j-1].rgbtGreen + image[i-1][j-1].rgbtGreen) / 6;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i][j].rgbtBlue + image[i-1][j].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i][j-1].rgbtBlue + image[i-1][j-1].rgbtBlue) / 6;
copy[i][j].rgbtBlue = blueav;
}
else if (i > 0 && i < height - 1 && j == 0)
{
int redav = (image[i][j].rgbtRed + image[i-1][j].rgbtRed + image[i+1][j].rgbtRed + image[i+1]
[j+1].rgbtRed + image[i][j+1].rgbtRed + image[i-1][j+1].rgbtRed) / 6;
copy[i][j].rgbtRed = redav;
int greenav = (image[i][j].rgbtGreen + image[i-1][j].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j+1].rgbtGreen + image[i][j+1].rgbtGreen + image[i-1][j+1].rgbtGreen) / 6;
copy[i][j].rgbtGreen = greenav;
int blueav = (image[i][j].rgbtBlue + image[i-1][j].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue + image[i][j+1].rgbtBlue + image[i-1][j+1].rgbtBlue) / 6;
copy[i][j].rgbtBlue = blueav;
}
else
{
return;
}
}
before you start hating on me the blur corners function is similar and it worked
i tried changing how i adress each pixel many times but it didnt work
here is the error i get:
:( blur correctly filters pixel on edge
expected "80 95 105\n", not "80 95 108\n"
i think the problem is with the blue

in the blue of the first if in the bluredge:
int blueav = (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 + image[i][j+1].rgbtBlue) / 6;
copy[i][j].rgbtBlue = blueav;
the value
image[i+1][j+1] is there twice, one of them needs to be edited into image[i+1][j-1]

Because it wouldn't be right to write working code for you that you hadn't already tried to write for yourself, the following is to illustrate the advantages of pausing the "advance" to improve on the technique. Here is a version of most of your blurcorner() showing how you could make your code more readable and robust. Trying to find an errant '+' that should be a '-' in the OP code is tantamount to looking for a needle in a haystack. Perhaps you will consider this before spending too much time struggling to make a poor implementation work.
void blurcorner( int i, int j, int height, int width,
RGBTRIPLE image[][width], RGBTRIPLE copy[][width])
{
RGBTRIPLE u0, u1, u2, u3;
u0 = image[i][j];
if (i == 0 ) { // Top
u1 = image[ i + 1 ][ j ];
int off_j = ( j == 0 ) ? j + 1 : j - 1;
u2 = image[ i ][ off_j ];
u3 = image[ i + 1 ][ off_j ];
} else { // Bottom
// left as an exercise
}
int red = u0.rgbtRed + u1.rgbtRed + u2.rgbtRed + u3.rgbtRed ;
int grn = u0.rgbtGreen + u1.rgbtGreen + u2.rgbtGreen + u3.rgbtGreen;
int blu = u0.rgbtBlue + u1.rgbtBlue + u2.rgbtBlue + u3.rgbtBlue ;
copy[i][j].rgbtRed = red / 4;
copy[i][j].rgbtGreen = grn / 4;
copy[i][j].rgbtBlue = blu / 4;
}
(The integer division problem has not been addressed here.)

Related

CS50 - blur, image is correctly blurred but fails check 50

After a lot of work I've got the problem solved but the check50 test does not pass. (Some integers are not rounded in the way they want)
Any ideas what to do with rounding up / down?
(I've used the round function - doesn't seem to work)
The answer is always off by 1 - so it seem to be a rounding problem.
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
//creathing a copy of image in a global scope.
RGBTRIPLE copy[height][width];
for ( int i = 0; i < height; i++)
{
for (int j=0 ; j < width; j++ )
{
copy[i][j] = image[i][j];
}
}
/////////////////////////////
for ( int i = 0; i < height; i++)
{
for (int j=0 ; j < width; j++ )
{
// creating veriablles
float avgRed,avgGreen,avgBlue;
avgRed = 0;
avgGreen =0;
avgBlue=0;
//creating all the special cases (corners, top, bottum,left side, right side)
//top-left corner VV
if (i==0 && j==0)
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i+1][j].rgbtRed + copy[i+1][j+1 ].rgbtRed + copy[i][j+1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i+1][j].rgbtGreen + copy[i+1][j+1 ].rgbtGreen + copy[i][j+1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i+1][j].rgbtBlue + copy[i+1][j+1 ].rgbtBlue + copy[i][j+1].rgbtBlue;
avgRed = round(totalR/4);
avgGreen = round(totalG/4);
avgBlue = round(totalB/4);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
// top-right cornder VV
else if (i==0 && j == width-1 )
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i+1][j].rgbtRed + copy[i+1][j-1].rgbtRed + copy[i][j-1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i+1][j].rgbtGreen + copy[i+1][j-1].rgbtGreen + copy[i][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i+1][j].rgbtBlue + copy[i+1][j-1].rgbtBlue + copy[i][j-1].rgbtBlue;
avgRed = round(totalR/4);
avgGreen = round(totalG/4);
avgBlue = round(totalB/4);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//top row
else if (i == 0 && j!=0 && j!=width-1 )
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i][j-1].rgbtRed + copy[i][j+1 ].rgbtRed + copy[i+1][j+1].rgbtRed + copy[i+1][j].rgbtRed + copy[i+1][j-1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i][j-1].rgbtGreen + copy[i][j+1 ].rgbtGreen + copy[i+1][j+1].rgbtGreen+ copy[i+1][j].rgbtGreen+ copy[i+1][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i][j-1].rgbtBlue + copy[i][j+1 ].rgbtBlue + copy[i+1][j+1].rgbtBlue + copy[i+1][j].rgbtBlue + copy[i+1][j-1].rgbtBlue;
avgRed = round(totalR/6);
avgGreen = round(totalG/6);
avgBlue = round(totalB/6);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//bottom left corner
else if (i == height -1 && j == 0 )
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i-1][j].rgbtRed + copy[i-1][j+1 ].rgbtRed + copy[i][j+1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i-1][j].rgbtGreen + copy[i-1][j+1 ].rgbtGreen + copy[i][j+1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i-1][j].rgbtBlue + copy[i-1][j+1 ].rgbtBlue + copy[i][j+1].rgbtBlue;
avgRed = round(totalR/4);
avgGreen = round(totalG/4);
avgBlue = round(totalB/4);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//bottom right corner
else if ( i == height -1 && j==width-1 )
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i-1][j].rgbtRed + copy[i-1][j-1 ].rgbtRed + copy[i][j-1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i-1][j].rgbtGreen + copy[i-1][j-1 ].rgbtGreen + copy[i][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i-1][j].rgbtBlue + copy[i-1][j-1 ].rgbtBlue + copy[i][j-1].rgbtBlue;
avgRed = round(totalR/4);
avgGreen = round(totalG/4);
avgBlue = round(totalB/4);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//left side
else if (j == 0 && (i!= 0 || i!= height-1) )
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i-1][j].rgbtRed + copy[i-1][j+1 ].rgbtRed + copy[i][j+1].rgbtRed + copy[i+1][j+1].rgbtRed + copy[i+1][j].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i-1][j].rgbtGreen + copy[i-1][j+1 ].rgbtGreen + copy[i][j+1].rgbtGreen+ copy[i+1][j+1].rgbtGreen+ copy[i+1][j].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i-1][j].rgbtBlue + copy[i-1][j+1 ].rgbtBlue + copy[i][j+1].rgbtBlue + copy[i+1][j+1].rgbtBlue + copy[i+1][j].rgbtBlue;
avgRed = round(totalR/6);
avgGreen = round(totalG/6);
avgBlue = round(totalB/6);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
// right side
else if (j == width-1 && i!= 0 && i!= height-1)
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i-1][j].rgbtRed + copy[i-1][j-1 ].rgbtRed + copy[i][j-1].rgbtRed + copy[i+1][j-1].rgbtRed + copy[i+1][j].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i-1][j].rgbtGreen + copy[i-1][j-1 ].rgbtGreen + copy[i][j-1].rgbtGreen+ copy[i+1][j-1].rgbtGreen+ copy[i+1][j].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i-1][j].rgbtBlue + copy[i-1][j-1 ].rgbtBlue + copy[i][j-1].rgbtBlue + copy[i+1][j-1].rgbtBlue + copy[i+1][j].rgbtBlue;
avgRed = round(totalR/6);
avgGreen = round(totalG/6);
avgBlue = round(totalB/6);
image[i][j].rgbtRed =avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//bottom
else if (i== height -1 && j!= 0 && j!= width-1)
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i][j-1].rgbtRed + copy[i][j+1 ].rgbtRed + copy[i-1][j+1].rgbtRed + copy[i-1][j].rgbtRed + copy[i-1][j-1].rgbtRed;
totalG = copy[i][j].rgbtGreen + copy[i][j-1].rgbtGreen + copy[i][j+1 ].rgbtGreen + copy[i-1][j+1].rgbtGreen+ copy[i-1][j].rgbtGreen+ copy[i-1][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i][j-1].rgbtBlue + copy[i][j+1 ].rgbtBlue + copy[i-1][j+1].rgbtBlue + copy[i-1][j].rgbtBlue + copy[i-1][j-1].rgbtBlue;
avgRed = round(totalR/6);
avgGreen = round(totalG/6);
avgBlue = round(totalB/6);
image[i][j].rgbtRed = avgRed;
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
//everything else
else if ( i!=0 && i!= height-1 && j != 0 && j != width-1)
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i][j-1].rgbtRed + copy[i][j+1 ].rgbtRed + copy[i+1][j+1].rgbtRed + copy[i+1][j].rgbtRed + copy[i+1][j-1].rgbtRed+copy[i-1][j].rgbtRed +copy[i-1][j+1].rgbtRed +copy[i-1][j-1].rgbtRed ;
totalG = copy[i][j].rgbtGreen + copy[i][j-1].rgbtGreen + copy[i][j+1 ].rgbtGreen + copy[i+1][j+1].rgbtGreen+ copy[i+1][j].rgbtGreen+ copy[i+1][j-1].rgbtGreen+copy[i-1][j].rgbtGreen+copy[i-1][j+1].rgbtGreen+copy[i-1][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i][j-1].rgbtBlue + copy[i][j+1 ].rgbtBlue + copy[i+1][j+1].rgbtBlue + copy[i+1][j].rgbtBlue + copy[i+1][j-1].rgbtBlue+copy[i-1][j].rgbtBlue+copy[i-1][j+1].rgbtBlue+copy[i-1][j-1].rgbtBlue;
avgRed = (totalR/9);
avgGreen = (totalG/9);
avgBlue = (totalB/9);
image[i][j].rgbtRed = round(avgRed);
image[i][j].rgbtGreen =avgGreen;
image[i][j].rgbtBlue =avgBlue;
}
}
}
}
I tried using floats and rounding the numbers using the round function. Seems to be off by 1 every time it fails.
When calculating the avarage, one should use 6.0 instead of just 6 in order to force the compiler into counting it as float number and not integer thus not "losing" the remainder.
after that the rounding function will work proparly and the Check50 Test will PASS.
thanks to #gerhardh for helping.
example for fixed code:
else if ( i!=0 && i!= height-1 && j != 0 && j != width-1)
{
int totalR,totalG,totalB;
totalR = copy[i][j].rgbtRed + copy[i][j-1].rgbtRed + copy[i][j+1 ].rgbtRed + copy[i+1][j+1].rgbtRed + copy[i+1][j].rgbtRed + copy[i+1][j-1].rgbtRed+copy[i-1][j].rgbtRed +copy[i-1][j+1].rgbtRed +copy[i-1][j-1].rgbtRed ;
totalG = copy[i][j].rgbtGreen + copy[i][j-1].rgbtGreen + copy[i][j+1 ].rgbtGreen + copy[i+1][j+1].rgbtGreen+ copy[i+1][j].rgbtGreen+ copy[i+1][j-1].rgbtGreen+copy[i-1][j].rgbtGreen+copy[i-1][j+1].rgbtGreen+copy[i-1][j-1].rgbtGreen;
totalB = copy[i][j].rgbtBlue + copy[i][j-1].rgbtBlue + copy[i][j+1 ].rgbtBlue + copy[i+1][j+1].rgbtBlue + copy[i+1][j].rgbtBlue + copy[i+1][j-1].rgbtBlue+copy[i-1][j].rgbtBlue+copy[i-1][j+1].rgbtBlue+copy[i-1][j-1].rgbtBlue;
avgRed = roundf(totalR/9.0);
avgGreen = roundf(totalG/9.0);
avgBlue = roundf(totalB/9.0);
image[i][j].rgbtRed = (avgRed);
image[i][j].rgbtGreen =(avgGreen);
image[i][j].rgbtBlue =(avgBlue);
}

How to create a Blur effect in C

Part of a problem set for a course im doing (CS50) requires us to do apply a blur filter on an image. From a two dimensional array[i][j] we need to find the adjacent pixels to the one we want to blur and take the average RGB values and exchange them for the values in the pixel.
This is the code that I came up with yet it does not work.
I have watched some tutorials and they say to find the relative position of the pixel but i cannot really get my head aroud it.
Can anyone help me?
Here is the code I wrote for now:
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
int red = 0;
int green = 0;
int blue = 0;
int counter_pixel = 0;
//I would assume that we would need to tell the computer to free up space for the new imafe with malloc()
RGBTRIPLE temporary[height][width];
for (int i = 0; i < height; i++)
{
// go through every column
for (int j = 0; j < width; j++)
{
temporary[i][j] = image[i][j];
}
}
// go through every row
for (int i = 0; i < height; i++)
{
// go through every column
for (int j = 0; j < width; j++)
{
//checking if the pixel is inside the image
red = green = blue = 0;
if (i < 0 || j < 0 || i > height +1 || j > width + 1)
{
image[i + 1][j].rgbtRed = temporary[i + 1][j].rgbtRed;
image[i - 1][j].rgbtRed = temporary[i - 1][j].rgbtRed;
image[i][j + 1].rgbtRed = temporary[i][j + 1].rgbtRed;
image[i][j - 1].rgbtRed = temporary[i][j - 1].rgbtRed;
image[i + 1][j].rgbtGreen = temporary[i + 1][j].rgbtGreen;
image[i - 1][j].rgbtGreen = temporary[i - 1][j].rgbtGreen;
image[i][j + 1].rgbtGreen = temporary[i][j + 1].rgbtGreen;
image[i][j - 1].rgbtGreen = temporary[i][j - 1].rgbtGreen;
image[i + 1][j].rgbtBlue = temporary[i + 1][j].rgbtBlue;
image[i - 1][j].rgbtBlue = temporary[i - 1][j].rgbtBlue;
image[i][j + 1].rgbtBlue = temporary[i][j + 1].rgbtBlue;
image[i][j - 1].rgbtBlue = temporary[i][j - 1].rgbtBlue;
counter_pixel++;
red = round(((temporary[i + 1][j].rgbtRed + temporary[i - 1][j].rgbtRed + temporary[i][j + 1].rgbtRed + temporary[i][j -1].rgbtRed) / counter_pixel));
green = round(((temporary[i + 1][j].rgbtGreen + temporary[i - 1][j].rgbtGreen + temporary[i][j + 1].rgbtGreen + temporary[i][j -1].rgbtGreen) / counter_pixel));
blue = round(((temporary[i + 1][j].rgbtBlue + temporary[i - 1][j].rgbtBlue + temporary[i][j + 1].rgbtBlue + temporary[i][j -1].rgbtBlue) / counter_pixel));
}
}
}
return;
}

CS50 PSET4 - Help on Blur Filter

So the problem is called "Filters" PSET4 and I was assigned to code a "blur" function that blurs an image. My code blurs the sample pictures but when I use the in-website tool to check the code it says that the program was "unable to blur a 3x3 and 4x4 pictures correctly". This is the code:
Here's what the tool says:
4x4
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE image0[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
image0[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
if (i == 0 && j == 0) //topleft
{
float red00 = round((float)(image0[0][0].rgbtRed + image0[0][1].rgbtRed + image0[1][1].rgbtRed + image[1][0].rgbtRed) / 4);
float green00 = round((image0[0][0].rgbtGreen + image0[0][1].rgbtGreen + image0[1][1].rgbtGreen + image[1][0].rgbtGreen) / 4);
float blue00 = round((image0[0][0].rgbtBlue + image0[0][1].rgbtBlue + image0[1][1].rgbtBlue + image[1][0].rgbtBlue) / 4);
image[0][0].rgbtRed = red00;
image[0][0].rgbtGreen = green00;
image[0][0].rgbtBlue = blue00;
}
else if (i == 0 && j == width - 1) //topright
{
float red01 = round((float)(image0[0][width - 1].rgbtRed + image0[0][width - 2].rgbtRed + image0[1][width - 2].rgbtRed + image0[1][width - 1].rgbtRed)
/ 4);
float green01 = round((float)(image0[0][width - 1].rgbtGreen + image0[0][width - 2].rgbtGreen + image0[1][width - 2].rgbtGreen + image0[1][width - 1].rgbtGreen)
/ 4);
float blue01 = round(((float)image0[0][width - 1].rgbtBlue + image0[0][width - 2].rgbtBlue + image0[1][width - 2].rgbtBlue + image0[1][width - 1].rgbtBlue)
/ 4);
image[0][width - 1].rgbtRed = red01;
image[0][width - 1].rgbtGreen = green01;
image[0][width - 1].rgbtBlue = blue01;
}
else if (i == height - 1 && j == 0) //bottomleft
{
float red10 = round((float)(image0[height - 1][0].rgbtRed + image0[height - 2][0].rgbtRed + image0[height - 2][1].rgbtRed + image0[height - 1][1].rgbtRed)
/ 4);
float green10 = round((float)(image0[height - 1][0].rgbtGreen + image0[height - 2][0].rgbtGreen + image0[height - 2][1].rgbtGreen + image0[height - 1][1].rgbtGreen)
/ 4);
float blue10 = round((float)(image0[height - 1][0].rgbtBlue + image0[height - 2][0].rgbtBlue + image0[height - 2][1].rgbtBlue + image0[height - 1][1].rgbtBlue)
/ 4);
image[height - 1][0].rgbtRed = red10;
image[height - 1][0].rgbtGreen = green10;
image[height - 1][0].rgbtBlue = blue10;
}
else if (i == height - 1 && j == width - 1) //bottomright
{
float red11 = round((float)(image0[height - 1][width - 1].rgbtRed + image0[height - 2][width - 1].rgbtRed + image0[height - 2][width - 2].rgbtRed
+ image0[height - 1][width - 2].rgbtRed) / 4);
float green11 = round((float)(image0[height - 1][width - 1].rgbtGreen + image0[height - 2][width - 1].rgbtGreen + image0[height - 2][width - 2].rgbtGreen
+ image0[height - 1][width - 2].rgbtGreen) / 4);
float blue11 = round((float)(image0[height - 1][width - 1].rgbtBlue + image0[height - 2][width - 1].rgbtBlue + image0[height - 2][width - 2].rgbtBlue
+ image0[height - 1][width - 2].rgbtBlue) / 4);
image[height - 1][width - 1].rgbtRed = red11;
image[height - 1][width - 1].rgbtGreen = green11;
image[height - 1][width - 1].rgbtBlue = blue11;
}
else if (i == 0 && j != 0 && j != width - 1) //top
{
float redtop = round((float)(image0[i][j].rgbtRed + image0[i][j - 1].rgbtRed + image0[i + 1][j - 1].rgbtRed
+ image0[i + 1][j].rgbtRed + image0[i + 1][j + 1].rgbtRed + image0[i][j + 1].rgbtRed) / 6);
float greentop = round((float)(image0[i][j].rgbtGreen + image0[i][j - 1].rgbtGreen + image0[i + 1][j - 1].rgbtGreen
+ image0[i + 1][j].rgbtGreen + image0[i + 1][j + 1].rgbtGreen + image0[i][j + 1].rgbtGreen) / 6);
float bluetop = round((float)(image0[i][j].rgbtBlue + image0[i][j - 1].rgbtBlue + image0[i + 1][j - 1].rgbtBlue
+ image0[i + 1][j].rgbtBlue + image0[i + 1][j + 1].rgbtBlue + image0[i][j + 1].rgbtBlue) / 6);
image[i][j].rgbtRed = redtop;
image[i][j].rgbtGreen = greentop;
image[i][j].rgbtBlue = bluetop;
}
else if (i != 0 && i != height - 1 && j == 0) //left
{
float redleft = round((float)(image0[i][j].rgbtRed + image0[i - 1][j].rgbtRed + image0[i - 1][j + 1].rgbtRed
+ image0[i][j + 1].rgbtRed + image0[i + 1][j + 1].rgbtRed + image0[i + 1][j].rgbtRed) / 6);
float greenleft = round((float)(image0[i][j].rgbtGreen + image0[i - 1][j].rgbtGreen + image0[i - 1][j + 1].rgbtGreen
+ image0[i][j + 1].rgbtGreen + image0[i + 1][j + 1].rgbtGreen + image0[i + 1][j].rgbtGreen) / 6);
float blueleft = round((float)(image0[i][j].rgbtBlue + image0[i - 1][j].rgbtBlue + image0[i - 1][j + 1].rgbtBlue
+ image0[i][j + 1].rgbtBlue + image0[i + 1][j + 1].rgbtBlue + image0[i + 1][j].rgbtBlue) / 6);
image[i][j].rgbtRed = redleft;
image[i][j].rgbtGreen = greenleft;
image[i][j].rgbtBlue = blueleft;
}
else if (i != 0 && i != height - 1 && j == width - 1) //right
{
float redright = round((float)(image0[i][j].rgbtRed + image[i - 1][j].rgbtRed + image0[i - 1][j - 1].rgbtRed + image0[i][j - 1].rgbtRed
+ image0[i + 1][j - 1].rgbtRed + image0[i + 1][j].rgbtRed) / 6);
float greenright = round((float)(image0[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image0[i - 1][j - 1].rgbtGreen + image0[i][j - 1].rgbtGreen
+ image0[i + 1][j - 1].rgbtGreen + image0[i + 1][j].rgbtGreen) / 6);
float blueright = round((float)(image0[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image0[i - 1][j - 1].rgbtBlue + image0[i][j - 1].rgbtBlue
+ image0[i + 1][j - 1].rgbtBlue + image0[i + 1][j].rgbtBlue) / 6);
image[i][j].rgbtRed = redright;
image[i][j].rgbtGreen = greenright;
image[i][j].rgbtBlue = blueright;
}
else if (i == height - 1 && j != 0 && j != width - 1) //bottom
{
float redbottom = round((float)(image0[i][j].rgbtRed + image0[i][j - 1].rgbtRed + image0[i - 1][j - 1].rgbtRed + image0[i - 1][j].rgbtRed
+ image0[i - 1][j + 1].rgbtRed + image0[i][j + 1].rgbtRed) / 6);
float greenbottom = round((float)(image0[i][j].rgbtGreen + image0[i][j - 1].rgbtGreen + image0[i - 1][j - 1].rgbtGreen + image0[i - 1][j].rgbtGreen
+ image0[i - 1][j + 1].rgbtGreen + image0[i][j + 1].rgbtGreen) / 6);
float bluebottom = round((float)(image0[i][j].rgbtBlue + image0[i][j - 1].rgbtBlue + image0[i - 1][j - 1].rgbtBlue + image0[i - 1][j].rgbtBlue
+ image0[i - 1][j + 1].rgbtBlue + image0[i][j + 1].rgbtBlue) / 6);
image[i][j].rgbtRed = redbottom;
image[i][j].rgbtGreen = greenbottom;
image[i][j].rgbtBlue = bluebottom;
}
else
{
float red = round((float)(image0[i][j].rgbtRed + image0[i - 1][j - 1].rgbtRed + image0[i - 1][j].rgbtRed + image0[i - 1][j + 1].rgbtRed
+ image0[i][j - 1].rgbtRed + image0[i][j + 1].rgbtRed + image0[i + 1][j - 1].rgbtRed + image0[i + 1][j].rgbtRed + image0[i + 1][j + 1].rgbtRed)
/ 9);
float green = round((float)(image0[i][j].rgbtGreen + image0[i - 1][j - 1].rgbtGreen + image0[i - 1][j].rgbtGreen + image0[i - 1][j + 1].rgbtGreen
+ image0[i][j - 1].rgbtGreen + image0[i][j + 1].rgbtGreen + image0[i + 1][j - 1].rgbtGreen + image0[i + 1][j].rgbtGreen + image0[i + 1][j + 1].rgbtGreen)
/ 9);
float blue = round((float)(image0[i][j].rgbtBlue + image0[i - 1][j - 1].rgbtBlue + image0[i - 1][j].rgbtBlue + image0[i - 1][j + 1].rgbtBlue
+ image0[i][j - 1].rgbtBlue + image0[i][j + 1].rgbtBlue + image0[i + 1][j - 1].rgbtBlue + image0[i + 1][j].rgbtBlue + image0[i + 1][j + 1].rgbtBlue)
/ 9);
image[i][j].rgbtRed = red;
image[i][j].rgbtGreen = green;
image[i][j].rgbtBlue = blue;
}
}
}
return;
}
In this piece of code block, you use image in round function for three times by mistake. It should be image0.
if (i == 0 && j == 0) //topleft
{
float red00 = round((float)(image0[0][0].rgbtRed + image0[0][1].rgbtRed + image0[1][1].rgbtRed + image[1][0].rgbtRed) / 4);
float green00 = round((image0[0][0].rgbtGreen + image0[0][1].rgbtGreen + image0[1][1].rgbtGreen + image[1][0].rgbtGreen) / 4);
float blue00 = round((image0[0][0].rgbtBlue + image0[0][1].rgbtBlue + image0[1][1].rgbtBlue + image[1][0].rgbtBlue) / 4);

CS50 - PSet4 (Filter) - Blur

I'm running the following code
void blur(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int div = 1;
if ( j + 1 < width - 1 && j + 1 > 0)
{
div++;
}
else
{
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
}
if ( i + 1 < height - 1 && i + 1 > 0)
{
div++;
}
else
{
image[i + 1][j].rgbtRed = 0;
image[i + 1][j].rgbtRed = 0;
image[i + 1][j].rgbtRed = 0;
}
if ( j + 1 < width - 1 && j + 1 > 0 && i + 1 < height - 1 && i + 1 > 0)
{
div++;
}
else
{
image[i + 1][j + 1].rgbtRed = 0;
image[i + 1][j + 1].rgbtRed = 0;
image[i + 1][j + 1].rgbtRed = 0;
}
if ( i - 1 < height - 1 && i - 1 > 0)
{
div++;
}
else
{
image[i - 1][j].rgbtRed = 0;
image[i - 1][j].rgbtRed = 0;
image[i - 1][j].rgbtRed = 0;
}
if ( i - 1 < height - 1 && i - 1 > 0 && j + 1 < width - 1 && j + 1 > 0)
{
div++;
}
else
{
image[i - 1][j + 1].rgbtRed = 0;
image[i - 1][j + 1].rgbtRed = 0;
image[i - 1][j + 1].rgbtRed = 0;
}
if ( j - 1 < width - 1 && j - 1 > 0)
{
div++;
}
else
{
image[i][j - 1].rgbtRed = 0;
image[i][j - 1].rgbtRed = 0;
image[i][j - 1].rgbtRed = 0;
}
if ( j - 1 < width - 1 && j - 1 > 0 && i + 1 < height - 1 && i + 1 > 0)
{
div++;
}
else
{
image[i + 1][j - 1].rgbtRed = 0;
image[i + 1][j - 1].rgbtRed = 0;
image[i + 1][j - 1].rgbtRed = 0;
}
if ( j - 1 < width - 1 && j - 1 > 0 && i - 1 < height - 1 && i - 1 > 0)
{
div++;
}
else
{
image[i - 1][j - 1].rgbtRed = 0;
image[i - 1][j - 1].rgbtRed = 0;
image[i - 1][j - 1].rgbtRed = 0;
}
int averageR = (float)(image[i][j].rgbtRed + image[i][j + 1].rgbtRed + image[i][j - 1].rgbtRed + image[i + 1][j].rgbtRed + image[i - 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed) / div;
int averageG = (float)(image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen + image[i][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen) / div;
int averageB = (float)(image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue + image[i][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue) / div;
image[i][j].rgbtRed = round(averageR);
image[i][j].rgbtGreen = round(averageG);
image[i][j].rgbtBlue = round(averageB);
}
}
return;
}
Unfortnately, everytime I try to run it in the blur part it appears this message:
UndefinedBehaviorSanitizer:DEADLYSIGNAL
==8771==ERROR: UndefinedBehaviorSanitizer: SEGV on unknown address 0x7f7a4ec2890a (pc 0x000000427faa bp 0x7ffd07cd9170 sp 0x7ffd07cd7560 T8771)
==8771==The signal is caused by a WRITE memory access.
#0 0x427fa9 (/home/ubuntu/pset4/filter/filter+0x427fa9)
#1 0x4232b1 (/home/ubuntu/pset4/filter/filter+0x4232b1)
#2 0x7f7a4db1bb96 (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)
#3 0x402dd9 (/home/ubuntu/pset4/filter/filter+0x402dd9)
UndefinedBehaviorSanitizer can not provide additional info.
==8771==ABORTING
Any idea what this might be?
You are accessing out of the bounds of your image 2D array.
This happens in several points.
Consider your loops:
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
}
}
i and j are indexes that can vary respectively from 0 and height and from 0 and width.
But for both these loops you access beyond this limit. For example if j = width-1:
if ( j + 1 < width - 1 && j + 1 > 0)
{
div++;
}
else
{
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
}
The first conditional won't be true as width-1+1 > width -1, so you will end up in the else section, in which you will access
image[i][width].rgbtRed = 0;
that is out of bounds!
And the same happens whenever i = height-1: rows such as image[i + 1][j] will access
image[height][j].rgbtRed = 0;
that is out of bounds as well.
Accessing arrays out of bounds results in undefined behavior, and that's what your sanitizer detects.
Note: although it is unrelated to the error you are asking for, you might also want to correct the mistake in
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
image[i][j + 1].rgbtRed = 0;
and in similar parts all over the function. Note that only Red level is affected (three times!); I suppose that you intended affect also Green and Blue, instead.
How to proceed
Implementing the whole function for you would be beyond the scope of this question, but I'll try to suggest how to proceed.
For each pixel, you currently
Count the elements that are not in the edge of the image (div++)
Set to 0 the elements that should not contribute to the average (that are actually out of bounds and caused your undefined behavior)
Sum all the values of the elements surrounding the pixel (including those you set to 0) and divide by div
But what forces you to sum all the elements? Just sum those which are actually useful! You already have a correct place in which to perform this sum: it's the place in which you increment div.
Something like that:
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
int div = 1;
int curRedSum = 0, curGReenSum = 0, curBlueSum = 0;
if ( j + 1 < width - 1 && j + 1 > 0)
{
div++;
curRedSum += image[i][j + 1].rgbtRed;
curGreenSum += image[i][j + 1].rgbtGreen;
curBlueSum += image[i][j + 1].rgbtBlue;
}
if ( i + 1 < height - 1 && i + 1 > 0)
{
div++;
curRedSum += image[i+1][j].rgbtRed;
curGreenSum += image[i+1][j].rgbtGreen;
curBlueSum += image[i+1][j].rgbtBlue;
}
/* ... */
float averageR = (float)(curRedSum / ( float )div );
float averageG = (float)(curGreenSum / ( float )div );
float averageB = (float)(curBlueSum / ( float )div );
image[i][j].rgbtRed = round(averageR); // Shouldn't this assignemnt be performed on a copy of the image?
image[i][j].rgbtGreen = round(averageG); // Shouldn't this assignemnt be performed on a copy of the image?
image[i][j].rgbtBlue = round(averageB); // Shouldn't this assignemnt be performed on a copy of the image?
}
}
Disclaimer: this suggestion is supposed to be just an hint. I don't guarantee this will compile and work without any further adjustment.

CS50x - Filter (blur) - Receiving a runtime error on first nested else state + seeking for feedback on length of code

Terminal photo HERE!I'm currently having a runtime error and have tried modifying my code but it will not pass.
If there is any specific pointers I could get (no pun intended) to help me approach this issue.
I'm also seeking some feedback on the length of my code - I wrote it as it came to my head and I'm aware that I could make this more short and coherent.
I'm currently working on filtering each independent pixel within the image grid.
Would one suggest writing code as it comes to our head or spend more time trying to decipher an algorithm much simpler.
The code would be the following:
any feedback is welcomed!
// Blur image
void
blur(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
int redAvg, greenAvg, blueAvg;
if (i == 0) {
if (j == 0) {
redAvg = image[i][j].rgbtRed + image[i][j + 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed / 4.0;
greenAvg = image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen / 4.0;
blueAvg = image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue / 4.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
if (j == width - 1) {
redAvg = image[i][j].rgbtRed + image[i][j - 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed / 4.0;
greenAvg = image[i][j].rgbtGreen + image[i][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen / 4.0;
blueAvg = image[i][j].rgbtBlue + image[i][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue / 4.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
else {
redAvg = 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 + image[i][j + 1].rgbtRed / 6.0;
greenAvg = 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 + image[i][j - +1].rgbtGreen / 6.0;
blueAvg = 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 + image[i][j + 1].rgbtBlue / 6.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
}
if (i > 0 && i < i - 2) {
if (j == 0) {
redAvg = image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed / 6.0;
greenAvg = image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen / 6.0;
blueAvg = image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue / 6.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
if (j == width - 1) {
redAvg = image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i][j + 1].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i + 1][j].rgbtRed / 6.0;
greenAvg = image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen / 6.0;
blueAvg = image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j - 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue / 6.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
}
else if (i == i - 1) {
if (j == 0) {
redAvg = image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed / 4.0;
greenAvg = image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen / 4.0;
blueAvg = image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i][j + 1].rgbtBlue / 4.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
if (j == width - 1) {
redAvg = image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed / 4.0;
greenAvg = image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen / 4.0;
blueAvg = image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j - 1].rgbtBlue + image[i][j - 1].rgbtBlue / 4.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
else {
redAvg = 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 + image[i][j + 1].rgbtRed / 6.0;
greenAvg = 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 + image[i][j + 1].rgbtGreen / 6.0;
blueAvg = 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 + image[i][j + 1].rgbtBlue / 6.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
}
else {
redAvg = image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed + image[i - 1][j + 1].rgbtRed / 9.0;
greenAvg = image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen / 9.0;
blueAvg = image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i - 1][j - 1].rgbtBlue + image[i][j - 1].rgbtBlue + image[i + 1][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue / 9.0;
image[i][j].rgbtRed = redAvg;
image[i][j].rgbtGreen = greenAvg;
image[i][j].rgbtBlue = blueAvg;
}
}
}
}
As others have mentioned, you need a separate output matrix to prevent average of averages.
Using relative offset values and some limit checks, you can simplify the function.
Also, you may need to do "saturation math" (e.g. prevent a 256 value from wrapping to 1 because it gets stored into a byte). This may not be necessary if avg / count is always <= 255, but I've included the code to show this
Here's a refactored version:
// Blur image
void
blur(int height, int width,
RGBTRIPLE image[height][width],
RGBTRIPLE imgout[height][width])
{
//RGBTRIPLE *src;
RGBTRIPLE *dst;
for (int i = 0; i < height; i++) {
dst = &imgout[i][0];
for (int j = 0; j < width; j++, dst++) {
int redAvg = 0, greenAvg = 0, blueAvg = 0;
int curcnt = 0;
for (int yoff = -1; yoff <= 1; ++yoff) {
int ycur = i + yoff;
// row index out of range
if (ycur < 0)
continue;
if (ycur >= height)
continue;
RGBTRIPLE *yptr = &image[ycur][0];
for (int xoff = -1; xoff <= 1; ++xoff) {
int xcur = j + xoff;
// index into row (i.e. column index) out of range
if (xcur < 0)
continue;
if (xcur >= width)
continue;
RGBTRIPLE *xptr = &yptr[xcur];
redAvg += xptr->rgbtRed;
greenAvg += xptr->rgbtGreen;
blueAvg += xptr->rgbtBlue;
++curcnt;
}
}
redAvg /= curcnt;
blueAvg /= curcnt;
greenAvg /= curcnt;
// prevent (e.g.) 256 from wrapping to 1 -- clip to max of byte
// NOTE: _may_ not be necessary
if (redAvg > 255)
redAvg = 255;
if (greenAvg > 255)
greenAvg = 255;
if (blueAvg > 255)
blueAvg = 255;
dst->rgbtRed = redAvg;
dst->rgbtBlue = blueAvg;
dst->rgbtGreen = greenAvg;
}
}
}
Note this could be made faster if the border pixels were handled outside the main loop
UPDATE:
Here's a version that might be slightly faster:
// Blur image
void
blur(int height, int width,
RGBTRIPLE image[height][width],
RGBTRIPLE imgout[height][width])
{
int ylim = height - 1;
int xlim = width - 1;
//RGBTRIPLE *src;
RGBTRIPLE *dst;
for (int i = 0; i < height; i++) {
dst = &imgout[i][0];
for (int j = 0; j < width; j++, dst++) {
int redAvg = 0, greenAvg = 0, blueAvg = 0;
int curcnt = 0;
int ylo = i - 1;
if (ylo < 0)
ylo = 0;
int yhi = i + 1;
if (yhi > ylim)
yhi = ylim;
for (int ycur = ylo; ycur <= yhi; ++ycur) {
RGBTRIPLE *yptr = &image[ycur][0];
int xlo = j - 1;
if (xlo < 0)
xlo = 0;
int xhi = j + 1;
if (xhi > xlim)
xhi = xlim;
for (int xcur = xlo; xcur <= xhi; ++xcur) {
RGBTRIPLE *xptr = &yptr[xcur];
redAvg += xptr->rgbtRed;
greenAvg += xptr->rgbtGreen;
blueAvg += xptr->rgbtBlue;
++curcnt;
}
}
redAvg /= curcnt;
blueAvg /= curcnt;
greenAvg /= curcnt;
// prevent (e.g.) 256 from wrapping to 1 -- clip to max of byte
// NOTE: _may_ not be necessary
if (redAvg > 255)
redAvg = 255;
if (greenAvg > 255)
greenAvg = 255;
if (blueAvg > 255)
blueAvg = 255;
dst->rgbtRed = redAvg;
dst->rgbtBlue = blueAvg;
dst->rgbtGreen = greenAvg;
}
}
}
UPDATE #2:
Here's a version that moves more of the limit checks out of the inner loops:
// Blur image
void
blur(int height, int width,
RGBTRIPLE image[height][width],
RGBTRIPLE imgout[height][width])
{
int ylim = height - 1;
int xlim = width - 1;
//RGBTRIPLE *src;
RGBTRIPLE *dst;
for (int i = 0; i < height; i++) {
dst = &imgout[i][0];
int ylo = i - 1;
if (ylo < 0)
ylo = 0;
int yhi = i + 1;
if (yhi > ylim)
yhi = ylim;
for (int j = 0; j < width; j++, dst++) {
int redAvg = 0, greenAvg = 0, blueAvg = 0;
int curcnt = 0;
int xlo = j - 1;
if (xlo < 0)
xlo = 0;
int xhi = j + 1;
if (xhi > xlim)
xhi = xlim;
for (int ycur = ylo; ycur <= yhi; ++ycur) {
RGBTRIPLE *yptr = &image[ycur][0];
for (int xcur = xlo; xcur <= xhi; ++xcur) {
RGBTRIPLE *xptr = &yptr[xcur];
redAvg += xptr->rgbtRed;
greenAvg += xptr->rgbtGreen;
blueAvg += xptr->rgbtBlue;
++curcnt;
}
}
redAvg /= curcnt;
blueAvg /= curcnt;
greenAvg /= curcnt;
// prevent (e.g.) 256 from wrapping to 1 -- clip to max of byte
// NOTE: _may_ not be necessary
if (redAvg > 255)
redAvg = 255;
if (greenAvg > 255)
greenAvg = 255;
if (blueAvg > 255)
blueAvg = 255;
dst->rgbtRed = redAvg;
dst->rgbtBlue = blueAvg;
dst->rgbtGreen = greenAvg;
}
}
}

Resources