Recent

Author Topic: [SOLVED] Create and save PNG  (Read 3713 times)

tk

  • Sr. Member
  • ****
  • Posts: 367
[SOLVED] Create and save PNG
« on: December 30, 2016, 12:53:20 pm »
Hi, I would like to create a new PNG image, modify its pixels and save it. I adapted code from following example (http://wiki.lazarus.freepascal.org/Developing_with_Graphics#Drawing_text_with_sharp_edges_.28non_antialiased.29) but it does not work properly, alpha channel is not respected:

Code: Pascal  [Select][+][-]
  1. uses
  2.   IntfGraphics, FPImage;
  3.  
  4. { TForm1 }
  5.  
  6. procedure TForm1.Button1Click(Sender: TObject);
  7. var
  8.   I, J, W, H: Integer;
  9.   FC: TFPColor;
  10.   IM: TLazIntfImage;
  11.   Png: TPortableNetworkGraphic;
  12. begin
  13.   W := 32;
  14.   H := 32;
  15.   Png := TPortableNetworkGraphic.Create;
  16.   try
  17.     Png.SetSize(W, H);
  18.     IM := Png.CreateIntfImage;
  19.     try
  20.       for I := 0 to W - 1 do
  21.       begin
  22.         for J := 0 to H - 1 do
  23.         begin
  24.           FC.red := (128 + I) shl 8;
  25.           FC.green := (128 + J) shl 8;
  26.           FC.blue := 128 shl 8;
  27.           FC.alpha := 128 shl 8; // no matter what value here, always get full opacity
  28.           IM.Colors[I, J] := FC;
  29.         end;
  30.       end;
  31.       Png.LoadFromIntfImage(IM);
  32.     finally
  33.       IM.Free;
  34.     end;
  35.     Png.SaveToFile('test.png');
  36.   finally
  37.     Png.Free;
  38.   end;
  39. end;

Bug?
« Last Edit: December 30, 2016, 02:49:32 pm by tk »

derek.john.evans

  • Guest
Re: Create and save PNG
« Reply #1 on: December 30, 2016, 02:05:50 pm »
TPortableNetworkGraphic.CreateIntfImage doesn't create an image that supports alpha. It also loads the PNG into the image, which isn't required if you are creating a new image.

Also, you dont need TPortableNetworkGraphic, since TLazIntfImage will load/save png/jpeg/etc.

So, try this:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   X, Y: integer;
  4.   LColor: TFPColor;
  5.   LImage: TLazIntfImage;
  6. begin
  7.   LImage := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);
  8.   try
  9.     LImage.SetSize(32, 32);
  10.     for X := 0 to LImage.Width - 1 do begin
  11.       for Y := 0 to LImage.Height - 1 do begin
  12.         LColor.red := (128 + X) shl 8;
  13.         LColor.green := (128 + Y) shl 8;
  14.         LColor.blue := 128 shl 8;
  15.         LColor.alpha := 200 shl 8; // no matter what value here, always get full opacity
  16.         LImage.Colors[X, Y] := LColor;
  17.       end;
  18.     end;
  19.     LImage.SaveToFile('test.png');
  20.   finally
  21.     LImage.Free;
  22.   end;
  23. end;  
  24.  

NOTE: There does seem to be a bug in TLazIntfImage which I've know about for a while. You cant provide a width/height via the constructor.

Hence the additional SetSize() command.

derek.john.evans

  • Guest
Re: Create and save PNG
« Reply #2 on: December 30, 2016, 02:12:40 pm »
O, bugger. You do need TPortableNetworkGraphic. TLazIntfImage.SaveToFile() doesn't save the alpha.

So, yes, you also need todo:
Code: Pascal  [Select][+][-]
  1.     with TPortableNetworkGraphic.Create do begin
  2.       try
  3.         LoadFromIntfImage(LImage);
  4.         SaveToFile('test.png');
  5.       finally
  6.         Free;
  7.       end;
  8.     end;  
  9.  

tk

  • Sr. Member
  • ****
  • Posts: 367
Re: Create and save PNG
« Reply #3 on: December 30, 2016, 02:49:18 pm »
Hi Geepster, thank you, it works now.

Summarized to my example:

Code: Pascal  [Select][+][-]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   I, J, W, H: Integer;
  4.   FC: TFPColor;
  5.   IM: TLazIntfImage;
  6.   Png: TPortableNetworkGraphic;
  7. begin
  8.   W := 32;
  9.   H := 32;
  10.   Png := TPortableNetworkGraphic.Create;
  11.   try
  12.     IM := TLazIntfImage.Create(0, 0, [riqfRGB, riqfAlpha]);
  13.     try
  14.       IM.SetSize(W, H);
  15.       for I := 0 to W - 1 do
  16.       begin
  17.         for J := 0 to H - 1 do
  18.         begin
  19.           FC.red := (128 + I) shl 8;
  20.           FC.green := (128 + J) shl 8;
  21.           FC.blue := 128 shl 8;
  22.           FC.alpha := 128 shl 8; // now works fine
  23.           IM.Colors[I, J] := FC;
  24.         end;
  25.       end;
  26.       Png.LoadFromIntfImage(IM);
  27.     finally
  28.       IM.Free;
  29.     end;
  30.     Png.SaveToFile('test.png');
  31.   finally
  32.     Png.Free;
  33.   end;
  34. end;
  35.  

 

TinyPortal © 2005-2018