Home > Software engineering >  CS50x PSet4 Blur - Issue with taking original value
CS50x PSet4 Blur - Issue with taking original value

Time:06-11

I have been struggling with implementing the blur function these past days and am on the verge of a meltdown.

I think the issue might lie in the usage of the pointer and address, but I am unsure. For some reason, whenever I try to get the pixel that the loop had changed in the previous loop, I end up with something completely different.

Output from CS50 checker:

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)

Block 00
R: 10 G: 20 B: 30 (check middle main block)
R: 110 G: 130 B: 140 (check south block)
R: 120 G: 140 B: 150 (check southeast block)
R: 40 G: 50 B: 60 (check east block)

Block 01
R: 40 G: 50 B: 60 (check middle main block)
R: 120 G: 140 B: 150 (check south block)
R: 110 G: 130 B: 140 (check southwest block)
R: 130 G: 150 B: 160 (check southeast block)
R: 49 G: 247 B: 0 (suppose to be west block (10, 20, 30) - not sure what happened here)
R: 70 G: 80 B: 90 (check east block)

Block 0 2
R: 70G: 80B: 90
R: 130G: 150B: 160
R: 120G: 140B: 150
R: 0G: 0B:...

I have enclosed my code below:

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width])
{
    RGBTRIPLE temp[height][width];

    for (int i = 0; i < height; i  )
    {
        for (int j = 0; j < width; j  )
        {
            temp[i][j] = image[i][j];
        }
    }

    for (int h = 0; h < height; h  )
    {
        for (int w = 0; w < width; w  )
        {
            printf("Block %i %i", h, w);

            int totalRed = 0;
            int totalGreen = 0;
            int totalBlue = 0;
            float cellCounter = 0.0;

            //adds rgb for designated cell
            rgbAdd(&temp[h][w], &totalRed, &totalGreen, &totalBlue);
            cellCounter  = 1.0;

            //north row has to be at least 0
            if ((h - 1) >= 0)
            {
                //tally up north cell
                rgbAdd(&temp[h - 1][w], &totalRed, &totalGreen, &totalBlue);
                cellCounter  = 1.0;

                //east col has to be at least 0 for northeast corner to exist
                if ((w - 1) >= 0)
                {
                    //tally up northeast corner
                    rgbAdd(&temp[h - 1][w - 1], &totalRed, &totalGreen, &totalBlue);
                    cellCounter  = 1.0;
                }

                //west col has to be (width - 1) or less for northwest corner to exist
                if ((w   1) <= (width - 1))
                {
                    //tally up northwest corner
                    rgbAdd(&temp[h - 1][w   1], &totalRed, &totalGreen, &totalBlue);
                    cellCounter  = 1.0;
                }
            }

            //south row has to be (height -1) or less
            if ((h   1) <= height - 1)
            {
                //tally up south cell
                rgbAdd(&temp[h   1][w], &totalRed, &totalGreen, &totalBlue);
                cellCounter  = 1.0;

                //east col has to be at least 0 for southeast corner to exist
                if ((w - 1) >= 0)
                {
                    //tally up northeast corner
                    rgbAdd(&temp[h   1][w - 1], &totalRed, &totalGreen, &totalBlue);
                    cellCounter  = 1.0;
                }

                //west col has to be less than (width - 1) for southwest corner to exist
                if ((w   1) <= (width - 1))
                {
                    //tally up northwest corner
                    rgbAdd(&temp[h   1][w   1], &totalRed, &totalGreen, &totalBlue);
                    cellCounter  = 1.0;
                }
            }

            //west col has to be at least 0
            if ((w - 1) >= 0)
            {
                //tally up west point
                rgbAdd(&temp[h - 1][w - 1], &totalRed, &totalGreen, &totalBlue);
                cellCounter  = 1.0;
            }

            //east col has to be equal to or less than (width - 1)
            if ((w   1) <= (width - 1))
            {
                //tally up east point
                rgbAdd(&temp[h][w   1], &totalRed, &totalGreen, &totalBlue);
                cellCounter  = 1.0;
            }

            image[h][w].rgbtRed = round(totalRed / cellCounter);
            image[h][w].rgbtGreen = round(totalGreen / cellCounter);
            image[h][w].rgbtBlue = round(totalBlue / cellCounter);
        }
    }
    return;
}

//total the red, green, blue values of the original and surrounding cells
void rgbAdd(RGBTRIPLE *p, int *totalRed, int *totalGreen, int *totalBlue)
{
    RGBTRIPLE pixel = *p;

    BYTE pRed = pixel.rgbtRed;
    printf("R: %i", pRed);
    BYTE pGreen = pixel.rgbtGreen;
    printf("G: %i", pGreen);
    BYTE pBlue = pixel.rgbtBlue;
    printf("B: %i", pBlue);

    *totalRed  = pRed;
    *totalGreen  = pGreen;
    *totalBlue  = pBlue;
}

CodePudding user response:

There is an error in the coordinates of the west point: you wrote rgbAdd(&temp[h - 1][w - 1], &totalRed, &totalGreen, &totalBlue); instead of:

    rgbAdd(&temp[h][w - 1], &totalRed, &totalGreen, &totalBlue);

It is very frustrating to stare at the obvious and not see it, but it happens to all programmers...

To make it harder for bugs to hide in plain sight, I recommend simplifying the code along these ideas:

  • use a structure for the averaging state
  • update the colors and pixel count in rgbAvgAdd() for pixels in a consistent order top to botton, left to right
  • store the final value in rgbAvgEnd()
  • the north, south, east and west metaphors are not used consistently in your code, I would just remove these comments for clarity.

Here is the modified code:

typedef struct AvgState {
    int red, green, blue;
    int count;
} AvgState;

// update the red, green, blue components and number of pixels
void rgbAvgAdd(AvgState *s, RGBTRIPLE pixel) {
    s->red    = pixel.rgbtRed;
    s->green  = pixel.rgbtGreen;
    s->blue   = pixel.rgbtBlue;
    s->count  = 1;
}

// update the red, green, blue components and number of pixels
void rgbAvgEnd(AvgState *s, RGBTRIPLE *p) {
    double num   = s->count;
    p->rgbtRed   = round(s->red   / num);
    p->rgbtGreen = round(s->green / num);
    p->rgbtRed   = round(s->blue  / num);
}

// Blur image
void blur(int height, int width, RGBTRIPLE image[height][width]) {
    // use a local copy of the image (potential UB for large images)
    RGBTRIPLE temp[height][width];

    for (int i = 0; i < height; i  ) {
        for (int j = 0; j < width; j  ) {
            temp[i][j] = image[i][j];
        }
    }

    for (int h = 0; h < height; h  ) {
        for (int w = 0; w < width; w  ) {
            AvgState state = { 0, 0, 0, 0 };

            if (h > 0) {
                // handle pixels from the row above
                if (w > 0) {
                    rgbAvgAdd(&state, temp[h - 1][w - 1]);
                }
                if ((1)) {
                    rgbAvgAdd(&state, temp[h - 1][w]);
                }
                if (w   1 < width) {
                    rgbAvgAdd(&state, temp[h - 1][w   1]);
                }
            }
            if ((1)) {
                // handle pixels from the current row
                if (w > 0) {
                    rgbAvgAdd(&state, temp[h][w - 1]);
                }
                if ((1)) {
                    rgbAvgAdd(&state, temp[h][w]);
                }
                if (w   1 < width) {
                    rgbAvgAdd(&state, temp[h][w   1]);
                }
            }
            if (h   1 < height) {
                // handle pixels from the row below
                if (w > 0) {
                    rgbAvgAdd(&state, temp[h   1][w - 1]);
                }
                if ((1)) {
                    rgbAvgAdd(&state, temp[h   1][w]);
                }
                if (w   1 < width) {
                    rgbAvgAdd(&state, temp[h   1][w   1]);
                }
            }
            rgbAvgEnd(&state, &image[h][w]);
        }
    }
}
  • Related