1

I am trying to modify a bitmap file and in order to do this, I need its size.

I am pretty sure I read the headers properly, I used these structs(btw, using C) :

#pragma pack(1)

struct bmp_fileheader
{
    unsigned char  fileMarker1; /* 'B' */
    unsigned char  fileMarker2; /* 'M' */
    unsigned int   bfSize; /* File's size */
    unsigned short unused1;
    unsigned short unused2;
    unsigned int   imageDataOffset; /* Offset to the start of image data */
};

struct bmp_infoheader
{
    unsigned int   biSize; /* Size of the info header - 40 bytes */
    signed int     width; /* Width of the image */
    signed int     height; /* Height of the image */
    unsigned short planes;
    unsigned short bitPix;
    unsigned int   biCompression;
    unsigned int   biSizeImage; /* Size of the image data */
    int            biXPelsPerMeter;
    int            biYPelsPerMeter;
    unsigned int   biClrUsed;
    unsigned int   biClrImportant;
};

#pragma pack()

At the end of the day I am getting a buggy result, and I think it's because the bfSize doesn't match the properties of the file. (right click properties differs from printf bfSize.

From what I understand from this link (https://en.wikipedia.org/wiki/BMP_file_format#Example_1 ), the bfSize should contain the whole size, including the padding.

Is it okay if the bfSize differs from properties?

I just got an idea, do you think that my buggy result is because I read the structs using pragma pack, then I continue reading from the file, as if I read from where the pixels' array starts?

I am using something like

FILE *pf 

I read those structs.

I calculate the number of octets stored inside the pixels' array.

Then I read those octets continuing from pf's location, which should be, according to my logic, exactly where the array starts.

Thanks for reading.

edit: ps: those differences are something like: bfSize says 3645 and on the properties it displays 3702, which is a pretty big difference. The bfSize number is always less than the properties number, when it differs.

  • If the `bfSize` is less than the _Size on Disk_ bytes, then the `bfSize` is wrong. From MSDN: `bfSize` _Specifies the size, in bytes, of the bitmap file_. – Paul Ogilvie Dec 16 '17 at 12:28
  • Do you open the file in mode `"rb"`? – Paul Ogilvie Dec 16 '17 at 12:30
  • I do open it in mode "rb". I read those 2 structs using the same FILE* pf. Then I read each byte. – NuSuntStudent Dec 16 '17 at 13:10
  • Technically an app can write anything it wants after the pixel data, it has no affect on an app that reads the bmp file. Consider using a hex viewer to see what is there. Could be interesting, it probably is something boring like a copyright notice. – Hans Passant Dec 16 '17 at 14:07
  • my objective relies on the correctness of the bfSize information. Otherwise I can't do anything. I noticed I forgot about the biSizeImage though, I will check it out. – NuSuntStudent Dec 16 '17 at 15:39
  • You may need to add more of your code. The structs *look* fine to me (without double-checking against the specs; I am sure you already did that) so is possible you are doing something else wrong. By the way, are you trying on one image file only? Try with another and see if it also deviates. – Jongware Dec 16 '17 at 17:32
  • image files only. and they all respect a certain pattern: white background and a few digits of different colors. the structs were given by our staff, for now I have to take a picture and change all digits' colors to a given color. – NuSuntStudent Dec 16 '17 at 18:29
  • Post a link to one of these files. At the very least we can check if your result is correct, for that file. – Jongware Dec 17 '17 at 00:17
  • 1
    https://ufile.io/dxej8 this is an example. 3420 in bfSize and 3454 in properties. The difference is because of the padding octets, I figured out last night. But from wikipedia I saw that bfSize should be covering the padding octets as well! – NuSuntStudent Dec 17 '17 at 11:27

1 Answers1

1

bfSize is the size of the file, including the headers.

biSizeImage is the size of the pixel data, in bytes. The data starts at imageDataOffset (more commonly called bfOffBits).

It is correct to define the headers with #pragma pack(1). After defining them, you should restore the packing but for the reading it doesn't matter.

If you want to change the size of the image, You need to calculate the new heigth times the size of the new scanline. A scanline is rounded up to the nearest word using:

// WIDTHBYTES takes # of bits in a scanline and rounds up to nearest word.
#define WIDTHBYTES(bits)    (((bits) + 31) / 32 * 4)

which you call like:

int scanlineSize= WIDTHBYTES(bih.biWidth * bih.biBitCount);

with bih the bitmap info header struct read from the file.

See also pointer file randomly changes value in middle of reading raw bitmap data on how to read a bitmap.

Paul Ogilvie
  • 25,048
  • 4
  • 23
  • 41
  • 1
    I don't want to change the size of the file. Look, I am getting a picture with digits and a white background. The digits have different colors and are placed randomly. My goal is to change the digits' color to a given color. And do this to all digits, then generate a new bmp file. My problem, so far, seems to be because my bfSize is incorrect, and I can't figure out why. – NuSuntStudent Dec 16 '17 at 13:15