1

I'm making a blur filter that takes the RGB values of the surrounding pixels, takes the average of each, and applies it to the pixel. Have been working on it for days and I'm still not sure what the problem is or how to fix it. I did do it the long way and there is probably a shorter faster way but I can't seem to figure it out. Here's the important part of the code:

for (int i = 0; i < height; i++) {
  for (int j = 0; j < width; j++) {
    int avrgRed;
    int avrgBlue;
    int avrgGreen;
    int maxj = width - 1;
    int maxi = height - 1;
    if (i == 0) {
      if (j == 0) {
        avrgRed =
            round((image[i][j].rgbtRed + image[i][j + 1].rgbtRed +
                   image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed) /
                  4);
        avrgBlue =
            round((image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue +
                   image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue) /
                  4);
        avrgGreen =
            round((image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen +
                   image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen) /
                  4);
      } else if (j == maxj) {
        avrgRed =
            round((image[i][j - 1].rgbtRed + image[i][j].rgbtRed +
                   image[i + 1][j - 1].rgbtRed + image[i + 1][j].rgbtRed) /
                  4);
        avrgBlue =
            round((image[i][j - 1].rgbtBlue + image[i][j].rgbtBlue +
                   image[i + 1][j - 1].rgbtBlue + image[i + 1][j].rgbtBlue) /
                  4);
        avrgGreen =
            round((image[i][j - 1].rgbtGreen + image[i][j].rgbtGreen +
                   image[i + 1][j - 1].rgbtGreen + image[i + 1][j].rgbtGreen) /
                  4);
      } else {
        avrgRed =
            round((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) /
                  6);
        avrgBlue =
            round((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) /
                  6);
        avrgGreen =
            round((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) /
                  6);
      }
    } else if (i == maxi) {
      if (j == 0)
      //{
      //    avrgRed = round((image[i][j].rgbtRed + image[i][j + 1].rgbtRed +
      //    image[i + 1][j].rgbtRed + image[i + 1][j + 1])/4);

      //}
      {
        avrgRed = round((image[i - 1][j].rgbtRed + image[i - 1][j + 1].rgbtRed +
                         image[i][j].rgbtRed + image[i][j + 1].rgbtRed) /
                        4);
        avrgBlue =
            round((image[i - 1][j].rgbtBlue + image[i - 1][j + 1].rgbtBlue +
                   image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue) /
                  4);
        avrgGreen =
            round((image[i - 1][j].rgbtGreen + image[i - 1][j + 1].rgbtGreen +
                   image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen) /
                  4);
      } else if (j == maxj) {
        avrgRed =
            round((image[i][j].rgbtRed + image[i][j + 1].rgbtRed +
                   image[i + 1][j].rgbtRed + image[i + 1][j + 1].rgbtRed) /
                  4);
        avrgBlue =
            round((image[i][j].rgbtBlue + image[i][j + 1].rgbtBlue +
                   image[i + 1][j].rgbtBlue + image[i + 1][j + 1].rgbtBlue) /
                  4);
        avrgGreen =
            round((image[i][j].rgbtGreen + image[i][j + 1].rgbtGreen +
                   image[i + 1][j].rgbtGreen + image[i + 1][j + 1].rgbtGreen) /
                  4);
      } else {
        avrgRed =
            round((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) /
                  6);
        avrgBlue =
            round((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) /
                  6);
        avrgGreen =
            round((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) /
                  6);
      }
    } else {
      if (j == 0) {
        avrgRed =
            round((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) /
                  6);
        avrgBlue =
            round((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) /
                  6);
        avrgGreen =
            round((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) /
                  6);
      } else if (j == maxj) {
        avrgRed =
            round((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) /
                  6);
        avrgBlue =
            round((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) /
                  6);
        avrgGreen =
            round((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) /
                  6);
      } else {
        avrgRed = 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);
        avrgBlue =
            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);
        avrgGreen =
            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);
      }
    }
    newimageRed[i][j] = avrgRed;
    newimageBlue[i][j] = avrgBlue;
    newimageGreen[i][j] = avrgGreen;
  }
}

Here is a 4x4 image test (the RGB values are written) Expected result

70 85 95      80 95 105     100 115 125   110 125 135
113 126 136   123 136 145   142 155 163   152 165 173
113 119 136   143 151 164   156 166 171   180 190 194
113 112 132   155 156 171   169 174 177   203 207 209

Actual result

70 85 95      80 95 105     100 115 125   110 125 135   
92 104 112    122 135 145   141 154 163   140 147 164   
140 147 164   143 150 163   156 165 171   119 121 135   
112 111 131   135 89 97     140 139 138   76 138 143

What do you guys think is the problem? or should I rewrite it in another way?

Update: I did solve the bigger problems, I messed up the + and - placements and mixed them up. Now I just have to fix the 1 problems, which may be because of the round function, have tried a few now but they all end up being off by 1 somewhere. Gonna check if the problem is a float > int conversion problem later.

Michael M.
  • 10,486
  • 9
  • 18
  • 34
  • Use a [*debugger*](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) to step through the code line by line, monitoring variables and their values. Pay attention to all the array indexing, and compare them with the limits of the array. – Some programmer dude Oct 19 '22 at 14:49
  • No bugs btw, the code runs and compiles just fine. It's the results that are the problem. – Selman Bela Oct 19 '22 at 14:51
  • 1
    Please clarify what you mean by "off by 1" and "nowhere near the mark". Give examples for both. Ideally, provide [mcve]. The process of providing that may lead you to find your problem. If not, people here can help. Otherwise, you can hope that someone has a clever guess and fix your problem without having any data. But this is just hoping for good luck. – anatolyg Oct 19 '22 at 14:51
  • 2
    Just because some code compiles, even with out warnings, and seems to run doesn't mean its correct. If you get unexpected results from your function then it's more than likely that you go out of bounds of you arrays, leading to *undefined behavior*. – Some programmer dude Oct 19 '22 at 14:54
  • BTW regarding "compiles just fine" — are there any warnings? I think `avrgRed = round(...)` should generate a warning for float to int conversion, but not sure. – anatolyg Oct 19 '22 at 14:55
  • "No bugs" means the code compiles, runs fine, does not show weird behaviour, always creates the expected result and so on... That is the opposite of "always off by one or..." – Gerhardh Oct 19 '22 at 14:56
  • Your code is way too incomplete. That is not even a complete function. Also, what input data was used to create that output? – Gerhardh Oct 19 '22 at 15:00
  • @anatolyg I'm pretty sure that warning is silenced since I divide by 9. The avrg values do turn to floats I'm pretty sure since I cannot directly apply them to the new image – Selman Bela Oct 19 '22 at 15:01
  • @Someprogrammerdude I thought so too, but I made a prototype where that DOES happen and it led to segmentation fault, I decided that since I am getting an output and no error code then that means I didn't get out of bounds – Selman Bela Oct 19 '22 at 15:03
  • 1
    `else if (j == maxj) { ... + image[i - 1][j + 1].rgbtRed + ...}` That doesn't go together well... Same for `if (j == 0) { avrgRed = round((image[i - 1][j - 1].rgbtRed +...` – Gerhardh Oct 19 '22 at 15:05
  • @Gerhardh It is a complete function? theres just a tiny part that I left out since that works fine and its unimportant to the problem (according to the testing I did) as for the input data it's just an image and its height and width – Selman Bela Oct 19 '22 at 15:05
  • That "tiny part" are basically **all** variable definitions you are using in that code. You might adjust your view about what "complete" means. – Gerhardh Oct 19 '22 at 15:06
  • @Gerhardh Why? maxj is just the max height the image can go without getting out of bounds, if it's not less than the bounds or more then its inside them. That was my thought process writing the if statements – Selman Bela Oct 19 '22 at 15:07
  • The issue is that you messed up the limits. What element is addressed by `[j+1]` if `j==maxj`? In some of the blocks it looks OK, in some you seem to mix up lower and upper boundary – Gerhardh Oct 19 '22 at 15:08
  • @Gerhardh this is a problem I have to solve. Those definitions are already done by the guys who gave me it, I forgot to mention CS50 in the post so sorry about that. If it is a problem on the other end though that's quite infuriating – Selman Bela Oct 19 '22 at 15:09
  • We do not have mental power to read your hidden code. We only see what you show us. Your code is useless without proper context. If I didn't just by accident know that CS50 task, I would not have any idea what you are even talking about. – Gerhardh Oct 19 '22 at 15:11
  • @Gerhardh This conversation is quite long but its a 2 dimensional array, [i] is the row and [j] is the column. Now that I think about it that might be the problem, i have to switch + with -. Will update as soon as I can – Selman Bela Oct 19 '22 at 15:15
  • Exactly. Some +/- are swapped. But as mentioned, some look fine. Look closely... – Gerhardh Oct 19 '22 at 15:16
  • If your program crashes due to undefined behavior, you should consider yourself lucky because it's very easy to find and debug. But the problem with undefined behavior (abbreviated to UB) is that it's really unpredictable. If you're unlucky it might actually seem to work, as seems to be the case here. – Some programmer dude Oct 19 '22 at 15:23
  • @Gerhardh Yes, the results did change now they are MUCH closer to the original, they aren't exactly there yet but that's because I might've missed a few wrong statements and they are still off by 1 due to the round function not rounding them properly for some reason. I did stumble on the latter before though, so I'll find a way to fix that as well. Thanks for the help man, really appreciate it. – Selman Bela Oct 19 '22 at 15:24
  • @Someprogrammerdude I think I found the issue, but doesn't undefined behavior act different every time? I thought the composition of memory is always changing so if any of that was happening id get different results each time – Selman Bela Oct 19 '22 at 15:26

1 Answers1

-1

Find the first value which is incorrect. In your example, it's the first pixel in second row (i.e. first row's results are correct - that's valuable info!).

Expected result: 113

Actual result: 92

Follow the execution path for that pixel. Your code has 9 nearly identical sections; this specific example points you exactly in which section to look.

anatolyg
  • 26,506
  • 9
  • 60
  • 134
  • Thanks for the tip but a commenter helped me find the problem. It was some +'s and -'s that I used in the wrong section. Now though I am still of by 1's which I only have the round function to blame, or it happens while transferring the integers. – Selman Bela Oct 19 '22 at 15:34
  • 1
    @SelmanBela This answer is not for you. It's for other people who may read this post in future. – anatolyg Oct 20 '22 at 14:39