Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

RESOURCE LEAK: TBitmap.LoadFromFile (and Assign?)

173 views
Skip to first unread message

Robert Winkler

unread,
Jan 1, 1999, 3:00:00 AM1/1/99
to
I am running out of system resources on WinNT4SP3 over time. What I have
track it down to is that resources are not being freed by TBitmap;
specifically the internal palette that it uses.

I discovered that this is the problem using MemProof. Which showed that
CreatePalette did not have a corresponding DeleteObject after the program
ended. I could be misreading the results, but this is the only thing I can
find that is causing my resource problem.

Note: My client application's images are being updated when changes occur on
the server. I am creating a network based game and therefore changes to the
user's view do change quite frequently.

Can anyone help or steer me to a solution to the issue?

Thanks in advance,
Robert

r.fellner bigfoot dot com

unread,
Jan 3, 1999, 3:00:00 AM1/3/99
to
Hello,

if you are using Delphi 3, this is a documented bug I had terrible
hours with until I found a fix at the Delphi Buglist by Reinier
Sterkenburg. Find a link to it on my "Delphi-Box" Tips area,
the buglist also shows a fix for the leak.

regards,
Richey

Robert Winkler

unread,
Jan 3, 1999, 3:00:00 AM1/3/99
to
Thanks Richey! I just looked at the zipped buglist from your site, and I
think that will fix the problem. <Hurray!>

Robert

r.fellner _@_ bigfoot dot com (http://come.to/Delphi-Box) wrote in message
<368fd909...@forums.inprise.com>...

Robert Winkler

unread,
Jan 8, 1999, 3:00:00 AM1/8/99
to
Richey and newsgroup,

The resolution to the problem was not obvious, but the Bitmap.ReadDIB and
HintWindow.WMNCPaint removed 99% of the resource leaks.

There still remain a dozen, which do not grow as the application is run, but
I have applied every fix that applies, except the JPEG one. Since I do not
have any JPEG images I am guessing this is not one of the last leaks. But
am not sure because MemProof is being arcane in its reporting of these last
leaks.

Thanks again for the reference Richey.

Btw, it seems Delphi shipped the JPEG.dcu but not the source. Where do I
get the source? If it is not available to a Delphi3 developer, or a better
fix has been found, perhaps the Palette leak can be fixed in the Graphics
unit? (Note: I do not use Packages)

Robert

Robert Winkler wrote in message <76o5ro$6i...@forums.borland.com>...

Chris Roberts

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
"Robert Winkler" <rwin...@earthlink.net> wrote:

>Btw, it seems Delphi shipped the JPEG.dcu but not the source. Where do I
>get the source? If it is not available to a Delphi3 developer, or a better
>fix has been found, perhaps the Palette leak can be fixed in the Graphics
>unit? (Note: I do not use Packages)

Hi Robert.

You'll find the JPEG source on the Delphi CD in D:\INFO\EXTRAS\JPEG.
Note this uses the .obj files in D:\INFO\EXTRAS\JPEG\OBJ which are
compiled from the C code in D:\INFO\EXTRAS\JPEG\SRC.

The palette leak for JPEGs is only a problem when run on 256 colour
displays. The following was published by Greg Chapman on 16/02/98. I
can email the modified JPEG.PAS and .DCU if you require.

Regards,
Chris Roberts

================================================================
More on JPEG Unit leaves Palettes behind (Greg Chapman 16/02/98)
================================================================
There was a thread in this group back in December about GDI palettes not
being freed by the JPEG unit. A fix for one bug was posted by Xavier
Pacheco, but a second bug, which occurs when the JPEG's PixelFormat =
pf8Bit, did not have a fix posted. I would like to propose a temporary
fix here (a permanent fix requires modifying the VCL Graphics unit).

The leak occurs in the TJPEGImage.GetBitmap method in cases in which the
newly allocated FBitmap's PixelFormat is set to pf8Bit. In
TBitmap.SetPixelFormat, the pf8Bit parameter will result in a call to
CreateHalftonePalette, which returns a newly allocated GDI palette which
is then passed to TBitmap.CopyImage. CopyImage creates a new
TBitmapImage for the bitmap, and, in so doing, it creates a new copy of
the passed in palette (through the call to CopyPalette). The problem is
that the original copy (allocated in SetPixelFormat) is never freed.

As far as I can tell, there is no way to fix this palette leak without
modifying the Graphics unit (and thus forcing oneself to do without
packages). However, the leak can be limited to one palette per
application by adding the following routine to the JPEG unit:

var pf8BitBitmap: TBitmap = nil;

procedure Set8BitPixelFormat(ABitmap: TBitmap);
begin
if not Assigned(pf8BitBitmap) then begin
pf8BitBitmap:= TBitmap.Create;
pf8BitBitmap.PixelFormat:= pf8Bit;
end;
ABitmap.Assign(pf8BitBitmap);
end;

Then change the TJPEGImage.GetBitmap routine as follows:

// Set the bitmap pixel format
FBitmap.Handle := 0;
if (PixelFormat = jf8Bit) or (jc.d.out_color_space =
JCS_GRAYSCALE)
then
// FBitmap.PixelFormat := pf8bit {causes palette leak}
Set8BitPixelFormat(FBitmap)
else
FBitmap.PixelFormat := pf24bit;

Finally, include a call to pf8BitBitmap.Free in the unit's finalization
section.

All comments appreciatd. Thanks.

Greg Chapman
===================

Robert Winkler

unread,
Jan 11, 1999, 3:00:00 AM1/11/99
to
Chris,

Thanks for the info. I should have searched my CD and not just my
harddrive. I found the source on the CD and can hopefully figure out how to
get the .DCU compiled and in the right spot for Delphi, however before I
attempt this I have a question.

Does "TBitmap" use the jpeg code? I can find no reference to the
"TJPEGImage" object anywhere in the Delphi source. Therefore, I assumed,
when I read about the bug previously, that the palette leak would not affect
me. Note: I do sometimes use the 256 color display mode when testing for
potential client configurations.

Thanks,
Robert

Chris Roberts wrote in message <369a05f8...@forums.inprise.com>...

Chris Roberts

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
"Robert Winkler" <rwin...@earthlink.net> wrote:

>Thanks for the info. I should have searched my CD and not just my
>harddrive. I found the source on the CD and can hopefully figure out how to
>get the .DCU compiled and in the right spot for Delphi, however before I
>attempt this I have a question.
>
>Does "TBitmap" use the jpeg code? I can find no reference to the
>"TJPEGImage" object anywhere in the Delphi source. Therefore, I assumed,
>when I read about the bug previously, that the palette leak would not affect
>me. Note: I do sometimes use the 256 color display mode when testing for
>potential client configurations.

Robert,

As you can see below in the initialization code for the JPEG.PAS unit,
TJPEGImage is registered as a TPicture file format during run-time
startup. The method of registering file formats lets you add other 3rd
party add-ons such as TGIFImage to work with the standard Delphi3
TImage. You can work with the resulting TBitmap on screen or in memory,
leaving TJPEGImage to do all the conversion hard yakka to and from disk.

Greg Chapman's palette leak fix does not fully cure the problem. It
just limits the leak to one palette per application, not one palette per
JPEG loaded. By fixing JPEG.PAS and not GRAPHICS.PAS you can still use
packages.

Regards,
Chris Roberts

=================
initialization
InitDefaults;
TPicture.RegisterFileFormat('jpg', 'JPEG Image File', TJPEGImage);
TPicture.RegisterFileFormat('jpeg', 'JPEG Image File', TJPEGImage);

finalization
TPicture.UnregisterGraphicClass(TJPEGImage);
if pf8BitBitmap <> nil then // palette bug fix Greg Chapman 15/02/98
pf8BitBitmap.Free;
end.
=================


Robert Winkler

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
Chris,

I hope I am not being obtuse, but I still don't see that TBitmap is using
the jpeg code. MemProof is not reporting that I am leaking repeatedly for
each image and so I am guessing that TBitmap does not use TJPEGImage.

Note that, if jpeg.dcu is being used, then it would be too bad that there is
not a graphics.pas fix, for people like me who do not use packages.
However, eliminating the leaks down to one is better than running out of
resources.<g>

Thanks,
Robert


Chris Roberts

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
"Robert Winkler" <rwin...@earthlink.net> wrote:

>I hope I am not being obtuse, but I still don't see that TBitmap is using
>the jpeg code. MemProof is not reporting that I am leaking repeatedly for
>each image and so I am guessing that TBitmap does not use TJPEGImage.

Roberts,

"I just use the stuff. I don't know how it works." ;-)

'My' way of explaining it is that TBitmap does not use TJPEGImage, but
the two objects have 'equivalences' which can be 'exchanged'. See code
below. TJPEGImage will only be used for JPEG images.

Regards,
Chris Roberts

==============
procedure TForm1.Button1Click(Sender: TObject);
begin
StatusBar1.SimpleText := '';
if OpenPicDialog1.Execute then
try
Image1.Picture.LoadFromFile(OpenPicDialog1.FileName);
Button2.Enabled := (Image1.Picture.Graphic is TBitmap);
Button3.Enabled := (Image1.Picture.Graphic is TJPEGImage);
Button4.Enabled := (Image1.Picture.Graphic is TGIFImage);
StatusBar1.SimpleText := OpenPicDialog1.FileName;
except
on EInvalidGraphic do MessageDlg('Invalid Graphic Format', mtError,
[mbOK],0);
end;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
JP : TJPEGImage;
begin
if Image1.Picture.Graphic is TBitmap then
begin
{Convert a Bitmap image to a JPEG image}
Jp := TJPEGImage.Create;
try
Jp.Assign(Image1.Picture.Graphic);
Jp.SaveToFile('c:\bmp2jpeg.jpg');
finally
Jp.Free;
end;
end;
end;
=======================


Erik Berry

unread,
Jan 12, 1999, 3:00:00 AM1/12/99
to
In article <369be23f...@forums.borland.com>,
gou...@remove.this.globalnet.co.uk says...
> So we just carry on using TImage but Delphi now knows what to do with
> JPEGs. Clever isn't it? Not that I really understand it either :-)

This is a very nice feature of Delphi. TPicture.RegisterFileFormat
tells TPicture what graphics types have been registered for TImage to
manipulate -- you supply the file extension, the english name of the
format, and the class that implements the routines to read the format:

TPicture.RegisterFileFormat('jpg', 'JPEG Image File', TJPEGImage);

Erik

Steve Gouldstone

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to
"Robert Winkler" <rwin...@earthlink.net> wrote:
>Chris,

>I hope I am not being obtuse, but I still don't see that TBitmap is using
>the jpeg code. MemProof is not reporting that I am leaking repeatedly for
>each image and so I am guessing that TBitmap does not use TJPEGImage.

I suppose that's just the wonder of object orientation.

By adding the JPEG unit to the project, Delphi inherits the ability to
handle JPEG images and adds it to its existing knowledge and methods
for handling TImages.

So we just carry on using TImage but Delphi now knows what to do with
JPEGs. Clever isn't it? Not that I really understand it either :-)

I wonder how many other people (like me) don't really understand or
use the object oriented features of Delphi to the full?

Steve
--
Steve Gouldstone, Helpburger: the easy to use
and affordable Windows Help authoring tool.
http://www.euro-share.com/langdale/helpburger.htm

Robert Winkler

unread,
Jan 13, 1999, 3:00:00 AM1/13/99
to
Thanks Chris. Even though the feature you have mentioned is not used by me,
I like knowing about and will look into it in the future (when I support
Jpeg, and other, images).

Robert


0 new messages