So i wrote this block of code
void grayscale(int height, int width, RGBTRIPLE image[height][width])
{
for (int i = 0 ; i < (height) ; i )
{
for(int j = 0 ; j <(width); j ){
float blue = image[i][j].rgbtBlue;
float green = image[i][j].rgbtGreen;
float red = image[i][j].rgbtRed;
int average_color = round((blue green red) /3);
image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = average_color;
// red = blue = green = average_color; WHY IS THAT WORNG INSTEAD OF THE LINE ABOVE?
}
}
return;
}
and in the comment i had my first attempt on the code but it didnt get the value of average_color this way?
and only when i tried it like this
image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = average_color;
why red=blu=green=avergae_color; doesnt work?
CodePudding user response:
Lets understand one of your statements
float blue = image[i][j].rgbtBlue;
This statement is a definition in C, i.e. it is a declaration which is then instantiated. A declaration in simple terms, informs the compiler that the given identifier(blue)
is associated with the given data type(float)
. When you assign a value to it using an assignment operator, it reserves a separate memory space in the process stack which would be identified by the identifier you used (blue)
. Clearly this memory address will not the same as that image[i][j]
, where the averaging needs to happen, hence the behaviour.
Perhaps you thought that you creating a variable would make it point to the RHS of assignment operator. While this is true in some languages like python and javascript, C does not behave that way.
CodePudding user response:
I thought they will point there , out of pure human logic
Heh well, take that up with the creators of C. float blue = image[i][j].rgbtBlue;
et al, creates a copy of the value, two distinct memory spaces. Mutating one doesn't affect the other. C does, however, have pointers, types whose values are memory addresses. You can have several pointers point to the same location in memory, and you can dereference any of them to read/write the memory they point to. For example, you can do the following:
...
// in this context, the * means declare blue as a float _pointer_. That is, a
// pointer that points to a float value. The & means "take the address of",
// in this case, the address of image[i][j].rgbBlue. I don't _think_ the
// parenthesis are necessary, but I routinely forget the order of operations
// in C, so I prefer using them when there's any doubt.
float* blue = &(image[i][j].rgbtBlue);
// and declare pointers for green and red as well
float* green = &(image[i][j].rgbtGreen);
float* red = &(image[i][j].rgbtRed);
// In this context, the * means _dereference_ the pointer. That is, retrieve the
// value the pointer points to, which is the float image data
int average_color = round((*blue *green *red) /3);
//image[i][j].rgbtBlue = image[i][j].rgbtGreen = image[i][j].rgbtRed = average_color;
// again, we want to dereference with *. This will assign average_color to each
// of the memory spaces that red, blue, and green point to
*red = *blue = *green = average_color;
// now, image[i][j].rgbtBlue, et al, will hold the value of average_color
One more thing, round
returns a double
, your compiler should be warning that you're assigning this to an int
. Use roundf
(described in same link above) instead and make that float average_color
.