C++ 从位集创建单色BMP

C++ 从位集创建单色BMP,c++,bitmap,bmp,bitset,monochrome,C++,Bitmap,Bmp,Bitset,Monochrome,我可能需要一些帮助来找出如何为下面的进程提供反馈。我需要写一个单色BMP文件。下面的代码(它的发件人:)看起来可以这样做。我现在一直在研究如何将std::bitset或更好的boost::dynamic\u bitset转换成这种byte*格式。到目前为止,我的所有尝试都失败了,我无法在BMP中写入类似8x8棋盘格图案的内容。这个过程创建了BMP,Photoshop可以读取它,但是内容很混乱。因此,任何关于如何解决此问题的建议都将不胜感激 Save1BppImage(byte* ImageDat

我可能需要一些帮助来找出如何为下面的进程提供反馈。我需要写一个单色BMP文件。下面的代码(它的发件人:)看起来可以这样做。我现在一直在研究如何将
std::bitset
或更好的
boost::dynamic\u bitset
转换成这种
byte*
格式。到目前为止,我的所有尝试都失败了,我无法在BMP中写入类似8x8棋盘格图案的内容。这个过程创建了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();
}
-编辑-

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

    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);
字节测试[64];

对于(无符号整数i=0;i我有一个非常相似的东西

  • 这种方法不处理BMP格式的填充,因此只能制作宽度为4倍的位图

  • 这不是单色位图。它是RGB格式,但您可以轻松调整它

  • 这不是一个确切的答案,但肯定会对你有用

好好享受吧

void createBitmap( byte * imageData, const char * filename, int width, int height )
{
    BITMAPFILEHEADER bitmapFileHeader;
    memset( &bitmapFileHeader, 0, sizeof( bitmapFileHeader ) );
    bitmapFileHeader.bfType = ( 'B' | 'M' << 8 );
    bitmapFileHeader.bfOffBits = sizeof( BITMAPFILEHEADER ) + sizeof( BITMAPINFOHEADER );
    bitmapFileHeader.bfSize = bitmapFileHeader.bfOffBits + width * height * 3;

    BITMAPINFOHEADER bitmapInfoHeader;
    memset( &bitmapInfoHeader, 0, sizeof( bitmapInfoHeader ) );
    bitmapInfoHeader.biSize = sizeof( BITMAPINFOHEADER );
    bitmapInfoHeader.biWidth = width;
    bitmapInfoHeader.biHeight = height;
    bitmapInfoHeader.biPlanes = 1;
    bitmapInfoHeader.biBitCount = 24;

    std::ofstream file( filename, std::fstream::binary );

    file.write( reinterpret_cast< char * >( &bitmapFileHeader ), sizeof( bitmapFileHeader ) );
    file.write( reinterpret_cast< char * >( &bitmapInfoHeader ), sizeof( bitmapInfoHeader ) );

    // the pixels!
    file.write( imageData, width * height * 3 );

    file.close();
}

int main( int argc, const char * argv[] )
{
    int width = 12; // multiple of 4
    int height = 12;

    byte imageData[ width * height * 3 ];

    // fill imageData the way you want, this is just a sample
    // on how to set the pixel at any specific (X,Y) position

    for ( int y = 0; y < height; ++y )
    {
        for ( int x = 0; x < width; ++x )
        {
            int pos = 3 * ( y * width + x );

            byte pixelColor = ( x == 2 && y == 2 ) ? 0x00 : 0xff;

            imageData[ pos ] = pixelColor;
            imageData[ pos + 1 ] = pixelColor;
            imageData[ pos + 2 ] = pixelColor;
        }
    }

    createBitmap( imageData, "bitmap.bmp", width, height );

    return 0;
}
void createBitmap(字节*图像数据,常量字符*文件名,整数宽度,整数高度)
{
BITMAPFILEHEADER BITMAPFILEHEADER;
memset(&bitmapFileHeader,0,sizeof(bitmapFileHeader));
bitmapFileHeader.bfType=('B'|'M'(&bitmapFileHeader),sizeof(bitmapFileHeader));
write(reinterpret_cast(&BitMapInfo头文件),sizeof(BitMapInfo头文件));
//像素!
文件写入(图像数据,宽*高*3);
file.close();
}
int main(int argc,const char*argv[]
{
int width=12;//4的倍数
整数高度=12;
字节图像数据[宽度*高度*3];
//按照您想要的方式填充imageData,这只是一个示例
//关于如何在任何特定(X,Y)位置设置像素
对于(int y=0;y
在这个示例中,我们需要一个白色位图,在X=2,Y=2的位置有一个黑色像素

BMP格式要求Y从下向上生长


如果位图宽度为每比特一个像素(真正的单色位图)您可以测试位并填充图像数据。要测试字节中的位,请执行以下操作:
myByte>>position&1
其中
position
是您要从0到7进行测试的位。

您的代码非常接近。下面是一些关于关闭位置的想法

bOffBits
值必须包括调色板的大小

fileHeader.bfOffBits   = sizeof(BITMAPFILEHEADER) + (sizeof(BITMAPINFOHEADER)) + 2*sizeof(RGBQUAD);
有些软件可能会将
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);
}

仅用于存档,低于工作版本。它采用boost位集作为输入像素存储

void bitsetToBmp(boost::dynamic_bitset<unsigned char> bitset, const char* filename, int width, int height){
//write the bitset to file as 1-bit deep bmp
//bit order 0...n equals image pixels  top left...bottom right, row by row
//the bitset must be at least the size of width*height, this is not checked

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)) + 2*sizeof(RGBQUAD); 

infoHeader->biSize          = (sizeof(BITMAPINFOHEADER) );
infoHeader->biWidth         = width;    
infoHeader->biHeight        = height;
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

// convert the bits into bytes and write the file
int offset, numBytes = ((width + 31) / 32) * 4;
byte* bytes = (byte*) malloc(numBytes * sizeof(byte));

for(int y=height - 1; y>=0; --y){
    offset = y * width;
    memset(bytes, 0, (numBytes * sizeof(byte)));
    for(int x=0; x<width; ++x)
        if(bitset[offset++]){
            bytes[x / 8] |= 1 << (7 - x % 8);
    };
    file.write((const char *)bytes, numBytes);
};
free(bytes);
file.close();
void bitsetToBmp(boost::dynamic_bitset bitset,const char*filename,int-width,int-height){
//将位集作为1位深度的bmp写入文件
//位顺序0…n等于图像像素左上…右下,逐行
//位集的大小必须至少为宽度*高度,不勾选此项
流文件的std::of(文件名,std::ios::binary | std::ios::trunc);
如果(!文件)返回;
//保存位图文件头
BITMAPFILEHEADER文件头;
BitMapInfo头*信息头;
infoHeader=(BitMapInfo头*)malloc(sizeof(BitMapInfo头));
RGBQUAD bl={0,0,0,0};//黑色
RGBQUAD wh={0xff,0xff,0xff,0xff};//白色
fileHeader.bfType=0x4d42;
fileHeader.bfSize=0;
fileHeader.bfReserved1=0;
fileHeader.bfReserved2=0;
fileHeader.bfOffBits=sizeof(BITMAPFILEHEADER)+(sizeof(bitmapinfo头))+2*sizeof(RGBQUAD);
infoHeader->biSize=(sizeof(BitMapInfo头));
信息头->宽度=宽度;
infoHeader->biHeight=高度;
信息头->双平面=1;
infoHeader->bibibitcount=1;
infoHeader->biCompression=BI_RGB;//无需压缩
infoHeader->biSizeImage=0;
infoHeader->biXPelsPerMeter=0;
infoHeader->biYPelsPerMeter=0;
infoHeader->biClrUsed=2;
infoHeader->biclr=2;
file.write((char*)&fileHeader,sizeof(fileHeader));//写入bitmapfileheader
write((char*)infoHeader,(sizeof(BitMapInfo头));//write BitMapInfo头
file.write((char*)&bl,sizeof(bl));//为黑色写RGBQUAD
file.write((char*)&wh,sizeof(wh));//为白色写入RGBQUAD
//将位转换为字节并写入文件
整数偏移量,单位为(宽度+31)/32)*4;
byte*bytes=(byte*)malloc(numBytes*sizeof(byte));
对于(int y=高度-1;y>=0;--y){
偏移=y*宽度;
memset(字节,0,(numBytes*sizeof(字节));

for(int x=0;x)感谢回复,但这段代码的确切问题仍然是:如何填充字节数组?用“字节”表示的位图中白色和黑色的表示是什么类型?我尝试了0、0x00、1、0xff之类的值-一切都失败了。你能为你的代码创建一个4x4 b/w棋盘格模式的字节示例吗?在我的示例中,每3个字节代表RGB通道…如果我将它们设置为R=G=b,我们会得到一个单色图像。我不能确切地知道你的示例,因为我不知道获取位的输入位图格式