Recent

Author Topic: [Solved for now ] TPicture content ownership ?  (Read 522 times)

jamie

  • Hero Member
  • *****
  • Posts: 7300
[Solved for now ] TPicture content ownership ?
« on: September 05, 2025, 08:53:10 pm »
If I directly set the Picture.Graphic  from a PNG for example, I need to free the PNG along with the TPicture object.

However, If I load the TPicture from a stream for example, the Graphic object is valid, just like it is if I directly set it from an external object like a PNG but I only need to free the TPicture object.

 Question:
     How do I determine who owns the data?

Jamie
« Last Edit: September 06, 2025, 10:55:04 pm by jamie »
The only true wisdom is knowing you know nothing

cdbc

  • Hero Member
  • *****
  • Posts: 2462
    • http://www.cdbc.dk
Re: TPicture content ownership ?
« Reply #1 on: September 05, 2025, 09:55:59 pm »
Hi
I'm pretty the sure '.Graphic' _owns_ its current graphic-bitmap, thus if you _assign_ another graphic-object e.g.: .Graphic.Assign(SomePng); it will clear/free its internal bitmap and then unpack&copy the new into the internal object/handle.
If I were you, I'd have a look at the PNGReader class and after that a 'looksee' in TGraphic.LoadFromStream, respectively 'TGaphic.SetGraphic and '.Assign'.
If you follow the flow in the debugger, I'll bet you'll find a point where TGraphic releases the previous image-object...
Note: I'd do it for you, but right now the second half is starting in football -- Denmark vs. Scotland in FiFa WorldCup qualifying...  ;D
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

jamie

  • Hero Member
  • *****
  • Posts: 7300
Re: TPicture content ownership ?
« Reply #2 on: September 05, 2025, 10:15:49 pm »
I have already done some test of course and this is what I find.

 If I directly set the graphic object of the TPicture from a PNG for example and then free the PNG the TPicture no longer has a Valid image, which indicates it did not make an assigned copy of it.

 So, I need to keep both alive until finished.

 If I use the "Picture.Assign(From A PNG)", then it has its own copy, and I can free the external PNG or ignore it.

 This is the problem, in either case the Picture has valid image, it could be from a direct assignment which only uses the external PNG and both must be alive until finished or, you can load from a stream or use Assign, and it creates a unique image in the TPicture.

  The problem is, how do we determine this if the TPicture is given to a remote procedure/Method as a parameter?

 Jamie


The only true wisdom is knowing you know nothing

cdbc

  • Hero Member
  • *****
  • Posts: 2462
    • http://www.cdbc.dk
Re: TPicture content ownership ?
« Reply #3 on: September 05, 2025, 11:03:31 pm »
Hi jamie
Right, so 'Assign' & 'LoadFromStream' results in a valid internal graphic-object, whereas a 'directly set graphic-object' results in a reference to said external graphic-object...
There has to be way to tell them apart -- Size?!?
In what is the internal object stored -- check if allocated / valid...
Maybe check if the Handle corresponds to the internal object or not...
...Now I understand this phrase "Fluffy Monkeys Chasing Hazelnuts"  :D ;D
Hehehe -- Happy hunting
Regards Benny
If it ain't broke, don't fix it ;)
PCLinuxOS(rolling release) 64bit -> KDE6 -> FPC 3.2.2 -> Lazarus 4.0 up until Jan 2025 from then on it's both above &: KDE6/QT6 -> FPC 3.3.1 -> Lazarus 4.99

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 1565
    • Lebeau Software
Re: TPicture content ownership ?
« Reply #4 on: September 06, 2025, 12:12:40 am »
If I directly set the graphic object of the TPicture from a PNG for example and then free the PNG the TPicture no longer has a Valid image, which indicates it did not make an assigned copy of it.

That is NOT how it's supposed to work.  Assigning an external graphic object to the Picture.Graphic property SHOULD create a new copy, not a reference.

... whereas a 'directly set graphic-object' results in a reference to said external graphic-object...

If that were true, that would be a serious deviation from Delphi compatibility.

When you directly assign an external graphic object to the Picture.Graphic property, a COPY of that object should be created and become owned by the Picture.Graphic property, freeing any previously owned object. This is exactly how Picture.Graphic used to work a long time ago:

https://forum.lazarus.freepascal.org/index.php/topic,28874.msg181415.html#msg181415

Likewise, when you Assign() an external graphic object to the Picture, a COPY of that object should be created and become owned by the Picture.Graphic property, freeing any previously owned object.

And, when you LoadFrom...() an external graphic file/stream into the Picture, a new graphic object should be created and become owned by the Picture.Graphic property, freeing any previously owned object.

So, either way, the Picture.Graphic property should ALWAYS hold an independent object that is owned by TPicture, allowing you to safely free any original external object you had assigned to the Picture.

If that is not working correctly anymore, then that would be a bug that needs to be fixed.
« Last Edit: September 06, 2025, 12:20:28 am by Remy Lebeau »
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)

jamie

  • Hero Member
  • *****
  • Posts: 7300
Re: TPicture content ownership ?
« Reply #5 on: September 06, 2025, 12:31:23 am »
Yes, I understand how it suppose to work!  :D

It should be an Assignment either way and TPicture creates its own., not just a reference.

This problem seems to be random atm, I can't reproduce it every time even in a simple test app.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. Var
  3.   S:TMemoryStream;
  4.   P:TPicture;
  5.   PNG:TPortableNetworkGraphic;
  6. begin
  7.   S:= TMemoryStream.Create;
  8.   PNG := TPortableNetWorkGraphic.Create;
  9.   PNG.Width := 200;
  10.   PNG.Height:= 200;
  11.   P:= TPicture.Create;
  12.   P.Graphic := Png;
  13.   Png.free; //Freeing here sometimes causes an error with following code.
  14.   P.SaveToStream(S);
  15.   P.SaveToStream(S);
  16.   S.Position :=0;
  17.   P.LoadFromStream(S);
  18.   P.LoadFromStream(S);
  19.   Caption := P.Graphic.GetFileExtensions+','+S.Position.Tostring;
  20.   P.Free;
  21.   S.Free;
  22. //  PNG.Free;
  23. end;                                                  
  24.  
  25.  

It could be something totally elsewhere.

Jamie


The only true wisdom is knowing you know nothing

jamie

  • Hero Member
  • *****
  • Posts: 7300
Re: TPicture content ownership ?
« Reply #6 on: September 06, 2025, 10:54:35 pm »
I tried that same code with the 64Bit windows compiler and it worked every time without any strangeness.
Then back to the 32-bit version and it worked somewhat randomly.

 I have two installs of Lazarus and also, I've noticed lately other small, strange things are happening with the 32 bits install.

 So, I did a clean rebuild of the 32-bit install of Lazarus and the compiler complained a little about some component I had installed about duplicated files, so I fixed that and rebuilt the IDE, it all works now in both 32 and 64
 
   Maybe I should investigate that component, it's not a stock one.

Jamie
 
The only true wisdom is knowing you know nothing

 

TinyPortal © 2005-2018