GDI Bitmap color conversion

Started by
1 comment, last by Vortez 12 years, 9 months ago
Hi, i need a little help with some code in my project, i've been using this code below to generate a screenshot, store it into some buffer, then converting it to 24 bits using my own conversion routine.


HWND hDesktopWnd = GetDesktopWindow();
HDC hdc = GetDC(hDesktopWnd);

SShot s;
s.x = 0;
s.y = 0;
s.w = GetSystemMetrics(SM_CXSCREEN);
s.h = GetSystemMetrics(SM_CYSCREEN);

s.hdc = CreateCompatibleDC(hdc);
s.hbmp = CreateCompatibleBitmap(hdc,s.w,s.h);
s.ex_hbmp = (HBITMAP)SelectObject(s.hdc, s.hbmp);

BitBlt(s.hdc,0,0,s.w,s.h,hdc,s.x,s.y,SRCCOPY);
//StretchBlt(s.hdc,0,0,s.w,s.h,hdc,0,s.h,s.w,-s.h,SRCCOPY);

ReleaseDC(hDesktopWnd,hdc);

/////////////////////////////////////////////////////////////////////////////////////////

// Allocate buffers
DWORD NumPixels = s.w * s.h;
Buffers.ScreenShot.Allocate(NumPixels * 4);
Buffers.Converted.Allocate(NumPixels * 3);

// Fill the ScreenShot buffer
GetBitmapBits(s.hbmp, Buffers.ScreenShot.GetBufferSize(), Buffers.ScreenShot.GetBuffer());

// Convert it to 24 bits in another buffer
DWORD Ret = ConvertTo24bits(Buffers.Converted.GetBuffer(), Buffers.ScreenShot.GetBuffer(), Buffers.ScreenShot.GetBufferSize());

/////////////////////////////////////////////////////////////////////////////////////////

// Release the bitmap handles
if(SelectObject(s.hdc, s.hbmp)){
DeleteObject(s.hbmp);
DeleteDC(s.hdc);
}


The problem is, if the screen resolution use another color format than 32 bits, this code won't work.
So, i would like to know how can i convert the image to 24 bits from any pixel format the desktop is currently using.

Thx.
Advertisement
The simplest solution would be to create another bitmap in memory, this time with 24 bits. Then you select each into their own HDC and BitBlt the graphic from one to the other. Let Windows take care of the conversion.

Fruny: Ftagn! Ia! Ia! std::time_put_byname! Mglui naflftagn std::codecvt eY'ha-nthlei!,char,mbstate_t>

After some experimentation and some explanation about GetDIBits, all i had to do was to replace the GetBitmapBits call by this, getting rid of my own format routine at the same time:


LPBITMAPINFO lpbi = (LPBITMAPINFO)(new char[sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD)]);
ZeroMemory(lpbi, sizeof(BITMAPINFO));
int x = sizeof(BITMAPINFOHEADER);
int y = sizeof(BITMAPINFOHEADER) + 256 * sizeof(RGBQUAD);
lpbi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);

SelectObject(s.hdc, s.ex_hbmp);

GetDIBits(s.hdc, s.hbmp, 0, s.h, NULL, lpbi, DIB_RGB_COLORS);
lpbi->bmiHeader.biBitCount = 16;
lpbi->bmiHeader.biSizeImage = (s.w * s.h) * (lpbi->bmiHeader.biBitCount / 8);
lpbi->bmiHeader.biCompression = BI_RGB;

LPVOID lpvBits = new char[lpbi->bmiHeader.biSizeImage];
ZeroMemory(lpvBits, lpbi->bmiHeader.biSizeImage);

GetDIBits(s.hdc, s.hbmp, 0, s.h, lpvBits, lpbi, DIB_RGB_COLORS);
SelectObject(s.hdc, s.hbmp);

SAFE_DELETE_ARRAY(lpvBits);
SAFE_DELETE_ARRAY(lpbi);


Just posting in case this can help someone else...

This topic is closed to new replies.

Advertisement