Click here to Skip to main content
15,671,266 members
Please Sign up or sign in to vote.
3.40/5 (3 votes)
See more:
This sample code below demonstrates using CImage (from ATLImage.h) to load a file based image, save it to a stream, and create a COM picture interface which can be the return value in an OLE automation property.

The crazy thing is that OleLoadPicture fails with an error code indicating a corrupted file format. However, I am able to demonstrate in the error condition that the stream can again be loaded in a second CImage and saved back to disk. Comparison of the two file based bitmaps shows them to be identical.

It is a confounding problem as this seems the best way to pass image data around in COM.

Can anyone think of why this fails? My only suspicion is that the saved BMP somehow does not conform to some standard but then again I can look at it with any image viewer

// OLE Stream file necessary for OleLoadPicture support
COleStreamFile ImageStream;

// Prepare the Image for memory stream serialization
if (ImageStream.CreateMemoryStream())
	// GDI+ Image support
	CImage ImageDIB;

	// Attach the DIB to the Image
	if (SUCCEEDED(ImageDIB.Load(L"C:\\Users\\abantly\\AppData\\Local\\Temp\\Image.bmp")))
		// Serialize to the memory stream the DIB to the BMP format
		IStream * pImageStream = ImageStream.GetStream();
		if (pImageStream && SUCCEEDED(ImageDIB.Save(pImageStream,Gdiplus::ImageFormatBMP)))
			CComPtr<IPicture> Picture;
			HRESULT hr = OleLoadPicture(pImageStream,(LONG)ImageStream.GetLength(),FALSE,IID_IPicture,(LPVOID *)&Picture);
			if (SUCCEEDED(hr))
				// FAILS TO GET HERE with code -2146827807
				CComQIPtr<IPictureDisp> PictureDisp(Picture);
				CImage ImageDIB2;
				if (SUCCEEDED(ImageDIB2.Load(pImageStream)))

			// Release the stream
Updated 29-Jun-17 5:54am
Matthew Faithfull 11-Apr-13 5:33am    
Does seem like it should work. Have you tried playing around with the OleLoadPicture options e.g.

HRESULT hr = OleLoadPicture(pImageStream, 0, TRUE, IID_IPicture,(LPVOID *)&Picture);

To let it work out how much data to get and to not attempt to keep the original format.
Andy Bantly 11-Apr-13 18:08pm    
You know, I didn't try changing from FALSE to TRUE to let it convert the image. I did try the 0 value but got the same result. It is so confounding to me. I can go through those gyrations to save the file to disk and then use my alternate solution below to load it into a IPictureDisp. The only other thing I could think to do is to somehow create a CStreamArchive from a IStream. It should be possible since IStream is CStreamArchives base class. I should probably try to look at the data for both cases in memory and see if there is anything obviously different about the streams. e.g. one is store unicode and the other as raw byte data.
Matthew Faithfull 11-Apr-13 18:18pm    
Sorry I can't offer more in the way of suggestions. I've not done much with IStream except for marshalling stuff between thread apartments and that was nightmarish enough. At least you have some things to try. As you have a nice canned example you might even get some joy from Microsoft support given that you're getting an error not listed in the MSDN documentation from an API for which your parameters appear to be valid.

1 solution

I finally did solve the problem (long ago) and am now updating the question. The issue was that the stream needs to be rewound before OleLoadPicture. The code I added to fix it and make it work was:

 // Rewind the stream for picture loading
li.QuadPart  = 0;
Share this answer
Patrice T 29-Jun-17 14:10pm    
You can as well accept your answer.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900