从内存中获取 jpeg 的大小(使用 GDI++ 转换)

发布于 2024-07-25 20:40:55 字数 930 浏览 2 评论 0原文

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

我已经编写了使用 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 吗?

谢谢。

This is my first post here. I have a problem.
I need to take a sceenshot of the desktop, convert it to jpeg, store it in a buffer and then manipulate it and send it over the internet.

I have written the code for doing this with GetDC....and GDI+ for converting the HBITMAP to jpeg. The problem I am having now is that I don't know the size of the jpeg that has been saved into the IStream. Here is part of the code that transforms the bitmap referenced by the HBITMAP hBackBitmap into jpeg and save it into pStream. I need to know how many bytes have been written into pStream and how I can use pStream (get a PVOID handle):

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);

What I need is:
1. Find out the size of jpeg, how many bytes have been written in the stream
2. How to use the stream. Can I get a PVOID for the data in stream for example?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

剩余の解释 2024-08-01 20:40:55

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

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

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

HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);

保存到流后,结果大小将可用为

size_t size = GlobalSize(hGlobal);

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

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

According to the CreateStreamOnHGlobal documentation, your use of it is incorrent. Quote:

The current contents of the memory block are undisturbed by the creation of the new stream object. Thus, you can use this function to open an existing stream in memory.
The initial size of the stream is the size of the memory handle returned by the GlobalSize function.

Therefore, you should replace nBlockSize with 0 to allocate an zero-sized buffer. As the memory buffer must be moveable, you'll also need to replace GMEM_FIXED with GMEM_MOVEABLE:

HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);

After saving to the stream, the resulting size will be available as

size_t size = GlobalSize(hGlobal);

To access the JPEG encoded data, you'll need to use GlobalLock to get a pointer to the actual location in memory.

Note that Global and Local functions are marked as deprecated and should not be used anymore, but I don't know a better IStream implementation for your needs without crawling the MSDN documentation. Perhaps somebody else can help here!?

赠意 2024-08-01 20:40:55

好的,我在这里找到了这个问题的解决方案:
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;

OK I found the solution to this problem here:
http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/6dfc2e62-e2d1-4be3-a93b-a7d97d3f8469

I will also put it here for future reference.
To find out the size that has been written to the stream one can use the method Seek of the stream. To get access to the buffer you can use 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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文