从8 bpp位图

时间:2016-06-20 15:41:54

标签: c++ bitmap mfc

我有一个现场设备,它使用位图中的光栅字节来显示每像素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%确定这些函数存在问题(我的下一步是将原始位图中的字节与现场设备中的字节进行比较)。 enter image description here

编辑:我检查了现场设备中的字节,它们与原始位图栅格字节100%匹配,所以我认为问题出在其中一个函数中。

0 个答案:

没有答案