Reputation: 243
I wrote some quick code that is supposed to invert colors of a BMP image. I test with a 40x40 dimensional BMP image, created by paint. However the function seem to fill it entirelly with white pixels instead.
void
negate
(char *FILE_NAME)
{
FILE* fp = fopen(FILE_NAME, "r+b");
uint_64 raw_data, i;
fseek(fp, 35, SEEK_SET);
//raw_data = fgetc(fp) + fgetc(fp)*256;
raw_data = 4800; // calculated
fseek(fp, 54, SEEK_SET);
for(i = 54; i != 54 + raw_data; i++) // <=
{
int old = fgetc(fp);
fseek(fp, i, SEEK_SET);
fputc(255 - old, fp);
}
fclose(fp);
}
Where am I mistaken?
Upvotes: 0
Views: 219
Reputation: 34839
The C11 draft specification has this to say about the problem
When a file is opened with update mode ('+' as the second or third character in the above list of mode argument values), both input and output may be performed on the associated stream. However, output shall not be directly followed by input without an intervening call to the fflush function or to a file positioning function (fseek, fsetpos, or rewind), and input shall not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end- of-file.
Upvotes: 3
Reputation: 3861
Adding an fseek into the loop fixes it, although I don't understand why:
for (i = 54; i != 54 + raw_data; i++) // <=
{
fseek(fp, i, SEEK_SET);
int old = fgetc(fp);
fseek(fp, i, SEEK_SET);
fputc(255 - old, fp);
}
In trying to figure out the problem, I did this, to see if the position in the stream was correct:
for (i = 54; i != 54 + raw_data; i++) // <=
{
long x = ftell(fp);
printf("%d,", x);
int old = fgetc(fp);
fseek(fp, i, SEEK_SET);
fputc(255 - old, fp);
}
And indeed it is. It ouputs 54,55,56,57,... so the fseek() should not be necessary! But if you look at the result of the fgetc(), the "old" value always seems to be reading the pixel at 54. I think @RSahu was correct: don't read and write like that to one file. Better to read the data into a buffer, then negate the buffer, then write it to disk. Or write to a different file entirely.
Maybe this has to do with buffering?
Upvotes: 2