Recent

Author Topic: Fractal Tree: How to save picture with a transparent background  (Read 2031 times)

Boleeman

  • Hero Member
  • *****
  • Posts: 766
Hi All.

Been playing around with a Fractal Tree Drawer and was wondering if some someone could possibly explain how to save the paintbox to transparent png using BGRABitmap. I am able to save the paintbox1 to png, by seem to be stumped in getting the background transparent. Looked at some other examples but still quite lost in understanding the process.

Thanks in advance.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, LCLIntf, LCLType;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     btn_drawtree: TButton;
  16.     btn_save: TButton;
  17.     PaintBox1: TPaintBox;
  18.     Panel1: TPanel;
  19.     procedure btn_drawtreeClick(Sender: TObject);
  20.     procedure btn_saveClick(Sender: TObject);
  21.     procedure PaintBox1Paint(Sender: TObject);
  22.   private
  23.  
  24.   public
  25.         procedure ctreefractal(X, Y, Size : Integer; Angle : Real);
  26.  
  27.   end;
  28.  
  29. var
  30.   Form1: TForm1;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.ctreefractal(X, Y, Size : Integer; Angle : Real);
  39. Var x2, y2 : Integer;
  40. begin
  41.   if size < 3  then paintBox1.Canvas.Pen.color := clRed    else
  42.   if size < 5  then paintBox1.Canvas.Pen.color := clYellow else
  43.   if size < 8  then paintBox1.Canvas.Pen.color := clLime   else
  44.   if size < 16 then paintBox1.Canvas.Pen.color := clGreen  else
  45.                     paintBox1.Canvas.Pen.color := clMaroon;
  46.  
  47.   if size < 3  then paintBox1.Canvas.Pen.Width := 1 else
  48.   if size < 5  then paintBox1.Canvas.Pen.Width := 2 else
  49.   if size < 8  then paintBox1.Canvas.Pen.Width := 4 else
  50.   if size < 16 then paintBox1.Canvas.Pen.Width := 6 else
  51.                     paintBox1.Canvas.Pen.Width := 6;
  52.  
  53.   x2 := round(x + size * sin(angle)); // round(x + size * sin(angle)+5)  changer ces valeurs
  54.   y2 := round(y + size * cos(angle));//  round(y + size * cos(angle)+5)
  55.  
  56.   paintBox1.Canvas.MoveTo(X, Y);
  57.   paintBox1.Canvas.LineTo(x2, y2);
  58.  
  59.   { Two recursive calls. }
  60.   if Size > 0 then
  61.   begin
  62.     ctreefractal(x2, y2, 3 * size div 4, angle + Pi / (5 + random(6)));
  63.     ctreefractal(x2, y2, 3 * size div 4, angle - Pi / (5 + random(6)));
  64.   end
  65. end;
  66.  
  67. procedure TForm1.btn_drawtreeClick(Sender: TObject);
  68. begin
  69.  
  70.       //PaintBox1Paint(PaintBox1);
  71.       PaintBox1.Invalidate;
  72. end;
  73.  
  74. procedure TForm1.btn_saveClick(Sender: TObject);
  75. var mypng:TPortableNetworkGraphic;
  76.   //bmp:tbitmap;
  77. begin
  78.   mypng:=TPortableNetworkGraphic.create;
  79.   mypng.SetSize(PaintBox1.ClientWidth,PaintBox1.ClientHeight);
  80.   mypng.PixelFormat:= pf24bit;
  81.   mypng.Canvas.Brush.Color := clnone;
  82.   mypng.clear;
  83.   mypng.Canvas.CopyRect(rect(0, 0, mypng.Width, mypng.Height),PaintBox1.canvas,rect(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight));
  84.   mypng.SaveToFile('testpngimage.png');
  85.   mypng.free;
  86. end;
  87.  
  88.  
  89. procedure TForm1.PaintBox1Paint(Sender: TObject);
  90. begin
  91.  
  92.   ctreefractal(PaintBox1.ClientWidth div 2 ,
  93.            PaintBox1.clientHeight,
  94.            PaintBox1.clientHeight div 4,
  95.            Pi)
  96. end;
  97.  
  98. end.                          


lainz

  • Hero Member
  • *****
  • Posts: 4659
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Fractal Tree: How to save picture with a transparent background
« Reply #1 on: July 20, 2023, 04:07:23 pm »
You can use BGRABitmap.

Check the tutorials, basically, you can draw with classic canvas on a bgrabitmap, so your code will be the same.

Then save the bgrabitmap to file.

Zvoni

  • Hero Member
  • *****
  • Posts: 2793
Re: Fractal Tree: How to save picture with a transparent background
« Reply #2 on: July 20, 2023, 04:16:55 pm »
Look at Line 80. I've inserted something there.
Untested, but i saw a few mentions of that
Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, Forms, Controls, Graphics, Dialogs, ExtCtrls, StdCtrls, LCLIntf, LCLType;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     btn_drawtree: TButton;
  16.     btn_save: TButton;
  17.     PaintBox1: TPaintBox;
  18.     Panel1: TPanel;
  19.     procedure btn_drawtreeClick(Sender: TObject);
  20.     procedure btn_saveClick(Sender: TObject);
  21.     procedure PaintBox1Paint(Sender: TObject);
  22.   private
  23.  
  24.   public
  25.         procedure ctreefractal(X, Y, Size : Integer; Angle : Real);
  26.  
  27.   end;
  28.  
  29. var
  30.   Form1: TForm1;
  31.  
  32. implementation
  33.  
  34. {$R *.lfm}
  35.  
  36. { TForm1 }
  37.  
  38. procedure TForm1.ctreefractal(X, Y, Size : Integer; Angle : Real);
  39. Var x2, y2 : Integer;
  40. begin
  41.   if size < 3  then paintBox1.Canvas.Pen.color := clRed    else
  42.   if size < 5  then paintBox1.Canvas.Pen.color := clYellow else
  43.   if size < 8  then paintBox1.Canvas.Pen.color := clLime   else
  44.   if size < 16 then paintBox1.Canvas.Pen.color := clGreen  else
  45.                     paintBox1.Canvas.Pen.color := clMaroon;
  46.  
  47.   if size < 3  then paintBox1.Canvas.Pen.Width := 1 else
  48.   if size < 5  then paintBox1.Canvas.Pen.Width := 2 else
  49.   if size < 8  then paintBox1.Canvas.Pen.Width := 4 else
  50.   if size < 16 then paintBox1.Canvas.Pen.Width := 6 else
  51.                     paintBox1.Canvas.Pen.Width := 6;
  52.  
  53.   x2 := round(x + size * sin(angle)); // round(x + size * sin(angle)+5)  changer ces valeurs
  54.   y2 := round(y + size * cos(angle));//  round(y + size * cos(angle)+5)
  55.  
  56.   paintBox1.Canvas.MoveTo(X, Y);
  57.   paintBox1.Canvas.LineTo(x2, y2);
  58.  
  59.   { Two recursive calls. }
  60.   if Size > 0 then
  61.   begin
  62.     ctreefractal(x2, y2, 3 * size div 4, angle + Pi / (5 + random(6)));
  63.     ctreefractal(x2, y2, 3 * size div 4, angle - Pi / (5 + random(6)));
  64.   end
  65. end;
  66.  
  67. procedure TForm1.btn_drawtreeClick(Sender: TObject);
  68. begin
  69.  
  70.       //PaintBox1Paint(PaintBox1);
  71.       PaintBox1.Invalidate;
  72. end;
  73.  
  74. procedure TForm1.btn_saveClick(Sender: TObject);
  75. var mypng:TPortableNetworkGraphic;
  76.   //bmp:tbitmap;
  77. begin
  78.   mypng:=TPortableNetworkGraphic.create;
  79.   mypng.SetSize(PaintBox1.ClientWidth,PaintBox1.ClientHeight);
  80.   mypng.Canvas.Brush.Style := bsClear;  //THIS ONE!!
  81.   mypng.PixelFormat:= pf24bit;
  82.   mypng.Canvas.Brush.Color := clnone;
  83.   mypng.clear;
  84.   mypng.Canvas.CopyRect(rect(0, 0, mypng.Width, mypng.Height),PaintBox1.canvas,rect(0, 0, PaintBox1.ClientWidth, PaintBox1.ClientHeight));
  85.   mypng.SaveToFile('testpngimage.png');
  86.   mypng.free;
  87. end;
  88.  
  89.  
  90. procedure TForm1.PaintBox1Paint(Sender: TObject);
  91. begin
  92.  
  93.   ctreefractal(PaintBox1.ClientWidth div 2 ,
  94.            PaintBox1.clientHeight,
  95.            PaintBox1.clientHeight div 4,
  96.            Pi)
  97. end;
  98.  
  99. end.                          
One System to rule them all, One Code to find them,
One IDE to bring them all, and to the Framework bind them,
in the Land of Redmond, where the Windows lie
---------------------------------------------------------------------
Code is like a joke: If you have to explain it, it's bad

Boleeman

  • Hero Member
  • *****
  • Posts: 766
Re: Fractal Tree: How to save picture with a transparent background
« Reply #3 on: July 21, 2023, 06:07:00 am »
Thanks Zvoni and Lainz for replying.

Zvoni, I tried your solution but I was not seeing a transparent background. I opened the saved png file in Firefox Browser and also in Greenfish Icon Editor (which can display transparent images) but the background was not transparent.

Lainz, which tutorial in particular shows how to toggle between saving the background transparently and opaquely? I was also looking at some code that KodeZwerg helped me with your SuperShapes program (and VisualLab that did transparent regular polygons) but I did not fully understand the transparency when saving to png image. Feel like I need some more guidance (I can save to png, but how to do the transparent background save?)
« Last Edit: July 21, 2023, 06:23:11 am by Boleeman »

lainz

  • Hero Member
  • *****
  • Posts: 4659
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Fractal Tree: How to save picture with a transparent background
« Reply #4 on: July 21, 2023, 05:08:20 pm »
Here is the video that explains it
https://www.youtube.com/watch?v=HGYSLgtYx-U

Basically you create a TBGRABitmap and draw on it using CanvasBGRA methods
« Last Edit: July 21, 2023, 05:13:03 pm by lainz »

Boleeman

  • Hero Member
  • *****
  • Posts: 766
Re: Fractal Tree: How to save picture with a transparent background
« Reply #5 on: July 21, 2023, 05:47:00 pm »
Thankyou Lainz. Much appreciated.

I will watch the video and learn from it.

Been playing around with another (Lsystem) fractals  program and realized it can make some great art.
So I would like to add save to transparent background to that as well. Some samples are shown below but so far I am saving to non transparent png.

« Last Edit: July 21, 2023, 05:54:29 pm by Boleeman »

Boleeman

  • Hero Member
  • *****
  • Posts: 766
Re: Fractal Tree: How to save picture with a transparent background
« Reply #6 on: July 22, 2023, 05:43:48 pm »
Wow Thankyou Lainz for coming to the rescue.

Was getting a bit frustrated. I downloaded the BGRABitmap version of yours and was so impressed. Now I have a better idea of what to do after looking at your "deluxe version" of the fractal tree maker. Just SUPERB.

Thanks Lainz for your great help.
« Last Edit: July 23, 2023, 01:00:20 am by Boleeman »

Boleeman

  • Hero Member
  • *****
  • Posts: 766
Re: Fractal Tree: How to save picture with a transparent background
« Reply #7 on: July 23, 2023, 02:30:45 pm »
Lainz,  now see how CanvasBGRA is specified in the code. That was the bit that was really confusing me before. Now that I see how you implemented it, it makes more sense.


I was looking over the code to the transparent save and noticed that Bitmap.free was not made.
I was under the impression that this needed to be done so as not to cause a memory leak after saving.
I watched that utube video about "How to add antialiasing to your Lazarus project" and saw a bit that had

Bitmap.SaveToFile('graphics.bmp');
Bitmap.Free';

but in the code you did that was not there.

Also in the procedure TForm1.btn_drawtreeClick event PaintBox1.DiscardBitmap(); was made. Is this like an invalidate or refresh?

Lastly is  Bitmap.Fill(Acolor);   used to toggle back to non transparent background?

Once again thanks for providing that code implementation of BGRABitmap for me to learn from. I will now try to work on a few different projects to use the BGRABitmap and transparent background save.


lainz

  • Hero Member
  • *****
  • Posts: 4659
  • Web, Desktop & Android developer
    • https://lainz.github.io/
Re: Fractal Tree: How to save picture with a transparent background
« Reply #8 on: July 23, 2023, 06:01:34 pm »
Quote
Bitmap.SaveToFile('graphics.bmp');
Bitmap.Free';

but in the code you did that was not there.

Is not freed by myself, but within the TBGRAGraphicControl. That control manages the Bitmap.

Quote
Also in the procedure TForm1.btn_drawtreeClick event PaintBox1.DiscardBitmap(); was made. Is this like an invalidate or refresh?

It deletes the current bitmap and creates it again, calling the redraw event.

Quote
Lastly is  Bitmap.Fill(Acolor);   used to toggle back to non transparent background?

That fills the backround with any color, TColor or TBGRAPixel


Boleeman

  • Hero Member
  • *****
  • Posts: 766
Re: Fractal Tree: How to save picture with a transparent background
« Reply #9 on: July 25, 2023, 08:41:28 am »
I was reading about DiscardBitmap() in other threads.

" BGRAGraphicControl and BGRAVirtualScreen both has a resize code that frees the previous drawing and then call OnRedraw event" so now I understand.

I thought possibly that you included BGRAVirtualScreen in the Uses section because DiscardBitmap() was called. When compiling Lazarus sent a message saying that BGRAVirtualScreen was not used.

Thanks once again Lainz for the extra info.

 

TinyPortal © 2005-2018