我不确定我的电脑是否在欺骗我,还是我太累了找不到这个错误。几个小时甚至几天,我一直试图用纯C语言编写一个位图文件。我对格式和填充没有任何问题,但是内容有问题。下面是一个最小可行示例。
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;
}
当我填充每个像素的“蓝色字节”时,使用“255-i”的值,我希望在每行中得到从深蓝色到黑色平滑渐变的效果。但是实际上我得到了这样的结果:example1 您可以看到,每行都存在一个字节偏移,导致每一行中的颜色发生变化,并且每隔三行出现一个像素偏移。奇怪的是,只有当我尝试将“13”写入文件时才会出现这种情况。通过16进制编辑器,我发现在下一个值进入文件之前,第二个“13”被写入文件中。当我将宽度减小到240(此时位图内容变为14至255之间)时,我得到了平滑的图片而没有任何偏移:example2 您可能会认为,在写入“13”时出现此故障是纯粹的巧合,也许确实如此。但我还尝试将数据写入文件中,其中“13”出现在非确定性位置,结果出现完全相同的效果。
我已经束手无策了,请帮帮我!!!
fwrite man page
,在mode
描述下,b
标志仅供兼容使用,并且在所有符合POSIX标准的系统上都会被忽略,包括Linux。该操作者未指示其所开发的平台。 - hookenzb
标志只是修复了向文件写入额外0A
的问题。在Linux或Mac上,他首先就不会遇到这个问题。我更新了我的答案以澄清这一点。 - Random Davis