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.
Related
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;
}
I´m working on a CS50 task where I should create image filters. I have written the code, it works and passes all tests. However part of the code in my blur filter is not well designed in my view. I have copy-pasted a code chunk three times instead of looping over it. I have tried looping it, but could not figure it out. Basically want to access struct members dynamically.
The struct:
typedef struct
{
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
RGBTRIPLE;
The image created from the struct:
RGBTRIPLE image[height][width]
As you see below I have three code chunks that are almost the same in the loop. The difference is the name of the struct member "rgbtRed", "rgbtGreen" & "rgbtBlue".
for (int k = 0; k < 3; k++)
{
// array to put our values in
int sqr[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
int tempSum = 0;
if (k == 0)
{
if (i > 0)
{
sqr[0] = j > 0 ? image[i - 1][j - 1].rgbtRed : -1;
sqr[1] = image[i - 1][j].rgbtRed;
sqr[2] = j < width - 1 ? image[i - 1][j + 1].rgbtRed : -1;
}
sqr[3] = j > 0 ? image[i][j - 1].rgbtRed : -1;
sqr[4] = image[i][j].rgbtRed;
sqr[5] = j < width - 1 ? image[i][j + 1].rgbtRed : -1;
if (i < (height - 1))
{
sqr[6] = j > 0 ? image[i + 1][j - 1].rgbtRed : -1;
sqr[7] = image[i + 1][j].rgbtRed;
sqr[8] = j < width - 1 ? image[i + 1][j + 1].rgbtRed : -1;
}
}
else if (k == 1)
{
if (i > 0)
{
sqr[0] = j > 0 ? image[i - 1][j - 1].rgbtGreen : -1;
sqr[1] = image[i - 1][j].rgbtGreen;
sqr[2] = j < width - 1 ? image[i - 1][j + 1].rgbtGreen : -1;
}
sqr[3] = j > 0 ? image[i][j - 1].rgbtGreen : -1;
sqr[4] = image[i][j].rgbtGreen;
sqr[5] = j < width - 1 ? image[i][j + 1].rgbtGreen : -1;
if (i < (height - 1))
{
sqr[6] = j > 0 ? image[i + 1][j - 1].rgbtGreen : -1;
sqr[7] = image[i + 1][j].rgbtGreen;
sqr[8] = j < width - 1 ? image[i + 1][j + 1].rgbtGreen : -1;
}
}
else if (k == 2)
{
if (i > 0)
{
sqr[0] = j > 0 ? image[i - 1][j - 1].rgbtBlue : -1;
sqr[1] = image[i - 1][j].rgbtBlue;
sqr[2] = j < width - 1 ? image[i - 1][j + 1].rgbtBlue : -1;
}
sqr[3] = j > 0 ? image[i][j - 1].rgbtBlue : -1;
sqr[4] = image[i][j].rgbtBlue;
sqr[5] = j < width - 1 ? image[i][j + 1].rgbtBlue : -1;
if (i < (height - 1))
{
sqr[6] = j > 0 ? image[i + 1][j - 1].rgbtBlue : -1;
sqr[7] = image[i + 1][j].rgbtBlue;
sqr[8] = j < width - 1 ? image[i + 1][j + 1].rgbtBlue : -1;
}
}
// sum temp.
float divider = 0.0;
for (int l = 0; l < 9; l++)
{
if (sqr[l] >= 0 && sqr[l] <= 255)
{
tempSum = tempSum + sqr[l];
divider++;
}
}
// calulate average color for each
avgRGB[k] = round(tempSum / divider);
}
I did try to create dynamic names as variables using:
if (k == 0)
{
char *color = "rgbtRed";
} else if (k == 1)
char...
And then using that variable as dynamic name to access the struct member with brackets [] instead of (.) as follows:
...image[i][j][color];
However that did not work and as I´m new to learning C I would much appreciate some guidance to improve my code.
All the best!
You could make RBGTRIPLE a union of the anonymous struct combined with 3-element array.
typedef union {
struct {
BYTE rgbtBlue;
BYTE rgbtGreen;
BYTE rgbtRed;
} __attribute__((__packed__))
BYTE rbgt[3];
} RGBTRIPLE;
Now you can access individual components of the image as image[y][x].rgbt[1] rather than image[y][x].rgbtGreen.
Now you can replace repetitive chain of if (k == ...) { ... } else with a single case:
if (i > 0) {
sqr[0] = j > 0 ? image[i - 1][j - 1].rgbt[k] : -1;
sqr[1] = image[i - 1][j].rgbt[k];
sqr[2] = j < width - 1 ? image[i - 1][j + 1].rgbt[k] : -1;
}
sqr[3] = j > 0 ? image[i][j - 1].rgbt[k] : -1;
sqr[4] = image[i][j].rgbt[k];
sqr[5] = j < width - 1 ? image[i][j + 1].rgbt[k] : -1;
if (i < (height - 1)) {
sqr[6] = j > 0 ? image[i + 1][j - 1].rgbt[k] : -1;
sqr[7] = image[i + 1][j].rgbt[k];
sqr[8] = j < width - 1 ? image[i + 1][j + 1].rgbt[k] : -1;
}
So in this project , I need to take an image.bmp file and blur it using "box blur".
The instructions for Box Blurring as follows:
For this problem, we’ll use the “box blur,” which works by taking each pixel and, for each color value, giving it a new value by averaging the color values of neighboring pixels.
(example) The new value of each pixel would be the average of the values of all of the pixels that are within 1 row and column of the original pixel (forming a 3x3 box). For example, each of the color values for pixel 6 would be obtained by averaging the original color values of pixels 1, 2, 3, 5, 6, 7, 9, 10, and 11 (note that pixel 6 itself is included in the average). Likewise, the color values for pixel 11 would be be obtained by averaging the color values of pixels 6, 7, 8, 10, 11, 12, 14, 15 and 16.
For a pixel along the edge or corner, like pixel 15, we would still look for all pixels within 1 row and column: in this case, pixels 10, 11, 12, 14, 15, and 16.
Now I know my code is a bit long and amateur,but it is only because I am an amateur but I have come this far without any help:
void blur(int height, int width, RGBTRIPLE image[height][width])
{
// iterate through every row
for (int i = 0; i < height; i++)
{
//for every column
for (int j = 0; j < width; j++)
{
int avRed = 0;
int avGreen = 0;
int avBlue = 0;
// check if the current index is an index of an edge
if ((i == 0 && (j >= 0 && j <= width - 1))
|| ((i >= 0 && i <= height - 1) && j == 0)
|| (i == height - 1 && (j >= 0 && j <= width - 1))
|| ((i >= 0 && i <= height -1) && j == width - 1))
{
// if it is : check if it is a corner
if ((i == 0 && j == 0)
|| (i == 0 && j == width - 1)
|| (i == height - 1 && j == 0)
|| (i == height - 1 && j == width - 1))
{
if (i == 0 && j == 0)
{
avRed = round((image[i][j].rgbtRed + image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed) / 4.0);
avGreen = round((image[i][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen) / 4.0);
avBlue = round((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 = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if (i == 0 && j == width - 1)
{
avRed = round((image[i][j].rgbtRed + image[i +1 ][j].rgbtRed + image[i + 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed) / 4.0);
avGreen = round((image[i][j].rgbtGreen + image[i + 1][j].rgbtGreen + image[i + 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen) / 4.0);
avBlue = round((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 = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if(i == height - 1 && j == 0)
{
avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i][j + 1].rgbtRed) / 4.0);
avGreen= round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i][j + 1].rgbtGreen) / 4.0);
avRed = round((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 = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if (i == height - 1 && j == width - 1)
{
avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i - 1][j - 1].rgbtRed + image[i][j - 1].rgbtRed) / 4.0);
avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i - 1][j - 1].rgbtGreen + image[i][j - 1].rgbtGreen) / 4.0);
avBlue = round((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 = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
}
else // if it is not a corner index
{
if (i == 0 && (j >= 1 && j <= width - 2))
{
avRed = round((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.0);
avGreen = round((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.0);
avBlue = round((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.0);
image[i][j].rgbtRed = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if ((i >= 1 && i <= height - 2) && j == 0)
{
avRed = round((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.0);
avGreen = round((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.0);
avBlue = round((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.0);
image[i][j].rgbtRed = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if (i == height - 1 && (j >= 1 && j <= width - 2))
{
avRed = round((image[i][j].rgbtRed + image[i - 1][j].rgbtRed + image[i][j - 1].rgbtRed + image[i][j + 1].rgbtRed + image[i - 1][j + 1].rgbtRed + image[i - 1][j - 1].rgbtRed) / 6.0);
avGreen = round((image[i][j].rgbtGreen + image[i - 1][j].rgbtGreen + image[i][j - 1].rgbtGreen + image[i][j + 1].rgbtGreen + image[i - 1][j + 1].rgbtGreen + image[i - 1][j - 1].rgbtGreen) / 6.0);
avBlue = round((image[i][j].rgbtBlue + image[i - 1][j].rgbtBlue + image[i][j - 1].rgbtBlue + image[i][j + 1].rgbtBlue + image[i - 1][j + 1].rgbtBlue + image[i - 1][j - 1].rgbtBlue) / 6.0);
image[i][j].rgbtRed = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
if ((i >= 1 && i <= height -2) && j == width - 1)
{
avRed = round((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.0);
avGreen = round((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.0);
avBlue = round((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.0);
image[i][j].rgbtRed = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
}
}
else // if it is not an index of an edge at all
{
avRed = round(((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.0);
avGreen = round(((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.0);
avBlue = round(((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.0);
image[i][j].rgbtRed = avRed;
image[i][j].rgbtGreen = avGreen;
image[i][j].rgbtBlue = avBlue;
}
}
}
return;
}
Now at this point, program somewhat blurs the image, but not for the right amount. When I test it via cs50's pre-set test cases, my RGB ratios are correct for corner indexes, but off for all the others. Why that might be happening?
first make shure to copy the orignal image's pixels into another varial of type RGBTRIPLE pixel by pixel using forloop if not the first blured pixel would affect the next pixel to abe blured then do you math.
this works for me!
// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE copy[height][width];
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
copy[i][j] = image[i][j];
}
}
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
// check for an edge
if ((i == 0 && (j >= 0 && j <= width - 1))
|| ((i >= 0 && i <= height - 1) && j == 0)
|| (i == height - 1 && (j >= 0 && j <= width - 1))
|| ((i >= 0 && i <= height -1) && j == width - 1))
{
//check if it is a corner
if ((i == 0 && j == 0)
|| (i == 0 && j == width - 1)
|| (i == height - 1 && j == 0)
|| (i == height - 1 && j == width - 1))
{
if (i == 0 && j == 0)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i + 1][j + 1].rgbtRed + copy[i][j + 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j + 1].rgbtGreen + copy[i][j + 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j + 1].rgbtBlue + copy[i][j + 1].rgbtBlue) / 4.0);
}
if (i == 0 && j == width - 1)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i +1 ][j].rgbtRed + copy[i + 1][j - 1].rgbtRed + copy[i][j - 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j - 1].rgbtGreen + copy[i][j - 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j - 1].rgbtBlue + copy[i][j - 1].rgbtBlue) / 4.0);
}
if (i == height - 1 && j == 0)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i][j + 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i][j + 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i][j + 1].rgbtBlue) / 4.0);
}
if (i == height - 1 && j == width - 1)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i - 1][j - 1].rgbtRed + copy[i][j - 1].rgbtRed) / 4.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i - 1][j - 1].rgbtGreen + copy[i][j - 1].rgbtGreen) / 4.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i - 1][j - 1].rgbtBlue + copy[i][j - 1].rgbtBlue) / 4.0);
}
}
// if not a corner index
else
{
if (i == 0 && (j >= 1 && j <= width - 2))
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i][j + 1].rgbtRed + copy[i + 1][j].rgbtRed + copy[i + 1][j - 1].rgbtRed + copy[i + 1][j + 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i + 1][j - 1].rgbtGreen + copy[i + 1][j + 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i + 1][j - 1].rgbtBlue + copy[i + 1][j + 1].rgbtBlue) / 6.0);
}
if ((i >= 1 && i <= height - 2) && j == 0)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i][j + 1].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i + 1][j + 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i + 1][j + 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i + 1][j + 1].rgbtBlue) / 6.0);
}
if (i == height - 1 && (j >= 1 && j <= width - 2))
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i][j + 1].rgbtRed + copy[i - 1][j + 1].rgbtRed + copy[i - 1][j - 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i][j + 1].rgbtGreen + copy[i - 1][j + 1].rgbtGreen + copy[i - 1][j - 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i][j + 1].rgbtBlue + copy[i - 1][j + 1].rgbtBlue + copy[i - 1][j - 1].rgbtBlue) / 6.0);
}
if ((i >= 1 && i <= height -2) && j == width - 1)
{
image[i][j].rgbtRed = (int) round((copy[i][j].rgbtRed + copy[i - 1][j].rgbtRed + copy[i + 1][j].rgbtRed + copy[i][j - 1].rgbtRed + copy[i - 1][j - 1].rgbtRed + copy[i + 1][j - 1].rgbtRed) / 6.0);
image[i][j].rgbtGreen = (int) round((copy[i][j].rgbtGreen + copy[i - 1][j].rgbtGreen + copy[i + 1][j].rgbtGreen + copy[i][j - 1].rgbtGreen + copy[i - 1][j - 1].rgbtGreen + copy[i + 1][j - 1].rgbtGreen) / 6.0);
image[i][j].rgbtBlue = (int) round((copy[i][j].rgbtBlue + copy[i - 1][j].rgbtBlue + copy[i + 1][j].rgbtBlue + copy[i][j - 1].rgbtBlue + copy[i - 1][j - 1].rgbtBlue + copy[i + 1][j - 1].rgbtBlue) / 6.0);
}
}
}
// for normal pixel no edge at all
else
{
image[i][j].rgbtRed = (int) round(((copy[i - 1][j - 1].rgbtRed) + (copy[i - 1][j].rgbtRed) + (copy[i - 1][j + 1].rgbtRed) + (copy[i][j - 1].rgbtRed) + (copy[i][j].rgbtRed) + (copy[i][j + 1].rgbtRed) + (copy[i + 1][j - 1].rgbtRed) + (copy[i + 1][j].rgbtRed) + (copy[i + 1][j + 1].rgbtRed)) / 9.0);
image[i][j].rgbtGreen = (int) round(((copy[i - 1][j - 1].rgbtGreen) + (copy[i - 1][j].rgbtGreen) + (copy[i - 1][j + 1].rgbtGreen) + (copy[i][j - 1].rgbtGreen) + (copy[i][j].rgbtGreen) + (copy[i][j + 1].rgbtGreen) + (copy[i + 1][j - 1].rgbtGreen) + (copy[i + 1][j].rgbtGreen) + (copy[i + 1][j + 1].rgbtGreen)) / 9.0);
image[i][j].rgbtBlue = (int) round(((copy[i - 1][j - 1].rgbtBlue) + (copy[i - 1][j].rgbtBlue) + (copy[i - 1][j + 1].rgbtBlue) + (copy[i][j - 1].rgbtBlue) + (copy[i][j].rgbtBlue) + (copy[i][j + 1].rgbtBlue) + (copy[i + 1][j - 1].rgbtBlue) + (copy[i + 1][j].rgbtBlue) + (copy[i + 1][j + 1].rgbtBlue)) / 9.0);
}
}
}
return;
}
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;
}
}
}
I am having some issues fulfilling the requirements for the edges filter in Problem Set 4 of CS50. A description of the problem can be found here: https://cs50.harvard.edu/x/2020/psets/4/filter/more/. My code makes sense to me, so hopefully someone can shed some light on this for me, as I have been staring at my code for days on end now ): To be clear, my code does compile, so I do not think there are any bugs per se, but probably a logical flaw in my thinking.
My code is as follows:
void edges(int height, int width, RGBTRIPLE image[height][width])
{
RGBTRIPLE tempimage[height][width];
for (int i = 0; i < height; i++)
{
for (int j = 0; j < width; j++)
{
tempimage[i][j] = image[i][j];
int sGxRed = 0;
int sGxGreen = 0;
int sGxBlue = 0;
int sGyRed = 0;
int sGyGreen = 0;
int sGyBlue = 0;
if (j + 1 < width)
{
sGxRed += 2 * image[i][j + 1].rgbtRed;
sGxGreen += 2 * image[i][j + 1].rgbtGreen;
sGxBlue += 2 * image[i][j + 1].rgbtBlue;
}
if (j > 0)
{
sGxRed += -2 * image[i][j - 1].rgbtRed;
sGxGreen += -2 * image[i][j - 1].rgbtGreen;
sGxBlue += -2 * image[i][j - 1].rgbtBlue;
}
if (i + 1 < height)
{
sGyRed += 2 * image[i + 1][j].rgbtRed;
sGyGreen += 2 * image[i + 1][j].rgbtGreen;
sGyBlue += 2 * image[i + 1][j].rgbtBlue;
}
if (i > 0)
{
sGyRed += -2 * image[i - 1][j].rgbtRed;
sGyGreen += -2 * image[i - 1][j].rgbtGreen;
sGyBlue += -2 * image[i - 1][j].rgbtBlue;
}
if (i + 1 < height && j + 1 < width)
{
sGxRed += image[i + 1][j + 1].rgbtRed;
sGxGreen += image[i + 1][j + 1].rgbtGreen;
sGxBlue += image[i + 1][j + 1].rgbtBlue;
sGyRed += image[i + 1][j + 1].rgbtRed;
sGyGreen += image[i + 1][j + 1].rgbtGreen;
sGyBlue += image[i + 1][j + 1].rgbtBlue;
}
if (i > 0 && j + 1 < width)
{
sGxRed += image[i - 1][j + 1].rgbtRed;
sGxGreen += image[i - 1][j + 1].rgbtGreen;
sGxBlue += image[i - 1][j + 1].rgbtBlue;
sGyRed += -1 * image[i - 1][j + 1].rgbtRed;
sGyGreen += -1 * image[i - 1][j + 1].rgbtGreen;
sGyBlue += -1 * image[i - 1][j + 1].rgbtBlue;
}
if (i > 0 && j > 0)
{
sGxRed += -1 * image[i - 1][j - 1].rgbtRed;
sGxGreen += -1 * image[i - 1][j - 1].rgbtGreen;
sGxBlue += -1 * image[i - 1][j - 1].rgbtBlue;
sGyRed += -1 * image[i - 1][j - 1].rgbtRed;
sGyGreen += -1 * image[i - 1][j - 1].rgbtGreen;
sGyBlue += -1 * image[i - 1][j - 1].rgbtBlue;
}
if (i + 1 < height && j > 0)
{
sGxRed += -1 * image[i + 1][j - 1].rgbtRed;
sGxGreen += -1 * image[i + 1][j - 1].rgbtGreen;
sGxBlue += -1 * image[i + 1][j - 1].rgbtBlue;
sGyRed += image[i + 1][j - 1].rgbtRed;
sGyGreen += image[i + 1][j - 1].rgbtGreen;
sGyBlue += image[i + 1][j - 1].rgbtBlue;
}
int sRed = 0;
int sGreen = 0;
int sBlue = 0;
sRed = round((float)(sqrt(sGxRed^2 + sGyRed^2)));
if (sRed > 255)
{
sRed = 255;
}
sGreen = round((float)(sqrt(sGxGreen^2 + sGyGreen^2)));
if (sGreen > 255)
{
sGreen = 255;
}
sBlue = round((float)(sqrt(sGxBlue^2 + sGyBlue^2)));
if (sBlue > 255)
{
sBlue = 255;
}
tempimage[i][j].rgbtRed = sRed;
tempimage[i][j].rgbtGreen = sGreen;
tempimage[i][j].rgbtBlue = sBlue;
}
}
for(int i = 0; i < height; i++)
{
for(int j = 0; j < width; j++)
{
image[i][j].rgbtRed = tempimage[i][j].rgbtRed;
image[i][j].rgbtGreen = tempimage[i][j].rgbtGreen;
image[i][j].rgbtBlue = tempimage[i][j].rgbtBlue;
}
}
return;
}
I am very new to coding. Prior to taking this course, I have only tried my hand at a little VBA. This is my first time coding in C and the learning curve for CS50 is steep, so pardon me if my question is trivial!
Thank you all in advance! :)
P.S Apart from my actual question, please feel free to comment on how my code can be more efficient/shortened as well. I am always open to different points of view!
Common misunderstanding: ^ does not mean power-of, it means bit-wise XOR, which is not what you want here. Replace it with pow() from math.h.
Or in case of power of 2 specifically, simply do variable * variable.