写.bmp文件时的字节移位

时间:2016-11-10 23:53:27

标签: c bitmap bmp

我不确定我的电脑是在试图欺骗我,还是我只是厌倦了找到这个错误。几个小时甚至几天我都试图用纯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中出现在非确定性位置的文件中,并且发生了完全相同的效果。

我在我的智慧结束,请帮助我!!!

1 个答案:

答案 0 :(得分:4)

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

要使用二进制模式,只需将"w"替换为"wb"中的fopen,它就能正常工作。我刚刚验证了这一点,输出是正确的:

test.bmp

在其他平台上,首先不会发生此问题,因此此修复程序仅适用于Windows平台,并且仅在Windows平台上使用。