C++ gdi::Bitmap to PNG Image in memory(C++ gdi::Bitmap to PNG Image in memory)
问题描述
我正在尝试通过 tcp 将窗口的屏幕截图发送到服务器.获取屏幕截图没有问题(使用 GDIplus).网络对我来说也很容易.问题是试图将 gdi+ 位图转换为 png(在内存中)以从中获取数据并将其发送到服务器.有人可以帮我吗?
I'm trying to send a screenshot of a window over tcp to a server. Getting the screenshot is no problem (using GDIplus). The networking is also easy for me. The problem is trying to convert the gdi+ Bitmap to a png (in memory) to get the data out of it and send it to the server. Can anyone help me please?
推荐答案
Gdiplus 可以保存到文件,或者使用 IStream 保存到内存.请参阅 Gdiplus::Image::Save 方法>
Gdiplus can save to file, or save to memory using IStream. See Gdiplus::Image::Save method
//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 复制到单个缓冲区:
The memory size is small enough that you can copy from IStream to a single buffer:
//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 以通过网络发送
PNG is now available in buffer, its size is bufsize. You can work directly with the binary data, or convert to Base64 to send over the network
...
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;
}
这篇关于C++ gdi::Bitmap to PNG Image in memory的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++ gdi::Bitmap to PNG Image in memory
基础教程推荐
- C++结构和函数声明。为什么它不能编译? 2022-11-07
- 在 C++ 中计算滚动/移动平均值 2021-01-01
- 静态库、静态链接动态库和动态链接动态库的 .lib 文件里面是什么? 2021-01-01
- 如何检查GTK+3.0中的小部件类型? 2022-11-30
- 常量变量在标题中不起作用 2021-01-01
- 如何通过C程序打开命令提示符Cmd 2022-12-09
- 如何将 std::pair 的排序 std::list 转换为 std::map 2022-01-01
- 如何在 C++ 中初始化静态常量成员? 2022-01-01
- 这个宏可以转换成函数吗? 2022-01-01
- 我有静态或动态 boost 库吗? 2021-01-01
