Link to home
Start Free TrialLog in
Avatar of Olympus
Olympus

asked on

BitBlt/StretchBlt color conversion

In my program, it is necessary to convert the screen capture image from the screen's bit depth (usually 32bpp) to a 24bit format. With this code, I get about 0.5 to 1.0 seconds of lag (system freeze; the mouse cannot be moved) during StretchBlt() when converting from my desktop depth of 32bits to 24bits. As far as I can tell, this could perhaps be windows XP dependant?

Here's the code:

HBITMAP Bitmap;
int ScreenWidth, ScreenHeight, Width, Height, Scale;
HDC DesktopDC, CaptureDC;
BITMAPINFO BitmapInfo;
unsigned char *Data;

Scale = 50;
DesktopDC = GetDC(GetDesktopWindow());
ScreenWidth = GetDeviceCaps(DesktopDC, HORZRES);
ScreenHeight = GetDeviceCaps(DesktopDC, VERTRES);
Width = (ScreenWidth * Scale) / 100;
Height = (ScreenHeight * Scale) / 100;

memset(&BitmapInfo.bmiHeader, 0, sizeof(BitmapInfo.bmiHeader));
BitmapInfo.bmiHeader.biWidth = Width;
BitmapInfo.bmiHeader.biHeight = Height;
BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
BitmapInfo.bmiHeader.biPlanes = 1;
BitmapInfo.bmiHeader.biBitCount = 24;
BitmapInfo.bmiHeader.biCompression = BI_RGB;

CaptureDC = CreateCompatibleDC(DesktopDC);
Bitmap = CreateDIBSection(DesktopDC, &BitmapInfo, DIB_RGB_COLORS, (void **)&Data, 0, 0);

SelectObject(CaptureDC, Bitmap);
StretchBlt(CaptureDC, 0, 0, Width, Height, DesktopDC, 0, 0, ScreenWidth, ScreenHeight, SRCCOPY); // 1 second freeze occurs here...

Any suggestions? It seems as if StrechBlt() is freezing up due to having to convert from 32bpp to 24bpp. I have the exact same problem when doing BitBlt() from the screen to a bitmap of similar size.
Avatar of Roshan Davis
Roshan Davis
Flag of United States of America image

The problem is not in StreachBlt, or in BitBlt. The lag is due to the bit conversion loop.
HBITMAP Bitmap;
     int ScreenWidth, ScreenHeight, Width, Height, Scale;
     HDC DesktopDC, CaptureDC;
     BITMAPINFO BitmapInfo;
     unsigned char *Data;

     Scale = 50;
     DesktopDC = ::GetDC(::GetDesktopWindow());
     ScreenWidth = GetDeviceCaps(DesktopDC, HORZRES);
     ScreenHeight = GetDeviceCaps(DesktopDC, VERTRES);
     Width = (ScreenWidth * Scale) / 100;
     Height = (ScreenHeight * Scale) / 100;

     memset(&BitmapInfo.bmiHeader, 0, sizeof(BitmapInfo.bmiHeader));
     BitmapInfo.bmiHeader.biWidth = Width;
     BitmapInfo.bmiHeader.biHeight = Height;
     BitmapInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
     BitmapInfo.bmiHeader.biPlanes = 1;
     BitmapInfo.bmiHeader.biBitCount = 24;
     BitmapInfo.bmiHeader.biCompression = BI_RGB;

     CaptureDC = CreateCompatibleDC(DesktopDC);
     HBITMAP hCurrentBMP = (HBITMAP)GetCurrentObject(DesktopDC, OBJ_BITMAP);
     Bitmap = CreateDIBSection(DesktopDC, &BitmapInfo, DIB_RGB_COLORS, (void **)&Data, 0, 0);
     DWORD     dw1 = GetTickCount();
     ::GetDIBits(DesktopDC, hCurrentBMP, 0, BitmapInfo.bmiHeader.biHeight, Data, &BitmapInfo, DIB_RGB_COLORS);
     TRACE("Diff = %d \n", GetTickCount() - dw1);
     SelectObject(CaptureDC, Bitmap);

     I think this will get some more performance...
     These things can be apply to avoid the freezing,
     1. U can do ur own converion method and use SetDIBits .. So in that loop u can Peek and Dispatch Message
     2. Do these things in a seperate thread

GOOD LUCK
Avatar of Olympus
Olympus

ASKER

Will GetDIBits do the same as BitBlt?
Have you tried other computers? This could be a hardware design problem. During a Blt operation, the bus is very busy.
Avatar of Olympus

ASKER

Yes, I have tried on 4 Windows XP computers and 2 Windows 98 computers; all the windows XPs have this problem.
ASKER CERTIFIED SOLUTION
Avatar of Roshan Davis
Roshan Davis
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial