I really can't find what's the problem with my code here. The output image is not even converting to sepia at all; it's kind of like grayscale and has pinkish sky. The algorithm I applied is correct and I did use the round function implemented in math.h. I guess there might be something wrong with my if-else statements?
void sepia(int height, int width, RGBTRIPLE image[height][width])
{
//process pixels by row
for (int i = 0; i < height; i )
{
//process a single pixel in a row
for(int j = 0; j < width; j )
{
//implement the algorithm
float sepiaRed = 0.393 * image[i][j].rgbtRed 0.769 * image[i][j].rgbtGreen 0.189 * image[i][j].rgbtBlue;
//round sepiaRed
image[i][j].rgbtRed = round(sepiaRed);
if (image[i][j].rgbtRed > 255)
{
image[i][j].rgbtRed = 255;
}
else
{
image[i][j].rgbtRed = image[i][j].rgbtRed;
}
float sepiaGreen = 0.349 * image[i][j].rgbtRed 0.686 * image[i][j].rgbtGreen 0.168 * image[i][j].rgbtBlue;
//round sepiaGreen
image[i][j].rgbtGreen = round(sepiaGreen);
if (image[i][j].rgbtGreen > 255)
{
image[i][j].rgbtGreen = 255;
}
else
{
image[i][j].rgbtGreen = image[i][j].rgbtGreen;
}
float sepiaBlue = 0.272 * image[i][j].rgbtRed 0.534 * image[i][j].rgbtGreen 0.131 * image[i][j].rgbtBlue;
//round sepiaBlue
image[i][j].rgbtBlue = round(sepiaBlue);
if (image[i][j].rgbtBlue > 255)
{
image[i][j].rgbtBlue = 255;
}
else
{
image[i][j].rgbtBlue = image[i][j].rgbtBlue;
}
}
}
return;
}
CodePudding user response:
Problem is here:
image[i][j].rgbtRed = round(sepiaRed);
I assume that rgbtRed
is 8-bit long unsigned integer (usually called "byte"). Therefore this operation will leave only 8 least significant bits of rounded part of sepiaRed
. The rest of bits will be truncated during conversion to 8 bit integer.
The checks later on like:
if (image[i][j].rgbtGreen > 255)
make no sense because 8-bit unsigned integer can represent number form 0-255 range. It's not possible for it to be larger than 255.
Moreover, the line below looks quite redundant:
image[i][j].rgbtRed = image[i][j].rgbtRed;
The correct solution should apply limitation to the float value and next round it and store to 8-bit integer.
if (sepiaGreen > 255)
sepiaGreen = 255;
image[i][j].rgbtGreen = round(sepiaGreen);
Another problem.
Compute all sepia components BEFORE updating image[i][j]
.
Otherwise sepiaRed
would be used as rgbtRed
during computation of sepiaGreen
.
The final code for the body of the inner loop could be:
// extract color component for give pixel
float r = image[i][j].rgbtRed;
float g = image[i][j].rgbtGreen;
float b = image[i][j].rgbtBlue;
// compute sepia components
float sepiaRed = 0.393 * r 0.769 * g 0.189 * b;
float sepiaGreen = 0.349 * r 0.686 * g 0.168 * b;
float sepiaBlue = 0.272 * r 0.534 * g 0.131 * b;
// truncate to 0-255
if (sepiaRed > 255) sepiaRed = 255;
if (sepiaGreen > 255) sepiaGreen = 255;
if (sepiaBlue > 255) sepiaBlue = 255;
// round and store
image[i][j].rgbtRed = round(sepiaRed);
image[i][j].rgbtGreen = round(sepiaGreen);
image[i][j].rgbtBlue = round(sepiaBlue);