First, as an aside, when you have a CS50 question, please search for the keywords in StackOverflow before asking. The answer is probably there. If you search for sepia RGBTRIPLE cs50
you get quite a few hits.
After doing a lot of pixel processing, you'll hone some useful debugging intuitions. Among those:
- If you see diagonal offsets, your image's bytes-per-row may be greater than the width times the pixel size. (Especially in YCbCr images or on platforms where image buffers are aligned to 128-bit vector sizes.)
- 2x or 0.5x image displays probably mean you're not heeding the scale value on a Retina display.
- Certain colorspace errors will point you immediately to BGR vs RGB byte ordering issues. No blue channel at all or all blue? Probably mixing ARGB with BGRA.
But more to the point:
- If you see wackiness in the bright or color-saturated areas, your pixel component values are probably oversaturating (exceeding the maximum value, and dropping the high bit(s)).
Every time you either (1) multiply a color component by a number great than 1 or (2) add multiple color components together, you need to think about what happens if you exceed the maximum value. If your intermediate math will add two values and then divide by 2, make sure your compiled operations will be using a large enough variable size to hold that extra bit.
So in your inner loop here, when operating on a white pixel, almost every color component will exceed 255 (i.e. red and green will exceed, but not blue, because sepia is low in blue):
int sepiared = image[i][j].rgbtRed *.393 + image[i][j].rgbtGreen *.769 + image[i][j].rgbtBlue *.189;
int sepiagreen = image[i][j].rgbtRed *.349 + image[i][j].rgbtGreen *.686 + image[i][j].rgbtBlue *.168;
int sepiablue = image[i][j].rgbtRed *.272 + image[i][j].rgbtGreen *.534 + image[i][j].rgbtBlue *.131;
The resulting value would be {255, 255, 255} x {.393+.769+.189, .349+.686+.168, .272+.534+.131}, or {344.5, 306.8, 238.9}.
But because you don't have that enough bits for those values in the BYTE components of an RGBTRIPLE struct, your values will be incorrect. So instead, you can do this:
int sepiared = (int) image[i][j].rgbtRed *.393 + image[i][j].rgbtGreen *.769 + image[i][j].rgbtBlue *.189;
int sepiagreen = (int) image[i][j].rgbtRed *.349 + image[i][j].rgbtGreen *.686 + image[i][j].rgbtBlue *.168;
int sepiablue = (int) image[i][j].rgbtRed *.272 + image[i][j].rgbtGreen *.534 + image[i][j].rgbtBlue *.131;
sepiared = min(sepiared, 255);
sepiagreen = min(sepiagreen, 255);
sepiablue = min(sepiablue, 255);
Note that I have made two changes:
- Cast the first value in each expression to (int); otherwise the calculation will be done on bytes and you'll lose your high bit.
- Enforce the maximum value of 255 on each pixel component.
When considering the other answers, please add my first fix. Checking for a max of 255 won't help if you've already dropped your high bit!