Below I provide my code in advance.
The whole problem is the incomplete cleaning of the LPSTREAM memory after using it in GDIplus::Bitmap::Save()
Specifically in this line:
bmp->Save(stream, &jpegClsid, &encoderParameters); After returning from the function, I read the contents of the stream and try to clear it with
str->Release(); but the memory is not cleared; in the screenshot, calls to the TakeScreenshot function are:
(The jumps in memory usage when saving to HBITMAP, a clean screenshot weighs 14mb, as the snapshot of 2 screens)
Maybe I missed the rest of the code?
Spent on this problem the whole day, poke your nose at the error, please.
void SaveJpeg(HBITMAP hbmpImage, unsigned int Quality, LPSTREAM stream) { Gdiplus::GdiplusStartupInput gdiplusStartupInput; ULONG_PTR gdiplusToken; GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL); Gdiplus::EncoderParameters encoderParameters; encoderParameters.Count = 1; encoderParameters.Parameter[0].Guid = Gdiplus::EncoderQuality; encoderParameters.Parameter[0].Type = Gdiplus::EncoderParameterValueTypeLong; encoderParameters.Parameter[0].NumberOfValues = 1; encoderParameters.Parameter[0].Value = &Quality; CLSID jpegClsid; GetEncoderClsid(L"image/jpeg", &jpegClsid); Gdiplus::Bitmap* bmp = new Gdiplus::Bitmap(hbmpImage, (HPALETTE)0); //bmp->Save(L"1.jpg", &jpegClsid, &encoderParameters); bmp->Save(stream, &jpegClsid, &encoderParameters); delete(bmp); } void WINAPI TakeScreenshot(unsigned int quality, LPBYTE* fs, ULONG* written) { HDC hdc = GetDC(NULL); HDC hDest = CreateCompatibleDC(hdc); int height = GetSystemMetrics(SM_CYVIRTUALSCREEN); int width = GetSystemMetrics(SM_CXVIRTUALSCREEN); HBITMAP hbDesktop = CreateCompatibleBitmap(hdc, width, height); SelectObject(hDest, hbDesktop); BitBlt(hDest, 0, 0, width, height, hdc, 0, 0, SRCCOPY); LPSTREAM str; CreateStreamOnHGlobal(NULL, FALSE, &str); SaveJpeg(hbDesktop, quality, str); STATSTG Stat; if (str->Stat(&Stat, STATFLAG_NONAME) == S_OK && Stat.cbSize.HighPart == 0) { LARGE_INTEGER li; li.HighPart = 0; li.LowPart = 0; str->Seek(li, STREAM_SEEK_SET, NULL); LPBYTE buf = (LPBYTE)malloc(sizeof(DWORD) + Stat.cbSize.LowPart); if (buf != NULL) { if (str->Read(buf + sizeof(DWORD), Stat.cbSize.LowPart, &Stat.cbSize.LowPart) == S_OK) { *((LPDWORD)buf) = Stat.cbSize.LowPart; *fs = buf; *written = sizeof(DWORD) + Stat.cbSize.LowPart; } } free(buf); } str->Release(); ReleaseDC(NULL, hdc); DeleteDC(hDest); } 