2
// This unit is part of the GLScene Engine https://github.com/glscene
5
Simple TGA formats supports for Delphi.
6
Currently supports only 24 and 32 bits RGB formats (uncompressed
9
Based on David McDuffee's document from www.wotsit.org
12
07/03/11 - Yar - Removed LazTGA, added workaround of ScanLine for Lazarus
13
20/04/10 - Yar - Removed registration for FPC (thanks to Rustam Asmandiarov aka Predator)
14
07/01/10 - DaStr - TTGAImage is now replaced by LazTGA.TTGAImage
15
in Lazarus (thanks Predator)
16
08/07/04 - LR - Uses of Graphics replaced by GLCrossPlatform for Linux
17
21/11/02 - Egg - Creation
33
{ TGA image load/save capable class for Delphi.
34
TGA formats supported : 24 and 32 bits uncompressed or RLE compressed,
35
saves only to uncompressed TGA. }
36
TTGAImage = class (TGLBitmap)
41
constructor Create; override;
42
destructor Destroy; override;
44
procedure LoadFromStream(stream : TStream); override;
45
procedure SaveToStream(stream : TStream); override;
48
ETGAException = class (Exception)
52
// ------------------------------------------------------------------
53
// ------------------------------------------------------------------
54
// ------------------------------------------------------------------
56
// ------------------------------------------------------------------
57
// ------------------------------------------------------------------
58
// ------------------------------------------------------------------
61
GLGraphics,GraphType, LCLType ;
67
TTGAHeader = packed record
71
ColorMapOrigin : Word;
72
ColorMapLength : Word;
73
ColorMapEntrySize : Byte;
79
ImageDescriptor : Byte;
82
// ReadAndUnPackRLETGA24
84
procedure ReadAndUnPackRLETGA24(stream : TStream; destBuf : PAnsiChar; totalSize : Integer);
86
TRGB24 = packed record
96
bufEnd:=@destBuf[totalSize];
97
while destBuf<bufEnd do
103
stream.Read(color, 3);
107
PRGB24(destBuf)^:=color;
114
n:=((b and 127)+1)*3;
115
stream.Read(destBuf^, n);
121
// ReadAndUnPackRLETGA32
123
procedure ReadAndUnPackRLETGA32(stream : TStream; destBuf : PAnsiChar; totalSize : Integer);
125
TRGB32 = packed record
135
bufEnd:=@destBuf[totalSize];
136
while destBuf<bufEnd do
142
stream.Read(color, 4);
146
PRGB32(destBuf)^:=color;
153
n:=((b and 127)+1)*4;
154
stream.Read(destBuf^, n);
161
// ------------------ TTGAImage ------------------
166
constructor TTGAImage.Create;
173
destructor TTGAImage.Destroy;
180
procedure TTGAImage.LoadFromStream(stream : TStream);
183
y, rowSize, bufSize : Integer;
184
verticalFlip : Boolean;
185
unpackBuf : PAnsiChar;
190
function GetLineAddress(ALine: Integer): PByte;
192
Result := PByte(@PGLPixel32Array(rimg.Data)[ALine*Width]);
196
stream.Read(header, Sizeof(TTGAHeader));
198
if header.ColorMapType<>0 then
199
raise ETGAException.Create('ColorMapped TGA unsupported');
201
case header.PixelSize of
202
24 : PixelFormat:=glpf24bit;
203
32 : PixelFormat:=glpf32bit;
205
raise ETGAException.Create('Unsupported TGA ImageType');
209
Height:=header.Height;
210
rowSize:=(Width*header.PixelSize) div 8;
211
verticalFlip:=((header.ImageDescriptor and $20)=0);
212
if header.IDLength>0 then
213
stream.Seek(header.IDLength, soFromCurrent);
218
rimg.Description.Init_BPP32_B8G8R8A8_BIO_TTB(Width, Height);
219
rimg.Description.RedShift := 16;
220
rimg.Description.BlueShift := 0;
222
rimg.Description.LineOrder := riloTopToBottom
224
rimg.Description.LineOrder := riloBottomToTop;
225
RIMG.DataSize := Width * Height * 4;
226
GetMem(rimg.Data, RIMG.DataSize);
230
case header.ImageType of
231
0 : begin // empty image, support is useless but easy ;)
236
2 : begin // uncompressed RGB/RGBA
237
if verticalFlip then begin
238
for y:=0 to Height-1 do
239
stream.Read(GetLineAddress(Height-y-1)^, rowSize);
241
for y:=0 to Height-1 do
242
stream.Read(GetLineAddress(y)^, rowSize);
245
10 : begin // RLE encoded RGB/RGBA
246
bufSize:=Height*rowSize;
247
unpackBuf:=GetMemory(bufSize);
249
// read & unpack everything
250
if header.PixelSize=24 then
251
ReadAndUnPackRLETGA24(stream, unpackBuf, bufSize)
252
else ReadAndUnPackRLETGA32(stream, unpackBuf, bufSize);
254
if verticalFlip then begin
255
for y:=0 to Height-1 do begin
256
Move(unPackBuf[y*rowSize], GetLineAddress(Height-y-1)^, rowSize);
259
for y:=0 to Height-1 do
260
Move(unPackBuf[y*rowSize], GetLineAddress(y)^, rowSize);
263
FreeMemory(unpackBuf);
267
raise ETGAException.Create('Unsupported TGA ImageType '+IntToStr(header.ImageType));
271
LoadFromRawImage(rimg, False);
282
procedure TTGAImage.SaveToStream(stream : TStream);
286
// prepare the header, essentially made up from zeroes
287
FillChar(header, SizeOf(TTGAHeader), 0);
290
header.Height:=Height;
292
header.PixelSize:=32;
293
stream.Write(header, SizeOf(TTGAHeader));
294
stream.Write(RawImage.Data^, Width*Height*4);
298
// ------------------------------------------------------------------
299
// ------------------------------------------------------------------
300
// ------------------------------------------------------------------
303
// ------------------------------------------------------------------
304
// ------------------------------------------------------------------
305
// ------------------------------------------------------------------
306
TGLPicture.RegisterFileFormat('tga', 'Targa', TTGAImage);
310
TGLPicture.UnregisterGraphicClass(TTGAImage);