这是我在这里的第一篇文章。我有个问题。 我需要对桌面进行一次扫描,将其转换为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吗?
谢谢。
答案 0 :(得分:5)
根据the CreateStreamOnHGlobal文档,您对它的使用是不正确的。引用:
通过创建新流对象,内存块的当前内容不受干扰。因此,您可以使用此功能在内存中打开现有流。 流的初始大小是GlobalSize函数返回的内存句柄的大小。
因此,您应该将nBlockSize替换为0以分配零大小的缓冲区。由于内存缓冲区必须是可移动的,因此您还需要将GMEM_FIXED替换为GMEM_MOVEABLE:
HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0);
保存到流后,结果大小将以
的形式显示size_t size = GlobalSize(hGlobal);
要访问JPEG编码数据,您需要使用GlobalLock获取指向内存中实际位置的指针。
请注意,全局和本地函数已标记为已弃用,不应再使用,但我不知道更好的IStream实现,无需抓取MSDN文档即可满足您的需求。也许其他人可以在这里帮忙!?
答案 1 :(得分:1)
好的,我在这里找到了解决这个问题的方法: http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/6dfc2e62-e2d1-4be3-a93b-a7d97d3f8469
我也会把它放在这里供将来参考。 要找出已写入流的大小,可以使用方法Seek of stream。要访问缓冲区,您可以使用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;