Home > Enterprise >  The output image is not converted to sepia. What is wrong with my sepia code?
The output image is not converted to sepia. What is wrong with my sepia code?

Time:09-30

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);
  • Related