【问题标题】:Get the size of jpeg from memory (converted using GDI++)从内存中获取 jpeg 的大小(使用 GDI++ 转换)
【发布时间】:2010-11-08 14:51:56
【问题描述】:

这是我在这里的第一篇文章。我有个问题。 我需要拍摄桌面截图,将其转换为 jpeg,将其存储在缓冲区中,然后对其进行操作并通过 Internet 发送。

我已经编写了使用 GetDC.. 和 GDI+ 将 HBITMAP 转换为 jpeg 的代码。我现在遇到的问题是我不知道已保存到 IStream 中的 jpeg 的大小。这是将HBITMAP hBackBitmap引用的位图转换为jpeg并将其保存到pStream中的部分代码。我需要知道已将多少字节写入 pStream 以及如何使用 pStream(获取 PVOID 句柄):

Gdiplus::Bitmap bitmap(hBackBitmap, NULL);///loading the HBITMAP
CLSID clsid;
GetEncoderClsid(L"image/jpeg", &clsid);
HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED, nBlockSize) ;//allocating memory, the size of the current bitmap size. i'm over allocating but i don't think there is any way to get the exact ammount I need to allocate, is there?
if(!hGlobal)
    return;
IStream* pStream = NULL ;
if(CreateStreamOnHGlobal(hGlobal, TRUE, &pStream) != S_OK )
    return;
bitmap.Save(pStream, &clsid);

我需要的是: 1.找出jpeg的大小,流中写入了多少字节 2. 如何使用流。例如,我可以为流中的数据获取 PVOID 吗?

谢谢。

【问题讨论】:

    标签: c++ gdi+ bitmap jpeg screenshot


    【解决方案1】:

    根据the CreateStreamOnHGlobal 文档,您对它的使用是不正确的。引用:

    内存块的当前内容不受创建新流对象的干扰。因此,您可以使用此函数打开内存中的现有流。 流的初始大小是 GlobalSize 函数返回的内存句柄的大小。

    因此,您应该将 nBlockSize 替换为 0 以分配零大小的缓冲区。由于内存缓冲区必须是可移动的,因此您还需要将 GMEM_FIXED 替换为 GMEM_MOVEABLE:

    HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);
    

    保存到流后,生成的大小将作为

    size_t size = GlobalSize(hGlobal);
    

    要访问 JPEG 编码数据,您需要使用 GlobalLock 来获取指向内存中实际位置的指针。

    请注意,全局和本地函数被标记为已弃用,不应再使用,但如果不爬取 MSDN 文档,我不知道更好的 IStream 实现以满足您的需求。也许其他人可以在这里提供帮助!?

    【讨论】:

    • 谢谢。这是一个很好的解决方案,因为我不需要为流分配额外的内存。
    【解决方案2】:

    好的,我在这里找到了解决此问题的方法: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/6dfc2e62-e2d1-4be3-a93b-a7d97d3f8469

    我也将其放在这里以供将来参考。 要找出已写入流的大小,可以使用流的方法 Seek。要访问缓冲区,您可以使用 Read。

       // Calculate reasonably safe buffer size
       int stride = 4 * ((image.GetWidth() + 3) / 4);
      size_t safeSize = stride * image.GetHeight() * 4 + sizeof(BITMAPINFOHEADER) +    sizeof(BITMAPFILEHEADER) + 256 * sizeof(RGBQUAD);
      HGLOBAL mem = GlobalAlloc(GHND, safeSize);
      assert(mem);
    
      // Create stream and save bitmap
      IStream* stream = 0;
      hr = CreateStreamOnHGlobal(mem, TRUE, &stream);
      assert(hr == S_OK);
      hr = image.Save(stream, Gdiplus::ImageFormatBMP);
      assert(hr == S_OK);
    
      // Allocate buffer for saved image
      LARGE_INTEGER seekPos = {0};
      ULARGE_INTEGER imageSize;
      hr = stream->Seek(seekPos, STREAM_SEEK_CUR, &imageSize);
      assert(hr == S_OK && imageSize.HighPart == 0);
      BYTE* buffer = new BYTE[imageSize.LowPart];
    
      // Fill buffer from stream
       hr = stream->Seek(seekPos, STREAM_SEEK_SET, 0);
       assert(hr == S_OK);
       hr = stream->Read(buffer, imageSize.LowPart, 0);
       assert(hr == S_OK);
    
    
       // Cleanup
      stream->Release();
      delete[] buffer;
      return 0;
    

    【讨论】:

      猜你喜欢
      • 2015-02-26
      • 1970-01-01
      • 2017-03-18
      • 2012-08-22
      • 2011-01-31
      • 1970-01-01
      • 1970-01-01
      • 2018-11-23
      • 2020-02-18
      相关资源
      最近更新 更多