Jan Drendel Jan Drendel - 24 days ago 9
C Question

byte-shift when writing .bmp-file

I'm not sure wheather my PC is trying to fool me or if I'm just to tired to find the bug. For hours and almost days I'm trying to write a bitmap file in pure C. I don't have any problems with the format or the padding, but the content.
Here's a MWE.

int main() {
FILE *file;
int w = 256;
int h = 15;
int pad = (4 - ((3 * w) % 4)) % 4;

int filesize = 54 + (3 * w + pad) * h;

// Create file header
unsigned char bmpfileheader[14] = { 'B','M', 0,0,0,0, 0,0, 0,0, 54,0,0,0 };

bmpfileheader[2] = (unsigned char)(filesize);
bmpfileheader[3] = (unsigned char)(filesize >> 8);
bmpfileheader[4] = (unsigned char)(filesize >> 16);
bmpfileheader[5] = (unsigned char)(filesize >> 24);

// Create Info Header
unsigned char bmpinfoheader[40] = { 40,0,0,0, 0,0,0,0, 0,0,0,0, 1,0, 24,0 };

bmpinfoheader[4] = (unsigned char)(w);
bmpinfoheader[5] = (unsigned char)(w >> 8);
bmpinfoheader[6] = (unsigned char)(w >> 16);
bmpinfoheader[7] = (unsigned char)(w >> 24);
bmpinfoheader[8] = (unsigned char)(h);
bmpinfoheader[9] = (unsigned char)(h >> 8);
bmpinfoheader[10] = (unsigned char)(h >> 16);
bmpinfoheader[11] = (unsigned char)(h >> 24);

// Create content
// Allocate memory dynamically
unsigned char *bmpcontent = (unsigned char *)calloc(filesize - 54, sizeof(unsigned char));

int index;

// map data values onto blue-red scale
for (int j = 0; j < h; j++)
{
for (int i = 0; i < w; i++)
{
index = 3 * i + (3 * w + pad) * j;

// blue
*(bmpcontent + index) = 255-i;
}
}

// Write to file
file = fopen("test.bmp", "w");

fwrite(bmpfileheader, sizeof(bmpfileheader[0]), 14, file);
fwrite(bmpinfoheader, sizeof(bmpinfoheader[0]), 40, file);
fwrite(bmpcontent, sizeof(bmpcontent[0]), filesize - 54, file);

fclose(file);

// free memory
free(bmpcontent);

return 0;
}


As I'm filling the 'blue-byte' of each pixel with
255-i
I'm expecting to get a smooth fade from dark blue to black in each line. But I'm getting this:
example1

As you can see there is a byte-shift in each line which causes a change of color in each new line plus a pixel-shift after every third line. The curious thing is, that it only happens, when I'm trying to write a
13
into the file. Using a hex editor I found out, that a second 13 is written before the next value finds its way into the file. When I'm reducing the width to 240 (now the content of the bitmap varies between 14 and 255) I'm getting the smooth picture without any shifts: example2

You may say that it is pure coincidence that this fault appears while writing a 13 and it may be so. But I also tried to write data into the file where the 13 appeared at non-deterministic positions, and exactly the same effect occured.

I'm at my wits end, please help me!!!

Answer

It's because a value of 13 corresponds with a newline in Windows. Windows newlines are \r\n, which corresponds to hex 0D0A. Since you're trying to write 0D, it's treated as a newline, so it's getting written to the file as 0D0A. This is so that if you put only \n in a string, it will correctly be written as \r\n to a file. Thus, to fix this, you should make sure you're writing to the file in binary mode, which prevents this "feature" from writing the extra byte to the file. See here for more info: Strange 0x0D being added to my binary file

To use binary mode, just replace "w" with "wb" in your fopen, and it will work fine. I've verified this just now, and the output is correct:

test.bmp

On other platforms, this problem won't happen in the first place, so this fix will only work on, and is only needed for, Windows platforms.

Comments