How to screenshot as a single color bitmap file?
-
Hello everybody ! I wan't to save the bitmap to convert to a single color bitmap (8 pixel / Byte). I use this way to save to 16 color bitmap. how to convert it to single bitmap ,or how to save it from the device context first ?
/************************************************************************
Function : Screenshot
Parameter: hwnd the window handle.
lpRect the window rect.
return : HBITMAP
other : NULL
************************************************************************/
HBITMAP GetWindowBitmap(HWND hwnd, LPRECT lpRect)
{if( !lpRect ) return NULL; HDC hDC; HDC hMemDC; HBITMAP hBitmap = NULL; HBITMAP hOldBitmap; if( hwnd == NULL ) hDC = ::GetDC(HWND\_DESKTOP); else hDC = ::GetWindowDC(hwnd); if( hDC == NULL ) return NULL; hMemDC = CreateCompatibleDC(hDC); hBitmap = CreateCompatibleBitmap(hDC, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top); if( hBitmap == NULL) return NULL; hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, hDC, lpRect->left, lpRect->top, SRCCOPY); SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); ::ReleaseDC(hwnd, hDC); return hBitmap;
}
/************************************************************************
Function : Write to file
Parameter: strFilePath the whole file path.
hBitmap the bitmap memory
return : if success return TRUE, otherwise return FALSE.
************************************************************************/
BOOL SaveBitmapToFile(CString strFilePath,HBITMAP hBitmap)
{
HDC hdc = NULL;
FILE* fp = NULL;
LPVOID pBuf = NULL;
BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;do{ hdc = ::GetDC(NULL); ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB\_RGB\_COLORS); //bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it ,bmp is invalid. bmpInfo.bmiHeader.biBitCount = 0x10; // 16 if(bmpInfo.bmiHeader.biSizeImage <= 0) bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth\*abs(bmpInfo.bmiHeader.biHeight)\*(bmpInfo.bmiHeader.biBitCount+7)/8; if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) { ::MessageBox(NULL,\_T("Unable to Alloca
-
Hello everybody ! I wan't to save the bitmap to convert to a single color bitmap (8 pixel / Byte). I use this way to save to 16 color bitmap. how to convert it to single bitmap ,or how to save it from the device context first ?
/************************************************************************
Function : Screenshot
Parameter: hwnd the window handle.
lpRect the window rect.
return : HBITMAP
other : NULL
************************************************************************/
HBITMAP GetWindowBitmap(HWND hwnd, LPRECT lpRect)
{if( !lpRect ) return NULL; HDC hDC; HDC hMemDC; HBITMAP hBitmap = NULL; HBITMAP hOldBitmap; if( hwnd == NULL ) hDC = ::GetDC(HWND\_DESKTOP); else hDC = ::GetWindowDC(hwnd); if( hDC == NULL ) return NULL; hMemDC = CreateCompatibleDC(hDC); hBitmap = CreateCompatibleBitmap(hDC, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top); if( hBitmap == NULL) return NULL; hOldBitmap = (HBITMAP)SelectObject(hMemDC, hBitmap); BitBlt(hMemDC, 0, 0, lpRect->right - lpRect->left, lpRect->bottom - lpRect->top, hDC, lpRect->left, lpRect->top, SRCCOPY); SelectObject(hMemDC, hOldBitmap); DeleteDC(hMemDC); ::ReleaseDC(hwnd, hDC); return hBitmap;
}
/************************************************************************
Function : Write to file
Parameter: strFilePath the whole file path.
hBitmap the bitmap memory
return : if success return TRUE, otherwise return FALSE.
************************************************************************/
BOOL SaveBitmapToFile(CString strFilePath,HBITMAP hBitmap)
{
HDC hdc = NULL;
FILE* fp = NULL;
LPVOID pBuf = NULL;
BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;do{ hdc = ::GetDC(NULL); ZeroMemory(&bmpInfo,sizeof(BITMAPINFO)); bmpInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); GetDIBits(hdc,hBitmap,0,0,NULL,&bmpInfo,DIB\_RGB\_COLORS); //bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it ,bmp is invalid. bmpInfo.bmiHeader.biBitCount = 0x10; // 16 if(bmpInfo.bmiHeader.biSizeImage <= 0) bmpInfo.bmiHeader.biSizeImage = bmpInfo.bmiHeader.biWidth\*abs(bmpInfo.bmiHeader.biHeight)\*(bmpInfo.bmiHeader.biBitCount+7)/8; if((pBuf = malloc(bmpInfo.bmiHeader.biSizeImage)) == NULL) { ::MessageBox(NULL,\_T("Unable to Alloca
You can do it by following way. First, you need storage space for color table as being palette entries.
typedef struct tagBITMAPINFO_8BPP
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} BITMAPINFO_8BPP;I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.
...
LPVOID pBuf = NULL;
BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;...
bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.
...
bmpInfo.bmiHeader.biCompression = BI_RGB;
GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);...
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
bmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);...
-
You can do it by following way. First, you need storage space for color table as being palette entries.
typedef struct tagBITMAPINFO_8BPP
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} BITMAPINFO_8BPP;I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.
...
LPVOID pBuf = NULL;
BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;...
bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.
...
bmpInfo.bmiHeader.biCompression = BI_RGB;
GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);...
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
bmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);...
thanks ! ;)
-
You can do it by following way. First, you need storage space for color table as being palette entries.
typedef struct tagBITMAPINFO_8BPP
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD bmiColors[256];
} BITMAPINFO_8BPP;I've used above structure for simplicity. You can also allocate it dynamically as much (sizeof(BITMAPINFO) + sizeof(RGBQUAD) * 255) in bytes. In that case, you need to adjust values in BITMAPFILEHEADER and file write operation accordingly.
...
LPVOID pBuf = NULL;
BITMAPINFO_8BPP bmpInfo; // instead of BITMAPINFO bmpInfo;
BITMAPFILEHEADER bmpFileHeader;...
bmpInfo.bmiHeader.biBitCount = 0x08; // 8bit,when I use it,bmp is invalid.
...
bmpInfo.bmiHeader.biCompression = BI_RGB;
GetDIBits(hdc, hBitmap, 0, bmpInfo.bmiHeader.biHeight,
pBuf, (BITMAPINFO*)&bmpInfo, DIB_RGB_COLORS);...
bmpFileHeader.bfReserved1 = 0;
bmpFileHeader.bfReserved2 = 0;
bmpFileHeader.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP) +
bmpInfo.bmiHeader.biSizeImage;
bmpFileHeader.bfType = 'MB';
bmpFileHeader.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFO_8BPP);fwrite(&bmpFileHeader, sizeof(BITMAPFILEHEADER), 1, fp);
fwrite(&bmpInfo.bmiHeader, sizeof(BITMAPINFO_8BPP), 1, fp);
fwrite(pBuf, bmpInfo.bmiHeader.biSizeImage, 1, fp);...
There is two different with me: 1、RGBQUAD color table it used 256 count, but is "[1]" before. // why is it? 2、bmpInfo.bmiHeader.biBitCount = 0x01; // here is used 0x01 , means than is a single bitmap . I use the default RGBQUAD [1], and then set the biBitCount is 0x01, at last use the sam way to write to the file, but the bitmap is invalid. and then, you used RGBQUAD[256], the bitmap is right , why ? or this question may said: what's the color table in the bitmap file format ? (I google this ,but still don't quite understand.)
-
There is two different with me: 1、RGBQUAD color table it used 256 count, but is "[1]" before. // why is it? 2、bmpInfo.bmiHeader.biBitCount = 0x01; // here is used 0x01 , means than is a single bitmap . I use the default RGBQUAD [1], and then set the biBitCount is 0x01, at last use the sam way to write to the file, but the bitmap is invalid. and then, you used RGBQUAD[256], the bitmap is right , why ? or this question may said: what's the color table in the bitmap file format ? (I google this ,but still don't quite understand.)
bmiColors member of BITMAPINFO is variable sized array. Its size can be zero or more depending on other attributes such as biClrUsed, biBitCount and last parameter of GetDIBits() which can be DIB_PAL_COLORS or DIB_RGB_COLORS. BITMAPINFOHEADER[^] Excerpt from above link. If biCompression equals BI_RGB and the bitmap uses 8 bpp or less, the bitmap has a color table immediatelly following the BITMAPINFOHEADER structure. The color table consists of an array of RGBQUAD values. The size of the array is given by the biClrUsed member. If biClrUsed is zero, the array contains the maximum number of colors for the given bitdepth; that is, 2^biBitCount colors. In our case, 2 ^ 8 = 256 color table entries exist. You may also want to look at BITMAPINFO[^]. If bmpInfo.bmiHeader.biBitCount = 0x01; then it is a monochrome bitmap and color table will have two entries (e.g. RGB(0, 0, 0) and RGB(255, 255, 255)). Color table is array of colors used in the bitmap.