Reputation: 149
I'm trying to get an image with 16 color bitmap.
I can not find a solution on the internet post.
Simple implementation here.
#include "stdafx.h"
#include <windows.h>
#include <stdio.h>
LPBITMAPINFO ConstructBitmapInfo(int nBits, int nX, int nY);
VOID RocketBuffer(LPVOID lpData);
int _tmain(int argc, _TCHAR* argv[])
{
HWND hDesktop = NULL;
HDC hCurrenDC = NULL;
INT nX, nY;
LPBITMAPINFO lpBmpInfo;
HBITMAP hBmpScreen;
LPVOID lpBmpBuffer = NULL;
if(NULL == (hDesktop = GetDesktopWindow()))
return GetLastError();
if (NULL == (hCurrenDC = GetDC(hDesktop)))
return GetLastError();
nX = GetSystemMetrics(SM_CXSCREEN);
nY = GetSystemMetrics(SM_CYSCREEN);
HDC hOrgMemDC = NULL;
hOrgMemDC = CreateCompatibleDC(hCurrenDC);
lpBmpInfo = ConstructBitmapInfo(4, nX, nY);
hBmpScreen = CreateDIBSection(hCurrenDC, lpBmpInfo, DIB_RGB_COLORS, &lpBmpBuffer, NULL, 0);
SelectObject(hOrgMemDC, hBmpScreen);
if(!BitBlt(hOrgMemDC, 0, 0, nX, nY, hCurrenDC, 0, 0, SRCCOPY))
{
return GetLastError();
}
LPBYTE lpWriteData = new BYTE[lpBmpInfo->bmiHeader.biSizeImage * 2];
memcpy(lpWriteData, lpBmpBuffer, lpBmpInfo->bmiHeader.biSizeImage);
RocketBuffer(lpBmpBuffer);
delete[] lpWriteData;
return 0;
}
LPBITMAPINFO ConstructBitmapInfo(int nBits, int nX, int nY)
{
int color_num = nBits <= 8 ? 1 << nBits : 0;
int nBISize = sizeof(BITMAPINFOHEADER) + (color_num * sizeof(RGBQUAD));
BITMAPINFO *lpbmi = (BITMAPINFO *) new BYTE[nBISize];
BITMAPINFOHEADER *lpbmih = &(lpbmi->bmiHeader);
lpbmih->biSize = sizeof(BITMAPINFOHEADER);
lpbmih->biWidth = nX;
lpbmih->biHeight = nY;
lpbmih->biPlanes = 1;
lpbmih->biBitCount = nBits;
lpbmih->biCompression = BI_RGB;
lpbmih->biXPelsPerMeter = 0;
lpbmih->biYPelsPerMeter = 0;
lpbmih->biClrUsed = 0;
lpbmih->biClrImportant = 0;
lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;
if (nBits >= 16)
return lpbmi;
HDC hDC = GetDC(NULL);
HBITMAP hBmp = CreateCompatibleBitmap(hDC, 1, 1);
GetDIBits(hDC, hBmp, 0, 0, NULL, lpbmi, DIB_RGB_COLORS);
ReleaseDC(NULL, hDC);
DeleteObject(hBmp);
return lpbmi;
}
VOID RocketBuffer(LPVOID lpData)
{
// ...
}
I can not output lpWriteData
as a * .bmp
file. It's not BMP format.
Therefore, the function RocketBuffer (LPVOID lpData)
will not be able to perform its function correctly.
The problem is how to get screen shot output in memory with 16 color bitmap.
I want 4 bit image like this.
4 Bit Color Image
Upvotes: 2
Views: 731
Reputation: 31599
16 color 4-bit image includes a color table with 16 colors. The color table size is 16 * 4 bytes. BITMAPINFO
should be large enough to receive the color palette through GetDIBits
The code below works for the following bitmaps:
//bpp = 1
//bpp = 4
//bpp = 8
.
#include <iostream>
#include <fstream>
#include <vector>
#include <windows.h>
int main()
{
//4-bit bitmap: bpp = 4
//valid values with this method bpp = 1, 4, 8
WORD bpp = 4;
//color table:
int colorsize = (1 << bpp) * sizeof(RGBQUAD);
int width = GetSystemMetrics(SM_CXFULLSCREEN);
int height = GetSystemMetrics(SM_CYFULLSCREEN);
HDC hdc = GetDC(HWND_DESKTOP);
HBITMAP hbitmap = CreateCompatibleBitmap(hdc, width, height);
HDC memdc = CreateCompatibleDC(hdc);
HGDIOBJ oldbmp = SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, width, height, hdc, 0, 0, CAPTUREBLT | SRCCOPY);
SelectObject(memdc, oldbmp);
//size in bytes for pixel data:
DWORD size = ((width * bpp + 31) / 32) * 4 * height;
std::vector<BYTE> bi_memory;
bi_memory.resize(sizeof(BITMAPINFOHEADER) + colorsize, 0);
BITMAPINFO* bi = (BITMAPINFO*)&bi_memory[0];
bi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
bi->bmiHeader.biWidth = width;
bi->bmiHeader.biHeight = height;
bi->bmiHeader.biPlanes = 1;
bi->bmiHeader.biBitCount = bpp;
bi->bmiHeader.biCompression = BI_RGB;
bi->bmiHeader.biClrUsed = 16;
std::vector<BYTE> pixels(size + colorsize);
GetDIBits(hdc, hbitmap, 0, height, &pixels[0], bi, DIB_RGB_COLORS);
std::ofstream fout(TEXT("c:\\test\\_4bit.bmp"), std::ios::binary);
if(fout)
{
//bitmap file header
//(54 = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER))
BITMAPFILEHEADER filehdr = { 'MB', 54 + colorsize + size, 0, 0, 54 };
fout.write((char*)&filehdr, sizeof(BITMAPFILEHEADER));
//bitmap info header
fout.write((char*)&bi->bmiHeader, sizeof(BITMAPINFOHEADER));
//color table
fout.write((char*)bi->bmiColors, colorsize);
//pixel data
fout.write((char*)pixels.data(), pixels.size());
}
//cleanup:
DeleteObject(memdc);
DeleteObject(hbitmap);
ReleaseDC(HWND_DESKTOP, hdc);
return 0;
}
Upvotes: 3