Recent

Author Topic: Convertor PNG to TGA  (Read 861 times)

BIT

  • Full Member
  • ***
  • Posts: 158
Convertor PNG to TGA
« on: December 09, 2023, 11:05:25 am »
Hello, why is the image not being converted correctly?
Code: Pascal  [Select][+][-]
  1. unit ImageConverter;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   LCLIntf, Classes, SysUtils, Graphics;
  9.  
  10. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  11.  
  12. implementation
  13.  
  14. type
  15.   TGAHeader = packed record
  16.     IDLength: byte;
  17.     ColorMapType: byte;
  18.     ImageType: byte;
  19.  
  20.     colorMapIndex: word;
  21.     colorMapLength: word;
  22.     colorMapDepth: byte;
  23.  
  24.     offsetX: word;
  25.     offsetY: word;
  26.     Width: word;
  27.     Height: word;
  28.     pixelDepth: byte;
  29.  
  30.     origin: byte;
  31.   end;
  32.  
  33.  
  34. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  35. var
  36.   PNGImage: TPortableNetworkGraphic;
  37.   TGAFile: file of byte;
  38.   TGAHead: TGAHeader;
  39.   Col: TColor;
  40.   X, Y: integer;
  41.   A, B, G, R: byte;
  42. begin
  43.   PNGImage := TPortableNetworkGraphic.Create;
  44.   try
  45.     PNGImage.LoadFromFile(PNGFileName);
  46.     AssignFile(TGAFile, TGAFileName);
  47.     Rewrite(TGAFile);
  48.  
  49.     FillChar(TGAHead, SizeOf(TGAHead), 0);
  50.     TGAHead.ImageType := 2;
  51.     TGAHead.Width := PNGImage.Width;
  52.     TGAHead.Height := PNGImage.Height;
  53.     TGAHead.pixelDepth := 32;
  54.     BlockWrite(TGAFile, TGAHead, SizeOf(TGAHead));
  55.  
  56.     for Y := PNGImage.Height - 1 downto 0 do
  57.     begin
  58.       for X := 0 to PNGImage.Width - 1 do
  59.       begin
  60.  
  61.         Col := PNGImage.Canvas.Pixels[X, Y];
  62.  
  63.         A := byte(Col);
  64.         B := GetBValue(Col);
  65.         G := GetGValue(Col);
  66.         R := GetRValue(Col);
  67.  
  68.         BlockWrite(TGAFile, B, SizeOf(byte));
  69.         BlockWrite(TGAFile, G, SizeOf(byte));
  70.         BlockWrite(TGAFile, R, SizeOf(byte));
  71.         BlockWrite(TGAFile, A, SizeOf(byte));
  72.       end;
  73.     end;
  74.  
  75.   finally
  76.     PNGImage.Free;
  77.     CloseFile(TGAFile);
  78.   end;
  79. end;
  80.  
  81.  
  82. end.

Use
Code: Pascal  [Select][+][-]
  1.  
  2. ImageConverter.ConvertToTGA('original.png', 'output.tga');  
  3.  

images:
1: original PNG
2: output TGA

circular

  • Hero Member
  • *****
  • Posts: 4124
    • Personal webpage
Re: Convertor PNG to TGA
« Reply #1 on: December 09, 2023, 11:26:41 am »
The A value is not retrieved correctly.

The Pixels property returns a TColor so in principle it doesn't contain the alpha value. Instead you could try the Colors property that returns an TFPColor. The channels are stored as Word values so one need to shift them (shr 8) to get the byte value.

Conscience is the debugger of the mind

BIT

  • Full Member
  • ***
  • Posts: 158
Re: Convertor PNG to TGA
« Reply #2 on: December 09, 2023, 11:42:25 am »
The A value is not retrieved correctly.

The Pixels property returns a TColor so in principle it doesn't contain the alpha value. Instead you could try the Colors property that returns an TFPColor. The channels are stored as Word values so one need to shift them (shr 8) to get the byte value.
Can I have a complete example? Otherwise I don't understand how to do it)

circular

  • Hero Member
  • *****
  • Posts: 4124
    • Personal webpage
Re: Convertor PNG to TGA
« Reply #3 on: December 09, 2023, 01:47:12 pm »
I imagine it would be something like:
Code: Pascal  [Select][+][-]
  1. var Col: TFPColor;
  2. ...
  3.         Col := PNGImage.Canvas.Colors[X, Y];
  4.  
  5.         A := Col.alpha shr 8;
  6.         B := Col.blue shr 8;
  7.         G := Col.green shr 8;
  8.         R := Col.red shr 8;
Conscience is the debugger of the mind

BIT

  • Full Member
  • ***
  • Posts: 158
Re: Convertor PNG to TGA
« Reply #4 on: December 09, 2023, 02:03:06 pm »
I imagine it would be something like:
Code: Pascal  [Select][+][-]
  1. var Col: TFPColor;
  2. ...
  3.         Col := PNGImage.Canvas.Colors[X, Y];
  4.  
  5.         A := Col.alpha shr 8;
  6.         B := Col.blue shr 8;
  7.         G := Col.green shr 8;
  8.         R := Col.red shr 8;

it didn't help((

circular

  • Hero Member
  • *****
  • Posts: 4124
    • Personal webpage
Re: Convertor PNG to TGA
« Reply #5 on: December 09, 2023, 02:36:50 pm »
The LCL sometimes doesn't handle alpha channel.

You can instead use BGRABitmap package.

Code: Pascal  [Select][+][-]
  1. uses BGRABitmap;
  2.  
  3. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  4. var bmp: TBGRABitmap;
  5. begin
  6.   bmp.LoadFromFile(PNGFileName);
  7.   bmp.SaveToFile(TGAFileName); // TGA is already implemented
  8.   // or you can access bmp.Colors property
  9. end;
Conscience is the debugger of the mind

BIT

  • Full Member
  • ***
  • Posts: 158
Re: Convertor PNG to TGA
« Reply #6 on: December 09, 2023, 02:54:06 pm »
The LCL sometimes doesn't handle alpha channel.

You can instead use BGRABitmap package.

Code: Pascal  [Select][+][-]
  1. uses BGRABitmap;
  2.  
  3. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  4. var bmp: TBGRABitmap;
  5. begin
  6.   bmp.LoadFromFile(PNGFileName);
  7.   bmp.SaveToFile(TGAFileName); // TGA is already implemented
  8.   // or you can access bmp.Colors property
  9. end;
I've tried all the libraries, they don't suit me, the maximum suitable tga format for my purposes is the code in the first post.
But there's a problem with transparency, I don't know how to solve it((

AlexTP

  • Hero Member
  • *****
  • Posts: 2353
    • UVviewsoft
Re: Convertor PNG to TGA
« Reply #7 on: December 09, 2023, 03:02:41 pm »
If there is smthing that BGRABitmap does wrong with TGA, you can post the bugreport (with the full demo project) to the GitHub
https://github.com/bgrabitmap/bgrabitmap/issues

circular

  • Hero Member
  • *****
  • Posts: 4124
    • Personal webpage
Re: Convertor PNG to TGA
« Reply #8 on: December 09, 2023, 03:28:04 pm »
Well @BIT, as indicated in my commentary, there is also a Colors property in TBGRABitmap. So your example can be adapted like this:
Code: Pascal  [Select][+][-]
  1. unit ImageConverter;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, BGRABitmap, FPImage;
  9.  
  10. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  11.  
  12. implementation
  13.  
  14. type
  15.   TGAHeader = packed record
  16.     IDLength: byte;
  17.     ColorMapType: byte;
  18.     ImageType: byte;
  19.  
  20.     colorMapIndex: word;
  21.     colorMapLength: word;
  22.     colorMapDepth: byte;
  23.  
  24.     offsetX: word;
  25.     offsetY: word;
  26.     Width: word;
  27.     Height: word;
  28.     pixelDepth: byte;
  29.  
  30.     origin: byte;
  31.   end;
  32.  
  33.  
  34. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  35. var
  36.   PNGImage: TBGRABitmap;
  37.   TGAFile: file of byte;
  38.   TGAHead: TGAHeader;
  39.   Col: TFPColor;
  40.   X, Y: integer;
  41.   A, B, G, R: byte;
  42. begin
  43.   PNGImage := TBGRABitmap.Create(PNGFileName);
  44.   AssignFile(TGAFile, TGAFileName);
  45.   Rewrite(TGAFile);
  46.   try
  47.     FillChar(TGAHead, SizeOf(TGAHead), 0);
  48.     TGAHead.ImageType := 2;
  49.     TGAHead.Width := PNGImage.Width;
  50.     TGAHead.Height := PNGImage.Height;
  51.     TGAHead.pixelDepth := 32;
  52.     BlockWrite(TGAFile, TGAHead, SizeOf(TGAHead));
  53.  
  54.     for Y := PNGImage.Height - 1 downto 0 do
  55.     begin
  56.       for X := 0 to PNGImage.Width - 1 do
  57.       begin
  58.  
  59.         Col := PNGImage.Colors[X, Y];
  60.  
  61.         A := Col.alpha shr 8;
  62.         B := Col.blue shr 8;
  63.         G := Col.green shr 8;
  64.         R := Col.red shr 8;
  65.  
  66.         BlockWrite(TGAFile, B, SizeOf(byte));
  67.         BlockWrite(TGAFile, G, SizeOf(byte));
  68.         BlockWrite(TGAFile, R, SizeOf(byte));
  69.         BlockWrite(TGAFile, A, SizeOf(byte));
  70.       end;
  71.     end;
  72.  
  73.   finally
  74.     PNGImage.Free;
  75.     CloseFile(TGAFile);
  76.   end;
  77. end;
  78.  
  79. end.
Conscience is the debugger of the mind

BIT

  • Full Member
  • ***
  • Posts: 158
Re: Convertor PNG to TGA
« Reply #9 on: December 09, 2023, 03:45:34 pm »
Well @BIT, as indicated in my commentary, there is also a Colors property in TBGRABitmap. So your example can be adapted like this:
Code: Pascal  [Select][+][-]
  1. unit ImageConverter;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.  Classes, SysUtils, BGRABitmap, FPImage;
  9.  
  10. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  11.  
  12. implementation
  13.  
  14. type
  15.   TGAHeader = packed record
  16.     IDLength: byte;
  17.     ColorMapType: byte;
  18.     ImageType: byte;
  19.  
  20.     colorMapIndex: word;
  21.     colorMapLength: word;
  22.     colorMapDepth: byte;
  23.  
  24.     offsetX: word;
  25.     offsetY: word;
  26.     Width: word;
  27.     Height: word;
  28.     pixelDepth: byte;
  29.  
  30.     origin: byte;
  31.   end;
  32.  
  33.  
  34. procedure ConvertToTGA(const PNGFileName: string; TGAFileName: string);
  35. var
  36.   PNGImage: TBGRABitmap;
  37.   TGAFile: file of byte;
  38.   TGAHead: TGAHeader;
  39.   Col: TFPColor;
  40.   X, Y: integer;
  41.   A, B, G, R: byte;
  42. begin
  43.   PNGImage := TBGRABitmap.Create(PNGFileName);
  44.   AssignFile(TGAFile, TGAFileName);
  45.   Rewrite(TGAFile);
  46.   try
  47.     FillChar(TGAHead, SizeOf(TGAHead), 0);
  48.     TGAHead.ImageType := 2;
  49.     TGAHead.Width := PNGImage.Width;
  50.     TGAHead.Height := PNGImage.Height;
  51.     TGAHead.pixelDepth := 32;
  52.     BlockWrite(TGAFile, TGAHead, SizeOf(TGAHead));
  53.  
  54.     for Y := PNGImage.Height - 1 downto 0 do
  55.     begin
  56.       for X := 0 to PNGImage.Width - 1 do
  57.       begin
  58.  
  59.         Col := PNGImage.Colors[X, Y];
  60.  
  61.         A := Col.alpha shr 8;
  62.         B := Col.blue shr 8;
  63.         G := Col.green shr 8;
  64.         R := Col.red shr 8;
  65.  
  66.         BlockWrite(TGAFile, B, SizeOf(byte));
  67.         BlockWrite(TGAFile, G, SizeOf(byte));
  68.         BlockWrite(TGAFile, R, SizeOf(byte));
  69.         BlockWrite(TGAFile, A, SizeOf(byte));
  70.       end;
  71.     end;
  72.  
  73.   finally
  74.     PNGImage.Free;
  75.     CloseFile(TGAFile);
  76.   end;
  77. end;
  78.  
  79. end.

Thank you this code is working!
Now the tga file is loaded into the UnrealEd editor

 

TinyPortal © 2005-2018