与GDI创建8bpp位图,保存为一个文件 [英] Creating 8bpp bitmap with GDI and saving it as a file

查看:378
本文介绍了与GDI创建8bpp位图,保存为一个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个完美的工作code,创建32bpp的位图,我需要改变它,会创建一个8bpp位图。

I have a perfectly working code that creates 32bpp bitmap and I need to change it so that 8bpp bitmap is created.

下面是一块code的创建32bpp的位图,画了进去,然后它会创建一个位图文件,并将其存储字节的矢量:

Here's the piece of code that creates 32bpp bitmap, draws into it, then it creates a bitmap file and store it into the vector of bytes:

// prepare bitmap:
BYTE* bitmap_data = NULL;
HDC hDC = GetDC(NULL);
HDC memHDC = CreateCompatibleDC(hDC);
BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bmi.bmiHeader.biWidth = desiredWidth;                 // desiredWidth is 800
bmi.bmiHeader.biHeight = desiredHeight;               // desiredHeight is 202
bmi.bmiHeader.biPlanes = 1;
bmi.bmiHeader.biBitCount = 32;
bmi.bmiHeader.biCompression = BI_RGB;
bmi.bmiHeader.biSizeImage = (((desiredWidth * bmi.bmiHeader.biBitCount + 31) & ~31) >> 3) * desiredHeight;
HBITMAP bitmap = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&bitmap_data, NULL, NULL);
ReleaseDC(NULL, hDC);
DeleteDC(hDC);

... // drawing into bitmap

// prepare bitmap file header:
BITMAPFILEHEADER bf;
memset(&bf, 0, sizeof(BITMAPFILEHEADER));
bf.bfType = MAKEWORD('B', 'M');
bf.bfOffBits = sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize;
bf.bfSize = bf.bfOffBits + bmi.bmiHeader.biSizeImage;

// write bitmap file into the vector:
std::vector<BYTE> bitmapData;
bitmapData.insert(bitmapData.end(), (BYTE*)&bf, ((BYTE*)&bf) + sizeof(BITMAPFILEHEADER));
bitmapData.insert(bitmapData.end(), (BYTE*)&bmi.bmiHeader, ((BYTE*)&bmi.bmiHeader) + sizeof(BITMAPINFOHEADER));
bitmapData.insert(bitmapData.end(), bitmap_data, bitmap_data + bmi.bmiHeader.biSizeImage);

和后面的矢量被存储在文件:

And later the vector is stored into the file:

std::ofstream of("picture.bmp", std::ofstream::out | std::ofstream::binary);
of.write((char*)&bitmapData[0], bitmapData.size());
of.close();

和这里的输出图像:

第一步是自然替换 32 8 在这一行: bmi.bmiHeader .biBitCount = 32; 导致成图像填充固体灰色。然后根据这个答案我做了以下变化:

First step was naturally replacing 32 with 8 in this line: bmi.bmiHeader.biBitCount = 32; which resulted into image filled with solid grey colour. Then based on this answer I made following changes:

BITMAPINFO bmi;
memset(&bmi, 0, sizeof(BITMAPINFO));

变成了:

struct BITMAPINFO256 {
    BITMAPINFOHEADER bmiHeader;
    RGBQUAD bmiColors[256];
} bmi;
memset(&bmi, 0, sizeof(BITMAPINFO256));

添加了这个循环前右 CreateDIBSection 正所谓:

for (UINT i = 0; i < 256; i++) {
    bmi.bmiColors[i].rgbRed   = i;
    bmi.bmiColors[i].rgbGreen = i;
    bmi.bmiColors[i].rgbBlue  = i;
}

bmi.bmiHeader 被写入到载体中, RGBQUAD 阵列包括:使的sizeof(BITMAPINFO256)前presses头的大小。

and when the bmi.bmiHeader is being written into the vector, the RGBQUAD array is included: so sizeof(BITMAPINFO256) expresses the size of the header.

新的code(满$ C $这里 C)产生这样的输出:

The new code (full code here) produces this output:

为什么新形象看起来是这样?那里发生了什么?我缺少什么?

Why the new image looks that way? What's going on there? What am I missing?

任何帮助将AP preciated。

Any help will be appreciated.

推荐答案

它看起来像一个对齐问题。请确保您在BITMAPFILEHEADER更新bfOffBits,使其指向像素数据的第一个字节。 (如果你不改变它,那么它很可能指向调色板的开始。)

It looks like an alignment problem. Make sure you update bfOffBits in the BITMAPFILEHEADER so that it points to the first byte of the pixel data. (If you don't change it, then it probably points to the beginning of the palette.)

在换句话说,的sizeof(RGBQUAD)* 256 此处应增加以及

In other words, sizeof(RGBQUAD)*256 should be added here as well:

bf.bfOffBits = sizeof(BITMAPFILEHEADER) + bmi.bmiHeader.biSize;

也确保第一扫描线一个DWORD边界开始。即,其从该文件的开始偏移应该是4字节的倍数。同样地,每个扫描线应被填充到四字节的倍数。 (您可能看不到这些问题,如果你的宽度是好的偶数。这是件好事,你的测试用例中奇数宽度的图像。)

Also makes sure the first scanline starts on a DWORD boundary. That is, its offset from the beginning of the file should be a multiple of four bytes. Likewise, each scanline should be padded out to a multiple of four bytes. (You may not see these problems if your widths are nice even numbers. It's good to have an odd-width image among your test cases.)

这篇关于与GDI创建8bpp位图,保存为一个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆