Unexpected return value from fread ()

#include <stdio.h> #include <stdint.h> #include <stdlib.h> int main() { FILE* bmp = NULL; uint32_t offset; uint8_t* temp = NULL; size_t read; unsigned int x_dim = 600, y_dim = 388; bmp = fopen("test_colour.bmp", "r"); if (!bmp) return -1; /* Get the image data offset */ fseek(bmp, 10, SEEK_SET); fgets((char*)&offset, 4, bmp); printf("Offset = %u\n", offset); temp = malloc(3*x_dim*y_dim*sizeof(uint8_t)); if (!temp) return -1; /* Go the the position where the image data is stored */ fseek(bmp, offset, SEEK_SET); /* Copy image data to array */ printf("%u bytes requested!\n", 3*x_dim*y_dim); read = fread((void*)temp, sizeof(uint8_t), 3*x_dim*y_dim, bmp); printf("%Iu bytes read!\n", read); fclose(bmp); free(temp); return 0; } 

I use the code above to read the RGB data of a 24-bit BMP image per pixel into an array. The offset from the beginning of the file into which the image data is loaded (after the BMP header) is set at offset 10 in accordance with the BMP specification. When executing the above code, I get the following output.

 Offset = 54 698400 bytes requested! 33018 bytes read! 

The offset output seems correct because the file size is 698,454 bytes (= 698400 + 54). However, the value returned by fread() indicates that not all image data can be read. However, I subsequently use the data in the temp array to convert the RGB data to grayscale and write that data back to the BMP file. Visual inspection of the output image does not indicate any errors, that is, it seems that I really read the entire input image in the first place, although fread() seems to indicate differently.

Can anyone explain this behavior?

+6
source share
1 answer

(I bet you're on Windows)

 bmp = fopen("test_colour.bmp", "r"); 

it should be

 bmp = fopen("test_colour.bmp", "rb"); 

If the file is opened in text mode on Windows, the runtime will cease to be counted when a byte 0x1a (Ctrl-Z) occurs, which Windows considers the EOF marker for text files. Even if this does not hit Ctrl-Z, you will get corrupted data when Windows converts CR / LF sequences to a single LF character.

However, I cannot explain why you can get a good image from a partial file (just lucky?).

You can render the image from the buffer, because the fread() implementation reads the number of bytes you requested (or almost so - the number is rounded to a multiple of a certain block size) into the buffer, then it scans the buffer looking for CR / LF sequences for conversion and EOF flags Ctrl -Z.

Thus, although fread() returns 33018 , the buffer is actually almost completely written with data from the file. The data is not 100% correct (for example, some CR characters probably were dropped) or completed, but in this case they are close enough to display an image that looks as you expected.

Of course, this is simply observing how this particular runtime behaves at present - it may not always behave this way in the future (or even in all systems today).

+20
source

Source: https://habr.com/ru/post/921644/


All Articles