Discussion:
How to load a JPEG from memory into a GDI+ Bitmap?
(too old to reply)
BartMan
2007-12-06 21:09:01 UTC
Permalink
Greetings,

I am currently getting a buffer from a device which is in JPEG form. I can
write the buffer to a file, and it appears to be fine. But I can not seem to
get it to display from the buffer.

Code used to write the image to a file, which If I look at the image using
paint, it shows up fine.
ULONG ulHeaderSize = 64;
unsigned char* pucData;// Points to the data.
fwrite( pucData+ulHeaderSize, 1, (BufferSize-ulHeaderSize), hFileImage );

Code that does not work for showing Image using GDI+.
HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED,BufferSize-ulHeaderSize);
CComPtr<IStream> spStream;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStream);

ULONG pcbWritten;
spStream->Write(pucData+BufferSize, BufferSize-ulHeaderSize, &pcbWritten);

Bitmap image(spStream, FALSE);

Then I use DrawImage to output the bitmap, and it is either empty, or has
garbage in it. I am not sure what I am doing wrong.

If I use Bitmap and load it from a file path (which I just outputted) it
draws correctly. I think it has something to do with loading it from
memory, but I am not sure what I am doing wrong?

Thanks in advance for any suggestions!
Michael Phillips, Jr.
2007-12-06 22:56:29 UTC
Permalink
Post by BartMan
I am not sure what I am doing wrong.
Rewind or position the stream pointer to position 0.
Post by BartMan
Greetings,
I am currently getting a buffer from a device which is in JPEG form. I can
write the buffer to a file, and it appears to be fine. But I can not seem to
get it to display from the buffer.
Code used to write the image to a file, which If I look at the image using
paint, it shows up fine.
ULONG ulHeaderSize = 64;
unsigned char* pucData;// Points to the data.
fwrite( pucData+ulHeaderSize, 1, (BufferSize-ulHeaderSize), hFileImage );
Code that does not work for showing Image using GDI+.
HGLOBAL hGlobal = GlobalAlloc(GMEM_FIXED,BufferSize-ulHeaderSize);
CComPtr<IStream> spStream;
HRESULT hr = CreateStreamOnHGlobal(hGlobal, TRUE, &spStream);
ULONG pcbWritten;
spStream->Write(pucData+BufferSize, BufferSize-ulHeaderSize, &pcbWritten);
Bitmap image(spStream, FALSE);
Then I use DrawImage to output the bitmap, and it is either empty, or has
garbage in it. I am not sure what I am doing wrong.
If I use Bitmap and load it from a file path (which I just outputted) it
draws correctly. I think it has something to do with loading it from
memory, but I am not sure what I am doing wrong?
Thanks in advance for any suggestions!
BartMan
2007-12-06 23:36:01 UTC
Permalink
Hello Michael,

Thanks for your time!

I tried setting the seek position as you suggested, and it did not solve my
problem.
Is there a better way to load a jpeg buffer from memory?
Michael Phillips, Jr.
2007-12-07 00:47:45 UTC
Permalink
Post by BartMan
Is there a better way to load a jpeg buffer from memory?
There is nothing better than a stream!

I use CreateStreamOnHGlobal(NULL, TRUE, &pStream);

Using a NULL for the HGlobal will cause the function to allocate the memory
when the stream is accessed via writing(i.e., it will grow as you write to
it).

The position must be rewound to 0. The GDI+ decoder will fail if the stream
is not at position 0.

Are you sure that the stream is properly formatted as a jpeg?
What error message is returned from GDI+?

One of the benefits of a stream, is that you have 3 ways to decode/encode an
image with Microsoft's imaging libaries.
1) Use any of the COM OleLoadPicture functions.
2) Use GDI+
3) Use Microsoft's Windows Imaging Component(i.e., WIC)

All three will encode/decode a jpeg directly from a stream.

One last test to to take your stream and write it to a file and open it with
any of the above API's.
If loaded without error, then your jpeg is properly encoded.
Post by BartMan
Hello Michael,
Thanks for your time!
I tried setting the seek position as you suggested, and it did not solve my
problem.
Is there a better way to load a jpeg buffer from memory?
BartMan
2007-12-07 15:22:04 UTC
Permalink
Post by Michael Phillips, Jr.
The position must be rewound to 0. The GDI+ decoder will fail if the stream
is not at position 0.
Here is the code I used to set it to 0, does this seem right?
ULARGE_INTEGER ulPos;
LARGE_INTEGER ulBeg;
ulBeg.QuadPart = 0x00000;
spStream->Seek(ulBeg,STREAM_SEEK_SET,&ulPos);
Post by Michael Phillips, Jr.
One last test to to take your stream and write it to a file and open it with
any of the above API's.
If loaded without error, then your jpeg is properly encoded.
I tried outputing the stream below to a file, and it only shows up as 1 kb.
I think I am not outputing the stream correctly.
ofstream theoutputfile;
theoutputfile.open("test.jpg");
theoutputfile << spStream;
theoutputfile.close();
Michael Phillips, Jr.
2007-12-07 16:41:05 UTC
Permalink
Post by BartMan
Here is the code I used to set it to 0, does this seem right?
ULARGE_INTEGER ulPos;
LARGE_INTEGER ulBeg;
ulBeg.QuadPart = 0x00000;
spStream->Seek(ulBeg,STREAM_SEEK_SET,&ulPos);
Correct.
Post by BartMan
I tried outputing the stream below to a file, and it only shows up as 1 kb.
I think I am not outputing the stream correctly.
ofstream theoutputfile;
theoutputfile.open("test.jpg");
theoutputfile << spStream;
theoutputfile.close();
spStream is a pointer to an IStream COM interface.

You cannot redirect to an ofstream.

Use the WIN32 API CreateFile to create the file and write to it with
WriteFile and the spStream.
Post by BartMan
Bitmap image(spStream, FALSE);
Additionally, make sure that you do not release the spStream interface
before GDI+ has loaded the jpeg from the stream.

The GDI+ decoder will read the jpeg signature first and if it can decode it,
it will allocate internal resources for the image when the image bits are
actually accessed.

Check the error returned from GetLastStatus().
Post by BartMan
Post by Michael Phillips, Jr.
The position must be rewound to 0. The GDI+ decoder will fail if the stream
is not at position 0.
Here is the code I used to set it to 0, does this seem right?
ULARGE_INTEGER ulPos;
LARGE_INTEGER ulBeg;
ulBeg.QuadPart = 0x00000;
spStream->Seek(ulBeg,STREAM_SEEK_SET,&ulPos);
Post by Michael Phillips, Jr.
One last test to to take your stream and write it to a file and open it with
any of the above API's.
If loaded without error, then your jpeg is properly encoded.
I tried outputing the stream below to a file, and it only shows up as 1 kb.
I think I am not outputing the stream correctly.
ofstream theoutputfile;
theoutputfile.open("test.jpg");
theoutputfile << spStream;
theoutputfile.close();
BartMan
2007-12-07 16:50:01 UTC
Permalink
Post by Michael Phillips, Jr.
You cannot redirect to an ofstream.
Use the WIN32 API CreateFile to create the file and write to it with
WriteFile and the spStream.
Got it, that makes sense to me. Thanks for the tip!
Post by Michael Phillips, Jr.
Additionally, make sure that you do not release the spStream interface
before GDI+ has loaded the jpeg from the stream.
That is what it was!! I was releasing the stream before the call!!
Thanks for all of your help!!!!
Richard Russell
2007-12-09 16:12:15 UTC
Permalink
Post by Michael Phillips, Jr.
1) Use any of the COM OleLoadPicture functions.
2) Use GDI+
3) Use Microsoft's Windows Imaging Component(i.e., WIC)
All three will encode/decode a jpeg directly from a stream.
Do they share the same code to do that, or are they using separate
JPEG libraries? Are they guaranteed to give identical results, or may
one work better than another?

Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
Michael Phillips, Jr.
2007-12-09 17:59:56 UTC
Permalink
Post by Richard Russell
Do they share the same code to do that, or are they using separate
JPEG libraries? Are they guaranteed to give identical results, or may
one work better than another?
They are all separate. I do not known if Microsoft reused, rewrote or
extended their codec's codebase.

WIC allows a developer to add functionality to the existing codecs or to add
your own codecs.

Once added, the codecs work seamlessly with the Net 3.0, Net 3.5 and
unmanaged code WIC framework.

I have written codecs for the tga and pcx graphics formats.

It is a pleasure to see that the operating system will recognize these
formats and allow opening, saving, and displaying these formats with no
extra effort.
Post by Richard Russell
Post by Michael Phillips, Jr.
1) Use any of the COM OleLoadPicture functions.
2) Use GDI+
3) Use Microsoft's Windows Imaging Component(i.e., WIC)
All three will encode/decode a jpeg directly from a stream.
Do they share the same code to do that, or are they using separate
JPEG libraries? Are they guaranteed to give identical results, or may
one work better than another?
Richard.
http://www.rtrussell.co.uk/
To reply by email change 'news' to my forename.
Loading...