简体   繁体   中英

When making sepia filter, error message pops up, meaning? C

I attempted the next requested filter and again had issues. The code compiles for once but when running the program in sepia it gives me an error message. Its as follows:

helpers.c:31:29: runtime error: 259.821 is outside the range of representable values of type 'unsigned char'

Now I know this means that the 255 limit has been breached (and doesn't work) so I wrote an if else statement since the instructions were:

"It's also possible that the result of the formula is a number greater than 255, the maximum value for an 8-bit color value. In that case, the red, green, and blue values should be capped at 255. As a result, we can guarantee that the resulting red, green, and blue values will be whole numbers between 0 and 255, inclusive."

However this makes another error prompt:

By "undeclared identifier," clang means you've used a name sepiaBlue on line 57 of helpers.c which hasn't been defined. If you mean to use sepiaBlue as a variable, make sure to declare it by specifying its type, and check that the variable name is spelled correctly.

But I made sepiaBlue a float variable. Here's my code:

void sepia(int height, int width, RGBTRIPLE image[height][width])
{
  for(int i = 0; i < height; i++)
  {
    for(int j = 0; j < width; j++)
    {
        RGBTRIPLE rgbt = image[i][j];
        if(rgbt.rgbtRed > 255)
        {
            rgbt.rgbtRed = 255;
        }
        else
        {
            float sepiaRed = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
        }
        
        if(rgbt.rgbtGreen > 255)
        {
            rgbt.rgbtGreen = 255;
        }
        else
        {
            float sepiaGreen = .349 * rgbt.rgbtRed + .686 * rgbt.rgbtGreen + .168 * rgbt.rgbtBlue;
        }
        if(rgbt.rgbtBlue > 255)
        {
            rgbt.rgbtBlue = 255;
        }
        else
        {
            float sepiaBlue = .272 * rgbt.rgbtRed + .534 * rgbt.rgbtGreen + .131 * rgbt.rgbtBlue;
        }
        
        rgbt.rgbtBlue = sepiaBlue;
        rgbt.rgbtGreen = sepiaGreen;
        rgbt.rgbtRed =  sepiaRed;
        image[i][j] = rgbt;
    }
  }
  return;
}

Thanks again (I dont think my brain is functioning properly today.).

First, as already noted, you've defined sepiaRed , sepiaGreen , and sepiaBlue in the local scope of a block that is inaccessible when you try to access it outside that block.

All of your range-checking is non-functional. Look at this condition:

if(rgbt.rgbtRed > 255)
{
   rgbt.rgbtRed = 255;
}
else
{
   sepiaRed = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
}

The condition will never be true, because rgbt.rgbtRed is a BYTE , which is an 8-bit unsigned char value. As such, it cannot have a value greater than 255. You need to do that range checking after the calculation.

Really, you can rewrite everything in the inner loop like this:

RGBTRIPLE rgbt = image[i][j];
float red   = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
float green = .349 * rgbt.rgbtRed + .686 * rgbt.rgbtGreen + .168 * rgbt.rgbtBlue
float blue  = .272 * rgbt.rgbtRed + .534 * rgbt.rgbtGreen + .131 * rgbt.rgbtBlue;

image[i][j].rgbtRed   = min(red, 255);
image[i][j].rgbtGreen = min(green, 255);
image[i][j].rgbtBlue  = min(blue, 255);

It's much simpler and as a bonus, should work.

The scope of sepiaBlue is the else block where you have defined it.

Outside the block, the variable is undefined.

Declare the local variable at the beginning of the function.

Without any knowledge about all the structure variables, here is the solution of "undeclared identifier".

Observe that I just declared the sepiaRed , sepiaGreen , sepiaBlue within the same scope as where you use them to set the rgbt values. You had declared them within the if else statements and thereby they won't exists when leaving the if else statements.

void sepia(int height, int width, RGBTRIPLE image[height][width])
{

   for(int i = 0; i < height; i++)
    {
        for(int j = 0; j < width; j++)
        {
            RGBTRIPLE rgbt = image[i][j];

            float sepiaRed, sepiaGreen, sepiaBlue;

            if(rgbt.rgbtRed > 255)
            {
                rgbt.rgbtRed = 255;
            }
            else
            {
                sepiaRed = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
            }
            
            if(rgbt.rgbtGreen > 255)
            {
                rgbt.rgbtGreen = 255;
            }
            else
            {
                sepiaGreen = .349 * rgbt.rgbtRed + .686 * rgbt.rgbtGreen + .168 * rgbt.rgbtBlue;
            }

            if(rgbt.rgbtBlue > 255)
            {
                rgbt.rgbtBlue = 255;
            }
            else
            {
                sepiaBlue = .272 * rgbt.rgbtRed + .534 * rgbt.rgbtGreen + .131 * rgbt.rgbtBlue;
            }
            
            rgbt.rgbtBlue = sepiaBlue;
            rgbt.rgbtGreen = sepiaGreen;
            rgbt.rgbtRed =  sepiaRed;
            image[i][j] = rgbt;
        }
    
    }
    
    return;
}

running your posted code through the compiler results in:

gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o" 

untitled1.c: In function ‘sepia’:

untitled1.c:20:25: warning: comparison is always false due to limited range of data type [-Wtype-limits]
   20 |         if(rgbt.rgbtRed > 255)
      |                         ^

untitled1.c:26:30: warning: conversion from ‘double’ to ‘float’ may change value [-Wfloat-conversion]
   26 |             float sepiaRed = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
      |                              ^~~~

untitled1.c:26:19: warning: unused variable ‘sepiaRed’ [-Wunused-variable]
   26 |             float sepiaRed = .393 * rgbt.rgbtRed + .769 * rgbt.rgbtGreen + .189 * rgbt.rgbtBlue;
      |                   ^~~~~~~~

untitled1.c:29:27: warning: comparison is always false due to limited range of data type [-Wtype-limits]
   29 |         if(rgbt.rgbtGreen > 255)
      |                           ^

untitled1.c:35:32: warning: conversion from ‘double’ to ‘float’ may change value [-Wfloat-conversion]
   35 |             float sepiaGreen = .349 * rgbt.rgbtRed + .686 * rgbt.rgbtGreen + .168 * rgbt.rgbtBlue;
      |                                ^~~~

untitled1.c:35:19: warning: unused variable ‘sepiaGreen’ [-Wunused-variable]
   35 |             float sepiaGreen = .349 * rgbt.rgbtRed + .686 * rgbt.rgbtGreen + .168 * rgbt.rgbtBlue;
      |                   ^~~~~~~~~~

untitled1.c:37:26: warning: comparison is always false due to limited range of data type [-Wtype-limits]
   37 |         if(rgbt.rgbtBlue > 255)
      |                          ^

untitled1.c:43:31: warning: conversion from ‘double’ to ‘float’ may change value [-Wfloat-conversion]
   43 |             float sepiaBlue = .272 * rgbt.rgbtRed + .534 * rgbt.rgbtGreen + .131 * rgbt.rgbtBlue;
      |                               ^~~~

untitled1.c:43:19: warning: unused variable ‘sepiaBlue’ [-Wunused-variable]
   43 |             float sepiaBlue = .272 * rgbt.rgbtRed + .534 * rgbt.rgbtGreen + .131 * rgbt.rgbtBlue;
      |                   ^~~~~~~~~

untitled1.c:46:25: error: ‘sepiaBlue’ undeclared (first use in this function)
   46 |         rgbt.rgbtBlue = sepiaBlue;
      |                         ^~~~~~~~~

untitled1.c:46:25: note: each undeclared identifier is reported only once for each function it appears in
untitled1.c:47:26: error: ‘sepiaGreen’ undeclared (first use in this function)
   47 |         rgbt.rgbtGreen = sepiaGreen;
      |                          ^~~~~~~~~~

untitled1.c:48:25: error: ‘sepiaRed’ undeclared (first use in this function); did you mean ‘sepia’?
   48 |         rgbt.rgbtRed =  sepiaRed;
      |                         ^~~~~~~~
      |                         sepia

Compilation failed.

TO fix those problems:

float literals end in a f , With out the f the result is a double literal.

the scope of those variables is limited by the nearest surrounding braces { and } . Suggest declaring the variables at the top of the sepia() function.

statements like:

if(rgbt.rgbtRed > 255)

will ALWAYS be false because a unsigned char has the range of 0...255, so can never be greater than 255.

The following proposed code:

  1. cleanly compiles
  2. performs the desired functionality

and now, the proposed code:

typedef unsigned char BYTE;

typedef struct tagRGBTRIPLE 
{
  BYTE rgbtBlue;
  BYTE rgbtGreen;
  BYTE rgbtRed;
} RGBTRIPLE;
    


void sepia(int height, int width, RGBTRIPLE image[height][width])
{
  for(int i = 0; i < height; i++)
  {
    for(int j = 0; j < width; j++)
    {
        RGBTRIPLE rgbt = image[i][j];
        //if(rgbt.rgbtRed > 255)
        ///{
        //    rgbt.rgbtRed = 255;
        //}
        //else
        //{
        float sepiaRed = .393f * rgbt.rgbtRed + .769f * rgbt.rgbtGreen + .189f * rgbt.rgbtBlue;
        //}
        
        //if(rgbt.rgbtGreen > 255)
        //{
        //   rgbt.rgbtGreen = 255;
        //}
        //else
        //{
        float sepiaGreen = .349f * rgbt.rgbtRed + .686f * rgbt.rgbtGreen + .168f * rgbt.rgbtBlue;
        //}
        //if(rgbt.rgbtBlue > 255)
        //{
        //    rgbt.rgbtBlue = 255;
        //}
        //else
        //{
        float    sepiaBlue = .272f * rgbt.rgbtRed + .534f * rgbt.rgbtGreen + .131f * rgbt.rgbtBlue;
        //}
        
        rgbt.rgbtBlue  = ( (BYTE)sepiaBlue  > 255 )? 255 : (BYTE)sepiaBlue;
        rgbt.rgbtGreen = ( (BYTE)sepiaGreen > 255 )? 255 : (BYTE)sepiaGreen;
        rgbt.rgbtRed   = ( (BYTE)sepiaRed   > 255 )? 255 : (BYTE)sepiaRed;
        image[i][j] = rgbt;
    }
  }
  return;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM