TStreamAdapter, GDI+ and C++ Builder |
|
Hello,
because someone had these problems before in 2004 and asked a lot of
questions about it in newsgroups, I think it's helpful that I post my
solution here for all people out there with the same problem: I wanted to
load a JPEG file with GDI+ in an application built with Codegear's C++
Builder 2007 and got strange invalid pointer exceptions. The following code
does NOT work and leads to exceptions when called more than once:
TMemoryStream * mem_p;
TStreamAdapter * streamadapter;
IStream * mystream;
mem = new TMemoryStream();
mem_p->LoadFromFile("test.jpg");
mem_p->Seek(0,0);
streamadapter_p = new TStreamAdapter(mem_p, soReference);
try{
mystream_p = *streamadapter_p;
gdi_image_p = new Gdiplus::Image(mystream_p, FALSE);
// Do something with our image object
delete gdi_image_p;
}//endtry
catch(const Exception &e){
output(e.Message);
}//entry
// delete streamadapter; // Don't try this. streamadapter is already
freed by deleting gdi_image_p
delete mem_p;
The following fix DOES work for me:
[...]
try{
mystream_p = *streamadapter_p;
mystream_p->AddRef(); // Fix: Increase reference counter
gdi_image_p = new Gdiplus::Image(mystream_p, FALSE);
// Do something with our image object
delete gdi_image_p;
mystream_p->Release(); // Fix: Free object
}//endtry
catch(const Exception &e){
output(e.Message);
}//entry
[...]
The reference counter seems to do the trick.
I did not need to use the TFixedStreamAdapter, which can often be found in
Delphi newsgroups and contains fixed code for the stat function, but if
someone is interested in its C++ code, here it is:
class TFixedStreamAdapter : public TStreamAdapter {
public:
__fastcall TFixedStreamAdapter(TStream * pMemStream, TStreamOwnership
OwnerShip) : TStreamAdapter(pMemStream, OwnerShip){}
virtual __stdcall HRESULT Stat(/* out */ TStatStg &statstg, int
grfStatFlag){
memset((void *)&statstg, 0, sizeof(TStatStg));
statstg.type = STGTY_STREAM;
statstg.cbSize.HighPart = Stream->Size >> 32;
statstg.cbSize.LowPart = Stream->Size;
statstg.mtime = DateTimeToFileTime(Now());
statstg.ctime = DateTimeToFileTime(Now());
statstg.atime = DateTimeToFileTime(Now());
statstg.grfLocksSupported = LOCK_WRITE;
return S_OK;
}
private:
TFileTime __fastcall DateTimeToFileTime(TDateTime DateTime){
TFileTime FileTime;
TSystemTime SystemTime;
DateTimeToSystemTime(DateTime, SystemTime);
SystemTimeToFileTime(&SystemTime, &FileTime);
return FileTime;
}
};
I hope that I could help someone with the same problems.
Bye, Eike
|
Re: TStreamAdapter, GDI+ and C++ Builder |
|
Hello Darko,
well, it was just an example. In reality I'm getting the stream via HTTP
from a webcam. This makes a difference. GDI+ is faster in JPEG decompression
than the TJPEGImage class provided by Codegear.
Bye, Eike
"Darko Miletic" schrieb im Newsbeitrag
news:4784eff7$1@newsgroups.borland.com...
> Eike Belgardt wrote:
>> Hello,
>>
>> because someone had these problems before in 2004 and asked a lot of
>> questions about it in newsgroups, I think it's helpful that I post my
>> solution here for all people out there with the same problem: I wanted to
>> load a JPEG file with GDI+ in an application built with Codegear's C++
>> Builder 2007 and got strange invalid pointer exceptions. The following
>> code does NOT work and leads to exceptions when called more than once:
>
> You are complicating something that is extremely simple.
>
> Image class from gdi+ can receive name of the file directly. You do not
> need this mumbo jumbo.
>
> Here you have a simple example of loading jpeg file:
>
> http://msdn2.microsoft.com/en-us/library/ms533830(VS.85).aspx
>
|
Re: TStreamAdapter, GDI+ and C++ Builder |
|
Eike Belgardt wrote:
> Hello,
>
> because someone had these problems before in 2004 and asked a lot of
> questions about it in newsgroups, I think it's helpful that I post my
> solution here for all people out there with the same problem: I wanted to
> load a JPEG file with GDI+ in an application built with Codegear's C++
> Builder 2007 and got strange invalid pointer exceptions. The following code
> does NOT work and leads to exceptions when called more than once:
You are complicating something that is extremely simple.
Image class from gdi+ can receive name of the file directly. You do not
need this mumbo jumbo.
Here you have a simple example of loading jpeg file:
http://msdn2.microsoft.com/en-us/library/ms533830(VS.85).aspx
|