写入 .bmp 文件时的字节移位
byte-shift when writing .bmp-file
我不确定我的 PC 是在试图愚弄我,还是我只是厌倦了寻找错误。几个小时甚至将近几天,我都在尝试用纯 C 语言编写一个位图文件。我对格式或填充没有任何问题,但对内容没有任何问题。
这是一个 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;
}
当我用 255-i
填充每个像素的 'blue-byte' 时,我希望每行都能从深蓝色平滑淡入黑色。但我得到这个:
example1
如您所见,每行中都有一个字节移位,这会导致每条新行中的颜色发生变化,并且每三行之后会发生像素移位。奇怪的是,它只会在我尝试将 13
写入文件时发生。我发现使用十六进制编辑器,在下一个值进入文件之前写入了第二个 13。当我将宽度减小到 240(现在位图的内容在 14 到 255 之间变化)时,我得到了没有任何偏移的平滑图片:example2
你说写13出现这个故障纯属巧合,可能就是这样。但是我也尝试将数据写入到13出现在非确定位置的文件中,结果完全一样。
我束手无策,请帮帮我!!!
这是因为 13
的值对应 Windows 中的一个换行符。 Windows 换行符是 \r\n
,对应十六进制 0D0A
。由于您尝试写入 0D
,它被视为换行符,因此它被写入文件作为 0D0A
。这样一来,如果您只将 \n
放入字符串中,它将被正确地写入文件 \r\n
。因此,要解决这个问题,您应该确保以二进制模式写入文件,这可以防止 "feature" 将额外的字节写入文件。有关详细信息,请参阅此处:Strange 0x0D being added to my binary file
要使用二进制模式,只需将 fopen
中的 "w"
替换为 "wb"
,即可正常工作。我刚才已经验证过了,输出是正确的:
在其他平台上,这个问题一开始就不会发生,所以这个修复只能在 Windows 平台上工作,并且只需要 Windows 平台。
我不确定我的 PC 是在试图愚弄我,还是我只是厌倦了寻找错误。几个小时甚至将近几天,我都在尝试用纯 C 语言编写一个位图文件。我对格式或填充没有任何问题,但对内容没有任何问题。 这是一个 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;
}
当我用 255-i
填充每个像素的 'blue-byte' 时,我希望每行都能从深蓝色平滑淡入黑色。但我得到这个:
example1
如您所见,每行中都有一个字节移位,这会导致每条新行中的颜色发生变化,并且每三行之后会发生像素移位。奇怪的是,它只会在我尝试将 13
写入文件时发生。我发现使用十六进制编辑器,在下一个值进入文件之前写入了第二个 13。当我将宽度减小到 240(现在位图的内容在 14 到 255 之间变化)时,我得到了没有任何偏移的平滑图片:example2
你说写13出现这个故障纯属巧合,可能就是这样。但是我也尝试将数据写入到13出现在非确定位置的文件中,结果完全一样。
我束手无策,请帮帮我!!!
这是因为 13
的值对应 Windows 中的一个换行符。 Windows 换行符是 \r\n
,对应十六进制 0D0A
。由于您尝试写入 0D
,它被视为换行符,因此它被写入文件作为 0D0A
。这样一来,如果您只将 \n
放入字符串中,它将被正确地写入文件 \r\n
。因此,要解决这个问题,您应该确保以二进制模式写入文件,这可以防止 "feature" 将额外的字节写入文件。有关详细信息,请参阅此处:Strange 0x0D being added to my binary file
要使用二进制模式,只需将 fopen
中的 "w"
替换为 "wb"
,即可正常工作。我刚才已经验证过了,输出是正确的:
在其他平台上,这个问题一开始就不会发生,所以这个修复只能在 Windows 平台上工作,并且只需要 Windows 平台。