Winapi 将BMP转换为PNG,并在发送前压缩。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘而不是内存?是的,这是可能的。您需要使用来自的PNG编码器。它在I

Winapi 将BMP转换为PNG,并在发送前压缩。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘而不是内存?是的,这是可能的。您需要使用来自的PNG编码器。它在I,winapi,png,bitblt,Winapi,Png,Bitblt,将BMP转换为PNG,并在发送前压缩。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘而不是内存?是的,这是可能的。您需要使用来自的PNG编码器。它在IStream接口上工作,因此您可以传递内存流实现。将BMP转换为PNG,并在发送之前压缩它。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘


将BMP转换为PNG,并在发送前压缩。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘而不是内存?是的,这是可能的。您需要使用来自的PNG编码器。它在
IStream
接口上工作,因此您可以传递内存流实现。将BMP转换为PNG,并在发送之前压缩它。。。转换为PNG后不需要压缩,因为PNG格式已经“压缩”了数据,而且比ZIP更有效。gdiplus保存到PNG不是更容易吗?或者它只能将PNG保存到磁盘,而不是内存?谢谢你的回复,让我在sizeit可以工作之前尝试并比较一下,转换后,缓冲区的大小仅为原始BMP文件大小的1/10,顺便说一句,在我将缓冲区发送到服务器后,如何在windows上绘制它,仍然使用bitblt?@yangl
bitblt
无法直接绘制PNG。如果你真的想
BitBlt
它,你应该将缓冲区写入
IStream*
,求零,用
bmp=Gdiplus::bitmap::FromStream(…)
,然后
bmp->GetHBITMAP()
BitBlt
从流创建位图。谢谢你的回复,让我在sizeit可以工作之前试一下,然后比较一下,转换后,缓冲区的大小只有原始BMP文件大小的1/10,顺便说一下,在我将缓冲区发送到服务器后,如何在windows上绘制它,仍然使用bitblt?@yangl
bitblt
无法直接绘制PNG。如果你真的想
BitBlt
它,你应该把缓冲区写进
IStream*
,求零,用
bmp=Gdiplus::bitmap::FromStream(…)
,然后
bmp->GetHBITMAP()
BitBlt
从流创建位图。
LPVOID  m_lpvFullBits = NULL;
HDC m_hFullDC, m_hFullMemDC;
LPBITMAPINFO  m_lpbmi_full;
m_hFullDC = GetDC(NULL);
int m_nFullWidth    = ::GetSystemMetrics(SM_CXSCREEN);
int m_nFullHeight   = ::GetSystemMetrics(SM_CYSCREEN);
m_hFullMemDC    = ::CreateCompatibleDC(m_hFullDC);

m_lpbmi_full = (BITMAPINFO *) new BYTE[40];
BITMAPINFOHEADER    *lpbmih = &(m_lpbmi_full ->bmiHeader);
lpbmih->biSize = sizeof(BITMAPINFOHEADER);
lpbmih->biWidth = m_nFullWidth  ;
lpbmih->biHeight = m_nFullHeight    ;
lpbmih->biPlanes = 1;
lpbmih->biBitCount = 32;       // 32 bit per pixel
lpbmih->biCompression = BI_RGB;
lpbmih->biXPelsPerMeter = 0;
lpbmih->biYPelsPerMeter = 0;
lpbmih->biClrUsed = 0;
lpbmih->biClrImportant = 0;
lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;

HBITMAP m_hFullBitmap   = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvFullBits, NULL, NULL);

::SelectObject(m_hFullMemDC, m_hFullBitmap);

::BitBlt(m_hFullMemDC, 0, 0, m_nFullWidth, m_nFullHeight, m_hFullDC, 0, 0, SRCCOPY);
::BitBlt(m_hFullMemDC, 0, 0, m_nFullWidth, m_nFullHeight, m_hFullDC, 0, 0, SRCCOPY);
#include <Windows.h>
#include <gdiplus.h>
#include <iostream>
using namespace Gdiplus;

#pragma comment(lib, "gdiplus.lib") // or you specify it in linker option

IStream * PngMemStreamFrom(HBITMAP hbm)
{
    // image/png  : {557cf406-1a04-11d3-9a73-0000f81ef32e}
    const CLSID clsidPngEncoder =
        { 0x557cf406, 0x1a04, 0x11d3,
        { 0x9a,0x73,0x00,0x00,0xf8,0x1e,0xf3,0x2e } };
    IStream *stream = NULL;
    Bitmap *bmp = Bitmap::FromHBITMAP(hbm, NULL);
    CreateStreamOnHGlobal(NULL, TRUE, &stream);
    bmp->Save(stream, &clsidPngEncoder);    
    delete bmp;
    return stream;
}

void ScreenshotTest(LPCWSTR szPath)
{
    LPVOID  m_lpvFullBits = NULL;
    HDC m_hFullDC, m_hFullMemDC;
    LPBITMAPINFO  m_lpbmi_full;
    m_hFullDC = GetDC(NULL);
    int m_nFullWidth    = ::GetSystemMetrics(SM_CXSCREEN);
    int m_nFullHeight   = ::GetSystemMetrics(SM_CYSCREEN);
    m_hFullMemDC    = ::CreateCompatibleDC(m_hFullDC);

    m_lpbmi_full = (BITMAPINFO *) new BYTE[40];
    BITMAPINFOHEADER    *lpbmih = &(m_lpbmi_full ->bmiHeader);
    lpbmih->biSize = sizeof(BITMAPINFOHEADER);
    lpbmih->biWidth = m_nFullWidth  ;
    lpbmih->biHeight = m_nFullHeight    ;
    lpbmih->biPlanes = 1;
    lpbmih->biBitCount = 32;       // 32 bit per pixel
    lpbmih->biCompression = BI_RGB;
    lpbmih->biXPelsPerMeter = 0;
    lpbmih->biYPelsPerMeter = 0;
    lpbmih->biClrUsed = 0;
    lpbmih->biClrImportant = 0;
    lpbmih->biSizeImage = (((lpbmih->biWidth * lpbmih->biBitCount + 31) & ~31) >> 3) * lpbmih->biHeight;

    HBITMAP m_hFullBitmap = ::CreateDIBSection(m_hFullDC, m_lpbmi_full, DIB_RGB_COLORS, &m_lpvFullBits, NULL, NULL);
    ::SelectObject(m_hFullMemDC, m_hFullBitmap);
    ::BitBlt(m_hFullMemDC, 0, 0, m_nFullWidth, m_nFullHeight, m_hFullDC, 0, 0, SRCCOPY);

    IStream *stream = PngMemStreamFrom(m_hFullBitmap);

    STATSTG stat = {0};
    stream->Stat(&stat, STATFLAG_NONAME);
    UINT64 cbSize = stat.cbSize.QuadPart;
    std::cout << "mem stream byte count = " << cbSize << "\n";
    LPBYTE buffer = new BYTE[cbSize];
    // IMPORTANT! must seek to offset zero before read it
    LARGE_INTEGER offZero = {0};
    stream->Seek(offZero, STREAM_SEEK_SET, NULL);
    stream->Read(buffer, cbSize, NULL);
    // do something with buffer, such as save to disk
    HANDLE hfile = CreateFile(szPath, GENERIC_WRITE, 0, NULL,
        CREATE_ALWAYS, 0, NULL);
    DWORD cbWritten = 0;
    WriteFile(hfile, buffer, cbSize, &cbWritten, NULL);
    CloseHandle(hfile);
    // TODO: release m_hFullDC, m_hFullMemDC... here
}

int main()
{
    ULONG_PTR token = NULL;
    GdiplusStartupInput gdipIn;
    GdiplusStartupOutput gdipOut;
    GdiplusStartup(&token, &gdipIn, &gdipOut);
    ScreenshotTest(L"D:\\Test.png");
    GdiplusShutdown(token);
    return 0;
}