我有一个现场设备,它使用位图中的光栅字节来显示每像素8位图像。设备使用自己的颜色表来显示在MS Paint中创建的位图。
鉴于现场设备不存储原始颜色表,是否可以下载图像字节,并在Windows中重新创建位图? bpp,高度和宽度都是已知的,只是颜色表本身缺失。 MS Paint似乎对256位图使用相同的颜色索引,所以看起来这应该是可能的。
我有一个位图工具类,我可以使用下面显示的函数创建一个24位位图,我正在尝试修改它以创建256(8 bpp)位图。要做到这一点需要什么?
// This function needs to be fixed.
// It only works for 24-BPP bitmaps.
void BitmapTools::SetHbitmap (BYTE* pBitmapBits, LONG lWidth,LONG lHeight, WORD wBitsPerPixel)
{
if (wBitsPerPixel < 24)
{
MessageBox (GetFrame()->m_hWnd,
"Error at BitmapTools::SetHbitmap(). This function only works with 24 BPP bitmaps.",
"Error", MB_ICONERROR);
return;
}
// Some basic bitmap parameters
unsigned long headers_size = sizeof( BITMAPFILEHEADER ) +
sizeof( BITMAPINFOHEADER );
unsigned long pixel_data_size = lHeight * ( ( lWidth * ( wBitsPerPixel / 8 ) ) );
BITMAPINFOHEADER bmpInfoHeader = {0};
// Set the size
bmpInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
// Bit count
bmpInfoHeader.biBitCount = wBitsPerPixel;
// Use all colors
bmpInfoHeader.biClrImportant = 0;
// Use as many colors according to bits per pixel
if (wBitsPerPixel < 24)
{
bmpInfoHeader.biClrUsed = (1<<wBitsPerPixel);
}
else
{
bmpInfoHeader.biClrUsed = 0;
}
// Store as un Compressed
bmpInfoHeader.biCompression = BI_RGB;
// Set the height in pixels
bmpInfoHeader.biHeight = lHeight;
// Width of the Image in pixels
bmpInfoHeader.biWidth = lWidth;
// Default number of planes
bmpInfoHeader.biPlanes = 1;
// Calculate the image size in bytes
bmpInfoHeader.biSizeImage = pixel_data_size;
BITMAPFILEHEADER bfh = {0};
bfh.bfType = 0x4D42;
// Offset to the RGBQUAD
bfh.bfOffBits = headers_size;
// Total size of image including size of headers
bfh.bfSize = headers_size + pixel_data_size;
HDC hdc = ::GetDC(NULL);
UINT usage;
// This does not work. Is there a way to add an arbitrary color
// table containing all 256 colors?
if (wBitsPerPixel < 24)
{
usage = DIB_PAL_COLORS;
}
else
{
usage = DIB_RGB_COLORS;
}
//usage = DIB_RGB_COLORS;
this->H_Bitmap = CreateDIBitmap (hdc, &bmpInfoHeader, CBM_INIT, pBitmapBits,(BITMAPINFO*)&bmpInfoHeader, usage);
}
编辑:我根据其他人的帖子创建了一个新功能来创建256色位图,并添加了MS Paint使用的颜色表中的值。它几乎可以工作,除了图像的右下角有一排黑色像素。这是我现在使用的代码:
Edit2:感谢大家的帮助,特别是。标记。我现在就开始工作了。我在下面的代码中进行了更正。
HBITMAP BitmapTools::Create8bppBitmap(HDC hdc, int width, int height, int paddedSize, LPVOID pBits)
{
BITMAPINFO *bmi = (BITMAPINFO *)malloc(sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * 256);
BITMAPINFOHEADER &bih(bmi->bmiHeader);
bih.biSize = sizeof (BITMAPINFOHEADER);
bih.biWidth = width;
bih.biHeight = -height;
bih.biPlanes = 1;
bih.biBitCount = 8;
bih.biCompression = BI_RGB;
bih.biSizeImage = 0;
//bih.biXPelsPerMeter = 14173;
//bih.biYPelsPerMeter = 14173;
bih.biClrUsed = 0;
bih.biClrImportant = 0;
BYTE red[256] = {0, 128, 0, 128, 0, 128, 0, 192, 192, 166, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96,
128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32,
64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224,
0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192,
224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160,
192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128,
160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96,
128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64,
96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32,
64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0,
32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 192, 224, 0, 32, 64, 96, 128, 160, 255, 160,
128, 255, 0, 255, 0, 255, 0, 255};
BYTE green[256] = {0, 0, 128, 128, 0, 0, 128, 192, 220, 202, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64,
64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160,
160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 0,
0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 96, 96, 96, 96, 96,
96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 192, 192, 192,
192, 192, 192, 192, 192, 224, 224, 224, 224, 224, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32,
32, 32, 32, 32, 64, 64, 64, 64, 64, 64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128,
128, 128, 128, 160, 160, 160, 160, 160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 192, 192, 224, 224,
224, 224, 224, 224, 224, 224, 0, 0, 0, 0, 0, 0, 0, 0, 32, 32, 32, 32, 32, 32, 32, 32, 64, 64, 64, 64, 64,
64, 64, 64, 96, 96, 96, 96, 96, 96, 96, 96, 128, 128, 128, 128, 128, 128, 128, 128, 160, 160, 160, 160,
160, 160, 160, 160, 192, 192, 192, 192, 192, 192, 251, 160, 128, 0, 255, 255, 0, 0, 255, 255};
BYTE blue[256] = {0, 0, 0, 0, 128, 128, 128, 192, 192, 240, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,
192, 192, 192, 240, 164, 128, 0, 0, 0, 255, 255, 255, 255};
for (int i = 0; i <= 255; i++)
{
bmi->bmiColors[i].rgbBlue = blue[i];
bmi->bmiColors[i].rgbGreen = green[i];
bmi->bmiColors[i].rgbRed = red[i];
bmi->bmiColors[i].rgbReserved = 0;
}
void *Pixels = NULL;
HBITMAP hbmp = CreateDIBSection(hdc, bmi, DIB_RGB_COLORS, &Pixels, NULL, 0);
//HBITMAP hbmp = CreateDIBSection(hdc, bmi, DIB_PAL_COLORS, &Pixels, NULL, 0);
if(pBits != NULL)
{
//fill the bitmap
BYTE* pbBits = (BYTE*)pBits;
BYTE *Pix = (BYTE *)Pixels;
memcpy(Pix, pbBits, paddedSize); // --Correction made here--
}
free(bmi);
return hbmp;
}
我使用此函数来保存位图:
BOOL BitmapTools::SaveHBitmap(const char* filename, HBITMAP hbitmap)
{
BITMAP bitmap;
if (!GetObjectW(hbitmap, sizeof(BITMAP), (void*)&bitmap))
return FALSE;
// Convert the color format to a count of bits.
WORD clrbits = (WORD)(bitmap.bmPlanes * bitmap.bmBitsPixel);
if (clrbits == 1) clrbits = 1;
else if (clrbits <= 4) clrbits = 4;
else if (clrbits <= 8) clrbits = 8;
else if (clrbits <= 16) clrbits = 16;
else if (clrbits <= 24) clrbits = 24;
else clrbits = 32;
//clrUsed is zero for 24 bit and higher
int clrUsed = (clrbits <= 8) ? (1 << clrbits) : 0;
//TRACE("clrUsed %d\n", clrUsed);
int bitmapInfoSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * clrUsed;
PBITMAPINFO bitmapInfo = (PBITMAPINFO)new char[bitmapInfoSize];
memset(bitmapInfo, 0, bitmapInfoSize);
// Initialize the fields in the BITMAPINFO structure.
bitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bitmapInfo->bmiHeader.biWidth = bitmap.bmWidth;
bitmapInfo->bmiHeader.biHeight = bitmap.bmHeight;
bitmapInfo->bmiHeader.biPlanes = bitmap.bmPlanes;
bitmapInfo->bmiHeader.biBitCount = bitmap.bmBitsPixel;
bitmapInfo->bmiHeader.biClrUsed = clrUsed;
bitmapInfo->bmiHeader.biCompression = BI_RGB;
// Compute the number of bytes in the array of color
// indices and store the result in biSizeImage.
// The width must be DWORD aligned unless the bitmap
// is RLE compressed.
int dibSize = ((bitmap.bmWidth * clrbits + 31) & ~31) / 8 * bitmap.bmHeight;
char* dib = new char[dibSize];
bitmapInfo->bmiHeader.biSizeImage = dibSize;
// Set biClrImportant to 0, indicating that all of
// the device colors are important.
bitmapInfo->bmiHeader.biClrImportant = 0;
//bitmapInfo->bmiColors [0].rgbBlue
PBITMAPINFOHEADER bmpInfoHeader = (PBITMAPINFOHEADER)bitmapInfo;
HDC hdc = CreateCompatibleDC(0);
if (!GetDIBits(hdc, hbitmap, 0, bmpInfoHeader->biHeight, dib, bitmapInfo, 0))
{
delete bitmapInfo;
delete[]dib;
return FALSE;
}
DWORD dwTmp;
BITMAPFILEHEADER bmpFileHeader;
bmpFileHeader.bfType = 0x4d42; // 0x42 = "B" 0x4d = "M"
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + clrUsed * sizeof(RGBQUAD);
bmpFileHeader.bfSize = bmpFileHeader.bfOffBits + dibSize;
HANDLE hfile = CreateFile(filename, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hfile != INVALID_HANDLE_VALUE)
{
WriteFile(hfile,(LPVOID)&bmpFileHeader, sizeof(BITMAPFILEHEADER), (LPDWORD) &dwTmp, NULL);
WriteFile(hfile, (void*)bmpInfoHeader, sizeof(BITMAPINFOHEADER) + clrUsed * sizeof(RGBQUAD), (LPDWORD) &dwTmp, NULL);
WriteFile(hfile, (void*)dib, dibSize, (LPDWORD) &dwTmp, NULL);
CloseHandle(hfile);
}
DeleteDC(hdc);
delete bitmapInfo;
delete[]dib;
return TRUE;
}
这是我得到的图像。请注意,最后一行有一组黑色像素。我不能100%确定这些函数存在问题(我的下一步是将原始位图中的字节与现场设备中的字节进行比较)。
编辑:我检查了现场设备中的字节,它们与原始位图栅格字节100%匹配,所以我认为问题出在其中一个函数中。