2009-07-07 69 views
4

这是我第一篇文章。我有个问题。 我需要拍摄一个桌面的sceenshot,将其转换为jpeg,将其存储在缓冲区中,然后对其进行处理并通过互联网发送。从内存中获取jpeg的大小(使用GDI ++转换)

我已经用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吗?

谢谢。

回答

5

根据the CreateStreamOnHGlobal文档,您的使用是不合法的。报价:

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

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

HGLOBAL gGlobal = GlobalAlloc(GMEM_MOVEABLE, 0); 

保存到流后,所产生的规模将可作为

size_t size = GlobalSize(hGlobal); 

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

注意整体和局部功能都被标记为已过时,不应再使用,但我不知道你需要一个更好的IStream实现无爬行的MSDN文档。也许别人可以在这里帮助!?

+0

谢谢。 这是一个很好的解决方案,因为我不需要为流分配额外的内存。 – Nemok 2009-07-07 10:26:50

1

OK我找到了解决这个问题在这里: 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;