问题
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;
}
}
}
}
回答1:
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;
}
}
}
来源:https://stackoverflow.com/questions/62330831/cs50x-filter-blur-receiving-a-runtime-error-on-first-nested-else-state-s