Search code examples
cdebuggingsegmentation-faultcs50

CS50 blur function only calculate the middle pixel correctly + seg fault


// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE blurred[height][width];
    int i = 0;
    int j = 0;
    int sumred;
    int sumgreen;
    int sumblue;
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            if (i == 0 && j == 0) //edge case 1: top left corner
            {
                // ([i][j] + [i][j+1] + [i+1][j] + [i+1][j+1])/4
                sumred = image[i][j].rgbtRed + image[i][j+1].rgbtRed + image[i+1][j].rgbtRed + image[i+1][j+1].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 4.0);
                sumgreen = image[i][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j+1].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 4.0);
                sumblue = image[i][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 4.0);
            }

            if (i == 0 && j > 0 && j < (width - 1)) //edgecase 2: top roll
            {
                // ([i][j-1] + [i][j] + [i][j+1] + [i+1][j-1] + [i+1][j] + [i+1][j+1])/6
                sumred = 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;
                blurred[i][j].rgbtRed = round(sumred / 6.0);
                sumgreen = 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;
                blurred[i][j].rgbtGreen = round(sumgreen / 6.0);
                sumblue = 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;
                blurred[i][j].rgbtBlue = round(sumblue / 6.0);
            }

            if (i == 0 && j == (width - 1)) //edge case 3: top right corner
            {
                sumred = image[i][j-1].rgbtRed + image[i][j].rgbtRed + image[i+1][j-1].rgbtRed + image[i+1][j].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 4.0);
                sumgreen = image[i][j-1].rgbtGreen + image[i][j].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i+1][j].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 4.0);
                sumblue = image[i][j-1].rgbtBlue + image[i][j].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i+1][j].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 4.0);
            }

            if (i > 0 && i < (height - 1) && j == 0) //edge case 4: left most column
            {
                sumred = image[i-1][j].rgbtRed + image[i-1][j+1].rgbtRed + image[i][j].rgbtRed + image[i][j+1].rgbtRed + + image[i+1][j].rgbtRed + image[i+1][j+1].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 6.0);
                sumgreen = image[i-1][j].rgbtGreen + image[i-1][j+1].rgbtGreen + image[i][j].rgbtGreen + image[i][j+1].rgbtGreen + image[i+1][j].rgbtGreen + image[i+1][j+1].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 6.0);
                sumblue = image[i-1][j].rgbtBlue + image[i-1][j+1].rgbtBlue + image[i][j].rgbtBlue + image[i][j+1].rgbtBlue + image[i+1][j].rgbtBlue + image[i+1][j+1].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 6.0);
            }

            if (i == (height - 1) && j == 0) // edge case 5: bottom left corner
            {
                sumred = image[i-1][j].rgbtRed + image[i-1][j+1].rgbtRed + image[i][j].rgbtRed + image[i][j+1].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 4.0);
                sumgreen = image[i-1][j].rgbtGreen + image[i-1][j+1].rgbtGreen + image[i][j].rgbtGreen + image[i][j+1].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 4.0);
                sumblue = image[i-1][j].rgbtBlue + image[i-1][j+1].rgbtBlue + image[i][j].rgbtBlue + image[i][j+1].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 4.0);
            }

            if (i == (height - 1) && j > 0 && j < (width -1)) // edge case 6: bottom roll
            {
                sumred = 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;
                blurred[i][j].rgbtRed = round(sumred / 6.0);
                sumgreen = 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;
                blurred[i][j].rgbtGreen = round(sumgreen / 6.0);
                sumblue = 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;
                blurred[i][j].rgbtBlue = round(sumblue / 6.0);
            }

            if (i == (height - 1) && j == (width - 1)) // edge case 7: bottom right corner
            {
                sumred = image[i-1][j-1].rgbtRed + image[i-1][j].rgbtRed + image[i][j-1].rgbtRed + image[i][j].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 4.0);
                sumgreen = image[i-1][j-1].rgbtGreen + image[i-1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i][j].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 4.0);
                sumblue = image[i-1][j-1].rgbtBlue + image[i-1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i][j].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 4.0);
            }

            if (i > 0 && i < (height - 1) && j == (width - 1)) // edge case 8: right most column
            {
                sumred = image[i-1][j-1].rgbtRed + image[i-1][j].rgbtRed + image[i][j-1].rgbtRed + image[i][j].rgbtRed + image[i+1][j-1].rgbtRed + image[i+1][j].rgbtRed;
                blurred[i][j].rgbtRed = round(sumred / 6.0);
                sumgreen = image[i-1][j-1].rgbtGreen + image[i-1][j].rgbtGreen + image[i][j-1].rgbtGreen + image[i][j].rgbtGreen + image[i+1][j-1].rgbtGreen + image[i+1][j].rgbtGreen;
                blurred[i][j].rgbtGreen = round(sumgreen / 6.0);
                sumblue = image[i-1][j-1].rgbtBlue + image[i-1][j].rgbtBlue + image[i][j-1].rgbtBlue + image[i][j].rgbtBlue + image[i+1][j-1].rgbtBlue + image[i+1][j].rgbtBlue;
                blurred[i][j].rgbtBlue = round(sumblue / 6.0);
            }

            else // everything else srrounded by 8 pixels
            {
                sumred = 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;
                blurred[i][j].rgbtRed = round(sumred / 9.0);
                sumgreen = 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;
                blurred[i][j].rgbtGreen = round(sumgreen / 9.0);
                sumblue = 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;
                blurred[i][j].rgbtBlue = round(sumblue / 9.0);
            }
        }
    }

    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            image[i][j].rgbtRed = blurred[i][j].rgbtRed;
            image[i][j].rgbtGreen = blurred[i][j].rgbtGreen;
            image[i][j].rgbtBlue = blurred[i][j].rgbtBlue;
        }
    }
    return;
}

This is probably the most unga bunga way to slove this (and it doesn't work) I've checked all loop conditions to be height-1 or width-1, considered all 8 edge cases, not sure why seg fault happens.

Seg fault while checking with bmp files.

**below is check50 results

testing with sample 3x3 image

first row: (10, 20, 30), (40, 50, 60), (70, 80, 90)

second row: (110, 130, 140), (120, 140, 150), (130, 150, 160)

third row: (200, 210, 220), (220, 230, 240), (240, 250, 255)

Expected Output:

70 85 95

80 95 105

90 105 115

117 130 140

127 140 149

137 150 159

163 178 188

170 185 194

178 193 201

Actual Output:

42 52 57

56 67 71

76 87 96

100 112 121

127 140 149

137 150 159

121 132 139

113 123 129

101 109 142**


Solution

  • // Blur image
    void blur(int height, int width, RGBTRIPLE image[height][width])
    {
    RGBTRIPLE blurred[height][width];
    int i = 0;
    int j = 0;
    int sumred = 0;
    int sumgreen = 0;
    int sumblue = 0;
    
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            int count_in = 0;
            sumred = 0;
            sumgreen = 0;
            sumblue = 0;
            // loop from grid 0 (i - 1, j - 1) to grid 8 (i + 1, j + 1) and check if anything out of bounds
            // count_in is the number of pixels in a 9-grid that's inside bounds
            for (int x = i - 1; x < i + 2; x++)
            {
                for (int y = j - 1; y < j + 2; y++)
                {
    
                    if (x < 0 || x > height - 1 || y < 0 || y > width - 1)
                    {
                        continue;
                    }
                    else
                    {
                        sumred = image[x][y].rgbtRed + sumred;
                        sumgreen = image[x][y].rgbtGreen + sumgreen;
                        sumblue = image[x][y].rgbtBlue + sumblue;
                        count_in++;
                    }
                }
            }
            blurred[i][j].rgbtRed = round(sumred / (float) count_in);
            blurred[i][j].rgbtGreen = round(sumgreen / (float) count_in);
            blurred[i][j].rgbtBlue = round(sumblue / (float) count_in);
        }
    }
    
    for (i = 0; i < height; i++)
    {
        for (j = 0; j < width; j++)
        {
            image[i][j].rgbtRed = blurred[i][j].rgbtRed;
            image[i][j].rgbtGreen = blurred[i][j].rgbtGreen;
            image[i][j].rgbtBlue = blurred[i][j].rgbtBlue;
        }
    }
    return;
    }
    

    Stopped using the unga bunga method and decided to loop inside the 9-grid pattern around the pixel [i][j] and check for out of bounds and skip them by using continue

    This code passes check50. Thank you comments