C ++ gdi :: Растровое изображение в PNG Изображение в памяти

Я пытаюсь отправить скриншот окна через tcp на сервер.
Получение скриншота не проблема (с помощью GDIplus). Сеть также легко для меня. Проблема заключается в попытке преобразовать растровое изображение gdi + в png (в памяти), чтобы извлечь из него данные и отправить их на сервер.
Кто-нибудь может мне помочь?

1

Решение

Gdiplus может сохранить в файл или сохранить в памяти, используя IStream, Увидеть Gdiplus :: Image :: Сохранить метод

//get gdi+ bitmap
Gdiplus::Bitmap bitmap(hbitmap, nullptr);

//write to IStream
IStream* istream = nullptr;
HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, &istream);
CLSID clsid_png;
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png);
bitmap.Save(istream, &clsid_png);

Объем памяти достаточно мал, чтобы вы могли скопировать с IStream в один буфер:

//copy IStream to buffer
int bufsize = GlobalSize(hg);
char *buffer = new char[bufsize];

//lock & unlock memory
LPVOID ptr = GlobalLock(hg);
memcpy(buffer, ptr, bufsize);
GlobalUnlock(hg);

//release will automatically free the memory allocated in CreateStreamOnHGlobal
istream->Release();

PNG теперь доступен в buffer, его размер bufsize, Вы можете работать напрямую с двоичными данными или конвертировать в Base64 для отправки по сети

...
delete[]buffer;

MCVE:

#include <iostream>
#include <fstream>
#include <vector>
#include <Windows.h>
#include <gdiplus.h>

bool save_png_memory(HBITMAP hbitmap, std::vector<BYTE> &data)
{
Gdiplus::Bitmap bmp(hbitmap, nullptr);

//write to IStream
IStream* istream = nullptr;
CreateStreamOnHGlobal(NULL, TRUE, &istream);

CLSID clsid_png;
CLSIDFromString(L"{557cf406-1a04-11d3-9a73-0000f81ef32e}", &clsid_png);
Gdiplus::Status status = bmp.Save(istream, &clsid_png);
if(status != Gdiplus::Status::Ok)
return false;

//get memory handle associated with istream
HGLOBAL hg = NULL;
GetHGlobalFromStream(istream, &hg);

//copy IStream to buffer
int bufsize = GlobalSize(hg);
data.resize(bufsize);

//lock & unlock memory
LPVOID pimage = GlobalLock(hg);
memcpy(&data[0], pimage, bufsize);
GlobalUnlock(hg);

istream->Release();
return true;
}

int main()
{
CoInitialize(NULL);

ULONG_PTR token;
Gdiplus::GdiplusStartupInput tmp;
Gdiplus::GdiplusStartup(&token, &tmp, NULL);

//take screenshot
RECT rc;
GetClientRect(GetDesktopWindow(), &rc);
auto hdc = GetDC(0);
auto memdc = CreateCompatibleDC(hdc);
auto hbitmap = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
auto oldbmp = SelectObject(memdc, hbitmap);
BitBlt(memdc, 0, 0, rc.right, rc.bottom, hdc, 0, 0, SRCCOPY);
SelectObject(memdc, oldbmp);
DeleteDC(memdc);
ReleaseDC(0, hdc);

//save as png
std::vector<BYTE> data;
if(save_png_memory(hbitmap, data))
{
//write from memory to file for testing:
std::ofstream fout("test.png", std::ios::binary);
fout.write((char*)data.data(), data.size());
}
DeleteObject(hbitmap);

Gdiplus::GdiplusShutdown(token);
CoUninitialize();

return 0;
}
2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]