* Fix by Laurent Jacques to read all formats

git-svn-id: trunk@9317 -
This commit is contained in:
michael 2007-11-22 18:14:44 +00:00
parent b0770c35ef
commit aa7f70fc5e

View File

@ -14,6 +14,8 @@
} }
{*****************************************************************************} {*****************************************************************************}
{ - 22/11/2007 Modified by Laurent Jacques for support all format }
{$mode objfpc} {$mode objfpc}
{$h+} {$h+}
@ -23,12 +25,22 @@ interface
uses FPImage, classes, sysutils, targacmn; uses FPImage, classes, sysutils, targacmn;
const
TARGA_EMPTY_IMAGE = 0;
TARGA_INDEXED_IMAGE = 1;
TARGA_TRUECOLOR_IMAGE = 2;
TARGA_GRAY_IMAGE = 3;
type type
{ TFPReaderTarga }
TFPReaderTarga = class (TFPCustomImageReader) TFPReaderTarga = class (TFPCustomImageReader)
Private Private
Procedure FreeBuffers; // Free (and nil) buffers. Procedure FreeBuffers; // Free (and nil) buffers.
protected protected
Header : TTargaHeader; Header : TTargaHeader;
AlphaBits : Byte;
Identification : ShortString; Identification : ShortString;
Compressed, Compressed,
BottomUp : Boolean; BottomUp : Boolean;
@ -42,6 +54,7 @@ type
FLastPixel : Packed Array[0..3] of byte; FLastPixel : Packed Array[0..3] of byte;
// AnalyzeHeader will allocate the needed buffers. // AnalyzeHeader will allocate the needed buffers.
Procedure AnalyzeHeader(Img : TFPCustomImage); Procedure AnalyzeHeader(Img : TFPCustomImage);
procedure CreateGrayPalette;
Procedure ReadPalette(Stream : TStream); Procedure ReadPalette(Stream : TStream);
procedure ReadScanLine(Row : Integer; Stream : TStream); virtual; procedure ReadScanLine(Row : Integer; Stream : TStream); virtual;
procedure WriteScanLine(Row : Integer; Img : TFPCustomImage); virtual; procedure WriteScanLine(Row : Integer; Img : TFPCustomImage); virtual;
@ -87,35 +100,21 @@ Procedure TFPReaderTarga.AnalyzeHeader(Img : TFPCustomImage);
begin begin
With Header do With Header do
begin begin
If (Flags shl 6)<>0 then if not (ImgType in [1, 2, 3, 9, 10, 11]) and
Raise Exception.Create('Interlaced targa images not supported.'); not (PixelSize in [8, 16, 24, 32]) then
If MapType>1 then Raise Exception.Create('Unknown/Unsupported Targa image type');
Raise Exception.CreateFmt('Unknown targa colormap type: %d',[MapType]);
if (PixelSize and 7)<>0 then
Raise Exception.Create('Pixelsize must be multiple of 8');
BottomUp:=(Flags and $20) <>0; BottomUp:=(Flags and $20) <>0;
BytesPerPixel:=PixelSize shr 3; AlphaBits := Flags and $0F;
BytesPerPixel:=PixelSize;
Compressed:=ImgType>8; Compressed:=ImgType>8;
If Compressed then If Compressed then
ImgType:=ImgType-8; ImgType:=ImgType-8;
Case ImgType of FLineSize:=(BytesPerPixel div 8)*ToWord(Width);
1: if (BytesPerPixel<>1) or (MapType<>1) then
Raise Exception.Create('Error in targa header: Colormapped image needs 1 byte per pixel and maptype 1');
2: If not (BytesPerPixel in [2..4]) then
Raise Exception.Create('Error in targa header: RGB image needs bytes per pixel between 2 and 4');
3: begin
if BytesPerPixel<>1 then
Raise Exception.Create('Error in targa header: Grayscale image needs 1 byte per pixel.');
end;
else
Raise Exception.CreateFmt('Unknown/Unsupported Targa image type : %d',[ImgType]);
end;
if (ToWord(MapLength)>0) and (MapEntrySize<>24) then
Raise Exception.CreateFmt('Only targa BGR colormaps are supported. Got : %d',[MapEntrySize]);
if (ToWord(MapLength)>0) and (MapType<>0) then
Raise Exception.Create('Empty colormap in Targa image file');
FLineSize:=BytesPerPixel*ToWord(Width);
GetMem(FScanLine,FLineSize); GetMem(FScanLine,FLineSize);
if ImgType = TARGA_GRAY_IMAGE then
FPaletteSize:=SizeOf(TFPColor)*255
else
FPaletteSize:=SizeOf(TFPColor)*ToWord(MapLength); FPaletteSize:=SizeOf(TFPColor)*ToWord(MapLength);
GetMem(FPalette,FPaletteSize); GetMem(FPalette,FPaletteSize);
Img.Width:=ToWord(Width); Img.Width:=ToWord(Width);
@ -123,25 +122,64 @@ begin
end; end;
end; end;
Procedure TFPReaderTarga.CreateGrayPalette;
Var
I : Integer;
Begin
For I:=0 To 255 Do
Begin
With FPalette[I] do
begin
Red:=I*255;
Green:=I*255;
Blue:=I*255;
Alpha:=AlphaOpaque;
end;
end;
End;
Procedure TFPReaderTarga.ReadPalette(Stream : TStream); Procedure TFPReaderTarga.ReadPalette(Stream : TStream);
Var Var
Entry : TBGREntry; BGREntry : TBGREntry;
BGRAEntry : TBGRAEntry;
I : Integer; I : Integer;
begin begin
Case Header.MapEntrySize Of
16, 24:
For I:=0 to ToWord(Header.MapLength)-1 do For I:=0 to ToWord(Header.MapLength)-1 do
begin begin
Stream.ReadBuffer(Entry,SizeOf(Entry)); Stream.ReadBuffer(BGREntry, SizeOf(BGREntry));
With FPalette[i] do With FPalette[I] do
begin begin
Red:=Entry.Red; Red:=BGREntry.Red shl 8;
Green:=Entry.Green; Green:=BGREntry.Green shl 8;
Blue:=Entry.Blue; Blue:=BGREntry.Blue shl 8;
Alpha:=alphaOpaque;
end;
end;
32:
For I:=0 to ToWord(Header.MapLength)-1 do
begin
Stream.ReadBuffer(BGRAEntry,SizeOf(BGRAEntry));
With FPalette[I] do
begin
Red:=BGRAEntry.Red shl 8;
Green:=BGRAEntry.Green shl 8;
Blue:=BGRAEntry.Blue shl 8;
if alphaBits = 8 then
if (BGRAEntry.Alpha and $80) <> 0 then
Alpha:=alphaTransparent
else
Alpha:=AlphaOpaque; Alpha:=AlphaOpaque;
end; end;
end; end;
end; end;
end;
Procedure TFPReaderTarga.InternalRead (Stream:TStream; Img:TFPCustomImage); Procedure TFPReaderTarga.InternalRead (Stream:TStream; Img:TFPCustomImage);
@ -158,8 +196,12 @@ begin
If Length(Identification)<>0 then If Length(Identification)<>0 then
Img.Extra[KeyIdentification]:=Identification; Img.Extra[KeyIdentification]:=Identification;
end; end;
If Toword(Header.MapLength)>0 then
If Header.MapType<>0 then
ReadPalette(Stream); ReadPalette(Stream);
if Header.ImgType = TARGA_GRAY_IMAGE then
CreateGrayPalette;
H:=Img.height; H:=Img.height;
If BottomUp then If BottomUp then
For Row:=0 to H-1 do For Row:=0 to H-1 do
@ -206,9 +248,9 @@ begin
else else
FBlockCount:=B and $7F FBlockCount:=B and $7F
end; end;
Stream.ReadBuffer(FlastPixel,BytesPerPixel); Stream.ReadBuffer(FlastPixel,BytesPerPixel shr 3);
end; end;
For J:=0 to BytesPerPixel-1 do For J:=0 to (BytesPerPixel shr 3)-1 do
begin begin
P[0]:=FLastPixel[j]; P[0]:=FLastPixel[j];
Inc(P); Inc(P);
@ -217,19 +259,10 @@ begin
end; end;
end; end;
const
c5to8bits : array[0..32-1] of Byte =
( 0, 8, 16, 25, 33, 41, 49, 58,
66, 74, 82, 90, 99, 107, 115, 123,
132, 140, 148, 156, 165, 173, 181, 189,
197, 206, 214, 222, 230, 239, 247, 255);
Procedure TFPReaderTarga.WriteScanLine(Row : Integer; Img : TFPCustomImage); Procedure TFPReaderTarga.WriteScanLine(Row : Integer; Img : TFPCustomImage);
Var Var
Col : Integer; Col : Integer;
B : Byte;
C : TFPColor; C : TFPColor;
W : Word; W : Word;
P : PByte; P : PByte;
@ -238,53 +271,65 @@ begin
C.Alpha:=AlphaOpaque; C.Alpha:=AlphaOpaque;
P:=FScanLine; P:=FScanLine;
Case Header.ImgType of Case Header.ImgType of
1 : for Col:=0 to Img.width-1 do TARGA_INDEXED_IMAGE
: for Col:=0 to Img.width-1 do
Img.Colors[Col,Row]:=FPalette[P[Col]]; Img.Colors[Col,Row]:=FPalette[P[Col]];
2 : for Col:=0 to Img.Width-1 do TARGA_TRUECOLOR_IMAGE
: for Col:=0 to Img.Width-1 do
begin begin
// Fill C depending on number of pixels. // Fill C depending on number of pixels.
case BytesPerPixel of case BytesPerPixel of
2 : begin 8,16 : begin
W:=P[0]; W:=P[0];
inc(P); inc(P);
W:=W or (P[0] shl 8); W:=W or (P[0] shl 8);
With C do With C do
begin begin
Blue:=c5to8bits[W and $1F]; Red:=((W)shr 10) shl 11;
W:=W shr 5; Green:=((w)shr 5) shl 11;
Green:=c5to8bits[W and $1F]; Blue:=((w)) shl 11;
W:=W shr 5;
Red:=c5to8bits[W and $1F];
end; end;
end; end;
3,4 : With C do 24,32 : With C do
begin begin
Blue:=P[0] or (P[0] shl 8); Blue:=P[0] or (P[0] shl 8);
Inc(P); Inc(P);
Green:=P[0] or (P[0] shl 8); Green:=P[0] or (P[0] shl 8);
Inc(P); Inc(P);
Red:=P[0] or (P[0] shl 8); Red:=P[0] or (P[0] shl 8);
If bytesPerPixel=4 then If bytesPerPixel=32 then
begin begin
Inc(P); Inc(P);
// Alpha:=P[0] or (P[0] shl 8); what is TARGA Attribute ?? Alpha:=AlphaOpaque;
if alphaBits = 8 then
if (P[0] and $80) = 0 then
Alpha:=alphaTransparent;
end; end;
end; end;
end; // Case BytesPerPixel; end; // Case BytesPerPixel;
Img[Col,Row]:=C; Img[Col,Row]:=C;
Inc(P); Inc(P);
end; end;
3 : For Col:=0 to Img.Width-1 do TARGA_GRAY_IMAGE
: case BytesPerPixel of
8 : for Col:=0 to Img.width-1 do
Img.Colors[Col,Row]:=FPalette[P[Col]];
16 : for Col:=0 to Img.width-1 do
begin begin
B:=FScanLine[Col];
B:=B+(B Shl 8);
With C do With C do
begin begin
Red:=B; Blue:=FPalette[P^].blue;
Green:=B; Green:=FPalette[P^].green;
Blue:=B; Red:=FPalette[P^].red;
Inc(P);
Alpha:=AlphaOpaque;
if alphaBits = 8 then
if (P[0] and $80) = 0 then
Alpha:=alphaTransparent;
Inc(P);
end;
Img[Col,Row]:=C;
end; end;
Img.Colors[Col,Row]:=C;
end; end;
end; end;
end; end;