从位集创建单色 BMP

zas*_*kar 5 c++ monochrome bitmap bmp bitset

我可能需要一些帮助来弄清楚如何喂养下面的过程。我需要编写一个单色 BMP 文件。下面的代码(来自:How to Save monochrome Image as bmp in windows C++ ?)看起来能够做到这一点。我现在陷入了如何将 astd::bitset或 最好转换boost::dynamic_bitset成这种byte*格式的困境。到目前为止我的所有尝试都失败了,我无法将 8x8 棋盘格图案之类的东西写入 BMP 中。该程序创建了BMP,并且可以被Photoshop读取,但内容很乱。因此,任何如何解决此问题的建议都将受到赞赏!

Save1BppImage(byte* ImageData, const char* filename, long w, long h){

    int bitmap_dx = w; // Width of image
    int bitmap_dy = h; // Height of Image

    // create file
    std::ofstream file(filename, std::ios::binary | std::ios::trunc);
    if(!file) return;

    // save bitmap file headers
    BITMAPFILEHEADER fileHeader;
    BITMAPINFOHEADER * infoHeader;
    infoHeader = (BITMAPINFOHEADER*) malloc(sizeof(BITMAPINFOHEADER) );
    RGBQUAD bl = {0,0,0,0};  //black color
    RGBQUAD wh = {0xff,0xff,0xff,0xff}; // white color


    fileHeader.bfType      = 0x4d42;
    fileHeader.bfSize      = 0;
    fileHeader.bfReserved1 = 0;
    fileHeader.bfReserved2 = 0;
    fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER));

    infoHeader->biSize          = (sizeof(BITMAPINFOHEADER) );
    infoHeader->biWidth         = bitmap_dx;    
    infoHeader->biHeight        = bitmap_dy;
    infoHeader->biPlanes        = 1;
    infoHeader->biBitCount      = 1;
    infoHeader->biCompression   = BI_RGB; //no compression needed
    infoHeader->biSizeImage     = 0;
    infoHeader->biXPelsPerMeter = 0;
    infoHeader->biYPelsPerMeter = 0;
    infoHeader->biClrUsed       = 2;
    infoHeader->biClrImportant  = 2;

    file.write((char*)&fileHeader, sizeof(fileHeader)); //write bitmapfileheader
    file.write((char*)infoHeader, (sizeof(BITMAPINFOHEADER) )); //write bitmapinfoheader
    file.write((char*)&bl,sizeof(bl)); //write RGBQUAD for black
    file.write((char*)&wh,sizeof(wh)); //write RGBQUAD for white

    int bytes = (w/8) * h ; //for example for 32X64 image = (32/8)bytes X 64 = 256;

    file.write((const char*)ImageData, bytes);

    file.close();
}
Run Code Online (Sandbox Code Playgroud)

-编辑-

我的一个天真的方法是这样的

    byte test[64];
for(unsigned int i=0; i<64; ++i)
    if(i % 2)
        test[i] = 0;
    else
        test[i] = 1;

Save1BppImage(test, "C:/bitmap.bmp", 8, 8);
Run Code Online (Sandbox Code Playgroud)

Mar*_*som 4

你的代码非常接近。以下是一些关于它可能存在的问题的想法。

bfOffBits值必须包括调色板的大小。

fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER)) + 2*sizeof(RGBQUAD);
Run Code Online (Sandbox Code Playgroud)

无论调色板显示什么内容,某些软件都可能将其解释0为白色和黑色。1尽管文件格式允许您选择任何一种方式,但您最好按该顺序指定调色板,并在必要时反转您的位。

位图的每一行将从 4 字节边界开始。如果位图宽度不是 32 的倍数,则每行之间需要一些填充。

BMP 文件从底行到顶行排序,这与大多数人组织数组的方式相反。

最后两个建议合并起来看起来像这样:

int bytes_in = (w + 7) / 8;
int bytes_out = ((w + 31) / 32) * 4;
const char * zeros[4] = {0, 0, 0, 0};
for (int y = h - 1;  y >= 0;  --y)
{
    file.write(((const char *)ImageData) + (y * bytes_in), bytes_in);
    if (bytes_out != bytes_in)
        file.write(zeros, bytes_out - bytes_in);
}
Run Code Online (Sandbox Code Playgroud)