mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-23 22:52:13 +02:00
* Patch from Mattias Gaertner to read LZW compressed images and more robust handling of faulty images
git-svn-id: trunk@12354 -
This commit is contained in:
parent
5ffec2d876
commit
e39c8631a4
@ -18,11 +18,11 @@
|
|||||||
RGB 8,16bit (optional alpha),
|
RGB 8,16bit (optional alpha),
|
||||||
Orientation,
|
Orientation,
|
||||||
skipping Thumbnail to read first image,
|
skipping Thumbnail to read first image,
|
||||||
compression: packbits, (LZW started)
|
compression: packbits, LZW
|
||||||
endian
|
endian
|
||||||
|
|
||||||
ToDo:
|
ToDo:
|
||||||
Compression: LZW, deflate, jpeg, ...
|
Compression: deflate, jpeg, ...
|
||||||
Planar
|
Planar
|
||||||
ColorMap
|
ColorMap
|
||||||
multiple images
|
multiple images
|
||||||
@ -35,6 +35,8 @@ unit FPReadTiff;
|
|||||||
|
|
||||||
{$mode objfpc}{$H+}
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
{$inline on}
|
||||||
|
|
||||||
interface
|
interface
|
||||||
|
|
||||||
uses
|
uses
|
||||||
@ -78,6 +80,8 @@ type
|
|||||||
procedure ReadShortValues(StreamPos: DWord;
|
procedure ReadShortValues(StreamPos: DWord;
|
||||||
out Buffer: PWord; out Count: DWord);
|
out Buffer: PWord; out Count: DWord);
|
||||||
procedure ReadImage(Index: integer);
|
procedure ReadImage(Index: integer);
|
||||||
|
procedure ReadImgValue(BitCount: Word; var Run: Pointer; x: dword;
|
||||||
|
Predictor: word; var LastValue: word; out Value: Word); inline;
|
||||||
function FixEndian(w: Word): Word; inline;
|
function FixEndian(w: Word): Word; inline;
|
||||||
function FixEndian(d: DWord): DWord; inline;
|
function FixEndian(d: DWord): DWord; inline;
|
||||||
procedure DecompressPackBits(var Buffer: Pointer; var Count: PtrInt);
|
procedure DecompressPackBits(var Buffer: Pointer; var Count: PtrInt);
|
||||||
@ -109,6 +113,31 @@ begin
|
|||||||
raise Exception.Create(Msg);
|
raise Exception.Create(Msg);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TFPReaderTiff.ReadImgValue(BitCount: Word; var Run: Pointer; x: dword;
|
||||||
|
Predictor: word; var LastValue: word; out Value: Word); inline;
|
||||||
|
begin
|
||||||
|
if BitCount=8 then begin
|
||||||
|
Value:=PCUInt8(Run)^;
|
||||||
|
if Predictor=2 then begin
|
||||||
|
// horizontal difference
|
||||||
|
if x>0 then
|
||||||
|
Value:=(Value+LastValue) and $ff;
|
||||||
|
LastValue:=Value;
|
||||||
|
end;
|
||||||
|
Value:=Value shl 8+Value;
|
||||||
|
inc(Run);
|
||||||
|
end else if BitCount=16 then begin
|
||||||
|
Value:=FixEndian(PCUInt16(Run)^);
|
||||||
|
if Predictor=2 then begin
|
||||||
|
// horizontal difference
|
||||||
|
if x>0 then
|
||||||
|
Value:=(Value+LastValue) and $ffff;
|
||||||
|
LastValue:=Value;
|
||||||
|
end;
|
||||||
|
inc(Run,2);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TFPReaderTiff.SetStreamPos(p: DWord);
|
procedure TFPReaderTiff.SetStreamPos(p: DWord);
|
||||||
var
|
var
|
||||||
NewPosition: int64;
|
NewPosition: int64;
|
||||||
@ -594,6 +623,19 @@ begin
|
|||||||
if Debug then
|
if Debug then
|
||||||
writeln('TFPReaderTiff.ReadDirectoryEntry HostComputer="',IDF.HostComputer,'"');
|
writeln('TFPReaderTiff.ReadDirectoryEntry HostComputer="',IDF.HostComputer,'"');
|
||||||
end;
|
end;
|
||||||
|
317:
|
||||||
|
begin
|
||||||
|
// Predictor
|
||||||
|
UValue:=word(ReadEntryUnsigned);
|
||||||
|
case UValue of
|
||||||
|
1: ;
|
||||||
|
2: ;
|
||||||
|
else TiffError('expected Predictor, but found '+IntToStr(UValue));
|
||||||
|
end;
|
||||||
|
IDF.Predictor:=UValue;
|
||||||
|
if Debug then
|
||||||
|
writeln('TFPReaderTiff.ReadDirectoryEntry Predictor="',IDF.Predictor,'"');
|
||||||
|
end;
|
||||||
320:
|
320:
|
||||||
begin
|
begin
|
||||||
// ColorMap: N = 3*2^BitsPerSample
|
// ColorMap: N = 3*2^BitsPerSample
|
||||||
@ -885,21 +927,21 @@ var
|
|||||||
CurOffset: DWord;
|
CurOffset: DWord;
|
||||||
CurByteCnt: PtrInt;
|
CurByteCnt: PtrInt;
|
||||||
Strip: PByte;
|
Strip: PByte;
|
||||||
Run: Dword;
|
Run: PByte;
|
||||||
y: DWord;
|
y: DWord;
|
||||||
y2: DWord;
|
y2: DWord;
|
||||||
x: DWord;
|
x: DWord;
|
||||||
GrayValue: DWord;
|
|
||||||
dx: LongInt;
|
dx: LongInt;
|
||||||
dy: LongInt;
|
dy: LongInt;
|
||||||
SampleCnt: DWord;
|
SampleCnt: DWord;
|
||||||
SampleBits: PWord;
|
SampleBits: PWord;
|
||||||
ExtraSampleCnt: DWord;
|
ExtraSampleCnt: DWord;
|
||||||
ExtraSamples: PWord;
|
ExtraSamples: PWord;
|
||||||
RedValue: Word;
|
GrayValue, LastGrayValue: Word;
|
||||||
GreenValue: Word;
|
RedValue, LastRedValue: Word;
|
||||||
BlueValue: Word;
|
GreenValue, LastGreenValue: Word;
|
||||||
AlphaValue: Word;
|
BlueValue, LastBlueValue: Word;
|
||||||
|
AlphaValue, LastAlphaValue: Word;
|
||||||
Col: TFPColor;
|
Col: TFPColor;
|
||||||
i: Integer;
|
i: Integer;
|
||||||
CurImg: TFPCustomImage;
|
CurImg: TFPCustomImage;
|
||||||
@ -909,7 +951,9 @@ var
|
|||||||
BlueBits: Word;
|
BlueBits: Word;
|
||||||
AlphaBits: Word;
|
AlphaBits: Word;
|
||||||
BytesPerPixel: Integer;
|
BytesPerPixel: Integer;
|
||||||
|
StripBitsPerPixel: DWord;
|
||||||
aContinue: Boolean;
|
aContinue: Boolean;
|
||||||
|
ExpectedStripLength: PtrInt;
|
||||||
begin
|
begin
|
||||||
CurImg:=nil;
|
CurImg:=nil;
|
||||||
if Debug then
|
if Debug then
|
||||||
@ -973,6 +1017,14 @@ begin
|
|||||||
BlueBits:=0;
|
BlueBits:=0;
|
||||||
AlphaBits:=0;
|
AlphaBits:=0;
|
||||||
BytesPerPixel:=0;
|
BytesPerPixel:=0;
|
||||||
|
StripBitsPerPixel:=0;
|
||||||
|
for i:=0 to SampleCnt-1 do begin
|
||||||
|
if SampleBits[i]>64 then
|
||||||
|
TiffError('Samples bigger than 64 bit not supported');
|
||||||
|
if SampleBits[i] and 7<>0 then
|
||||||
|
TiffError('Only samples of 8 and 16 bit supported');
|
||||||
|
inc(StripBitsPerPixel,SampleBits[i]);
|
||||||
|
end;
|
||||||
case IDF.PhotoMetricInterpretation of
|
case IDF.PhotoMetricInterpretation of
|
||||||
0,1:
|
0,1:
|
||||||
begin
|
begin
|
||||||
@ -983,6 +1035,10 @@ begin
|
|||||||
AlphaBits:=SampleBits[1+i];
|
AlphaBits:=SampleBits[1+i];
|
||||||
IDF.AlphaBits:=AlphaBits;
|
IDF.AlphaBits:=AlphaBits;
|
||||||
end;
|
end;
|
||||||
|
if not (GrayBits in [8,16]) then
|
||||||
|
TiffError('gray image only supported with gray BitsPerSample 8 or 16');
|
||||||
|
if not (AlphaBits in [0,8,16]) then
|
||||||
|
TiffError('gray image only supported with alpha BitsPerSample 8 or 16');
|
||||||
end;
|
end;
|
||||||
2:
|
2:
|
||||||
begin
|
begin
|
||||||
@ -997,6 +1053,14 @@ begin
|
|||||||
AlphaBits:=SampleBits[3+i];
|
AlphaBits:=SampleBits[3+i];
|
||||||
IDF.AlphaBits:=AlphaBits;
|
IDF.AlphaBits:=AlphaBits;
|
||||||
end;
|
end;
|
||||||
|
if not (RedBits in [8,16]) then
|
||||||
|
TiffError('RGB image only supported with red BitsPerSample 8 or 16');
|
||||||
|
if not (GreenBits in [8,16]) then
|
||||||
|
TiffError('RGB image only supported with green BitsPerSample 8 or 16');
|
||||||
|
if not (BlueBits in [8,16]) then
|
||||||
|
TiffError('RGB image only supported with blue BitsPerSample 8 or 16');
|
||||||
|
if not (AlphaBits in [0,8,16]) then
|
||||||
|
TiffError('RGB image only supported with alpha BitsPerSample 8 or 16');
|
||||||
end;
|
end;
|
||||||
5:
|
5:
|
||||||
begin
|
begin
|
||||||
@ -1013,6 +1077,16 @@ begin
|
|||||||
AlphaBits:=SampleBits[4+i];
|
AlphaBits:=SampleBits[4+i];
|
||||||
IDF.AlphaBits:=AlphaBits;
|
IDF.AlphaBits:=AlphaBits;
|
||||||
end;
|
end;
|
||||||
|
if not (RedBits in [8,16]) then
|
||||||
|
TiffError('CMYK image only supported with cyan BitsPerSample 8 or 16');
|
||||||
|
if not (GreenBits in [8,16]) then
|
||||||
|
TiffError('CMYK image only supported with magenta BitsPerSample 8 or 16');
|
||||||
|
if not (BlueBits in [8,16]) then
|
||||||
|
TiffError('CMYK image only supported with yellow BitsPerSample 8 or 16');
|
||||||
|
if not (GrayBits in [8,16]) then
|
||||||
|
TiffError('CMYK image only supported with black BitsPerSample 8 or 16');
|
||||||
|
if not (AlphaBits in [0,8,16]) then
|
||||||
|
TiffError('CMYK image only supported with alpha BitsPerSample 8 or 16');
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
BytesPerPixel:=(GrayBits+RedBits+GreenBits+BlueBits+AlphaBits) div 8;
|
BytesPerPixel:=(GrayBits+RedBits+GreenBits+BlueBits+AlphaBits) div 8;
|
||||||
@ -1095,43 +1169,34 @@ begin
|
|||||||
TiffError('compression '+IntToStr(IDF.Compression)+' not supported yet');
|
TiffError('compression '+IntToStr(IDF.Compression)+' not supported yet');
|
||||||
end;
|
end;
|
||||||
if CurByteCnt<=0 then continue;
|
if CurByteCnt<=0 then continue;
|
||||||
|
ExpectedStripLength:=(StripBitsPerPixel*IDF.ImageWidth+7) div 8;
|
||||||
|
ExpectedStripLength:=ExpectedStripLength*Min(IDF.RowsPerStrip,IDF.ImageHeight-y);
|
||||||
|
// writeln('TFPReaderTiff.ReadImage StripBitsPerPixel=',StripBitsPerPixel,' IDF.ImageWidth=',IDF.ImageWidth,' IDF.ImageHeight=',IDF.ImageHeight,' y=',y,' IDF.RowsPerStrip=',IDF.RowsPerStrip,' ExpectedStripLength=',ExpectedStripLength,' CurByteCnt=',CurByteCnt);
|
||||||
|
if CurByteCnt<ExpectedStripLength then
|
||||||
|
TiffError('TFPReaderTiff.ReadImage Strip too short ByteCnt='+IntToStr(CurByteCnt)+' y='+IntToStr(y)+' expected='+IntToStr(ExpectedStripLength));
|
||||||
|
|
||||||
Run:=0;
|
Run:=Strip;
|
||||||
dx:=0;
|
dx:=0;
|
||||||
dy:=0;
|
dy:=0;
|
||||||
for y2:=0 to IDF.RowsPerStrip-1 do begin
|
for y2:=0 to IDF.RowsPerStrip-1 do begin
|
||||||
if y>=IDF.ImageHeight then break;
|
if y>=IDF.ImageHeight then break;
|
||||||
//writeln('TFPReaderTiff.ReadImage y=',y,' IDF.ImageWidth=',IDF.ImageWidth);
|
//writeln('TFPReaderTiff.ReadImage y=',y,' IDF.ImageWidth=',IDF.ImageWidth);
|
||||||
|
LastRedValue:=0;
|
||||||
|
LastGreenValue:=0;
|
||||||
|
LastBlueValue:=0;
|
||||||
|
LastGrayValue:=0;
|
||||||
|
LastAlphaValue:=0;
|
||||||
for x:=0 to IDF.ImageWidth-1 do begin
|
for x:=0 to IDF.ImageWidth-1 do begin
|
||||||
if PtrInt(Run)+BytesPerPixel>CurByteCnt then begin
|
|
||||||
TiffError('TFPReaderTiff.ReadImage Strip too short Run='+IntToStr(Run)+' CurByteCnt='+IntToStr(CurByteCnt)+' x='+IntToStr(x)+' y='+IntToStr(y)+' y2='+IntToStr(y2));
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
case IDF.PhotoMetricInterpretation of
|
case IDF.PhotoMetricInterpretation of
|
||||||
0,1:
|
0,1:
|
||||||
begin
|
begin
|
||||||
if GrayBits=8 then begin
|
ReadImgValue(GrayBits,Run,x,IDF.Predictor,LastGrayValue,GrayValue);
|
||||||
GrayValue:=PCUInt8(Strip)[Run];
|
|
||||||
GrayValue:=GrayValue shl 8+GrayValue;
|
|
||||||
inc(Run);
|
|
||||||
end else if GrayBits=16 then begin
|
|
||||||
GrayValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end else
|
|
||||||
TiffError('gray image only supported with BitsPerSample 8 or 16 not yet supported');
|
|
||||||
if IDF.PhotoMetricInterpretation=0 then
|
if IDF.PhotoMetricInterpretation=0 then
|
||||||
GrayValue:=$ffff-GrayValue;
|
GrayValue:=$ffff-GrayValue;
|
||||||
AlphaValue:=alphaOpaque;
|
AlphaValue:=alphaOpaque;
|
||||||
for i:=0 to ExtraSampleCnt-1 do begin
|
for i:=0 to ExtraSampleCnt-1 do begin
|
||||||
if ExtraSamples[i]=2 then begin
|
if ExtraSamples[i]=2 then begin
|
||||||
if SampleBits[1+i]=8 then begin
|
ReadImgValue(AlphaBits,Run,x,IDF.Predictor,LastAlphaValue,AlphaValue);
|
||||||
AlphaValue:=PCUInt8(Strip)[Run];
|
|
||||||
AlphaValue:=AlphaValue shl 8+AlphaValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
AlphaValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
end else begin
|
end else begin
|
||||||
inc(Run,ExtraSamples[i] div 8);
|
inc(Run,ExtraSamples[i] div 8);
|
||||||
end;
|
end;
|
||||||
@ -1141,41 +1206,13 @@ begin
|
|||||||
|
|
||||||
2: // RGB(A)
|
2: // RGB(A)
|
||||||
begin
|
begin
|
||||||
if RedBits=8 then begin
|
ReadImgValue(RedBits,Run,x,IDF.Predictor,LastRedValue,RedValue);
|
||||||
RedValue:=PCUInt8(Strip)[Run];
|
ReadImgValue(GreenBits,Run,x,IDF.Predictor,LastGreenValue,GreenValue);
|
||||||
RedValue:=RedValue shl 8+RedValue;
|
ReadImgValue(BlueBits,Run,x,IDF.Predictor,LastBlueValue,BlueValue);
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
RedValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
if GreenBits=8 then begin
|
|
||||||
GreenValue:=PCUInt8(Strip)[Run];
|
|
||||||
GreenValue:=GreenValue shl 8+GreenValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
GreenValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
if BlueBits=8 then begin
|
|
||||||
BlueValue:=PCUInt8(Strip)[Run];
|
|
||||||
BlueValue:=BlueValue shl 8+BlueValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
BlueValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
AlphaValue:=alphaOpaque;
|
AlphaValue:=alphaOpaque;
|
||||||
for i:=0 to ExtraSampleCnt-1 do begin
|
for i:=0 to ExtraSampleCnt-1 do begin
|
||||||
if ExtraSamples[i]=2 then begin
|
if ExtraSamples[i]=2 then begin
|
||||||
if SampleBits[3+i]=8 then begin
|
ReadImgValue(AlphaBits,Run,x,IDF.Predictor,LastAlphaValue,AlphaValue);
|
||||||
AlphaValue:=PCUInt8(Strip)[Run];
|
|
||||||
AlphaValue:=AlphaValue shl 8+AlphaValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
AlphaValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
end else begin
|
end else begin
|
||||||
inc(Run,ExtraSamples[i] div 8);
|
inc(Run,ExtraSamples[i] div 8);
|
||||||
end;
|
end;
|
||||||
@ -1185,49 +1222,14 @@ begin
|
|||||||
|
|
||||||
5: // CMYK plus optional alpha
|
5: // CMYK plus optional alpha
|
||||||
begin
|
begin
|
||||||
if RedBits=8 then begin
|
ReadImgValue(RedBits,Run,x,IDF.Predictor,LastRedValue,RedValue);
|
||||||
RedValue:=PCUInt8(Strip)[Run];
|
ReadImgValue(GreenBits,Run,x,IDF.Predictor,LastGreenValue,GreenValue);
|
||||||
RedValue:=RedValue shl 8+RedValue;
|
ReadImgValue(BlueBits,Run,x,IDF.Predictor,LastBlueValue,BlueValue);
|
||||||
inc(Run);
|
ReadImgValue(GrayBits,Run,x,IDF.Predictor,LastGrayValue,GrayValue);
|
||||||
end else begin
|
|
||||||
RedValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
if GreenBits=8 then begin
|
|
||||||
GreenValue:=PCUInt8(Strip)[Run];
|
|
||||||
GreenValue:=GreenValue shl 8+GreenValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
GreenValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
if BlueBits=8 then begin
|
|
||||||
BlueValue:=PCUInt8(Strip)[Run];
|
|
||||||
BlueValue:=BlueValue shl 8+BlueValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
BlueValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
if GrayBits=8 then begin
|
|
||||||
GrayValue:=PCUInt8(Strip)[Run];
|
|
||||||
GrayValue:=GrayValue shl 8+GrayValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
GrayValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
AlphaValue:=alphaOpaque;
|
AlphaValue:=alphaOpaque;
|
||||||
for i:=0 to ExtraSampleCnt-1 do begin
|
for i:=0 to ExtraSampleCnt-1 do begin
|
||||||
if ExtraSamples[i]=2 then begin
|
if ExtraSamples[i]=2 then begin
|
||||||
if SampleBits[4+i]=8 then begin
|
ReadImgValue(AlphaBits,Run,x,IDF.Predictor,LastAlphaValue,AlphaValue);
|
||||||
AlphaValue:=PCUInt8(Strip)[Run];
|
|
||||||
AlphaValue:=AlphaValue shl 8+AlphaValue;
|
|
||||||
inc(Run);
|
|
||||||
end else begin
|
|
||||||
AlphaValue:=FixEndian(PCUInt16(@Strip[Run])^);
|
|
||||||
inc(Run,2);
|
|
||||||
end;
|
|
||||||
end else begin
|
end else begin
|
||||||
inc(Run,ExtraSamples[i] div 8);
|
inc(Run,ExtraSamples[i] div 8);
|
||||||
end;
|
end;
|
||||||
@ -1362,8 +1364,8 @@ type
|
|||||||
end;
|
end;
|
||||||
PLZWString = ^TLZWString;
|
PLZWString = ^TLZWString;
|
||||||
const
|
const
|
||||||
EoiCode = 257;
|
ClearCode = 256; // clear table, start with 9bit codes
|
||||||
ClearCode = 256;
|
EoiCode = 257; // end of input
|
||||||
var
|
var
|
||||||
NewBuffer: PByte;
|
NewBuffer: PByte;
|
||||||
NewCount: PtrInt;
|
NewCount: PtrInt;
|
||||||
@ -1383,7 +1385,7 @@ var
|
|||||||
begin
|
begin
|
||||||
Result:=0;
|
Result:=0;
|
||||||
// CurBitLength can be 9 to 12
|
// CurBitLength can be 9 to 12
|
||||||
writeln('GetNextCode CurBitLength=',CurBitLength,' SrcPos=',SrcPos,' SrcPosBit=',SrcPosBit,' ',hexstr(PByte(Buffer)[SrcPos],2),' ',hexstr(PByte(Buffer)[SrcPos+1],2),' ',hexstr(PByte(Buffer)[SrcPos+2],2));
|
//writeln('GetNextCode CurBitLength=',CurBitLength,' SrcPos=',SrcPos,' SrcPosBit=',SrcPosBit,' ',hexstr(PByte(Buffer)[SrcPos],2),' ',hexstr(PByte(Buffer)[SrcPos+1],2),' ',hexstr(PByte(Buffer)[SrcPos+2],2));
|
||||||
// read two or three bytes
|
// read two or three bytes
|
||||||
if CurBitLength+SrcPosBit>16 then begin
|
if CurBitLength+SrcPosBit>16 then begin
|
||||||
// read from three bytes
|
// read from three bytes
|
||||||
@ -1406,7 +1408,7 @@ var
|
|||||||
end;
|
end;
|
||||||
Result:=v and ((1 shl CurBitLength)-1);
|
Result:=v and ((1 shl CurBitLength)-1);
|
||||||
SrcPosBit:=(SrcPosBit+CurBitLength) and 7;
|
SrcPosBit:=(SrcPosBit+CurBitLength) and 7;
|
||||||
writeln('GetNextCode END SrcPos=',SrcPos,' SrcPosBit=',SrcPosBit,' Result=',Result,' Result=',hexstr(Result,4));
|
//writeln('GetNextCode END SrcPos=',SrcPos,' SrcPosBit=',SrcPosBit,' Result=',Result,' Result=',hexstr(Result,4));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure ClearTable;
|
procedure ClearTable;
|
||||||
@ -1433,44 +1435,43 @@ var
|
|||||||
var
|
var
|
||||||
s: TLZWString;
|
s: TLZWString;
|
||||||
b: byte;
|
b: byte;
|
||||||
i: Integer;
|
|
||||||
begin
|
begin
|
||||||
WriteLn('WriteStringFromCode Code=',Code,' AddFirstChar=',AddFirstChar);
|
//WriteLn('WriteStringFromCode Code=',Code,' AddFirstChar=',AddFirstChar,' x=',(NewCount div 4) mod IDF.ImageWidth,' y=',(NewCount div 4) div IDF.ImageWidth,' PixelByte=',NewCount mod 4);
|
||||||
if Code<256 then begin
|
if Code<256 then begin
|
||||||
// write byte
|
// write byte
|
||||||
b:=Code;
|
b:=Code;
|
||||||
s.Data:=@b;
|
s.Data:=@b;
|
||||||
s.Count:=1;
|
s.Count:=1;
|
||||||
end else begin
|
end else if Code>=258 then begin
|
||||||
// write string
|
// write string
|
||||||
if Code-258>=TableCount then
|
if Code-258>=TableCount then
|
||||||
TiffError('LZW code out of bounds');
|
TiffError('LZW code out of bounds');
|
||||||
s:=Table[Code-258];
|
s:=Table[Code-258];
|
||||||
end;
|
end else
|
||||||
|
TiffError('LZW code out of bounds');
|
||||||
if NewCount+s.Count+1>NewCapacity then begin
|
if NewCount+s.Count+1>NewCapacity then begin
|
||||||
NewCapacity:=NewCapacity*2+8;
|
NewCapacity:=NewCapacity*2+8;
|
||||||
ReAllocMem(NewBuffer,NewCapacity);
|
ReAllocMem(NewBuffer,NewCapacity);
|
||||||
end;
|
end;
|
||||||
System.Move(s.Data^,NewBuffer[NewCount],s.Count);
|
System.Move(s.Data^,NewBuffer[NewCount],s.Count);
|
||||||
for i:=0 to s.Count-1 do
|
//for i:=0 to s.Count-1 do write(HexStr(NewBuffer[NewCount+i],2)); // debug
|
||||||
write(HexStr(NewBuffer[NewCount+i],2));
|
|
||||||
inc(NewCount,s.Count);
|
inc(NewCount,s.Count);
|
||||||
if AddFirstChar then begin
|
if AddFirstChar then begin
|
||||||
NewBuffer[NewCount]:=s.Data^;
|
NewBuffer[NewCount]:=s.Data^;
|
||||||
write(HexStr(NewBuffer[NewCount],2));
|
//write(HexStr(NewBuffer[NewCount],2)); // debug
|
||||||
inc(NewCount);
|
inc(NewCount);
|
||||||
end;
|
end;
|
||||||
writeln(',WriteStringFromCode');
|
//writeln(',WriteStringFromCode'); // debug
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure AddStringToTable(Code, AddFirstCharFromCode: integer);
|
procedure AddStringToTable(Code, AddFirstCharFromCode: integer);
|
||||||
// add string from code plus first character of string from code as new string
|
// add string from code plus first character of string from code as new string
|
||||||
var
|
var
|
||||||
b: byte;
|
b1, b2: byte;
|
||||||
s1, s2: TLZWString;
|
s1, s2: TLZWString;
|
||||||
p: PByte;
|
p: PByte;
|
||||||
begin
|
begin
|
||||||
WriteLn('AddStringToTable Code=',Code,' FCFCode=',AddFirstCharFromCode,' TableCount=',TableCount,' TableCapacity=',TableCapacity);
|
//WriteLn('AddStringToTable Code=',Code,' FCFCode=',AddFirstCharFromCode,' TableCount=',TableCount,' TableCapacity=',TableCapacity);
|
||||||
// grow table
|
// grow table
|
||||||
if TableCount>=TableCapacity then begin
|
if TableCount>=TableCapacity then begin
|
||||||
TableCapacity:=TableCapacity*2+128;
|
TableCapacity:=TableCapacity*2+128;
|
||||||
@ -1479,20 +1480,21 @@ var
|
|||||||
// find string 1
|
// find string 1
|
||||||
if Code<256 then begin
|
if Code<256 then begin
|
||||||
// string is byte
|
// string is byte
|
||||||
b:=Code;
|
b1:=Code;
|
||||||
s1.Data:=@b;
|
s1.Data:=@b1;
|
||||||
s1.Count:=1;
|
s1.Count:=1;
|
||||||
end else begin
|
end else if Code>=258 then begin
|
||||||
// normal string
|
// normal string
|
||||||
if Code-258>=TableCount then
|
if Code-258>=TableCount then
|
||||||
TiffError('LZW code out of bounds');
|
TiffError('LZW code out of bounds');
|
||||||
s1:=Table[Code-258];
|
s1:=Table[Code-258];
|
||||||
end;
|
end else
|
||||||
|
TiffError('LZW code out of bounds');
|
||||||
// find string 2
|
// find string 2
|
||||||
if AddFirstCharFromCode<256 then begin
|
if AddFirstCharFromCode<256 then begin
|
||||||
// string is byte
|
// string is byte
|
||||||
b:=AddFirstCharFromCode;
|
b2:=AddFirstCharFromCode;
|
||||||
s2.Data:=@b;
|
s2.Data:=@b2;
|
||||||
s2.Count:=1;
|
s2.Count:=1;
|
||||||
end else begin
|
end else begin
|
||||||
// normal string
|
// normal string
|
||||||
@ -1517,10 +1519,11 @@ var
|
|||||||
end;
|
end;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
WriteLn('TFPReaderTiff.DecompressLZW START Count=',Count);
|
if Count=0 then exit;
|
||||||
for SrcPos:=0 to 19 do
|
//WriteLn('TFPReaderTiff.DecompressLZW START Count=',Count);
|
||||||
write(HexStr(PByte(Buffer)[SrcPos],2));
|
//for SrcPos:=0 to 19 do
|
||||||
writeln();
|
// write(HexStr(PByte(Buffer)[SrcPos],2));
|
||||||
|
//writeln();
|
||||||
|
|
||||||
NewBuffer:=nil;
|
NewBuffer:=nil;
|
||||||
NewCount:=0;
|
NewCount:=0;
|
||||||
@ -1536,12 +1539,15 @@ begin
|
|||||||
try
|
try
|
||||||
repeat
|
repeat
|
||||||
Code:=GetNextCode;
|
Code:=GetNextCode;
|
||||||
WriteLn('TFPReaderTiff.DecompressLZW Code=',Code);
|
//WriteLn('TFPReaderTiff.DecompressLZW Code=',Code);
|
||||||
if Code=EoiCode then break;
|
if Code=EoiCode then break;
|
||||||
if Code=ClearCode then begin
|
if Code=ClearCode then begin
|
||||||
InitializeTable;
|
InitializeTable;
|
||||||
Code:=GetNextCode;
|
Code:=GetNextCode;
|
||||||
|
//WriteLn('TFPReaderTiff.DecompressLZW after clear Code=',Code);
|
||||||
if Code=EoiCode then break;
|
if Code=EoiCode then break;
|
||||||
|
if Code=ClearCode then
|
||||||
|
TiffError('LZW code out of bounds');
|
||||||
WriteStringFromCode(Code);
|
WriteStringFromCode(Code);
|
||||||
OldCode:=Code;
|
OldCode:=Code;
|
||||||
end else begin
|
end else begin
|
||||||
|
@ -62,6 +62,7 @@ type
|
|||||||
CellWidth: DWord;
|
CellWidth: DWord;
|
||||||
ColorMap: DWord;// tiff position of entry
|
ColorMap: DWord;// tiff position of entry
|
||||||
Compression: DWord;
|
Compression: DWord;
|
||||||
|
Predictor: Word;
|
||||||
Copyright: string;
|
Copyright: string;
|
||||||
DateAndTime: string;
|
DateAndTime: string;
|
||||||
DocumentName: string;
|
DocumentName: string;
|
||||||
@ -161,6 +162,7 @@ begin
|
|||||||
PhotoMetricInterpretation:=High(PhotoMetricInterpretation);
|
PhotoMetricInterpretation:=High(PhotoMetricInterpretation);
|
||||||
PlanarConfiguration:=0;
|
PlanarConfiguration:=0;
|
||||||
Compression:=0;
|
Compression:=0;
|
||||||
|
Predictor:=1;
|
||||||
ImageHeight:=0;
|
ImageHeight:=0;
|
||||||
ImageWidth:=0;
|
ImageWidth:=0;
|
||||||
ImageIsThumbNail:=false;
|
ImageIsThumbNail:=false;
|
||||||
@ -202,6 +204,7 @@ begin
|
|||||||
PhotoMetricInterpretation:=IDF.PhotoMetricInterpretation;
|
PhotoMetricInterpretation:=IDF.PhotoMetricInterpretation;
|
||||||
PlanarConfiguration:=IDF.PlanarConfiguration;
|
PlanarConfiguration:=IDF.PlanarConfiguration;
|
||||||
Compression:=IDF.Compression;
|
Compression:=IDF.Compression;
|
||||||
|
Predictor:=IDF.Predictor;
|
||||||
ImageHeight:=IDF.ImageHeight;
|
ImageHeight:=IDF.ImageHeight;
|
||||||
ImageWidth:=IDF.ImageWidth;
|
ImageWidth:=IDF.ImageWidth;
|
||||||
ImageIsThumbNail:=IDF.ImageIsThumbNail;
|
ImageIsThumbNail:=IDF.ImageIsThumbNail;
|
||||||
|
Loading…
Reference in New Issue
Block a user