【问题标题】:byte-shift when writing .bmp-file写入 .bmp 文件时的字节移位
【发布时间】:2017-03-25 03:46:39
【问题描述】:

我不确定我的电脑是在试图愚弄我,还是我只是太累了才找到错误。几个小时甚至几天我都在尝试用纯 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 填充每个像素的“蓝色字节”时,我希望每行都能从深蓝色平滑渐变到黑色。但我得到了这个: example1

如您所见,每行中都有一个字节移位,这会导致每条新行的颜色发生变化,并且每三行之后就会发生一次像素移位。奇怪的是,它只发生在我试图将13 写入文件时。使用十六进制编辑器,我发现在下一个值进入文件之前会写入第二个 13。当我将宽度减小到 240(现在位图的内容在 14 到 255 之间变化)时,我得到了没有任何变化的平滑图片:example2

您可能会说,在编写 13 时出现此错误纯属巧合,而且可能确实如此。但是我也尝试将数据写入13出现在不确定位置的文件中,结果完全一样。

我无能为力了,请帮帮我!!!

【问题讨论】:

    标签: c bitmap bmp


    【解决方案1】:

    这是因为 13 的值对应于 Windows 中的换行符。 Windows 换行符是\r\n,对应于十六进制0D0A。由于您正在尝试编写0D,因此它被视为换行符,因此它会以0D0A 的形式写入文件。这样,如果您只将 \n 放入字符串中,它将正确地作为 \r\n 写入文件。因此,要解决此问题,您应该确保以二进制模式写入文件,以防止此“功能”将额外字节写入文件。更多信息请看这里:Strange 0x0D being added to my binary file

    要使用二进制模式,只需将fopen 中的"w" 替换为"wb",就可以正常工作。刚才验证过了,输出是正确的:

    在其他平台上,这个问题一开始就不会发生,所以这个修复程序只适用于 Windows 平台,并且只需要用于 Windows 平台。

    【讨论】:

    • 根据fwrite man page,在mode 描述下,b 标志仅用于兼容性,在包括Linux 在内的所有符合POSIX 的系统上都将被忽略。该运营商尚未说明他们正在开发的平台。
    • 它可以在 Linux 上正常工作。由于 fopen 默认是二进制的。
    • @Matt OP 的问题据我所知仅发生在 Windows 上。 b 标志只是解决了将额外的0A 写入文件的问题。在 Linux 或 Mac 上,他一开始就不会遇到这个问题。我更新了我的答案以澄清这一点。
    • 这是一个不错的答案!
    猜你喜欢
    • 2015-07-05
    • 1970-01-01
    • 1970-01-01
    • 2015-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多