我尝试用c ++编写一个bmp文件,但是bmp文件的宽度和高度似乎会影响结果,有时我得到一个坏的bmp文件

I try to write a bmp file in c++, but the bmp file's width and height seems to affect the result,sometimes I got a bad bmp file

本文关键字:bmp 文件 一个 影响 结果 高度 但是      更新时间:2023-10-16

如标题所述。代码如下所示

#include <Windows.h>
#include <string>
using namespace std;
#define WIDTH  90
#define HEIGHT 180
class Test {
public:
    static bool ShowWithBMP(string filename) {
        BITMAPFILEHEADER    bmfh;           // bitmap file header  
        BITMAPINFOHEADER    bmih;           // bitmap info header (windows)  
        const int OffBits = 54;
        bmfh.bfReserved1 = 0;
        bmfh.bfReserved2 = 0;
        bmfh.bfType = 0x4d42;   //"BM"
        bmfh.bfOffBits = OffBits;      
        bmfh.bfSize = WIDTH * HEIGHT * 3 + OffBits;
        memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
        bmih.biSize = 40;               
        bmih.biPlanes = 1;
        bmih.biSizeImage = 0;
        bmih.biBitCount = 24;
        bmih.biCompression = BI_RGB;
        bmih.biWidth = WIDTH;
        bmih.biHeight = HEIGHT;

        FILE* file = fopen(filename.c_str(), "w");
        fwrite((const void*)&bmfh, sizeof(BITMAPFILEHEADER), 1, file);
        fwrite((const void*)&bmih, sizeof(BITMAPINFOHEADER), 1, file);

        for (int row = 0; row < HEIGHT; ++row)
        {
            // RGB 24 BITS  
            for (int col = 0; col < WIDTH; ++col)
            {
                int index = row * WIDTH + col;
                RGBTRIPLE pix;
                pix.rgbtRed = 0;
                pix.rgbtGreen = 0;
                pix.rgbtBlue = 0; 
                fwrite((const void*)&pix, sizeof(RGBTRIPLE), 1, file);
            }
        }
        fclose(file);
        return true;
    }   
};
int main() {
    Test::ShowWithBMP("test.bmp");
    system("pause");
    return 0;
}

当我将WIDTH设置为90,HEIGHT设置为180时,输出文件"test.bmp"似乎是一个错误的文件,我无法打开它,但当将WIDTH设置为100,HEIGHTH设置为180,它就变得正确了。它怎么了?当我尝试用C++编写bmp文件时,有什么限制吗?

从内存(大约20年前)来看,BMP格式本质上包含像素数据的DIB格式。每个像素行需要是4个字节的倍数(即DWORD的整数);因此,您需要确保在每一行的末尾都有适当的填充。

以下是您的函数和修复程序,它们应该可以在中工作

static bool ShowWithBMP(string filename) {
    BITMAPFILEHEADER    bmfh;           // bitmap file header  
    BITMAPINFOHEADER    bmih;           // bitmap info header (windows)  
    const int OffBits = 54;
    bmfh.bfReserved1 = 0;
    bmfh.bfReserved2 = 0;
    bmfh.bfType = 0x4d42;   //"BM"
    bmfh.bfOffBits = OffBits; 
    DWORD bitmapLineSize = ((WIDTH * 3 + 3) / 4) * 4; //size of a row in bytes (ceil(WIDTH * 3 / 4) * 4)
    bmfh.bfSize = bitmapLineSize * HEIGHT + OffBits;
    memset(&bmih, 0, sizeof(BITMAPINFOHEADER));
    bmih.biSize = 40;               
    bmih.biPlanes = 1;
    bmih.biSizeImage = 0;
    bmih.biBitCount = 24;
    bmih.biCompression = BI_RGB;
    bmih.biWidth = WIDTH;
    bmih.biHeight = HEIGHT;
    DWORD paddingSize = bitmapLineSize - 3 * WIDTH;//extra 0 to 3 bytes per line to write
    FILE* file = fopen(filename.c_str(), "w");
    fwrite((const void*)&bmfh, sizeof(BITMAPFILEHEADER), 1, file);
    fwrite((const void*)&bmih, sizeof(BITMAPINFOHEADER), 1, file);

    for (int row = 0; row < HEIGHT; ++row)
    {
        // RGB 24 BITS  
        for (int col = 0; col < WIDTH; ++col)
        {
            int index = row * WIDTH + col;
            RGBTRIPLE pix;
            pix.rgbtRed = 0;
            pix.rgbtGreen = 0;
            pix.rgbtBlue = 0; 
            fwrite((const void*)&pix, sizeof(RGBTRIPLE), 1, file);
        }
        if (paddingSize > 0)
        {
            //write out the rest of the bitmap line filled with zeros
            DWORD padding = 0;
            fwrite((const void*)&padding, paddingSize, 1, file);
        }
    }
    fclose(file);
    return true;
}