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

亡梦爱人 提交于 2021-02-11 17:37:27

问题


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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!