C++ 从1bpp位图读取像素(CreateDIBSection)
此代码适用于32、24、16、8、4 bpp图像。但不是1个基点C++ 从1bpp位图读取像素(CreateDIBSection),c++,winapi,C++,Winapi,此代码适用于32、24、16、8、4 bpp图像。但不是1个基点 #include <stdio.h> #include <windows.h> #pragma comment(lib, "user32.lib") #pragma comment(lib, "gdi32.lib") void GetWindowBitmapBitsAndSave(const HWND& hWnd, int nBitCount, char *szFilePath); void E
#include <stdio.h>
#include <windows.h>
#pragma comment(lib, "user32.lib")
#pragma comment(lib, "gdi32.lib")
void GetWindowBitmapBitsAndSave(const HWND& hWnd, int nBitCount, char *szFilePath);
void EnumerateBits(LPBYTE pBits, int nBitCount, int nWidth, int nHeight);
int main(int argc, char **argv)
{
//GetWindowBitmapBits(HWND_DESKTOP, 32);
//32, 24, 16, 8, 4 works fine...
GetWindowBitmapBitsAndSave(HWND_DESKTOP, 1, "test.bmp");
return 0;
}
void EnumerateBits(LPBYTE pBits, int nBitCount, int nWidth, int nHeight)
{
int nPixels = nWidth * nHeight;
WORD wByteCount = nBitCount / 8;
if(wByteCount == 0)
wByteCount = 1;
int nBytes = nPixels * wByteCount;
for(int i = 0; i < nBytes; i += wByteCount)
{
int r = (int)(*(pBits+i));
//int g = (int)(*(pBits+i+1));
//int b = (int)(*(pBits+i+2));
//just for test
if(r != 0 /*&& g != 0 && b != 0*/)
if(r != 255 /*&& g != 255 && b != 255*/)
//printf("(%d, %d, %d)\n", r, g, b);
printf("%d\n", r);
}
}
void GetWindowBitmapBitsAndSave(const HWND& hWnd, int nBitCount, char* szFilePath)
{
HWND hScreenWnd = hWnd;
if(!hScreenWnd)
hScreenWnd = HWND_DESKTOP;
//calculate the number of color indexes in the color table
int nColorTableEntries = -1;
switch(nBitCount)
{
case 1:
nColorTableEntries = 2;
break;
case 4:
nColorTableEntries = 16;
break;
case 8:
nColorTableEntries = 256;
break;
case 16:
case 24:
case 32:
nColorTableEntries = 0;
break;
default:
nColorTableEntries = -1;
break;
}
if(nColorTableEntries == -1)
{
printf("bad bits-per-pixel argument\n");
return;
}
HDC hDC = GetDC(hScreenWnd);
HDC hMemDC = CreateCompatibleDC(hDC);
int nWidth = 0;
int nHeight = 0;
if(hScreenWnd != HWND_DESKTOP)
{
RECT rect;
GetClientRect(hScreenWnd, &rect);
nWidth = rect.right - rect.left;
nHeight = rect.bottom - rect.top;
}
else
{
nWidth = ::GetSystemMetrics(SM_CXSCREEN);
nHeight = ::GetSystemMetrics(SM_CYSCREEN);
}
HBITMAP hBMP = CreateCompatibleBitmap(hDC, nWidth, nHeight);
SelectObject(hMemDC, hBMP);
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDC, 0, 0, SRCCOPY);
int nStructLength = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries;
BITMAPINFOHEADER BitmapInfoHeader;
BitmapInfoHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfoHeader.biWidth = nWidth;
BitmapInfoHeader.biHeight = nHeight;
BitmapInfoHeader.biPlanes = 1;
BitmapInfoHeader.biBitCount = nBitCount;
BitmapInfoHeader.biCompression = BI_RGB;
BitmapInfoHeader.biXPelsPerMeter = 0;
BitmapInfoHeader.biYPelsPerMeter = 0;
BitmapInfoHeader.biClrUsed = nColorTableEntries;
BitmapInfoHeader.biClrImportant = nColorTableEntries;
DWORD dwBytes = ((DWORD) nWidth * nBitCount) / 32;
if(((DWORD) nWidth * nBitCount) % 32) {
dwBytes++;
}
dwBytes *= 4;
DWORD dwSizeImage = dwBytes * nHeight;
BitmapInfoHeader.biSizeImage = dwSizeImage;
BITMAPINFO* bitmapInfo = new BITMAPINFO[sizeof(BITMAPINFO) + sizeof(RGBQUAD) * nColorTableEntries];
bitmapInfo->bmiHeader = BitmapInfoHeader;
if(nBitCount < 16)
{
for(int i = 0; i != nColorTableEntries; ++i)
{
bitmapInfo->bmiColors[i].rgbRed =
bitmapInfo->bmiColors[i].rgbGreen =
bitmapInfo->bmiColors[i].rgbBlue = (BYTE)(i*(255/(nColorTableEntries-1)));
bitmapInfo->bmiColors[i].rgbReserved = 0;
}
}
LPBYTE lpDibBits = 0;
HBITMAP hBitmap = ::CreateDIBSection(hMemDC, bitmapInfo, DIB_RGB_COLORS, (void**)&lpDibBits, NULL, 0);
SelectObject(hMemDC, hBitmap);
BitBlt(hMemDC, 0, 0, nWidth, nHeight, hDC, 0, 0, SRCCOPY);
ReleaseDC(hScreenWnd, hDC);
//save bitmap
BITMAPFILEHEADER bmfh;
bmfh.bfType = 0x4d42; // 'BM'
int nHeaderSize = sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries;
bmfh.bfSize = 0;
bmfh.bfReserved1 = bmfh.bfReserved2 = 0;
bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + sizeof(RGBQUAD) * nColorTableEntries;
FILE *pFile = 0;
fopen_s(&pFile, szFilePath, "wb");
if(pFile)
{
fwrite(&bmfh, sizeof(BITMAPFILEHEADER), 1, pFile);
fwrite(bitmapInfo, nHeaderSize,1,pFile);
fwrite(lpDibBits, dwSizeImage, 1, pFile);
fclose(pFile);
}
EnumerateBits(lpDibBits, nBitCount, nWidth, nHeight);
delete[]bitmapInfo;
::DeleteObject(hBMP);
::DeleteObject(hBitmap);
}
#包括
#包括
#pragma注释(lib,“user32.lib”)
#pragma注释(lib,“gdi32.lib”)
void GetWindowBitmapBitsAndSave(常量HWND&HWND,int-nBitCount,char*szFilePath);
无效枚举位(LPBYTE-pBits、int-nBitCount、int-nWidth、int-nHeight);
int main(int argc,字符**argv)
{
//GetWindowBitmapBits(HWND_桌面,32);
//32,24,16,8,4行得很好。。。
GetWindowBitmapBitsAndSave(HWND_桌面,1,“test.bmp”);
返回0;
}
无效枚举位(LPBYTE pBits、int-nBitCount、int-nWidth、int-nHeight)
{
int nPixels=nWidth*nHeight;
字wByteCount=nBitCount/8;
如果(wByteCount==0)
wByteCount=1;
int nBytes=nPixels*wByteCount;
对于(int i=0;ibmiHeader=bitmapInfo标头;
如果(nBitCount<16)
{
for(int i=0;i!=nColorTableEntries;++i)
{
bitmapInfo->bmiColors[i]。RGR=
bitmapInfo->bmiColors[i].rgbGreen=
bitmapInfo->bmiColors[i].rgbBlue=(字节)(i*(255/(nColorTableEntries-1));
bitmapInfo->bmiColors[i].rgbReserved=0;
}
}
LPBYTE lpDibBits=0;
HBITMAP HBITMAP=::CreateDIBSection(hMemDC,bitmapInfo,DIB_RGB_颜色,(void**)和lpDibBits,NULL,0);
选择对象(hMemDC、hBitmap);
BitBlt(hMemDC,0,0,nWidth,nHeight,hDC,0,0,SRCCOPY);
释放DC(hScreenWnd,hDC);
//保存位图
位图文件头bmfh;
bmfh.bfType=0x4d42;//“BM”
int nHeaderSize=sizeof(bitmapinfo头)+sizeof(RGBQUAD)*nColorTableEntries;
bmfh.bfSize=0;
bmfh.bfReserved1=bmfh.bfReserved2=0;
bmfh.bfOffBits=sizeof(BITMAPFILEHEADER)+sizeof(BitMapInfo Header)+sizeof(RGBQUAD)*nColorTableEntries;
文件*pFile=0;
fopen_s(&pFile,szFilePath,“wb”);
if(pFile)
{
fwrite(&bmfh,sizeof(BITMAPFILEHEADER),1,pFile);
fwrite(bitmapInfo,nHeaderSize,1,pFile);
fwrite(lpbits,dwsizemage,1,pFile);
fclose(pFile);
}
枚举位(lpDibBits、nBitCount、nWidth、nHeight);
删除[]位图信息;
::删除对象(hBMP);
::删除对象(hBitmap);
}
第一个问题:为什么当比特数为1时,除了黑色和白色之外还有其他颜色?(但图像是单色的。只需在GetWindowBitmapBitsAndSave函数中调用注释枚举位即可)
第二个问题:如何正确计算颜色位数组的偏移量?我认为不是
nBitCount>>3
而是nBitCount/8
。每像素一位意味着每像素一位。每像素读取三个字节。您需要读取一个字节并将其拆分为8个像素。我正在编辑代码(nBitCount>>3=>nBitCount/8)。但是我的问题没有解决。关于:“第一个问题:为什么当比特数为1时,除了黑白之外还有其他颜色?”比特深度小于16,并且启用了比特压缩的16,使用相关的颜色数组(即位图的调色板)确定它们的颜色,其中比特值是该数组的索引。数组中可以有任何颜色。因此,没有什么需要1bpp位图只使用黑白色。雷米·勒博感谢您的回答。现在我明白为什么会这样了。P