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

GDI/GDI+截图转JPG后,如何获取TCP传输所需的字节数组?

从GDI+的IStream中提取JPG字节数组用于TCP传输

你现在的代码已经通过CreateStreamOnHGlobal创建了内存流并把JPG数据写入其中,但还没把流内的内容转换成可用于TCP传输的字节数组。下面是具体的实现步骤和修正后的完整代码:

关键问题修正

  1. 删掉delete &clsid;——clsid是栈上的局部变量,不能用delete释放,属于错误操作。
  2. 调整GDI资源释放顺序:必须先恢复DC中的旧位图,再销毁位图和DC,避免资源泄漏。
  3. 从IStream提取字节数据需要借助它绑定的HGLOBAL内存块来获取指针和数据长度。

修正后的完整代码

#include <Gdiplus.h>
#include <windows.h>
#include <iostream>

#pragma comment(lib, "Gdiplus.lib")

void screenshot() {
    using namespace Gdiplus;
    IStream* istream = nullptr;
    HRESULT res = CreateStreamOnHGlobal(NULL, true, &istream);
    if (FAILED(res)) {
        return;
    }

    GdiplusStartupInput gdiplusStartupInput;
    ULONG_PTR gdiplusToken;
    GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);

    {
        HDC scrdc = ::GetDC(0);
        if (!scrdc) {
            goto Cleanup;
        }

        int Height = GetSystemMetrics(SM_CYSCREEN);
        int Width = GetSystemMetrics(SM_CXSCREEN);

        HDC memdc = CreateCompatibleDC(scrdc);
        HBITMAP membit = CreateCompatibleBitmap(scrdc, Width, Height);
        if (!memdc || !membit) {
            goto CleanupDC;
        }

        HBITMAP hOldBitmap = (HBITMAP)SelectObject(memdc, membit);
        BitBlt(memdc, 0, 0, Width, Height, scrdc, 0, 0, SRCCOPY);

        Gdiplus::Bitmap bitmap(membit, NULL);
        CLSID clsid;
        GetEncoderClsid(L"image/jpeg", &clsid);

        // 将JPG数据写入内存流
        bitmap.Save(istream, &clsid, NULL);

        // 提取JPG字节数组的核心逻辑
        HGLOBAL hGlobal = NULL;
        if (SUCCEEDED(GetHGlobalFromStream(istream, &hGlobal))) {
            BYTE* pJpgBuffer = (BYTE*)GlobalLock(hGlobal);
            DWORD bufferSize = GlobalSize(hGlobal);

            // pJpgBuffer就是JPG原始字节数据,bufferSize是数据总长度
            // 转成char*直接用于TCP传输:
            char* tcpBuffer = reinterpret_cast<char*>(pJpgBuffer);
            
            // 示例:打印数据长度(替换成你的TCP发送逻辑即可)
            std::cout << "JPG数据字节数:" << bufferSize << std::endl;

            // 使用完必须解锁内存块
            GlobalUnlock(hGlobal);
        }

        // 正确释放GDI资源
        SelectObject(memdc, hOldBitmap);
        DeleteObject(membit);
        DeleteDC(memdc);
    CleanupDC:
        ::ReleaseDC(0, scrdc);
    }

Cleanup:
    GdiplusShutdown(gdiplusToken);
    if (istream) {
        istream->Release();
    }
}

核心提取逻辑说明

  1. GetHGlobalFromStream:获取IStream背后绑定的HGLOBAL内存句柄。
  2. GlobalLock:锁定内存块,返回的指针就是JPG数据的起始地址。
  3. GlobalSize:获取内存块的总字节数,也就是JPG数据的长度。
  4. 把BYTE*强制转成char*后,就可以直接传入TCP的send等传输函数使用。
  5. 必须调用GlobalUnlock解锁内存块,避免资源泄漏。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:45:16