You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将HDC截取的高分辨率屏幕位图缩小至约1MB用于TCP传输?

解决方案:缩小截图体积用于TCP传输

针对高分辨率屏幕截图体积过大的问题,有两种直接的解决思路:缩小截图分辨率或将位图压缩为JPEG/PNG格式,以下是具体实现:

方法一:直接缩小截图分辨率

通过StretchBlt替代BitBlt,直接生成低分辨率的位图,避免生成原始尺寸的大位图。你可以根据目标体积计算合适的缩放比例:

24位未压缩位图体积计算公式:宽 × 高 × 3 字节,要控制在1MB左右,目标像素总数大概在34万左右(1MB=1048576字节 ÷3≈349525)。按原屏幕2736×1824的3:2比例,可设目标宽为800,高约533,体积约1.27MB,接近需求。

修改后的代码:

HDC hdc = GetDC(NULL);
int srcWidth = GetSystemMetrics(SM_CXSCREEN);
int srcHeight = GetSystemMetrics(SM_CYSCREEN);

// 计算目标尺寸,按比例缩小
int destWidth = 800;
int destHeight = static_cast<int>(srcHeight * (static_cast<double>(destWidth) / srcWidth));

HDC hDest = CreateCompatibleDC(hdc);
HBITMAP hbDest = CreateCompatibleBitmap(hdc, destWidth, destHeight);
HBITMAP hbOld = static_cast<HBITMAP>(SelectObject(hDest, hbDest));

// 缩放截取屏幕内容
StretchBlt(hDest, 0, 0, destWidth, destHeight, hdc, 0, 0, srcWidth, srcHeight, SRCCOPY);

// 这里可以对hbDest进行后续处理(比如转为字节流发送)

// 务必清理资源
SelectObject(hDest, hbOld);
DeleteObject(hbDest);
DeleteDC(hDest);
ReleaseDC(NULL, hdc);

方法二:压缩位图为JPEG/PNG格式

如果需要保留更多画面细节,推荐将原始位图压缩为压缩格式(比如JPEG),即使是原始分辨率,中等质量的JPEG也能将体积控制在1MB以内。这里使用GDI+实现压缩:

#include <gdiplus.h>
#pragma comment(lib, "gdiplus.lib")
using namespace Gdiplus;

// 先按你的原有代码获取全屏位图HBITMAP hbDesktop
HDC hdc = GetDC(NULL);
HDC hDest = CreateCompatibleDC(hdc);
int width = GetSystemMetrics(SM_CXSCREEN);
int height = GetSystemMetrics(SM_CYSCREEN);
HBITMAP hbDesktop = CreateCompatibleBitmap(hdc, width, height);
SelectObject(hDest, hbDesktop);
BitBlt(hDest, 0,0, width, height, hdc, 0, 0, SRCCOPY);

// 初始化GDI+
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

// 将HBITMAP转为GDI+ Bitmap对象
Bitmap* pBitmap = Bitmap::FromHBITMAP(hbDesktop, NULL);

// 获取JPEG编码器CLSID
CLSID clsidJpeg;
GetEncoderClsid(L"image/jpeg", &clsidJpeg);

// 设置压缩质量(0-100,值越低体积越小,50左右即可将2736×1824的图压到1MB以内)
EncoderParameters encoderParams;
encoderParams.Count = 1;
encoderParams.Parameter[0].Guid = EncoderQuality;
encoderParams.Parameter[0].Type = EncoderParameterValueTypeLong;
encoderParams.Parameter[0].NumberOfValues = 1;
UINT quality = 50;
encoderParams.Parameter[0].Value = &quality;

// 将压缩后的图片写入内存流,方便TCP发送
IStream* pStream = NULL;
CreateStreamOnHGlobal(NULL, TRUE, &pStream);
pBitmap->Save(pStream, &clsidJpeg, &encoderParams);

// 获取流中的数据和大小
HGLOBAL hGlobal;
GetHGlobalFromStream(pStream, &hGlobal);
DWORD dataSize = GlobalSize(hGlobal);
BYTE* pData = static_cast<BYTE*>(GlobalLock(hGlobal));

// 这里可以将pData通过TCP发送...

// 清理所有资源
GlobalUnlock(hGlobal);
pStream->Release();
delete pBitmap;
GdiplusShutdown(gdiplusToken);

DeleteObject(hbDesktop);
DeleteDC(hDest);
ReleaseDC(NULL, hdc);

补充说明

  • 方法一适合对画质要求不高的场景,无需额外依赖库,操作简单。
  • 方法二能在保留更多细节的同时大幅压缩体积,推荐用于需要画面清晰度的场景。
  • 所有GDI/GDI+资源必须正确释放,避免内存泄漏。

内容的提问来源于stack exchange,提问作者Epic Speedy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 18:01:19