问题
I am displaying a live view video from camera. Every frame I download into a byte array (pImageData) which I have to allocate.
Now, to display, I am using a CImage (MFC). However, all samples I find are based on using GlobalAlloc, yet another memcpy and CreateStreamOnHGlobal.
I'd like to avoid doing another allocation/deallocation and memory copy. Each frame is over 2mb and I am pushing 30 fps!
Is it possible to create an IStream on non-HGLOBAL based memory? OR Is it somehow possible to coerce Image::Load() to work with byte array?
Here is the code:
// pImageData is an array with bytes, size is the sizeOfThatArray
CComPtr<IStream> stream;
HGLOBAL hMem = ::GlobalAlloc(GHND, size);
LPVOID pBuff = ::GlobalLock(hMem);
memcpy(pBuff, pImageData, size); // <-- would like to avoid this
::GlobalUnlock(hMem);
CreateStreamOnHGlobal(hMem, TRUE, &stream); // <-- or create stream on non-hglobal memory
CImage image;
image.Load(stream); // <-- Or load directly from pImageData
// .. display image
image.Destroy();
::GlobalFree(hMem);
回答1:
Thanks to Hans for pointing out SHCreateMemStream, which I did not know existed. The code is much cleaner, but still unsure whether SHCreateMemStream creates a copy internally (documentation is unclear)
[edit] As per Jonathan' comments, looks like it still has to make a copy internally. Dang ..
Final code
// pImageData is an array with bytes, size is the sizeOfThatArray
// Still not clear if this is making a copy internally
IStream* pMemStream = SHCreateMemStream(pImageData, size);
CComPtr<IStream> stream;
stream.Attach(pMemStream); // Need to Attach, otherwise ownership is not transferred and we leak memory
CImage image;
image.Load(stream);
// .. display image
image.Destroy();
// No need for further cleanup, CComPtr does the job
来源:https://stackoverflow.com/questions/38691416/cimageload-from-memory-without-using-createstreamonhglobal