View Issue Details

IDProjectCategoryView StatusLast Update
0035372LazarusLCLpublic2019-05-11 11:33
Reporterjamie philbrook Assigned ToMartin Friebe  
PrioritynormalSeverityminorReproducibilityhave not tried
Status resolvedResolutionfixed 
Platformmost likely allOSFound on Windows but not related 
Product Version2.0 
Fixed in Version2.0.4 
Summary0035372: Tbitmap.LoadFromRawImage creates memory leaks of image size.
DescriptionIf you use the Tbitmap.LoadFromRawImage it recreates the image and
does not clean up the old one, leaving behind memory when freeing the

See Post,45016.0.html
Steps To ReproduceEDITED BY MFR:

Code to reproduce, from forum:

    procedure TForm1.Button1Click(Sender: TObject);
      A := Tbitmap.Create; B := Tbitmap.Create;
      A.PixelFormat := pf24bit; B.PixelFormat := pf24bit;
      A.SetSize(320,240); B.SetSize(320, 240);
      A.Canvas.Changed; //Force a DIB GUI type in windows.
      A.LoadFromRawImage(B.RawImage,false); //Keep B as RAW only..

Below suggested fix from reporter (procedure is in TRasterImage, not TBitmap)

See posted articles and fixes that I have tested and works on my end...

I didn't recompile or rebuild the LCL for this fix, I simply tested with
a local override of the procedure..
procedure TBitmap.LoadFromRawImage(const AImage: TRawImage; ADataOwner: Boolean);
  img: PRawImage;
    if AImage.Description.Format = ricfNone then Exit; // empty image

    img := GetRawImagePtr;
    img^.Description := AImage.Description;
    if ADataOwner
    then begin
      img^.DataSize := AImage.DataSize;
      img^.Data := AImage.Data;
      img^.MaskSize := AImage.MaskSize;
      img^.Mask := AImage.Mask;
      img^.PaletteSize := AImage.PaletteSize;
      img^.Palette := AImage.Palette;
    else begin
      // copy needed
      img^.DataSize := AImage.DataSize;
      if img^.DataSize > 0
      then begin
        //GetMem(img^.Data, img^.DataSize);
        ReallocMem(img^.Data, img^.DataSize);
        Move(AImage.Data^, img^.Data^, img^.DataSize);
      else img^.Data := nil;

      img^.MaskSize := AImage.MaskSize;
      if img^.MaskSize > 0
      then begin
        //GetMem(img^.Mask, img^.MaskSize);
        Reallocmem(img^.Mask, img^.MaskSize);
        Move(AImage.Mask^, img^.Mask^, img^.MaskSize);
      else img^.Mask := nil;

      img^.PaletteSize := AImage.PaletteSize;
      if img^.PaletteSize > 0
      then begin
       // GetMem(img^.Palette, img^.PaletteSize);
        ReallocMem(img^.Palette, img^.PaletteSize);
        Move(AImage.Palette^, img^.Palette^, img^.PaletteSize);
      else img^.Palette := nil;
TagsNo tags attached.
Fixed in Revision61202
Attached Files


jamie philbrook

2019-04-13 13:59

reporter   ~0115473

The commented GETMEM and following ReallocMem lines is what has been done
to fixed

 GetRawImagePtr returns an already allocated image.

Martin Friebe

2019-05-11 11:29

manager   ~0116129

Edited steps to reproduce

Martin Friebe

2019-05-11 11:33

manager   ~0116130

Please test, and close if ok

Issue History

Date Modified Username Field Change
2019-04-13 13:56 jamie philbrook New Issue
2019-04-13 13:59 jamie philbrook Note Added: 0115473
2019-05-11 11:29 Martin Friebe Description Updated View Revisions
2019-05-11 11:29 Martin Friebe Steps to Reproduce Updated View Revisions
2019-05-11 11:29 Martin Friebe LazTarget => -
2019-05-11 11:29 Martin Friebe Note Added: 0116129
2019-05-11 11:32 Martin Friebe Assigned To => Martin Friebe
2019-05-11 11:32 Martin Friebe Status new => assigned
2019-05-11 11:33 Martin Friebe Status assigned => resolved
2019-05-11 11:33 Martin Friebe Resolution open => fixed
2019-05-11 11:33 Martin Friebe Fixed in Version => 2.0.4
2019-05-11 11:33 Martin Friebe Fixed in Revision => 61202
2019-05-11 11:33 Martin Friebe LazTarget - => 2.0.4
2019-05-11 11:33 Martin Friebe Note Added: 0116130