Get jpeg size from memory (converted using GDI ++)

This is my first post here. I have a problem. I need to make a desktop sceenshot, convert it to jpeg, save it to a buffer, and then manipulate it and send it over the Internet.

I wrote code for this with GetDC .... and GDI + to convert HBITMAP to jpeg. The problem that I am facing right now is that I do not know the size of the jpeg that was saved in IStream. Here is the piece of code that converts the bitmap referenced by HBITMAP hBackBitmap to jpeg and stores it in pStream. I need to know how many bytes were written to pStream and how I can use pStream (get the PVOID descriptor):

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

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

Thanks.

+4
source share
2 answers

According to the documentation of CreateStreamOnHGlobal , you use it. Quote:

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

Therefore, you must replace nBlockSize with 0 to allocate a zero-size buffer. Since the memory buffer must be movable, you 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 JPEG encoded data, you will need to use GlobalLock to get a pointer to the actual location in memory.

Note that global and local functions are deprecated and should no longer be used, but I don’t know the best implementation of IStream for your needs without going around the MSDN documentation. Maybe someone else can help here!

+5
source

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

I will also bring it here for future reference. To find out the size that was written to the stream, you can use the Seek of the stream method. To access 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; 
+1
source

All Articles