### Bookstore

 Computer Math and Games in Pascal (preview) Lazarus Handbook

### Author Topic: Solved: Porting efg2 Snowflake Curve Drawer  (Read 6241 times)

#### Boleeman

• Hero Member
• Posts: 647
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #15 on: August 06, 2023, 01:48:36 am »
The two efg fractal programs were created by Earl F. Glynn, who I believe created the beautiful Glynn Fractal. Wow, what a really talented guy.

I WAS THINKING for the KOCH SNOWFLAKE:

I would also like to add a feature to try to set the transparent color using a TShape and to toggle transparent save of the image when saving to bmp or png by using a checkbox. Is this possible without using BGRABitmap?

Attached is a screenshot of what I was thinking of.

I know that Bitmap.PixelFormat := pf24bit;  would have to be changed to Bitmap.PixelFormat := pf32bit; to accomodate the alpha but after that I am lost. I saw a thread that gave an example of how to make a transparent grid but I seemed to have not really understood that code.

Any thoughts on how to do it?

I was also looking at the stats. for the board
Users Online
Users: 7
Guests: 421
Total: 428

Wow that's a lot of guests
« Last Edit: August 06, 2023, 01:59:03 am by Boleeman »

#### wp

• Hero Member
• Posts: 12294
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #16 on: August 06, 2023, 12:44:03 pm »
The easiest way to get a transparent image is to set the Transparent property of the image to true and to define a color in the bitmap to be transparent. You probably want the background color to be transparent which is clSilver in your code.

Code: Pascal  [Select][+][-]
1.         Bitmap := TBitmap.Create;
2.         TRY
3.           Bitmap.Width  := ImageVonKoch.Width;
4.           Bitmap.Height := ImageVonKoch.Height;
5.           Bitmap.PixelFormat := pf24bit;
6.           Bitmap.Canvas.Brush.Color := clSilver;
7.           Bitmap.Canvas.FillRect(0, 0, Bitmap.Width, Bitmap.Height);
8.           Bitmap.TransparentColor := clSilver;  // <---- ADDED
9. ...

The next question probably is that you maybe want to fill the interior of the snow-flake with some color. If your Pantograph would draw the shape by the Canvas.Polygon command you simply could apply the Canvas.Brush to fill the interior. However, the Pantograph draws the shape as a series of line strokes where Canvas.Brush is not usable. You are left with the Canvas.FloodFill procedure that you already have in your code. But since you want to fill the interior of the shape you must modify it to start at a point somewhere inside the shape, for example at its center (Bitmap.Width div 2, Bitmap.Height div 2):
Code: Pascal  [Select][+][-]
1.             IF   SpinEditNgon.Value > 2
2.             THEN BEGIN
3.               Bitmap.Canvas.Brush.Color := clSkyBlue;
4.               Bitmap.Canvas.FloodFill(Bitmap.Width div 2, Bitmap.Height div 2, ShapePenColor.Brush.Color, fsBorder);
5.               // or
6.               // Bitmap.Canvas.FloodFill(Bitmap.Width div 2, Bitmap.Height div 2, clSilver, fsSurface);
7.             END;

Do not forget to update the other locations for this in your code: where the bitmap is saved to disk, and where the printer output is generated. For the latter case, you will notice that the FloodFill is not working - read http://www.delphigroups.info/2/65/212514.html about this issue. To fix this you could draw to an intermediate bitmap which you copy to the printer (as suggested in that reference), or you could rewrite the pantograph to draw the shape as a polygon. In this case you could even skip the entire FloodFill procedure which is often commented to be rather slow.
« Last Edit: August 06, 2023, 12:47:30 pm by wp »

#### Boleeman

• Hero Member
• Posts: 647
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #17 on: August 06, 2023, 11:15:09 pm »
Thanks once again WP.

I have worked through some of your suggestions for transparency.

Still working on the printing part.

Just a couple of short questions:

How come Bitmap.PixelFormat := pf24bit; is used and not Bitmap.PixelFormat := pf32bit;  ?

I tried a pf32bit format and got a 1025 kB sized BMP and with pf24bit format and got a 769 kB sized BMP
When I viewed both bitmaps in Greenfish Icon Editor which is able to view transparent images I did see the background gray color as opaque and not transparent.

I was able to remove the opaque background of the 32 bit BMP and save to PNG in Irfanview.

Many thanks once again WP for your great help and suggestions.
« Last Edit: August 07, 2023, 09:30:22 am by Boleeman »

#### wp

• Hero Member
• Posts: 12294
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #18 on: August 07, 2023, 10:14:57 am »
There are two kinds of transparency:
• Color transparency, the kind we were talking about so far: one specific color is defined as "transparent color"; only the pixels with a different color are painted.
• Alpha-channel transparency: Each pixel contains information for red, green and blue, but also for its transparency. These are 4 bytes again, like in TColor. BUT: TColor uses the 4th byte for system colors and thus is not available for the alpha channel. Therefore, the LCL canvas cannot handle alpha-channel transparency...
Fortunately, the FCL provides another graphics library, fcl-image, in which a color (type TFPColor here) is a record of 16-bit Red, Green, Blue and Alpha elements. The Lazarus unit IntfGraphics, in addition, provides TLazIntfImage which is a descendant of the basic fcl-image class, TFPCustomImage, but can also understand LCL bitmaps. Utilizing this, we can then iterate over all pixels in the image and replace those pixels with RGB equal to the RGB of the transparent color by pixels for which the Alpha channel is fully transparent (alphaTransparent, in the terms of fcl-image).

The next obstacle is saving to file. To be honest I do not know of a way how to save an alpha-channel transparent image as bmp file - I am always losing the alpha channel. But the png format, on the other hand, is well-prepared for an alpha-channel, and it even provides some good amount of compression. fcl-image can find the needed writer unit from the extension of the destination file, but for keeping the alpha channel we must set the writer's UseAlpha property to true. Therefore, we must create the writer explicitely to get access to this property.

In total, the following procedure should do everything needed to save a color-transparent bitmap to an alpha-channel transparent png image file:

Code: Pascal  [Select][+][-]
1. uses
2.     fpImage,              // TFPColor
3.     fpWritePNG,           // PNG writer
4.     IntfGraphics,         // TLazIntfImage
5.     ...;
6.
7. procedure SaveBitmapAsTransparentPNG(ABitmap: TBitmap; AFileName: String);
8. var
9.   img: TLazIntfImage;
10.   pixColor: TFPColor;
11.   transpColor: TFPColor;
12.   writerPNG: TFPWriterPNG;
13.   x, y: Integer;
14. begin
15.   // Determine the transparent color of the TBitmap.
16.   // Note: Use TColorToFPColor to convert an LCL TColor value to an fcl-image TFPColor
17.   if ABitmap.TransparentMode = tmFixed then
18.     transpColor := TColorToFPColor(ABitmap.TransparentColor)
19.   else
20.     transpColor := TColorToFPColor(ABitmap.Canvas.Pixels[0, 0]);
21.
22.   // Create a TLazIntfImage from the bitmap
23.   img := ABitmap.CreateIntfImage;
24.   try
25.     // Iterate over all pixels, find the pixels with the transparent color
26.     // and replace them by a FPColor with alpha=0
27.     for y := 0 to img.Height - 1 do
28.       for x := 0 to img.Width - 1 do
29.       begin
30.         // Read the FPColor of the pixel at x,y.
31.         pixColor := img.Colors[x, y];
32.         // ... set its Alpha value
33.         if (pixColor.Red = transpColor.Red) and
34.            (pixColor.Green = transpColor.Green) and
35.            (pixColor.Blue = transpColor.Blue)
36.         then
37.           pixColor.Alpha := alphaTransparent
38.         else
39.           pixColor.Alpha := alphaOpaque;
40.         // ... and write the modified pixel back into the LazIntfImage.
41.         img.Colors[x, y] := pixColor;
42.       end;
43.
44.     // Create a writer class for the PNG format
45.     writerPNG := TFPWriterPNG.Create;
46.     try
47.       // Activate alpha channel in the file output
48.       writerPNG.UseAlpha := true;
49.       // Save LazIntfImage to file.
50.       img.SaveToFile(AFileName, writerPNG);
51.     finally
52.       writerPNG.Free;
53.     end;
54.   finally
55.     img.Free;
56.   end;
57. end;

Important note: The pixel format of the LazIntfImage corresponds to that of the bitmap calling CreateIntfImage. Therefore, the TBitmap passed to this procedure must have been created with PixelFormat pf32Bit. Otherwise the LazIntfImage will not be constructed with an alpha channel.

Code: Pascal  [Select][+][-]
1. procedure TFormVonKoch.ButtonVonKochFileClick(Sender: TObject);
2. VAR
3.   Bitmap:  TBitmap;
4.   Curve :  TVonKochCurve;
5. BEGIN
6.   IF   SavePictureDialog.Execute
7.   THEN BEGIN
8.     Screen.Cursor := crHourGlass;
9.     TRY
10.       Bitmap := TBitmap.Create;
11.       TRY
12.         Bitmap.Width  := SpinEditKochSize.Value;
13.         Bitmap.Height := SpinEditKochSize.Value;
14.         Bitmap.PixelFormat := pf32bit;  // IMPORTANT!
15.
16.         Bitmap.canvas.Brush.Color := clWhite;
17.         Bitmap.Canvas.FillRect(0, 0, Bitmap.Width, Bitmap.Height);
18.
19.         {
20.         Place the drawing code here...
21.         }
22.
23.         SaveBitmapAsTransparentPNG(Bitmap, SavePictureDialog.FileName);
24.       FINALLY
25.         Bitmap.Free
26.       END
27.     FINALLY
28.       Screen.Cursor := crDefault
29.     END
30.   END
31. end;
« Last Edit: August 07, 2023, 10:39:58 am by wp »

#### Boleeman

• Hero Member
• Posts: 647
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #19 on: August 08, 2023, 02:10:50 pm »

I am so happy with the result. Fantastic. Just amazing. Superb.
Did a few tests to see if it was working to save fractal to a png with a transparent background.
Also imported the png images into Word and saved as a pdf and tried filling in the transparent imaage manually using Paint3D and Greenfish Icon  Editor (Paint3D filled the inside to the border correctly but Greenfish Icon  Editor filled the whole image to it's dimensions)

I like the way you had explained things.

I wanted to also make concentric snowflake curves (as shown in the pdf), where one picks the outer size and an offset gap and a repeat setting. AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with. There were also some examples of other AGGPAS examples converted to BGRABmp. Just love playing around with that graphics code and seeing some really cool effects.

Once again WP thank you for all the help and advice that you have provided.

Image transparency was confusing me. Now I see the difference between Color transparency and Alpha-channel transparency. I had previously come across some code that loads an image and then you pick the transparent color, but it had some sort of commandline form of BGRABmp which I could not get to work. Anyhow I am so happy with your latest PNG Alpha-channel transparency code.

« Last Edit: August 08, 2023, 02:43:49 pm by Boleeman »

#### wp

• Hero Member
• Posts: 12294
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #20 on: August 08, 2023, 04:00:18 pm »
AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with.
Had? AggPas still exists, and it even comes with Lazarus. It is in folder "components/aggpas" of your Lazarus installation, and ready to be used (i.e. no package installation required). The folder is stuffed with lots of examples, however, prepared for dephi. For running them with Lazarus, you should rename the extension of the project file from .dpr to .lpr, add {\$MODE Delphi} to the top of the project file, and add the path mentioned in the header to the "Other unit files" path in the project options, and "src" to the "include files" path.

#### lainz

• Hero Member
• Posts: 4591
• Web, Desktop & Android developer
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #21 on: August 08, 2023, 05:43:31 pm »
AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with.
Had? AggPas still exists, and it even comes with Lazarus. It is in folder "components/aggpas" of your Lazarus installation, and ready to be used (i.e. no package installation required). The folder is stuffed with lots of examples, however, prepared for dephi. For running them with Lazarus, you should rename the extension of the project file from .dpr to .lpr, add {\$MODE Delphi} to the top of the project file, and add the path mentioned in the header to the "Other unit files" path in the project options, and "src" to the "include files" path.

Why? Why don't ship lazarus projects since this is lazarus?

#### wp

• Hero Member
• Posts: 12294
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #22 on: August 08, 2023, 06:11:31 pm »
AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with.
Had? AggPas still exists, and it even comes with Lazarus. It is in folder "components/aggpas" of your Lazarus installation, and ready to be used (i.e. no package installation required). The folder is stuffed with lots of examples, however, prepared for dephi. For running them with Lazarus, you should rename the extension of the project file from .dpr to .lpr, add {\$MODE Delphi} to the top of the project file, and add the path mentioned in the header to the "Other unit files" path in the project options, and "src" to the "include files" path.

Why? Why don't ship lazarus projects since this is lazarus?
Yes, why? Don't ask me, I think it's been like this already when I first began using Lazarus... This folder always has been kind of scary to me until I recently checked out the demos and noticed the power of this library. Well, maybe I should take the time and restructure the folder and add ready-to use Lazarus examples...
« Last Edit: August 08, 2023, 06:57:28 pm by wp »

#### dsiders

• Hero Member
• Posts: 1213
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #23 on: August 08, 2023, 09:29:43 pm »
AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with.
Had? AggPas still exists, and it even comes with Lazarus. It is in folder "components/aggpas" of your Lazarus installation, and ready to be used (i.e. no package installation required). The folder is stuffed with lots of examples, however, prepared for dephi. For running them with Lazarus, you should rename the extension of the project file from .dpr to .lpr, add {\$MODE Delphi} to the top of the project file, and add the path mentioned in the header to the "Other unit files" path in the project options, and "src" to the "include files" path.

Why? Why don't ship lazarus projects since this is lazarus?

So, you're volunteering to be the maintainer?
Preview Lazarus 3.99 documentation at: https://dsiders.gitlab.io/lazdocsnext

#### lainz

• Hero Member
• Posts: 4591
• Web, Desktop & Android developer
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #24 on: August 08, 2023, 10:21:13 pm »
AGGPAS had an example of creating really colourful contoured  curves which I was really impressed with.
Had? AggPas still exists, and it even comes with Lazarus. It is in folder "components/aggpas" of your Lazarus installation, and ready to be used (i.e. no package installation required). The folder is stuffed with lots of examples, however, prepared for dephi. For running them with Lazarus, you should rename the extension of the project file from .dpr to .lpr, add {\$MODE Delphi} to the top of the project file, and add the path mentioned in the header to the "Other unit files" path in the project options, and "src" to the "include files" path.

Why? Why don't ship lazarus projects since this is lazarus?

So, you're volunteering to be the maintainer?

So, there is no maintainer?

#### wp

• Hero Member
• Posts: 12294
##### Re: Solved: Porting efg2 Snowflake Curve Drawer
« Reply #25 on: August 09, 2023, 01:27:51 am »
So, there is no maintainer?

Not really...

Converted a good part of the sample projects to Lazarus and moved them into separate directories. (Laz/main)

[EDIT]
Done with all.
« Last Edit: August 09, 2023, 02:11:51 pm by wp »