Browse Source

fcl-image: tiff: reading CMYK, handling of unorderd tags, alpha mode 1, multiple pages, tiles

git-svn-id: trunk@21483 -
Mattias Gaertner 13 years ago
parent
commit
ca0cc29a26

File diff suppressed because it is too large
+ 481 - 129
packages/fcl-image/src/fpreadtiff.pas


+ 162 - 48
packages/fcl-image/src/fptiffcmn.pas

@@ -1,6 +1,6 @@
 {
     This file is part of the Free Pascal run time library.
-    Copyright (c) 2008 by the Free Pascal development team
+    Copyright (c) 2012 by the Free Pascal development team
 
     Common stuff for Tiff image format.
 
@@ -49,12 +49,45 @@ const
   TiffXResolution = TiffExtraPrefix+'XResolution';
   TiffYResolution = TiffExtraPrefix+'YResolution';
 
+  TiffCompressionNone = 1; { No Compression, but pack data into bytes as tightly as possible,
+       leaving no unused bits (except at the end of a row). The component
+       values are stored as an array of type BYTE. Each scan line (row)
+       is padded to the next BYTE boundary. }
+  TiffCompressionCCITTRLE = 2; { CCITT Group 3 1-Dimensional Modified Huffman run length encoding. }
+  TiffCompressionCCITTFAX3 = 3; { CCITT Group 3 fax encoding }
+  TiffCompressionCCITTFAX4 = 4; { CCITT Group 4 fax encoding }
+  TiffCompressionLZW = 5; { LZW }
+  TiffCompressionOldJPEG = 6; { JPEG old style}
+  TiffCompressionJPEG = 7; { JPEG new style }
+  TiffCompressionDeflateAdobe = 8; { Deflate Adobe style }
+  TiffCompressionJBIGBW = 9; { RFC2301 JBIG black/white }
+  TiffCompressionJBIGCol = 10; { RFC2301 JBIG color }
+  TiffCompressionNext = 32766; { Next }
+  TiffCompressionCCITTRLEW = 32771; { CCITTRLEW }
+  TiffCompressionPackBits = 32773; { PackBits Compression, a simple byte-oriented run length scheme.
+         See the PackBits section for details. Data Compression applies
+         only to raster image data. All other TIFF fields are unaffected. }
+  TiffCompressionThunderScan = 32809; { THUNDERSCAN }
+  TiffCompressionIT8CTPAD = 32895; { IT8CTPAD }
+  TiffCompressionIT8LW = 32896; { IT8LW }
+  TiffCompressionIT8MP = 32897; { IT8MP }
+  TiffCompressionIT8BL = 32898; { IT8BL }
+  TiffCompressionPixarFilm = 32908; { PIXARFILM }
+  TiffCompressionPixarLog = 32909; { PIXARLOG }
+  TiffCompressionDeflate = 32946; { DEFLATE }
+  TiffCompressionDCS = 32947; { DCS }
+  TiffCompressionJBIG = 34661; { JBIG }
+  TiffCompressionSGILog = 34676; { SGILOG }
+  TiffCompressionSGILog24 = 34677; { SGILOG24 }
+  TiffCompressionJPEG2000 = 34712; { JP2000 }
 type
 
-  { TTiffIDF }
+  { TTiffIFD - Image File Directory }
 
-  TTiffIDF = class
+  TTiffIFD = class
   public
+    IFDStart: DWord; // tiff position
+    IFDNext: DWord; // tiff position
     Artist: String;
     BitsPerSample: DWord; // tiff position of entry
     BitsPerSampleArray: array of Word;
@@ -78,6 +111,8 @@ type
     Make_ScannerManufacturer: string;
     Model_Scanner: string;
     Orientation: DWord;
+    PageNumber: word; // the page number starting at 0, the total number of pages is PageCount
+    PageCount: word; // see PageNumber
     PhotoMetricInterpretation: DWord;
     PlanarConfiguration: DWord;
     ResolutionUnit: DWord;
@@ -86,11 +121,16 @@ type
     Software: string;
     StripByteCounts: DWord;// tiff position of entry
     StripOffsets: DWord; // tiff position of entry
+    TileWidth: DWord;
+    TileLength: DWord; // = Height
+    TileOffsets: DWord; // tiff position of entry
+    TileByteCounts: DWord; // tiff position of entry
     Treshholding: DWord;
     XResolution: TTiffRational;
     YResolution: TTiffRational;
     // image
     Img: TFPCustomImage;
+    FreeImg: boolean;
     RedBits: word;
     GreenBits: word;
     BlueBits: word;
@@ -98,7 +138,9 @@ type
     AlphaBits: word;
     BytesPerPixel: Word;
     procedure Clear;
-    procedure Assign(IDF: TTiffIDF);
+    procedure Assign(IFD: TTiffIFD);
+    function ImageLength: DWord; inline;
+    destructor Destroy; override;
   end;
 
 function TiffRationalToStr(const r: TTiffRational): string;
@@ -106,6 +148,7 @@ function StrToTiffRationalDef(const s: string; const Def: TTiffRational): TTiffR
 procedure ClearTiffExtras(Img: TFPCustomImage);
 procedure CopyTiffExtras(SrcImg, DestImg: TFPCustomImage);
 procedure WriteTiffExtras(Msg: string; Img: TFPCustomImage);
+function TiffCompressionName(c: Word): string;
 
 implementation
 
@@ -149,19 +192,51 @@ procedure WriteTiffExtras(Msg: string; Img: TFPCustomImage);
 var
   i: Integer;
 begin
-  {$ifdef FPC_Debug_Image}
   writeln('WriteTiffExtras ',Msg);
-
   for i:=Img.ExtraCount-1 downto 0 do
     //if SysUtils.CompareText(copy(Img.ExtraKey[i],1,4),'Tiff')=0 then
       writeln('  ',i,' ',Img.ExtraKey[i],'=',Img.ExtraValue[i]);
-  {$endif}      
 end;
 
-{ TTiffIDF }
+function TiffCompressionName(c: Word): string;
+begin
+  case c of
+  1: Result:='no compression';
+  2: Result:='CCITT Group 3 1-Dimensional Modified Huffman run length encoding';
+  3: Result:='CCITT Group 3 fax encoding';
+  4: Result:='CCITT Group 4 fax encoding';
+  5: Result:='LZW';
+  6: Result:='JPEG old style';
+  7: Result:='JPEG';
+  8: Result:='Deflate Adobe style';
+  9: Result:='RFC2301 JBIG white/black';
+  10: Result:='RFC2301 JBIG color';
+  32766: Result:='Next';
+  32771: Result:='CCITTRLEW';
+  32773: Result:='PackBits';
+  32809: Result:='THUNDERSCAN';
+  32895: Result:='IT8CTPAD';
+  32896: Result:='IT8LW';
+  32897: Result:='IT8MP';
+  32898: Result:='IT8BL';
+  32908: Result:='PIXARFILM';
+  32909: Result:='PIXARLOG';
+  32946: Result:='DEFLATE';
+  32947: Result:='DCS';
+  34661: Result:='JBIG';
+  34676: Result:='SGILOG';
+  34677: Result:='SGILOG24';
+  34712: Result:='JP2000';
+  else Result:='unknown';
+  end;
+end;
+
+{ TTiffIFD }
 
-procedure TTiffIDF.Clear;
+procedure TTiffIFD.Clear;
 begin
+  IFDStart:=0;
+  IFDNext:=0;
   PhotoMetricInterpretation:=High(PhotoMetricInterpretation);
   PlanarConfiguration:=0;
   Compression:=0;
@@ -192,6 +267,15 @@ begin
   CellLength:=0;
   FillOrder:=0;
   Orientation:=0;
+  PageNumber:=0;
+  PageCount:=0;
+
+  // tiles
+  TileWidth:=0;
+  TileLength:=0;
+  TileOffsets:=0;
+  TileByteCounts:=0;
+
   Treshholding:=0;
 
   RedBits:=0;
@@ -200,48 +284,78 @@ begin
   GrayBits:=0;
   AlphaBits:=0;
   BytesPerPixel:=0;
+
+  if FreeImg then begin
+    FreeImg:=false;
+    FreeAndNil(Img);
+  end;
+end;
+
+procedure TTiffIFD.Assign(IFD: TTiffIFD);
+begin
+  IFDStart:=IFD.IFDStart;
+  IFDNext:=IFD.IFDNext;
+
+  PhotoMetricInterpretation:=IFD.PhotoMetricInterpretation;
+  PlanarConfiguration:=IFD.PlanarConfiguration;
+  Compression:=IFD.Compression;
+  Predictor:=IFD.Predictor;
+  ImageHeight:=IFD.ImageHeight;
+  ImageWidth:=IFD.ImageWidth;
+  ImageIsThumbNail:=IFD.ImageIsThumbNail;
+  ImageIsPage:=IFD.ImageIsPage;
+  ImageIsMask:=IFD.ImageIsMask;
+  BitsPerSample:=IFD.BitsPerSample;
+  BitsPerSampleArray:=IFD.BitsPerSampleArray;
+  ResolutionUnit:=IFD.ResolutionUnit;
+  XResolution:=IFD.XResolution;
+  YResolution:=IFD.YResolution;
+  RowsPerStrip:=IFD.RowsPerStrip;
+  StripOffsets:=IFD.StripOffsets;
+  StripByteCounts:=IFD.StripByteCounts;
+  SamplesPerPixel:=IFD.SamplesPerPixel;
+  Artist:=IFD.Artist;
+  HostComputer:=IFD.HostComputer;
+  ImageDescription:=IFD.ImageDescription;
+  Make_ScannerManufacturer:=IFD.Make_ScannerManufacturer;
+  Model_Scanner:=IFD.Model_Scanner;
+  Copyright:=IFD.Copyright;
+  DateAndTime:=IFD.DateAndTime;
+  Software:=IFD.Software;
+  CellWidth:=IFD.CellWidth;
+  CellLength:=IFD.CellLength;
+  FillOrder:=IFD.FillOrder;
+  Orientation:=IFD.Orientation;
+  PageNumber:=IFD.PageNumber;
+  PageCount:=IFD.PageCount;
+
+  // tiles
+  TileWidth:=IFD.TileWidth;
+  TileLength:=IFD.TileLength;
+  TileOffsets:=IFD.TileOffsets;
+  TileByteCounts:=IFD.TileByteCounts;
+
+  Treshholding:=IFD.Treshholding;
+
+  RedBits:=IFD.RedBits;
+  GreenBits:=IFD.GreenBits;
+  BlueBits:=IFD.BlueBits;
+  GrayBits:=IFD.GrayBits;
+  AlphaBits:=IFD.AlphaBits;
+  if (Img<>nil) and (IFD.Img<>nil) then
+    Img.Assign(IFD.Img);
+end;
+
+function TTiffIFD.ImageLength: DWord;
+begin
+  Result:=ImageHeight;
 end;
 
-procedure TTiffIDF.Assign(IDF: TTiffIDF);
+destructor TTiffIFD.Destroy;
 begin
-  PhotoMetricInterpretation:=IDF.PhotoMetricInterpretation;
-  PlanarConfiguration:=IDF.PlanarConfiguration;
-  Compression:=IDF.Compression;
-  Predictor:=IDF.Predictor;
-  ImageHeight:=IDF.ImageHeight;
-  ImageWidth:=IDF.ImageWidth;
-  ImageIsThumbNail:=IDF.ImageIsThumbNail;
-  ImageIsPage:=IDF.ImageIsPage;
-  ImageIsMask:=IDF.ImageIsMask;
-  BitsPerSample:=IDF.BitsPerSample;
-  BitsPerSampleArray:=IDF.BitsPerSampleArray;
-  ResolutionUnit:=IDF.ResolutionUnit;
-  XResolution:=IDF.XResolution;
-  YResolution:=IDF.YResolution;
-  RowsPerStrip:=IDF.RowsPerStrip;
-  StripOffsets:=IDF.StripOffsets;
-  StripByteCounts:=IDF.StripByteCounts;
-  SamplesPerPixel:=IDF.SamplesPerPixel;
-  Artist:=IDF.Artist;
-  HostComputer:=IDF.HostComputer;
-  ImageDescription:=IDF.ImageDescription;
-  Make_ScannerManufacturer:=IDF.Make_ScannerManufacturer;
-  Model_Scanner:=IDF.Model_Scanner;
-  Copyright:=IDF.Copyright;
-  DateAndTime:=IDF.DateAndTime;
-  Software:=IDF.Software;
-  CellWidth:=IDF.CellWidth;
-  CellLength:=IDF.CellLength;
-  FillOrder:=IDF.FillOrder;
-  Orientation:=IDF.Orientation;
-  Treshholding:=IDF.Treshholding;
-  RedBits:=IDF.RedBits;
-  GreenBits:=IDF.GreenBits;
-  BlueBits:=IDF.BlueBits;
-  GrayBits:=IDF.GrayBits;
-  AlphaBits:=IDF.AlphaBits;
-  if (Img<>nil) and (IDF.Img<>nil) then
-    Img.Assign(IDF.Img);
+  if FreeImg then
+    FreeAndNil(Img);
+  inherited Destroy;
 end;
 
 end.

+ 85 - 66
packages/fcl-image/src/fpwritetiff.pas

@@ -1,8 +1,8 @@
 {
     This file is part of the Free Pascal run time library.
-    Copyright (c) 2008 by the Free Pascal development team
+    Copyright (c) 2012 by the Free Pascal development team
 
-    Tiff reader for fpImage.
+    Tiff writer for fpImage.
 
     See the file COPYING.FPC, included in this distribution,
     for details about the copyright.
@@ -85,7 +85,7 @@ type
     procedure ClearEntries;
     procedure WriteTiff;
     procedure WriteHeader;
-    procedure WriteIDFs;
+    procedure WriteIFDs;
     procedure WriteEntry(Entry: TTiffWriteEntry);
     procedure WriteData;
     procedure WriteEntryData(Entry: TTiffWriteEntry);
@@ -97,6 +97,7 @@ type
     procedure AddEntryString(Tag: word; const s: string);
     procedure AddEntryShort(Tag: word; Value: Word);
     procedure AddEntryLong(Tag: word; Value: DWord);
+    procedure AddEntryShortOrLong(Tag: word; Value: DWord);
     procedure AddEntryRational(Tag: word; const Value: TTiffRational);
     procedure AddEntry(Tag: Word; EntryType: Word; EntryCount: DWord;
                        Data: Pointer; Bytes: DWord;
@@ -159,7 +160,7 @@ begin
   {$ENDIF}
   fPosition:=0;
   WriteHeader;
-  WriteIDFs;
+  WriteIFDs;
   WriteData;
 end;
 
@@ -173,19 +174,19 @@ begin
   WriteDWord(8);
 end;
 
-procedure TFPWriterTiff.WriteIDFs;
+procedure TFPWriterTiff.WriteIFDs;
 var
   i: Integer;
   List: TFPList;
   j: Integer;
   Entry: TTiffWriteEntry;
-  NextIDFPos: DWord;
+  NextIFDPos: DWord;
 begin
   for i:=0 to FEntries.Count-1 do begin
     List:=TFPList(FEntries[i]);
     // write count
     {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.WriteIDFs Count=',List.Count);
+    writeln('TFPWriterTiff.WriteIFDs Count=',List.Count);
     {$ENDIF}
     WriteWord(List.Count);
     // write array of entries
@@ -193,12 +194,12 @@ begin
       Entry:=TTiffWriteEntry(List[j]);
       WriteEntry(Entry);
     end;
-    // write position of next IDF
+    // write position of next IFD
     if i<FEntries.Count-1 then
-      NextIDFPos:=fPosition+4
+      NextIFDPos:=fPosition+4
     else
-      NextIDFPos:=0;
-    WriteDWord(NextIDFPos);
+      NextIFDPos:=0;
+    WriteDWord(NextIFDPos);
   end;
 end;
 
@@ -278,7 +279,7 @@ end;
 
 procedure TFPWriterTiff.AddImage(Img: TFPCustomImage);
 var
-  IDF: TTiffIDF;
+  IFD: TTiffIFD;
   GrayBits: Word;
   RedBits: Word;
   GreenBits: Word;
@@ -308,37 +309,38 @@ var
   dy: Integer;
   CurEntries: TFPList;
   StripCounts: TTiffWriteEntry;
+  Shorts: array[0..3] of Word;
 begin
   StripOffsets:=nil;
   Strip:=nil;
-  IDF:=TTiffIDF.Create;
+  IFD:=TTiffIFD.Create;
   try
     // add new list of entries
     CurEntries:=TFPList.Create;
     FEntries.Add(CurEntries);
 
     if Img.Extra[TiffPhotoMetric]='' then
-      IDF.PhotoMetricInterpretation:=2
+      IFD.PhotoMetricInterpretation:=2
     else begin
-      IDF.PhotoMetricInterpretation:=StrToInt64Def(Img.Extra[TiffPhotoMetric],High(IDF.PhotoMetricInterpretation));
-      if SaveCMYKAsRGB and (IDF.PhotoMetricInterpretation=5) then
-        IDF.PhotoMetricInterpretation:=2;
+      IFD.PhotoMetricInterpretation:=StrToInt64Def(Img.Extra[TiffPhotoMetric],High(IFD.PhotoMetricInterpretation));
+      if SaveCMYKAsRGB and (IFD.PhotoMetricInterpretation=5) then
+        IFD.PhotoMetricInterpretation:=2;
     end;
-    if not (IDF.PhotoMetricInterpretation in [0,1,2]) then
+    if not (IFD.PhotoMetricInterpretation in [0,1,2]) then
       TiffError('PhotoMetricInterpretation="'+Img.Extra[TiffPhotoMetric]+'" not supported');
-    IDF.Artist:=Img.Extra[TiffArtist];
-    IDF.Copyright:=Img.Extra[TiffCopyright];
-    IDF.DocumentName:=Img.Extra[TiffDocumentName];
-    IDF.DateAndTime:=Img.Extra[TiffDateTime];
-    IDF.ImageDescription:=Img.Extra[TiffImageDescription];
-    IDF.Orientation:=StrToIntDef(Img.Extra[TiffOrientation],1);
-    if not (IDF.Orientation in [1..8]) then
-      IDF.Orientation:=1;
-    IDF.ResolutionUnit:=StrToIntDef(Img.Extra[TiffResolutionUnit],2);
-    if not (IDF.ResolutionUnit in [1..3]) then
-      IDF.ResolutionUnit:=2;
-    IDF.XResolution:=StrToTiffRationalDef(Img.Extra[TiffXResolution],TiffRational72);
-    IDF.YResolution:=StrToTiffRationalDef(Img.Extra[TiffYResolution],TiffRational72);
+    IFD.Artist:=Img.Extra[TiffArtist];
+    IFD.Copyright:=Img.Extra[TiffCopyright];
+    IFD.DocumentName:=Img.Extra[TiffDocumentName];
+    IFD.DateAndTime:=Img.Extra[TiffDateTime];
+    IFD.ImageDescription:=Img.Extra[TiffImageDescription];
+    IFD.Orientation:=StrToIntDef(Img.Extra[TiffOrientation],1);
+    if not (IFD.Orientation in [1..8]) then
+      IFD.Orientation:=1;
+    IFD.ResolutionUnit:=StrToIntDef(Img.Extra[TiffResolutionUnit],2);
+    if not (IFD.ResolutionUnit in [1..3]) then
+      IFD.ResolutionUnit:=2;
+    IFD.XResolution:=StrToTiffRationalDef(Img.Extra[TiffXResolution],TiffRational72);
+    IFD.YResolution:=StrToTiffRationalDef(Img.Extra[TiffYResolution],TiffRational72);
 
     GrayBits:=StrToIntDef(Img.Extra[TiffGrayBits],8);
     RedBits:=StrToIntDef(Img.Extra[TiffRedBits],8);
@@ -349,7 +351,7 @@ begin
     ImgHeight:=Img.Height;
     Compression:=1;
 
-    if IDF.Orientation in [1..4] then begin
+    if IFD.Orientation in [1..4] then begin
       OrientedWidth:=ImgWidth;
       OrientedHeight:=ImgHeight;
     end else begin
@@ -358,26 +360,26 @@ begin
     end;
 
     {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.AddImage PhotoMetricInterpretation=',IDF.PhotoMetricInterpretation);
+    writeln('TFPWriterTiff.AddImage PhotoMetricInterpretation=',IFD.PhotoMetricInterpretation);
     writeln('TFPWriterTiff.AddImage ImageWidth=',ImgWidth,' ImageHeight=',ImgHeight);
-    writeln('TFPWriterTiff.AddImage Orientation=',IDF.Orientation);
-    writeln('TFPWriterTiff.AddImage ResolutionUnit=',IDF.ResolutionUnit);
-    writeln('TFPWriterTiff.AddImage XResolution=',TiffRationalToStr(IDF.XResolution));
-    writeln('TFPWriterTiff.AddImage YResolution=',TiffRationalToStr(IDF.YResolution));
+    writeln('TFPWriterTiff.AddImage Orientation=',IFD.Orientation);
+    writeln('TFPWriterTiff.AddImage ResolutionUnit=',IFD.ResolutionUnit);
+    writeln('TFPWriterTiff.AddImage XResolution=',TiffRationalToStr(IFD.XResolution));
+    writeln('TFPWriterTiff.AddImage YResolution=',TiffRationalToStr(IFD.YResolution));
     writeln('TFPWriterTiff.AddImage GrayBits=',GrayBits,' RedBits=',RedBits,' GreenBits=',GreenBits,' BlueBits=',BlueBits,' AlphaBits=',AlphaBits);
     writeln('TFPWriterTiff.AddImage Compression=',Compression);
     {$ENDIF}
 
     // required meta entries
-    AddEntryShort(262,IDF.PhotoMetricInterpretation);
+    AddEntryShort(262,IFD.PhotoMetricInterpretation);
     AddEntryLong(256,ImgWidth);
     AddEntryLong(257,ImgHeight);
     AddEntryShort(259,Compression);
-    AddEntryShort(274,IDF.Orientation);
-    AddEntryShort(296,IDF.ResolutionUnit);
-    AddEntryRational(282,IDF.XResolution);
-    AddEntryRational(283,IDF.YResolution);
-    case IDF.PhotoMetricInterpretation of
+    AddEntryShort(274,IFD.Orientation);
+    AddEntryShort(296,IFD.ResolutionUnit);
+    AddEntryRational(282,IFD.XResolution);
+    AddEntryRational(283,IFD.YResolution);
+    case IFD.PhotoMetricInterpretation of
     0,1:
       begin
         BitsPerSample[0]:=GrayBits;
@@ -407,27 +409,36 @@ begin
       inc(BitsPerPixel,BitsPerSample[i]);
     BytesPerLine:=(BitsPerPixel*OrientedWidth+7) div 8;
     if OrientedWidth=0 then
-      IDF.RowsPerStrip:=8
+      IFD.RowsPerStrip:=8
     else
-      IDF.RowsPerStrip:=8192 div BytesPerLine;
-    if IDF.RowsPerStrip<1 then
-      IDF.RowsPerStrip:=1;
+      IFD.RowsPerStrip:=8192 div BytesPerLine;
+    if IFD.RowsPerStrip<1 then
+      IFD.RowsPerStrip:=1;
     {$IFDEF VerboseTiffWriter}
-    writeln('TFPWriterTiff.AddImage BitsPerPixel=',BitsPerPixel,' OrientedWidth=',OrientedWidth,' BytesPerLine=',BytesPerLine,' RowsPerStrip=',IDF.RowsPerStrip);
+    writeln('TFPWriterTiff.AddImage BitsPerPixel=',BitsPerPixel,' OrientedWidth=',OrientedWidth,' BytesPerLine=',BytesPerLine,' RowsPerStrip=',IFD.RowsPerStrip);
     {$ENDIF}
-    AddEntryLong(278,IDF.RowsPerStrip);
+    AddEntryLong(278,IFD.RowsPerStrip);
 
     // optional entries
-    if IDF.Artist<>'' then
-      AddEntryString(315,IDF.Artist);
-    if IDF.Copyright<>'' then
-      AddEntryString(33432,IDF.Copyright);
-    if IDF.DocumentName<>'' then
-      AddEntryString(269,IDF.DocumentName);
-    if IDF.DateAndTime<>'' then
-      AddEntryString(306,IDF.DateAndTime);
-    if IDF.ImageDescription<>'' then
-      AddEntryString(270,IDF.ImageDescription);
+    if IFD.ImageDescription<>'' then
+      AddEntryString(270,IFD.ImageDescription);
+    if IFD.DocumentName<>'' then
+      AddEntryString(269,IFD.DocumentName);
+    if IFD.DateAndTime<>'' then
+      AddEntryString(306,IFD.DateAndTime);
+    if IFD.Artist<>'' then
+      AddEntryString(315,IFD.Artist);
+    if IFD.PageCount>0 then begin
+      Shorts[0]:=IFD.PageNumber;
+      Shorts[1]:=IFD.PageCount;
+      AddEntry(297,3,2,@Shorts[0],2*2);
+    end;
+    if IFD.Copyright<>'' then
+      AddEntryString(33432,IFD.Copyright);
+    if IFD.TileWidth>0 then
+      AddEntryShortOrLong(322,IFD.TileWidth);
+    if IFD.TileLength>0 then
+      AddEntryShortOrLong(323,IFD.TileLength);
 
     // StripOffsets: StripOffsets, StripByteCounts
     StripOffsets:=TTiffWriteStripOffsets.Create;
@@ -438,7 +449,7 @@ begin
     StripOffsets.StripByteCounts:=StripCounts;
     AddEntry(StripCounts);
     if OrientedHeight>0 then begin
-      StripOffsets.SetCount((OrientedHeight+IDF.RowsPerStrip-1) div IDF.RowsPerStrip);
+      StripOffsets.SetCount((OrientedHeight+IFD.RowsPerStrip-1) div IFD.RowsPerStrip);
       // compute StripOffsets
       Row:=0;
       StripIndex:=0;
@@ -447,7 +458,7 @@ begin
       for y:=0 to OrientedHeight-1 do begin
         if Row=0 then begin
           // allocate Strip for the next rows
-          StripBytes:=Min(IDF.RowsPerStrip,OrientedHeight-y)*BytesPerLine;
+          StripBytes:=Min(IFD.RowsPerStrip,OrientedHeight-y)*BytesPerLine;
           //writeln('TFPWriterTiff.AddImage StripIndex=',StripIndex,' StripBytes=',StripBytes);
           GetMem(Strip,StripBytes);
           FillByte(Strip^,StripBytes,0);
@@ -459,7 +470,7 @@ begin
         // write line
         for x:=0 to OrientedWidth-1 do begin
           // Orientation
-          case IDF.Orientation of
+          case IFD.Orientation of
           1: begin dx:=x; dy:=y; end;// 0,0 is left, top
           2: begin dx:=OrientedWidth-x-1; dy:=y; end;// 0,0 is right, top
           3: begin dx:=OrientedWidth-x-1; dy:=OrientedHeight-y-1; end;// 0,0 is right, bottom
@@ -470,12 +481,12 @@ begin
           8: begin dx:=y; dy:=OrientedWidth-x-1; end;// 0,0 is bottom, left (rotated)
           end;
           Col:=Img.Colors[dx,dy];
-          case IDF.PhotoMetricInterpretation of
+          case IFD.PhotoMetricInterpretation of
           0,1:
             begin
               // grayscale
               Value:=(DWord(Col.red)+Col.green+Col.blue) div 3;
-              if IDF.PhotoMetricInterpretation=0 then
+              if IFD.PhotoMetricInterpretation=0 then
                 Value:=$ffff-Value;// 0 is white
               if GrayBits=8 then begin
                 Run^:=Value shr 8;
@@ -528,14 +539,14 @@ begin
         end;
         // next row
         inc(Row);
-        if (Row=IDF.RowsPerStrip) then
+        if (Row=IFD.RowsPerStrip) then
           Row:=0;
       end;
     end;
 
     CurEntries.Sort(@CompareTiffWriteEntries);
   finally
-    IDF.Free;
+    IFD.Free;
   end;
 end;
 
@@ -575,6 +586,14 @@ begin
   AddEntry(Tag,4,1,@Value,4);
 end;
 
+procedure TFPWriterTiff.AddEntryShortOrLong(Tag: word; Value: DWord);
+begin
+  if Value<High(Word) then
+    AddEntryShort(Tag,Value)
+  else
+    AddEntryLong(Tag,Value);
+end;
+
 procedure TFPWriterTiff.AddEntryRational(Tag: word; const Value: TTiffRational
   );
 begin

Some files were not shown because too many files changed in this diff