// SPDX-License-Identifier: LGPL-3.0-linking-exception {*****************************************************************************} { The original file is part of the Free Pascal's "Free Components Library". Copyright (c) 2003 by Mazen NEIFER of the Free Pascal development team Targa reader implementation modified by circular. } {*****************************************************************************} { - 22/11/2007 Modified by Laurent Jacques for support all format } {$mode objfpc} {$h+} unit BGRAReadTGA; interface uses FPReadTGA, FPimage, BGRAClasses; type { TBGRAReaderTarga } TBGRAReaderTarga = class (TFPReaderTarga) protected FBuffer: packed array of byte; FBufferPos, FBufferSize: integer; FBufferStream: TStream; procedure ReadScanLine({%H-}Row: Integer; Stream: TStream); override; procedure WriteScanLine(Row : Integer; Img : TFPCustomImage); override; procedure InitReadBuffer(AStream: TStream; ASize: integer); procedure CloseReadBuffer; function GetNextBufferByte: byte; end; Implementation uses BGRABitmapTypes, targacmn; procedure TBGRAReaderTarga.ReadScanLine(Row: Integer; Stream: TStream); Var P : PByte; B : Byte; I,J : Integer; PixelSizeInBytesMinus1: integer; begin If Not Compressed then Stream.ReadBuffer(FScanLine^,FLineSize) else begin InitReadBuffer(Stream, 2048); P:=FScanLine; PixelSizeInBytesMinus1 := (BytesPerPixel shr 3)-1; For I:=0 to ToWord(Header.Width)-1 do begin If (FPixelCount>0) then Dec(FPixelCount) else begin Dec(FBlockCount); If (FBlockCount<0) then begin B := GetNextBufferByte; If (B and $80)<>0 then begin FPixelCount:=B and $7F; FblockCount:=0; end else FBlockCount:=B and $7F end; For J:=0 to PixelSizeInBytesMinus1 do FLastPixel[j] := GetNextBufferByte; end; For J:=0 to PixelSizeInBytesMinus1 do begin P[0]:=FLastPixel[j]; Inc(P); end; end; CloseReadBuffer; end; end; Procedure TBGRAReaderTarga.WriteScanLine(Row : Integer; Img : TFPCustomImage); Var Col : Integer; Value : UInt32or64; P : PByte; PDest: PBGRAPixel; begin P:=FScanLine; PDest := TBGRACustomBitmap(img).ScanLine[Row]; Case Header.ImgType of TARGA_INDEXED_IMAGE : for Col:=Img.width-1 downto 0 do begin PDest^ := FPColorToBGRA(FPalette[P^]); Inc(PDest); Inc(P); end; TARGA_TRUECOLOR_IMAGE : if (BytesPerPixel = 32) and (AlphaBits = 8) then Move(P^,PDest^,Img.Width*sizeof(TBGRAPixel)) else if (BytesPerPixel = 24) then begin for Col:=Img.Width-1 downto 0 do begin PDest^ := BGRA((P+2)^,(P+1)^,P^); inc(Pdest); Inc(p,3); end; end else if (BytesPerPixel in[8,16]) then for Col:= Img.Width-1 to 0 do begin Value:=P[0]; inc(P); Value:=value or (P[0] shl 8); PDest^ := BGRA(((value)shr 10) shl 3,((value)shr 5) shl 3,((value)) shl 3); Inc(PDest); Inc(P); end; TARGA_GRAY_IMAGE : case BytesPerPixel of 8 : for Col:=Img.width-1 downto 0 do begin PDest^ := FPColorToBGRA(FPalette[P^]); Inc(PDest); Inc(P); end; 16 : for Col:=0 to Img.width-1 do begin With PDest^ do begin blue:=FPalette[P^].blue shr 8; green:=FPalette[P^].green shr 8; red:=FPalette[P^].red shr 8; Inc(P); if alphaBits = 8 then alpha := P^ else alpha:=255; Inc(P); end; inc(PDest); end; end; end; end; procedure TBGRAReaderTarga.InitReadBuffer(AStream: TStream; ASize: integer); begin setLength(FBuffer,ASize); FBufferSize := AStream.Read(FBuffer[0],ASize); FBufferPos := 0; FBufferStream := AStream; end; procedure TBGRAReaderTarga.CloseReadBuffer; begin FBufferStream.Position:= FBufferStream.Position-FBufferSize+FBufferPos; end; function TBGRAReaderTarga.GetNextBufferByte: byte; begin if FBufferPos < FBufferSize then begin result := FBuffer[FBufferPos]; inc(FBufferPos); end else if FBufferSize = 0 then result := 0 else begin FBufferSize := FBufferStream.Read(FBuffer[0],length(FBuffer)); FBufferPos := 0; if FBufferPos < FBufferSize then begin result := FBuffer[FBufferPos]; inc(FBufferPos); end else result := 0; end; end; initialization DefaultBGRAImageReader[ifTarga] := TBGRAReaderTarga; end.