TIFFReader.st
changeset 3984 e533a09c2c1d
parent 3980 209cd9407fe9
child 3985 3d9f0b1a06d0
--- a/TIFFReader.st	Sun Aug 27 16:35:52 2017 +0200
+++ b/TIFFReader.st	Sun Aug 27 19:59:10 2017 +0200
@@ -16,9 +16,26 @@
 ImageReader subclass:#TIFFReader
 	instanceVariableNames:'planarConfiguration subFileType stripOffsets rowsPerStrip
 		fillOrder compression group3options predictor stripByteCounts
-		currentOffset stripOffsetsPos stripByteCountsPos bitsPerSamplePos
-		colorMapPos orientation isBigTiff'
-	classVariableNames:'Verbose'
+		currentOffset stripOffsetsPos stripByteCountsPos stripRowCounts
+		bitsPerSamplePos colorMapPos orientation isBigTiff tileOffsets
+		tileByteCounts tileWidth tileLength sampleFormat minSampleValue
+		maxSampleValue subIfds decodeMetaTags loadFullResolutionImage
+		isDNGImage'
+	classVariableNames:'Verbose COMPRESSION_NONE COMPRESSION_CCITTRLE
+		COMPRESSION_CCITTFAX3 COMPRESSION_CCITTFAX4 COMPRESSION_LZW
+		COMPRESSION_OJPEG COMPRESSION_JPEG COMPRESSION_ADOBE_DEFLATE
+		COMPRESSION_JBIG_T85 COMPRESSION_JBIG_T43 COMPRESSION_NEXT
+		COMPRESSION_CCITTRLEW COMPRESSION_PACKBITS
+		COMPRESSION_THUNDERSCAN COMPRESSION_IT8CTPAD COMPRESSION_IT8LW
+		COMPRESSION_IT8MP COMPRESSION_IT8BL COMPRESSION_PIXARFILM
+		COMPRESSION_PIXARLOG COMPRESSION_DEFLATE COMPRESSION_DCS
+		COMPRESSION_JBIG COMPRESSION_JPEG2000 COMPRESSION_NIKON_NEF
+		COMPRESSION_JBIG2 COMPRESSION_NEXT_JPEG SAMPLEFORMAT_UINT
+		SAMPLEFORMAT_INT SAMPLEFORMAT_IEEEFP SAMPLEFORMAT_VOID
+		SAMPLEFORMAT_COMPLEXINT SAMPLEFORMAT_COMPLEXIEEEFP
+		COMPRESSION_SGILOG COMPRESSION_SGILOG24 PLANARCONFIG_CONTIG
+		PLANARCONFIG_SEPARATE FILETYPE_MASK_REDUCEDIMAGE
+		FILETYPE_MASK_PAGE FILETYPE_MASK_MASK'
 	poolDictionaries:''
 	category:'Graphics-Images-Readers'
 !
@@ -64,6 +81,7 @@
         It should write (at least) mono, 8-bit palette and 24 bit rgb formats.
 
       - bigTiff is supported
+      
       - some dng tags are supported
 
     More formats will come... (will they ever be needed?)
@@ -96,14 +114,590 @@
     "install myself in the Image classes fileFormat table
      for the `.tiff' and `.tif' extensions."
 
-    MIMETypes defineImageType:'image/tiff' suffix:'tif'  reader:self.
+    MIMETypes defineImageType:'image/tiff' suffix:'tif'  reader:self info:'tiff image'.
     MIMETypes defineImageType:nil          suffix:'tiff' reader:self.
 
+    MIMETypes defineImageType:'image/x-adobe-dng' suffix:'dng' reader:self info:'digital negative image'.
+
+    COMPRESSION_NONE            := 1.
+    COMPRESSION_CCITTRLE        := 2.
+    COMPRESSION_CCITTFAX3       := 3.
+    COMPRESSION_CCITTFAX4       := 4.
+    COMPRESSION_LZW             := 5.
+    COMPRESSION_OJPEG           := 6. "/ (old style jpeg)
+    COMPRESSION_JPEG            := 7. "/ (new style jpeg)
+    COMPRESSION_ADOBE_DEFLATE   := 8.
+    COMPRESSION_JBIG_T85        := 9.  "/ (ITU-T T85)
+    COMPRESSION_JBIG_T43        := 10. "/ (ITU-T T43)
+
+    COMPRESSION_NEXT            := 32766. "/ (NeXT 2-bit encoding)
+    COMPRESSION_CCITTRLEW       := 32771.
+    COMPRESSION_PACKBITS        := 32773.
+    COMPRESSION_THUNDERSCAN     := 32809. "/ (ThunderScan 4-bit encoding)
+    COMPRESSION_NEXT_JPEG       := 32865. "/ (NeXT jpeg encoding)
+    COMPRESSION_IT8CTPAD        := 32895.  
+    COMPRESSION_IT8LW           := 32896.
+    COMPRESSION_IT8MP           := 32897. 
+    COMPRESSION_IT8BL           := 32898. 
+    COMPRESSION_PIXARFILM       := 32908.
+    COMPRESSION_PIXARLOG        := 32909. "/ (Pixar companded 11-bit ZIP encoding)
+    COMPRESSION_DEFLATE         := 32946. "/ (PKZIP-style Deflate encoding)
+    COMPRESSION_DCS             := 32947. "/ (kodac)
+    COMPRESSION_JBIG            := 34661.
+    COMPRESSION_SGILOG          := 34676. "/ (SGI 32-bit Log Luminance encoding)
+    COMPRESSION_SGILOG24        := 34677. "/ (SGI 24-bit Log Luminance encoding)
+    COMPRESSION_JPEG2000        := 34712. "/ JPEG2000
+    COMPRESSION_NIKON_NEF       := 34713.
+    COMPRESSION_JBIG2           := 34715.
+    
+    SAMPLEFORMAT_UINT           := 1.       "/ !!unsigned integer data 
+    SAMPLEFORMAT_INT            := 2.       "/ !!signed integer data 
+    SAMPLEFORMAT_IEEEFP         := 3.       "/ !!IEEE floating point data 
+    SAMPLEFORMAT_VOID           := 4.       "/ !!untyped data 
+    SAMPLEFORMAT_COMPLEXINT     := 5.       "/ !!complex signed int 
+    SAMPLEFORMAT_COMPLEXIEEEFP  := 6.       "/ !!complex ieee floating 
+
+    PLANARCONFIG_CONTIG         := 1.
+    PLANARCONFIG_SEPARATE       := 2.
+
+    FILETYPE_MASK_REDUCEDIMAGE  := 1.
+    FILETYPE_MASK_PAGE          := 2.
+    FILETYPE_MASK_MASK          := 4. 
+
+"/    TYPE_NOTYPE := 0.           "/ placeholder 
+"/    TYPE_BYTE   := 1.           "/ 8-bit unsigned integer 
+"/    TYPE_ASCII  := 2.           "/ 8-bit bytes w/ last byte null 
+"/    TYPE_SHORT  := 3.           "/ 16-bit unsigned integer 
+"/    TYPE_LONG   := 4.           "/ 32-bit unsigned integer 
+"/    TYPE_RATIONAL := 5.         "/ 64-bit unsigned fraction 
+"/    TYPE_SBYTE  := 6.           "/ !!8-bit signed integer 
+"/    TYPE_UNDEFINED  := 7.       "/ !!8-bit untyped data 
+"/    TYPE_SSHORT     := 8.       "/ !!16-bit signed integer 
+"/    TYPE_SLONG      := 9.       "/ !!32-bit signed integer 
+"/    TYPE_SRATIONAL  := 10.      "/ !!64-bit signed fraction 
+"/    TYPE_FLOAT      := 11.      "/ !!32-bit IEEE floating point 
+"/    TYPE_DOUBLE     := 12.      "/ !!64-bit IEEE floating point 
+"/    TYPE_IFD        := 13.      "/ %32-bit unsigned integer (offset) 
+"/    TYPE_LONG8      := 16.      "/ BigTIFF 64-bit unsigned integer 
+"/    TYPE_SLONG8     := 17.      "/ BigTIFF 64-bit signed integer 
+"/    TYPE_IFD8       := 18.      "/ BigTIFF 64-bit unsigned integer (offset) 
+
+    "/
+    "/ TIFF tags
+    "/
+    
+"/    #define TIFFTAG_SUBFILETYPE             254     /* subfile data descriptor */
+"/    #define     FILETYPE_REDUCEDIMAGE       0x1     /* reduced resolution version */
+"/    #define     FILETYPE_PAGE               0x2     /* one page of many */
+"/    #define     FILETYPE_MASK               0x4     /* transparency mask */
+"/    #define TIFFTAG_OSUBFILETYPE            255     /* +kind of data in subfile */
+"/    #define     OFILETYPE_IMAGE             1       /* full resolution image data */
+"/    #define     OFILETYPE_REDUCEDIMAGE      2       /* reduced size image data */
+"/    #define     OFILETYPE_PAGE              3       /* one page of many */
+"/    #define TIFFTAG_IMAGEWIDTH              256     /* image width in pixels */
+"/    #define TIFFTAG_IMAGELENGTH             257     /* image height in pixels */
+"/    #define TIFFTAG_BITSPERSAMPLE           258     /* bits per channel (sample) */
+"/    #define TIFFTAG_COMPRESSION             259     /* data compression technique */
+"/    #define     COMPRESSION_NONE            1       /* dump mode */
+"/    #define     COMPRESSION_CCITTRLE        2       /* CCITT modified Huffman RLE */
+"/    #define     COMPRESSION_CCITTFAX3       3       /* CCITT Group 3 fax encoding */
+"/    #define     COMPRESSION_CCITT_T4        3       /* CCITT T.4 (TIFF 6 name) */
+"/    #define     COMPRESSION_CCITTFAX4       4       /* CCITT Group 4 fax encoding */
+"/    #define     COMPRESSION_CCITT_T6        4       /* CCITT T.6 (TIFF 6 name) */
+"/    #define     COMPRESSION_LZW             5       /* Lempel-Ziv  & Welch */
+"/    #define     COMPRESSION_OJPEG           6       /* !!6.0 JPEG */
+"/    #define     COMPRESSION_JPEG            7       /* %JPEG DCT compression */
+"/    #define     COMPRESSION_T85                     9       /* !!TIFF/FX T.85 JBIG compression */
+"/    #define     COMPRESSION_T43                     10      /* !!TIFF/FX T.43 colour by layered JBIG compression */
+"/    #define     COMPRESSION_NEXT            32766   /* NeXT 2-bit RLE */
+"/    #define     COMPRESSION_CCITTRLEW       32771   /* #1 w/ word alignment */
+"/    #define     COMPRESSION_PACKBITS        32773   /* Macintosh RLE */
+"/    #define     COMPRESSION_THUNDERSCAN     32809   /* ThunderScan RLE */
+"/    /* codes 32895-32898 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+"/    #define     COMPRESSION_IT8CTPAD        32895   /* IT8 CT w/padding */
+"/    #define     COMPRESSION_IT8LW           32896   /* IT8 Linework RLE */
+"/    #define     COMPRESSION_IT8MP           32897   /* IT8 Monochrome picture */
+"/    #define     COMPRESSION_IT8BL           32898   /* IT8 Binary line art */
+"/    /* compression codes 32908-32911 are reserved for Pixar */
+"/    #define     COMPRESSION_PIXARFILM       32908   /* Pixar companded 10bit LZW */
+"/    #define     COMPRESSION_PIXARLOG        32909   /* Pixar companded 11bit ZIP */
+"/    #define     COMPRESSION_DEFLATE         32946   /* Deflate compression */
+"/    #define     COMPRESSION_ADOBE_DEFLATE   8       /* Deflate compression,
+"/                                                       as recognized by Adobe */
+"/    /* compression code 32947 is reserved for Oceana Matrix <dev@oceana.com> */
+"/    #define     COMPRESSION_DCS             32947   /* Kodak DCS encoding */
+"/    #define     COMPRESSION_JBIG            34661   /* ISO JBIG */
+"/    #define     COMPRESSION_SGILOG          34676   /* SGI Log Luminance RLE */
+"/    #define     COMPRESSION_SGILOG24        34677   /* SGI Log 24-bit packed */
+"/    #define     COMPRESSION_JP2000          34712   /* Leadtools JPEG2000 */
+"/    #define     COMPRESSION_LZMA            34925   /* LZMA2 */
+"/    #define TIFFTAG_PHOTOMETRIC             262     /* photometric interpretation */
+"/    #define     PHOTOMETRIC_MINISWHITE      0       /* min value is white */
+"/    #define     PHOTOMETRIC_MINISBLACK      1       /* min value is black */
+"/    #define     PHOTOMETRIC_RGB             2       /* RGB color model */
+"/    #define     PHOTOMETRIC_PALETTE         3       /* color map indexed */
+"/    #define     PHOTOMETRIC_MASK            4       /* $holdout mask */
+"/    #define     PHOTOMETRIC_SEPARATED       5       /* !!color separations */
+"/    #define     PHOTOMETRIC_YCBCR           6       /* !!CCIR 601 */
+"/    #define     PHOTOMETRIC_CIELAB          8       /* !!1976 CIE L*a*b* */
+"/    #define     PHOTOMETRIC_ICCLAB          9       /* ICC L*a*b* [Adobe TIFF Technote 4] */
+"/    #define     PHOTOMETRIC_ITULAB          10      /* ITU L*a*b* */
+"/    #define     PHOTOMETRIC_CFA             32803   /* color filter array */
+"/    #define     PHOTOMETRIC_LOGL            32844   /* CIE Log2(L) */
+"/    #define     PHOTOMETRIC_LOGLUV          32845   /* CIE Log2(L) (u',v') */
+"/    #define TIFFTAG_THRESHHOLDING           263     /* +thresholding used on data */
+"/    #define     THRESHHOLD_BILEVEL          1       /* b&w art scan */
+"/    #define     THRESHHOLD_HALFTONE         2       /* or dithered scan */
+"/    #define     THRESHHOLD_ERRORDIFFUSE     3       /* usually floyd-steinberg */
+"/    #define TIFFTAG_CELLWIDTH               264     /* +dithering matrix width */
+"/    #define TIFFTAG_CELLLENGTH              265     /* +dithering matrix height */
+"/    #define TIFFTAG_FILLORDER               266     /* data order within a byte */
+"/    #define     FILLORDER_MSB2LSB           1       /* most significant -> least */
+"/    #define     FILLORDER_LSB2MSB           2       /* least significant -> most */
+"/    #define TIFFTAG_DOCUMENTNAME            269     /* name of doc. image is from */
+"/    #define TIFFTAG_IMAGEDESCRIPTION        270     /* info about image */
+"/    #define TIFFTAG_MAKE                    271     /* scanner manufacturer name */
+"/    #define TIFFTAG_MODEL                   272     /* scanner model name/number */
+"/    #define TIFFTAG_STRIPOFFSETS            273     /* offsets to data strips */
+"/    #define TIFFTAG_ORIENTATION             274     /* +image orientation */
+"/    #define     ORIENTATION_TOPLEFT         1       /* row 0 top, col 0 lhs */
+"/    #define     ORIENTATION_TOPRIGHT        2       /* row 0 top, col 0 rhs */
+"/    #define     ORIENTATION_BOTRIGHT        3       /* row 0 bottom, col 0 rhs */
+"/    #define     ORIENTATION_BOTLEFT         4       /* row 0 bottom, col 0 lhs */
+"/    #define     ORIENTATION_LEFTTOP         5       /* row 0 lhs, col 0 top */
+"/    #define     ORIENTATION_RIGHTTOP        6       /* row 0 rhs, col 0 top */
+"/    #define     ORIENTATION_RIGHTBOT        7       /* row 0 rhs, col 0 bottom */
+"/    #define     ORIENTATION_LEFTBOT         8       /* row 0 lhs, col 0 bottom */
+"/    #define TIFFTAG_SAMPLESPERPIXEL         277     /* samples per pixel */
+"/    #define TIFFTAG_ROWSPERSTRIP            278     /* rows per strip of data */
+"/    #define TIFFTAG_STRIPBYTECOUNTS         279     /* bytes counts for strips */
+"/    #define TIFFTAG_MINSAMPLEVALUE          280     /* +minimum sample value */
+"/    #define TIFFTAG_MAXSAMPLEVALUE          281     /* +maximum sample value */
+"/    #define TIFFTAG_XRESOLUTION             282     /* pixels/resolution in x */
+"/    #define TIFFTAG_YRESOLUTION             283     /* pixels/resolution in y */
+"/    #define TIFFTAG_PLANARCONFIG            284     /* storage organization */
+"/    #define     PLANARCONFIG_CONTIG         1       /* single image plane */
+"/    #define     PLANARCONFIG_SEPARATE       2       /* separate planes of data */
+"/    #define TIFFTAG_PAGENAME                285     /* page name image is from */
+"/    #define TIFFTAG_XPOSITION               286     /* x page offset of image lhs */
+"/    #define TIFFTAG_YPOSITION               287     /* y page offset of image lhs */
+"/    #define TIFFTAG_FREEOFFSETS             288     /* +byte offset to free block */
+"/    #define TIFFTAG_FREEBYTECOUNTS          289     /* +sizes of free blocks */
+"/    #define TIFFTAG_GRAYRESPONSEUNIT        290     /* $gray scale curve accuracy */
+"/    #define     GRAYRESPONSEUNIT_10S        1       /* tenths of a unit */
+"/    #define     GRAYRESPONSEUNIT_100S       2       /* hundredths of a unit */
+"/    #define     GRAYRESPONSEUNIT_1000S      3       /* thousandths of a unit */
+"/    #define     GRAYRESPONSEUNIT_10000S     4       /* ten-thousandths of a unit */
+"/    #define     GRAYRESPONSEUNIT_100000S    5       /* hundred-thousandths */
+"/    #define TIFFTAG_GRAYRESPONSECURVE       291     /* $gray scale response curve */
+"/    #define TIFFTAG_GROUP3OPTIONS           292     /* 32 flag bits */
+"/    #define TIFFTAG_T4OPTIONS               292     /* TIFF 6.0 proper name alias */
+"/    #define     GROUP3OPT_2DENCODING        0x1     /* 2-dimensional coding */
+"/    #define     GROUP3OPT_UNCOMPRESSED      0x2     /* data not compressed */
+"/    #define     GROUP3OPT_FILLBITS          0x4     /* fill to byte boundary */
+"/    #define TIFFTAG_GROUP4OPTIONS           293     /* 32 flag bits */
+"/    #define TIFFTAG_T6OPTIONS               293     /* TIFF 6.0 proper name */
+"/    #define     GROUP4OPT_UNCOMPRESSED      0x2     /* data not compressed */
+"/    #define TIFFTAG_RESOLUTIONUNIT          296     /* units of resolutions */
+"/    #define     RESUNIT_NONE                1       /* no meaningful units */
+"/    #define     RESUNIT_INCH                2       /* english */
+"/    #define     RESUNIT_CENTIMETER          3       /* metric */
+"/    #define TIFFTAG_PAGENUMBER              297     /* page numbers of multi-page */
+"/    #define TIFFTAG_COLORRESPONSEUNIT       300     /* $color curve accuracy */
+"/    #define     COLORRESPONSEUNIT_10S       1       /* tenths of a unit */
+"/    #define     COLORRESPONSEUNIT_100S      2       /* hundredths of a unit */
+"/    #define     COLORRESPONSEUNIT_1000S     3       /* thousandths of a unit */
+"/    #define     COLORRESPONSEUNIT_10000S    4       /* ten-thousandths of a unit */
+"/    #define     COLORRESPONSEUNIT_100000S   5       /* hundred-thousandths */
+"/    #define TIFFTAG_TRANSFERFUNCTION        301     /* !!colorimetry info */
+"/    #define TIFFTAG_SOFTWARE                305     /* name & release */
+"/    #define TIFFTAG_DATETIME                306     /* creation date and time */
+"/    #define TIFFTAG_ARTIST                  315     /* creator of image */
+"/    #define TIFFTAG_HOSTCOMPUTER            316     /* machine where created */
+"/    #define TIFFTAG_PREDICTOR               317     /* prediction scheme w/ LZW */
+"/    #define     PREDICTOR_NONE              1       /* no prediction scheme used */
+"/    #define     PREDICTOR_HORIZONTAL        2       /* horizontal differencing */
+"/    #define     PREDICTOR_FLOATINGPOINT     3       /* floating point predictor */
+"/    #define TIFFTAG_WHITEPOINT              318     /* image white point */
+"/    #define TIFFTAG_PRIMARYCHROMATICITIES   319     /* !!primary chromaticities */
+"/    #define TIFFTAG_COLORMAP                320     /* RGB map for palette image */
+"/    #define TIFFTAG_HALFTONEHINTS           321     /* !!highlight+shadow info */
+"/    #define TIFFTAG_TILEWIDTH               322     /* !!tile width in pixels */
+"/    #define TIFFTAG_TILELENGTH              323     /* !!tile height in pixels */
+"/    #define TIFFTAG_TILEOFFSETS             324     /* !!offsets to data tiles */
+"/    #define TIFFTAG_TILEBYTECOUNTS          325     /* !!byte counts for tiles */
+"/    #define TIFFTAG_BADFAXLINES             326     /* lines w/ wrong pixel count */
+"/    #define TIFFTAG_CLEANFAXDATA            327     /* regenerated line info */
+"/    #define     CLEANFAXDATA_CLEAN          0       /* no errors detected */
+"/    #define     CLEANFAXDATA_REGENERATED    1       /* receiver regenerated lines */
+"/    #define     CLEANFAXDATA_UNCLEAN        2       /* uncorrected errors exist */
+"/    #define TIFFTAG_CONSECUTIVEBADFAXLINES  328     /* max consecutive bad lines */
+"/    #define TIFFTAG_SUBIFD                  330     /* subimage descriptors */
+"/    #define TIFFTAG_INKSET                  332     /* !!inks in separated image */
+"/    #define     INKSET_CMYK                 1       /* !!cyan-magenta-yellow-black color */
+"/    #define     INKSET_MULTIINK             2       /* !!multi-ink or hi-fi color */
+"/    #define TIFFTAG_INKNAMES                333     /* !!ascii names of inks */
+"/    #define TIFFTAG_NUMBEROFINKS            334     /* !!number of inks */
+"/    #define TIFFTAG_DOTRANGE                336     /* !!0% and 100% dot codes */
+"/    #define TIFFTAG_TARGETPRINTER           337     /* !!separation target */
+"/    #define TIFFTAG_EXTRASAMPLES            338     /* !!info about extra samples */
+"/    #define     EXTRASAMPLE_UNSPECIFIED     0       /* !!unspecified data */
+"/    #define     EXTRASAMPLE_ASSOCALPHA      1       /* !!associated alpha data */
+"/    #define     EXTRASAMPLE_UNASSALPHA      2       /* !!unassociated alpha data */
+"/    #define TIFFTAG_SAMPLEFORMAT            339     /* !!data sample format */
+"/    #define     SAMPLEFORMAT_UINT           1       /* !!unsigned integer data */
+"/    #define     SAMPLEFORMAT_INT            2       /* !!signed integer data */
+"/    #define     SAMPLEFORMAT_IEEEFP         3       /* !!IEEE floating point data */
+"/    #define     SAMPLEFORMAT_VOID           4       /* !!untyped data */
+"/    #define     SAMPLEFORMAT_COMPLEXINT     5       /* !!complex signed int */
+"/    #define     SAMPLEFORMAT_COMPLEXIEEEFP  6       /* !!complex ieee floating */
+"/    #define TIFFTAG_SMINSAMPLEVALUE         340     /* !!variable MinSampleValue */
+"/    #define TIFFTAG_SMAXSAMPLEVALUE         341     /* !!variable MaxSampleValue */
+"/    #define TIFFTAG_CLIPPATH                343     /* %ClipPath
+"/                                                       [Adobe TIFF technote 2] */
+"/    #define TIFFTAG_XCLIPPATHUNITS          344     /* %XClipPathUnits
+"/                                                       [Adobe TIFF technote 2] */
+"/    #define TIFFTAG_YCLIPPATHUNITS          345     /* %YClipPathUnits
+"/                                                       [Adobe TIFF technote 2] */
+"/    #define TIFFTAG_INDEXED                 346     /* %Indexed
+"/                                                       [Adobe TIFF Technote 3] */
+"/    #define TIFFTAG_JPEGTABLES              347     /* %JPEG table stream */
+"/    #define TIFFTAG_OPIPROXY                351     /* %OPI Proxy [Adobe TIFF technote] */
+"/    /* Tags 400-435 are from the TIFF/FX spec */
+"/    #define TIFFTAG_GLOBALPARAMETERSIFD     400     /* !! */
+"/    #define TIFFTAG_PROFILETYPE                     401     /* !! */
+"/    #define     PROFILETYPE_UNSPECIFIED     0       /* !! */
+"/    #define     PROFILETYPE_G3_FAX          1       /* !! */
+"/    #define TIFFTAG_FAXPROFILE                      402     /* !! */
+"/    #define     FAXPROFILE_S                        1       /* !!TIFF/FX FAX profile S */
+"/    #define     FAXPROFILE_F                        2       /* !!TIFF/FX FAX profile F */
+"/    #define     FAXPROFILE_J                        3       /* !!TIFF/FX FAX profile J */
+"/    #define     FAXPROFILE_C                        4       /* !!TIFF/FX FAX profile C */
+"/    #define     FAXPROFILE_L                        5       /* !!TIFF/FX FAX profile L */
+"/    #define     FAXPROFILE_M                        6       /* !!TIFF/FX FAX profile LM */
+"/    #define TIFFTAG_CODINGMETHODS           403     /* !!TIFF/FX coding methods */
+"/    #define     CODINGMETHODS_T4_1D         (1 << 1)        /* !!T.4 1D */
+"/    #define     CODINGMETHODS_T4_2D         (1 << 2)        /* !!T.4 2D */
+"/    #define     CODINGMETHODS_T6            (1 << 3)        /* !!T.6 */
+"/    #define     CODINGMETHODS_T85           (1 << 4)        /* !!T.85 JBIG */
+"/    #define     CODINGMETHODS_T42           (1 << 5)        /* !!T.42 JPEG */
+"/    #define     CODINGMETHODS_T43           (1 << 6)        /* !!T.43 colour by layered JBIG */
+"/    #define TIFFTAG_VERSIONYEAR                     404     /* !!TIFF/FX version year */
+"/    #define TIFFTAG_MODENUMBER                      405     /* !!TIFF/FX mode number */
+"/    #define TIFFTAG_DECODE                          433     /* !!TIFF/FX decode */
+"/    #define TIFFTAG_IMAGEBASECOLOR          434     /* !!TIFF/FX image base colour */
+"/    #define TIFFTAG_T82OPTIONS                      435     /* !!TIFF/FX T.82 options */
+"/    /*
+"/     * Tags 512-521 are obsoleted by Technical Note #2 which specifies a
+"/     * revised JPEG-in-TIFF scheme.
+"/     */
+"/    #define TIFFTAG_JPEGPROC                512     /* !!JPEG processing algorithm */
+"/    #define     JPEGPROC_BASELINE           1       /* !!baseline sequential */
+"/    #define     JPEGPROC_LOSSLESS           14      /* !!Huffman coded lossless */
+"/    #define TIFFTAG_JPEGIFOFFSET            513     /* !!pointer to SOI marker */
+"/    #define TIFFTAG_JPEGIFBYTECOUNT         514     /* !!JFIF stream length */
+"/    #define TIFFTAG_JPEGRESTARTINTERVAL     515     /* !!restart interval length */
+"/    #define TIFFTAG_JPEGLOSSLESSPREDICTORS  517     /* !!lossless proc predictor */
+"/    #define TIFFTAG_JPEGPOINTTRANSFORM      518     /* !!lossless point transform */
+"/    #define TIFFTAG_JPEGQTABLES             519     /* !!Q matrix offsets */
+"/    #define TIFFTAG_JPEGDCTABLES            520     /* !!DCT table offsets */
+"/    #define TIFFTAG_JPEGACTABLES            521     /* !!AC coefficient offsets */
+"/    #define TIFFTAG_YCBCRCOEFFICIENTS       529     /* !!RGB -> YCbCr transform */
+"/    #define TIFFTAG_YCBCRSUBSAMPLING        530     /* !!YCbCr subsampling factors */
+"/    #define TIFFTAG_YCBCRPOSITIONING        531     /* !!subsample positioning */
+"/    #define     YCBCRPOSITION_CENTERED      1       /* !!as in PostScript Level 2 */
+"/    #define     YCBCRPOSITION_COSITED       2       /* !!as in CCIR 601-1 */
+"/    #define TIFFTAG_REFERENCEBLACKWHITE     532     /* !!colorimetry info */
+"/    #define TIFFTAG_STRIPROWCOUNTS          559 /* !!TIFF/FX strip row counts */
+"/    #define TIFFTAG_XMLPACKET               700     /* %XML packet
+"/                                                       [Adobe XMP Specification,
+"/                                                       January 2004 */
+"/    #define TIFFTAG_OPIIMAGEID              32781   /* %OPI ImageID
+"/                                                       [Adobe TIFF technote] */
+
+"/    /* tags 32952-32956 are private tags registered to Island Graphics */
+"/    #define TIFFTAG_REFPTS                  32953   /* image reference points */
+"/    #define TIFFTAG_REGIONTACKPOINT         32954   /* region-xform tack point */
+"/    #define TIFFTAG_REGIONWARPCORNERS       32955   /* warp quadrilateral */
+"/    #define TIFFTAG_REGIONAFFINE            32956   /* affine transformation mat */
+
+"/    /* tags 32995-32999 are private tags registered to SGI */
+"/    #define TIFFTAG_MATTEING                32995   /* $use ExtraSamples */
+"/    #define TIFFTAG_DATATYPE                32996   /* $use SampleFormat */
+"/    #define TIFFTAG_IMAGEDEPTH              32997   /* z depth of image */
+"/    #define TIFFTAG_TILEDEPTH               32998   /* z depth/data tile */
+
+"/    /* tags 33300-33309 are private tags registered to Pixar */
+"/    /*
+"/     * TIFFTAG_PIXAR_IMAGEFULLWIDTH and TIFFTAG_PIXAR_IMAGEFULLLENGTH
+"/     * are set when an image has been cropped out of a larger image.  
+"/     * They reflect the size of the original uncropped image.
+"/     * The TIFFTAG_XPOSITION and TIFFTAG_YPOSITION can be used
+"/     * to determine the position of the smaller image in the larger one.
+"/     */
+"/    #define TIFFTAG_PIXAR_IMAGEFULLWIDTH    33300   /* full image size in x */
+"/    #define TIFFTAG_PIXAR_IMAGEFULLLENGTH   33301   /* full image size in y */
+"/     /* Tags 33302-33306 are used to identify special image modes and data
+"/      * used by Pixar's texture formats.
+"/      */
+"/    #define TIFFTAG_PIXAR_TEXTUREFORMAT     33302   /* texture map format */
+"/    #define TIFFTAG_PIXAR_WRAPMODES         33303   /* s & t wrap modes */
+"/    #define TIFFTAG_PIXAR_FOVCOT            33304   /* cotan(fov) for env. maps */
+"/    #define TIFFTAG_PIXAR_MATRIX_WORLDTOSCREEN 33305
+"/    #define TIFFTAG_PIXAR_MATRIX_WORLDTOCAMERA 33306
+
+"/    /* tag 33405 is a private tag registered to Eastman Kodak */
+"/    #define TIFFTAG_WRITERSERIALNUMBER      33405   /* device serial number */
+
+"/    #define TIFFTAG_CFAREPEATPATTERNDIM     33421   /* dimensions of CFA pattern */
+"/    #define TIFFTAG_CFAPATTERN              33422   /* color filter array pattern */
+"/    /* tag 33432 is listed in the 6.0 spec w/ unknown ownership */
+"/    #define TIFFTAG_COPYRIGHT               33432   /* copyright string */
+"/    /* IPTC TAG from RichTIFF specifications */
+"/    #define TIFFTAG_RICHTIFFIPTC            33723
+"/    /* 34016-34029 are reserved for ANSI IT8 TIFF/IT <dkelly@apago.com) */
+"/    #define TIFFTAG_IT8SITE                 34016   /* site name */
+"/    #define TIFFTAG_IT8COLORSEQUENCE        34017   /* color seq. [RGB,CMYK,etc] */
+"/    #define TIFFTAG_IT8HEADER               34018   /* DDES Header */
+"/    #define TIFFTAG_IT8RASTERPADDING        34019   /* raster scanline padding */
+"/    #define TIFFTAG_IT8BITSPERRUNLENGTH     34020   /* # of bits in short run */
+"/    #define TIFFTAG_IT8BITSPEREXTENDEDRUNLENGTH 34021/* # of bits in long run */
+"/    #define TIFFTAG_IT8COLORTABLE           34022   /* LW colortable */
+"/    #define TIFFTAG_IT8IMAGECOLORINDICATOR  34023   /* BP/BL image color switch */
+"/    #define TIFFTAG_IT8BKGCOLORINDICATOR    34024   /* BP/BL bg color switch */
+"/    #define TIFFTAG_IT8IMAGECOLORVALUE      34025   /* BP/BL image color value */
+"/    #define TIFFTAG_IT8BKGCOLORVALUE        34026   /* BP/BL bg color value */
+"/    #define TIFFTAG_IT8PIXELINTENSITYRANGE  34027   /* MP pixel intensity value */
+"/    #define TIFFTAG_IT8TRANSPARENCYINDICATOR 34028  /* HC transparency switch */
+"/    #define TIFFTAG_IT8COLORCHARACTERIZATION 34029  /* color character. table */
+"/    #define TIFFTAG_IT8HCUSAGE              34030   /* HC usage indicator */
+"/    #define TIFFTAG_IT8TRAPINDICATOR        34031   /* Trapping indicator
+"/                                                       (untrapped=0, trapped=1) */
+"/    #define TIFFTAG_IT8CMYKEQUIVALENT       34032   /* CMYK color equivalents */
+
+"/    /* tags 34232-34236 are private tags registered to Texas Instruments */
+"/    #define TIFFTAG_FRAMECOUNT              34232   /* Sequence Frame Count */
+
+"/    /* tag 34377 is private tag registered to Adobe for PhotoShop */
+"/    #define TIFFTAG_PHOTOSHOP               34377 
+
+"/    /* tags 34665, 34853 and 40965 are documented in EXIF specification */
+"/    #define TIFFTAG_EXIFIFD                 34665   /* Pointer to EXIF private directory */
+
+"/    /* tag 34750 is a private tag registered to Adobe? */
+"/    #define TIFFTAG_ICCPROFILE              34675   /* ICC profile data */
+"/    #define TIFFTAG_IMAGELAYER              34732   /* !!TIFF/FX image layer information */
+
+"/    /* tag 34750 is a private tag registered to Pixel Magic */
+"/    #define TIFFTAG_JBIGOPTIONS             34750   /* JBIG options */
+"/    #define TIFFTAG_GPSIFD                  34853   /* Pointer to GPS private directory */
+
+"/    /* tags 34908-34914 are private tags registered to SGI */
+"/    #define TIFFTAG_FAXRECVPARAMS           34908   /* encoded Class 2 ses. parms */
+"/    #define TIFFTAG_FAXSUBADDRESS           34909   /* received SubAddr string */
+"/    #define TIFFTAG_FAXRECVTIME             34910   /* receive time (secs) */
+"/    #define TIFFTAG_FAXDCS                  34911   /* encoded fax ses. params, Table 2/T.30 */
+
+"/    /* tags 37439-37443 are registered to SGI <gregl@sgi.com> */
+"/    #define TIFFTAG_STONITS                 37439   /* Sample value to Nits */
+
+"/    /* tag 34929 is a private tag registered to FedEx */
+"/    #define TIFFTAG_FEDEX_EDR               34929   /* unknown use */
+"/    #define TIFFTAG_INTEROPERABILITYIFD     40965   /* Pointer to Interoperability private directory */
+
+    "/
+    "/ Adobe Digital Negative (DNG) format tags
+    "/
+
+"/    #define TIFFTAG_DNGVERSION              50706   /* &DNG version number */
+"/    #define TIFFTAG_DNGBACKWARDVERSION      50707   /* &DNG compatibility version */
+"/    #define TIFFTAG_UNIQUECAMERAMODEL       50708   /* &name for the camera model */
+"/    #define TIFFTAG_LOCALIZEDCAMERAMODEL    50709   /* &localized camera model name */
+"/    #define TIFFTAG_CFAPLANECOLOR           50710   /* &CFAPattern->LinearRaw space mapping */
+"/    #define TIFFTAG_CFALAYOUT               50711   /* &spatial layout of the CFA */
+"/    #define TIFFTAG_LINEARIZATIONTABLE      50712   /* &lookup table description */
+"/    #define TIFFTAG_BLACKLEVELREPEATDIM     50713   /* &repeat pattern size for the BlackLevel tag */
+"/    #define TIFFTAG_BLACKLEVEL              50714   /* &zero light encoding level */
+"/    #define TIFFTAG_BLACKLEVELDELTAH        50715   /* &zero light encoding level differences (columns) */
+"/    #define TIFFTAG_BLACKLEVELDELTAV        50716   /* &zero light encoding level differences (rows) */
+"/    #define TIFFTAG_WHITELEVEL              50717   /* &fully saturated encoding level */
+"/    #define TIFFTAG_DEFAULTSCALE            50718   /* &default scale factors */
+"/    #define TIFFTAG_DEFAULTCROPORIGIN       50719   /* &origin of the final image area */
+"/    #define TIFFTAG_DEFAULTCROPSIZE         50720   /* &size of the final image area */
+"/    #define TIFFTAG_COLORMATRIX1            50721   /* &XYZ->reference color space transformation matrix 1 */
+"/    #define TIFFTAG_COLORMATRIX2            50722   /* &XYZ->reference color space transformation matrix 2 */
+"/    #define TIFFTAG_CAMERACALIBRATION1      50723   /* &calibration matrix 1 */
+"/    #define TIFFTAG_CAMERACALIBRATION2      50724   /* &calibration matrix 2 */
+"/    #define TIFFTAG_REDUCTIONMATRIX1        50725   /* &dimensionality reduction matrix 1 */
+"/    #define TIFFTAG_REDUCTIONMATRIX2        50726   /* &dimensionality reduction matrix 2 */
+"/    #define TIFFTAG_ANALOGBALANCE           50727   /* &gain applied the stored raw values*/
+"/    #define TIFFTAG_ASSHOTNEUTRAL           50728   /* &selected white balance in linear reference space */
+"/    #define TIFFTAG_ASSHOTWHITEXY           50729   /* &selected white balance in x-y chromaticity coordinates */
+"/    #define TIFFTAG_BASELINEEXPOSURE        50730   /* &how much to move the zero point */
+"/    #define TIFFTAG_BASELINENOISE           50731   /* &relative noise level */
+"/    #define TIFFTAG_BASELINESHARPNESS       50732   /* &relative amount of sharpening */
+"/    #define TIFFTAG_BAYERGREENSPLIT         50733   /* &how closely the values of the green pixels in the blue/green rows track the values of the green pixels in the red/green rows */
+"/    #define TIFFTAG_LINEARRESPONSELIMIT     50734   /* &non-linear encoding range */
+"/    #define TIFFTAG_CAMERASERIALNUMBER      50735   /* &camera's serial number */
+"/    #define TIFFTAG_LENSINFO                50736   /* info about the lens */
+"/    #define TIFFTAG_CHROMABLURRADIUS        50737   /* &chroma blur radius */
+"/    #define TIFFTAG_ANTIALIASSTRENGTH       50738   /* &relative strength of the camera's anti-alias filter */
+"/    #define TIFFTAG_SHADOWSCALE             50739   /* &used by Adobe Camera Raw */
+"/    #define TIFFTAG_DNGPRIVATEDATA          50740   /* &manufacturer's private data */
+"/    #define TIFFTAG_MAKERNOTESAFETY         50741   /* &whether the EXIF MakerNote tag is safe to preserve along with the rest of the EXIF data */
+"/    #define TIFFTAG_CALIBRATIONILLUMINANT1  50778   /* &illuminant 1 */
+"/    #define TIFFTAG_CALIBRATIONILLUMINANT2  50779   /* &illuminant 2 */
+"/    #define TIFFTAG_BESTQUALITYSCALE        50780   /* &best quality multiplier */
+"/    #define TIFFTAG_RAWDATAUNIQUEID         50781   /* &unique identifier for the raw image data */
+"/    #define TIFFTAG_ORIGINALRAWFILENAME     50827   /* &file name of the original raw file */
+"/    #define TIFFTAG_ORIGINALRAWFILEDATA     50828   /* &contents of the original raw file */
+"/    #define TIFFTAG_ACTIVEAREA              50829   /* &active (non-masked) pixels of the sensor */
+"/    #define TIFFTAG_MASKEDAREAS             50830   /* &list of coordinates of fully masked pixels */
+"/    #define TIFFTAG_ASSHOTICCPROFILE        50831   /* &these two tags used to */
+"/    #define TIFFTAG_ASSHOTPREPROFILEMATRIX  50832   /* map cameras's color space into ICC profile space */
+"/    #define TIFFTAG_CURRENTICCPROFILE       50833   /* & */
+"/    #define TIFFTAG_CURRENTPREPROFILEMATRIX 50834   /* & */
+
+"/    /* tag 65535 is an undefined tag used by Eastman Kodak */
+"/    #define TIFFTAG_DCSHUESHIFTVALUES       65535   /* hue shift correction data */
+"/
+"/    /*
+"/     * The following are ``pseudo tags'' that can be used to control
+"/     * codec-specific functionality.  These tags are not written to file.
+"/     * Note that these values start at 0xffff+1 so that they'll never
+"/     * collide with Aldus-assigned tags.
+"/     *
+"/     * If you want your private pseudo tags ``registered'' (i.e. added to
+"/     * this file), please post a bug report via the tracking system at
+"/     * http://www.remotesensing.org/libtiff/bugs.html with the appropriate
+"/     * C definitions to add.
+"/     */
+"/    #define TIFFTAG_FAXMODE                 65536   /* Group 3/4 format control */
+"/    #define     FAXMODE_CLASSIC     0x0000          /* default, include RTC */
+"/    #define     FAXMODE_NORTC       0x0001          /* no RTC at end of data */
+"/    #define     FAXMODE_NOEOL       0x0002          /* no EOL code at end of row */
+"/    #define     FAXMODE_BYTEALIGN   0x0004          /* byte align row */
+"/    #define     FAXMODE_WORDALIGN   0x0008          /* word align row */
+"/    #define     FAXMODE_CLASSF      FAXMODE_NORTC   /* TIFF Class F */
+"/    #define TIFFTAG_JPEGQUALITY             65537   /* Compression quality level */
+"/    /* Note: quality level is on the IJG 0-100 scale.  Default value is 75 */
+"/    #define TIFFTAG_JPEGCOLORMODE           65538   /* Auto RGB<=>YCbCr convert? */
+"/    #define     JPEGCOLORMODE_RAW   0x0000          /* no conversion (default) */
+"/    #define     JPEGCOLORMODE_RGB   0x0001          /* do auto conversion */
+"/    #define TIFFTAG_JPEGTABLESMODE          65539   /* What to put in JPEGTables */
+"/    #define     JPEGTABLESMODE_QUANT 0x0001         /* include quantization tbls */
+"/    #define     JPEGTABLESMODE_HUFF 0x0002          /* include Huffman tbls */
+"/    /* Note: default is JPEGTABLESMODE_QUANT | JPEGTABLESMODE_HUFF */
+"/    #define TIFFTAG_FAXFILLFUNC             65540   /* G3/G4 fill function */
+"/    #define TIFFTAG_PIXARLOGDATAFMT         65549   /* PixarLogCodec I/O data sz */
+"/    #define     PIXARLOGDATAFMT_8BIT        0       /* regular u_char samples */
+"/    #define     PIXARLOGDATAFMT_8BITABGR    1       /* ABGR-order u_chars */
+"/    #define     PIXARLOGDATAFMT_11BITLOG    2       /* 11-bit log-encoded (raw) */
+"/    #define     PIXARLOGDATAFMT_12BITPICIO  3       /* as per PICIO (1.0==2048) */
+"/    #define     PIXARLOGDATAFMT_16BIT       4       /* signed short samples */
+"/    #define     PIXARLOGDATAFMT_FLOAT       5       /* IEEE float samples */
+"/    /* 65550-65556 are allocated to Oceana Matrix <dev@oceana.com> */
+"/    #define TIFFTAG_DCSIMAGERTYPE           65550   /* imager model & filter */
+"/    #define     DCSIMAGERMODEL_M3           0       /* M3 chip (1280 x 1024) */
+"/    #define     DCSIMAGERMODEL_M5           1       /* M5 chip (1536 x 1024) */
+"/    #define     DCSIMAGERMODEL_M6           2       /* M6 chip (3072 x 2048) */
+"/    #define     DCSIMAGERFILTER_IR          0       /* infrared filter */
+"/    #define     DCSIMAGERFILTER_MONO        1       /* monochrome filter */
+"/    #define     DCSIMAGERFILTER_CFA         2       /* color filter array */
+"/    #define     DCSIMAGERFILTER_OTHER       3       /* other filter */
+"/    #define TIFFTAG_DCSINTERPMODE           65551   /* interpolation mode */
+"/    #define     DCSINTERPMODE_NORMAL        0x0     /* whole image, default */
+"/    #define     DCSINTERPMODE_PREVIEW       0x1     /* preview of image (384x256) */
+"/    #define TIFFTAG_DCSBALANCEARRAY         65552   /* color balance values */
+"/    #define TIFFTAG_DCSCORRECTMATRIX        65553   /* color correction values */
+"/    #define TIFFTAG_DCSGAMMA                65554   /* gamma value */
+"/    #define TIFFTAG_DCSTOESHOULDERPTS       65555   /* toe & shoulder points */
+"/    #define TIFFTAG_DCSCALIBRATIONFD        65556   /* calibration file desc */
+"/    /* Note: quality level is on the ZLIB 1-9 scale. Default value is -1 */
+"/    #define TIFFTAG_ZIPQUALITY              65557   /* compression quality level */
+"/    #define TIFFTAG_PIXARLOGQUALITY         65558   /* PixarLog uses same scale */
+"/    /* 65559 is allocated to Oceana Matrix <dev@oceana.com> */
+"/    #define TIFFTAG_DCSCLIPRECTANGLE        65559   /* area of image to acquire */
+"/    #define TIFFTAG_SGILOGDATAFMT           65560   /* SGILog user data format */
+"/    #define     SGILOGDATAFMT_FLOAT         0       /* IEEE float samples */
+"/    #define     SGILOGDATAFMT_16BIT         1       /* 16-bit samples */
+"/    #define     SGILOGDATAFMT_RAW           2       /* uninterpreted data */
+"/    #define     SGILOGDATAFMT_8BIT          3       /* 8-bit RGB monitor values */
+"/    #define TIFFTAG_SGILOGENCODE            65561 /* SGILog data encoding control*/
+"/    #define     SGILOGENCODE_NODITHER       0     /* do not dither encoded values*/
+"/    #define     SGILOGENCODE_RANDITHER      1     /* randomly dither encd values */
+"/    #define TIFFTAG_LZMAPRESET              65562   /* LZMA2 preset (compression level) */
+"/    #define TIFFTAG_PERSAMPLE       65563   /* interface for per sample tags */
+"/    #define     PERSAMPLE_MERGED        0   /* present as a single value */
+"/    #define     PERSAMPLE_MULTI         1   /* present as multiple values */
+
+    "/
+    "/ EXIF tags
+    "/
+"/    #define EXIFTAG_EXPOSURETIME            33434   /* Exposure time */
+"/    #define EXIFTAG_FNUMBER                 33437   /* F number */
+"/    #define EXIFTAG_EXPOSUREPROGRAM         34850   /* Exposure program */
+"/    #define EXIFTAG_SPECTRALSENSITIVITY     34852   /* Spectral sensitivity */
+"/    #define EXIFTAG_ISOSPEEDRATINGS         34855   /* ISO speed rating */
+"/    #define EXIFTAG_OECF                    34856   /* Optoelectric conversion factor */
+"/    #define EXIFTAG_EXIFVERSION             36864   /* Exif version */
+"/    #define EXIFTAG_DATETIMEORIGINAL        36867   /* Date and time of original data generation */
+"/    #define EXIFTAG_DATETIMEDIGITIZED       36868   /* Date and time of digital data generation */
+"/    #define EXIFTAG_COMPONENTSCONFIGURATION 37121   /* Meaning of each component */
+"/    #define EXIFTAG_COMPRESSEDBITSPERPIXEL  37122   /* Image compression mode */
+"/    #define EXIFTAG_SHUTTERSPEEDVALUE       37377   /* Shutter speed */
+"/    #define EXIFTAG_APERTUREVALUE           37378   /* Aperture */
+"/    #define EXIFTAG_BRIGHTNESSVALUE         37379   /* Brightness */
+"/    #define EXIFTAG_EXPOSUREBIASVALUE       37380   /* Exposure bias */
+"/    #define EXIFTAG_MAXAPERTUREVALUE        37381   /* Maximum lens aperture */
+"/    #define EXIFTAG_SUBJECTDISTANCE         37382   /* Subject distance */
+"/    #define EXIFTAG_METERINGMODE            37383   /* Metering mode */
+"/    #define EXIFTAG_LIGHTSOURCE             37384   /* Light source */
+"/    #define EXIFTAG_FLASH                   37385   /* Flash */
+"/    #define EXIFTAG_FOCALLENGTH             37386   /* Lens focal length */
+"/    #define EXIFTAG_SUBJECTAREA             37396   /* Subject area */
+"/    #define EXIFTAG_MAKERNOTE               37500   /* Manufacturer notes */
+"/    #define EXIFTAG_USERCOMMENT             37510   /* User comments */
+"/    #define EXIFTAG_SUBSECTIME              37520   /* DateTime subseconds */
+"/    #define EXIFTAG_SUBSECTIMEORIGINAL      37521   /* DateTimeOriginal subseconds */
+"/    #define EXIFTAG_SUBSECTIMEDIGITIZED     37522   /* DateTimeDigitized subseconds */
+"/    #define EXIFTAG_FLASHPIXVERSION         40960   /* Supported Flashpix version */
+"/    #define EXIFTAG_COLORSPACE              40961   /* Color space information */
+"/    #define EXIFTAG_PIXELXDIMENSION         40962   /* Valid image width */
+"/    #define EXIFTAG_PIXELYDIMENSION         40963   /* Valid image height */
+"/    #define EXIFTAG_RELATEDSOUNDFILE        40964   /* Related audio file */
+"/    #define EXIFTAG_FLASHENERGY             41483   /* Flash energy */
+"/    #define EXIFTAG_SPATIALFREQUENCYRESPONSE 41484  /* Spatial frequency response */
+"/    #define EXIFTAG_FOCALPLANEXRESOLUTION   41486   /* Focal plane X resolution */
+"/    #define EXIFTAG_FOCALPLANEYRESOLUTION   41487   /* Focal plane Y resolution */
+"/    #define EXIFTAG_FOCALPLANERESOLUTIONUNIT 41488  /* Focal plane resolution unit */
+"/    #define EXIFTAG_SUBJECTLOCATION         41492   /* Subject location */
+"/    #define EXIFTAG_EXPOSUREINDEX           41493   /* Exposure index */
+"/    #define EXIFTAG_SENSINGMETHOD           41495   /* Sensing method */
+"/    #define EXIFTAG_FILESOURCE              41728   /* File source */
+"/    #define EXIFTAG_SCENETYPE               41729   /* Scene type */
+"/    #define EXIFTAG_CFAPATTERN              41730   /* CFA pattern */
+"/    #define EXIFTAG_CUSTOMRENDERED          41985   /* Custom image processing */
+"/    #define EXIFTAG_EXPOSUREMODE            41986   /* Exposure mode */
+"/    #define EXIFTAG_WHITEBALANCE            41987   /* White balance */
+"/    #define EXIFTAG_DIGITALZOOMRATIO        41988   /* Digital zoom ratio */
+"/    #define EXIFTAG_FOCALLENGTHIN35MMFILM   41989   /* Focal length in 35 mm film */
+"/    #define EXIFTAG_SCENECAPTURETYPE        41990   /* Scene capture type */
+"/    #define EXIFTAG_GAINCONTROL             41991   /* Gain control */
+"/    #define EXIFTAG_CONTRAST                41992   /* Contrast */
+"/    #define EXIFTAG_SATURATION              41993   /* Saturation */
+"/    #define EXIFTAG_SHARPNESS               41994   /* Sharpness */
+"/    #define EXIFTAG_DEVICESETTINGDESCRIPTION 41995  /* Device settings description */
+"/    #define EXIFTAG_SUBJECTDISTANCERANGE    41996   /* Subject distance range */
+"/    #define EXIFTAG_GAINCONTROL             41991   /* Gain control */
+"/    #define EXIFTAG_GAINCONTROL             41991   /* Gain control */
+"/    #define EXIFTAG_IMAGEUNIQUEID           42016   /* Unique image ID */
+
     "
      self initialize
     "
 
-    "Modified: 1.2.1997 / 15:00:01 / cg"
+    "Modified: / 27-08-2017 / 15:29:24 / cg"
 ! !
 
 !TIFFReader class methodsFor:'testing'!
@@ -116,33 +710,67 @@
 !
 
 isValidImageFile:aFileName
-    "return true, if aFileName contains a GIF image"
-
-    |inStream char1 char2 version|
+    "return true, if aFileName contains a TIFF image"
+
+    |inStream bytes1_2 byte3 byte4 versionLow versionHi|
 
     inStream := self streamReadingFile:aFileName.
     inStream isNil ifTrue:[^ false].
 
-    char1 := inStream next.
-    char2 := inStream next.
-
-    ((char1 ~~ char2) or:[(char1 ~~ $I) and:[char1 ~~ $M]]) ifTrue:[
-        inStream close.
-        ^ false
+    bytes1_2 := inStream next:2.
+    byte3 := inStream nextByte.
+    byte4 := inStream nextByte.
+    inStream close.
+    
+    ((bytes1_2 = 'II' "tiff") or:[bytes1_2 = 'PE' "mdi"]) ifTrue:[
+        "/ intel byte order (lsb)
+        versionLow := byte3. versionHi := byte4.
+    ] ifFalse:[
+        ((bytes1_2 = 'MM' "tiff") or:[bytes1_2 = 'EP' "mdi"])  ifTrue:[
+            "/ motorola byte order (msb)
+            versionLow := byte4. versionHi := byte3.
+        ] ifFalse:[
+            ^ false
+        ].    
+    ].
+    versionHi == 0 ifTrue:[
+        (versionLow == 42) ifTrue:[^ true].       "/ tiff
+        (versionLow == 43) ifTrue:[^ true].       "/ bigtiff
     ].
-
-    inStream binary.
-    version := inStream nextInt16MSB:(char1 == $M).
-    inStream close.
-
-    "/ 43 is bigTiff
-    ^ (version == 42) or:[ (version == 43) ]
-
-    "Modified: / 25-08-2017 / 08:39:20 / cg"
+    ^ false.
+
+    "Modified: / 26-08-2017 / 15:31:08 / cg"
+! !
+
+!TIFFReader methodsFor:'accessing'!
+
+decodeMetaTags:aBoolean
+    "by default, extra meta tags (photoshop) are not decoded;
+     set to true to get them in metatags"
+     
+    decodeMetaTags := aBoolean.
+
+    "Modified (comment): / 27-08-2017 / 18:37:04 / cg"
+!
+
+loadFullResolutionImage:aBoolean
+    "by default, the full-resolution dng image is not decoded;
+     set to true to get it in the imageSequence"
+     
+    loadFullResolutionImage := aBoolean.
+
+    "Created: / 27-08-2017 / 18:41:48 / cg"
 ! !
 
 !TIFFReader methodsFor:'private-data reading'!
 
+readAdobeDeflateTiffImageData
+    ^ self readDeflateTiffImageData
+
+    "Created: / 26-08-2017 / 14:44:35 / cg"
+    "Modified: / 27-08-2017 / 18:55:11 / cg"
+!
+
 readCCITT3RLETiffImageData
     ^ self fileFormatError:'ccitt G3 mod Huffman (rle) compression not implemented'
 
@@ -162,12 +790,13 @@
      stripNr       "{ Class: SmallInteger }"
      offset        "{ Class: SmallInteger }"
      row           "{ Class: SmallInteger }"
-     bytesPerStrip "{ Class: SmallInteger }" |
+     bytesPerStrip "{ Class: SmallInteger }" 
+     count dstIndex|
 
     nPlanes := samplesPerPixel.
     (nPlanes ~~ 1) ifTrue:[
         (nPlanes == 2) ifTrue:[
-            (planarConfiguration ~~ 2) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
                 ^ self fileFormatError:'only separate planes are supported'.
             ].
             'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -176,6 +805,9 @@
             ^ self fileFormatError:'only monochrome/greyscale ccitt3supported'.
         ].   
     ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
 
 "/    (rowsPerStrip ~~ 1) ifTrue:[
 "/        ^ self fileFormatError:'currently require rowsPerStrip to be 1'.
@@ -194,38 +826,54 @@
     "/ if the number of rows per strip is unknown (-1),
     "/ make it one big strip and decompress that
     rowsPerStrip = 16rFFFFFFFF ifTrue:[
-        compressedStrip := ByteArray uninitializedNew:(stripByteCounts sum).
+        self assert:(stripByteCounts size == 1).
+        count := stripByteCounts sum.
+        compressedStrip := ByteArray uninitializedNew:count.
         self positionToStrip:1.
-        inStream nextBytes:(compressedStrip size) into:compressedStrip.
-        self class 
-            decompressCCITT3From:compressedStrip
-            into:data
-            startingAt:1
-            count:compressedStrip size.
+
+        (inStream nextBytes:count into:compressedStrip) == count ifFalse:[
+            self error:'short read'
+        ].
+
+        compressedStrip := compressedStrip copyFrom:16r227.
+        
+        dstIndex := self class 
+                    _decompressCCITT3From:compressedStrip
+                    count:count
+                    into:data
+                    startingAt:1.
         ^ self 
     ].
     
     compressedStrip := ByteArray uninitializedNew:bytesPerRow.
 
     offset := 1.
-    stripNr := 0.
+    stripNr := 1.
 
     row := 1.
     bytesPerStrip := bytesPerRow * rowsPerStrip.
     [row <= height] whileTrue:[
+        self positionToStrip:stripNr.
+        count := stripByteCounts at:stripNr.
+        (inStream nextBytes:count into:compressedStrip) == count ifFalse:[
+            self error:'short read'
+        ].    
+        dstIndex := self class 
+                    _decompressCCITT3From:compressedStrip
+                    count:count
+                    into:data
+                    startingAt:offset
+                    count:width. "/ is this correct? - I think, that should be width*rowsPerStrip 
+        offset := offset + bytesPerStrip.
+        row := row + rowsPerStrip.
         stripNr := stripNr + 1.
-        self positionToStrip:stripNr.
-        inStream nextBytes:(stripByteCounts at:stripNr) into:compressedStrip.
-        self class 
-            decompressCCITT3From:compressedStrip
-            into:data
-            startingAt:offset
-            count:width.
-        offset := offset + bytesPerStrip.
-        row := row + rowsPerStrip
     ]
 
-    "Modified: / 25-08-2017 / 11:09:02 / cg"
+    "
+     TIFFReader fromFile:'/Users/cg/DownloadsUnsaved/image_software/libtiffpic/g3test.tif'
+    "
+
+    "Modified: / 27-08-2017 / 15:37:51 / cg"
 !
 
 readCCITTGroup4TiffImageData
@@ -245,9 +893,137 @@
 !
 
 readDeflateTiffImageData
-    ^ self fileFormatError:'deflate compression not implemented'.
-
-    "Modified: / 3.2.1998 / 18:04:54 / cg"
+    |bytesPerRowIn bytesPerRow nPlanes overAllBytes
+     bytesPerStrip "{ Class: SmallInteger }"
+     nBytes        "{ Class: SmallInteger }"
+     stripNr       "{ Class: SmallInteger }"
+     offset        "{ Class: SmallInteger }"
+     row           "{ Class: SmallInteger }" 
+     zlibReader nread msb
+     convertFloats convertDoubles conversionBuffer|
+
+    nPlanes := samplesPerPixel.
+    convertFloats := convertDoubles := false.
+    
+    (nPlanes >= 3) ifTrue:[
+        bytesPerRowIn := width * ((bitsPerSample sum + 7) // 8).
+        (bitsPerSample conform:[:each | each == 8]) ifTrue:[
+            sampleFormat == SAMPLEFORMAT_UINT ifFalse:[
+                ^ self fileFormatError:'unsupported sample format'.
+            ].
+        ] ifFalse:[
+            sampleFormat == SAMPLEFORMAT_IEEEFP ifTrue:[
+                nPlanes == 3 ifTrue:[
+                    (bitsPerSample conform:[:each | each == 64]) ifTrue:[
+                        convertDoubles := true.
+                        bytesPerRow := width * nPlanes.
+                        bitsPerSample := #(8 8 8).
+                    ] ifFalse:[
+                        (bitsPerSample conform:[:each | each == 32]) ifTrue:[
+                            convertFloats := true.
+                            bytesPerRow := width * nPlanes.
+                            bitsPerSample := #(8 8 8).
+                        ] ifFalse:[
+                            ^ self fileFormatError:'only 64/64/64 bits/sample are supported with IEEE_FP samples'.
+                        ].    
+                    ].    
+                ] ifFalse:[
+                    ^ self fileFormatError:'only support 3 planes with IEEE_FP sample format'.
+                ]    
+            ] ifFalse:[    
+                ^ self fileFormatError:'unsupported sample format'.
+            ].
+        ]
+    ] ifFalse:[
+        (nPlanes == 2) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
+                ^ self fileFormatError:'only separate planes are supported'.
+            ].
+            'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
+            nPlanes := 1
+        ].
+        (nPlanes == 1) ifFalse:[
+            ^ self fileFormatError:'unsupported nPlanes: ' , nPlanes printString, '; only 3-sample rgb / monochrome supported'.
+        ].
+        bytesPerRowIn := (width * (bitsPerSample at:1) + 7) // 8.
+    ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
+
+    "/ 'TIFFReader: decompressing Deflate ...' infoPrintNL.
+
+    bytesPerRow isNil ifTrue:[ bytesPerRow := bytesPerRowIn ].
+    
+    overAllBytes := bytesPerRow * height.
+    data := ByteArray new:overAllBytes.
+    (convertFloats or:[convertDoubles]) ifTrue:[
+        conversionBuffer := ByteArray new:(bytesPerRowIn * rowsPerStrip).
+    ].    
+    
+    offset := 1.
+    stripNr := 0.
+
+    row := 1.
+    bytesPerStrip := bytesPerRow * rowsPerStrip.
+
+    [row <= height] whileTrue:[
+        stripNr := stripNr + 1.
+        self positionToStrip:stripNr.
+        nBytes := stripByteCounts at:stripNr.
+        
+        zlibReader := ZipStream readOpenAsZipStreamOn:inStream suppressHeaderAndChecksum:false.
+        zlibReader binary.
+
+        conversionBuffer notNil ifTrue:[
+            nread := zlibReader next:nBytes into:conversionBuffer startingAt:1.
+            msb := (byteOrder == #msb).
+            convertFloats ifTrue:[
+                |i|
+
+                self assert:(nread \\ 4) == 0.
+                i := 0.
+                1 to:nread-1 by:4 do:[:iF |
+                    |dVal byteVal|
+                    dVal := conversionBuffer floatAt:iF MSB:msb.
+                    "/ rescale from 0..1 to 0..255
+                    byteVal := (dVal * 255) asInteger clampBetween:0 and:255.
+                    data at:offset+i put:byteVal.
+                    i := i + 1.
+                ].
+            ] ifFalse:[
+                convertDoubles ifTrue:[
+                    |i|
+                    
+                    self assert:(nread \\ 8) == 0.
+                    i := 0.
+                    1 to:nread-1 by:8 do:[:iF |
+                        |dVal byteVal|
+                        dVal := conversionBuffer doubleAt:iF MSB:msb.
+                        "/ rescale from 0..1 to 0..255
+                        byteVal := (dVal * 255) asInteger clampBetween:0 and:255.
+                        data at:offset+i put:byteVal.
+                        i := i + 1.
+                    ].
+                ]
+            ].    
+        ] ifFalse:[    
+            nread := zlibReader next:nBytes into:data startingAt:offset.
+        ].
+        
+        offset := offset + bytesPerStrip.
+        row := row + rowsPerStrip
+    ].
+
+    (predictor ~~ 1) ifTrue:[
+        (predictor == 2) ifTrue:[
+            self class decodeDelta:nPlanes in:data width:width height:height
+        ] ifFalse:[
+            ^ self fileFormatError:'unsupported predictor'
+        ].    
+    ]
+
+    "Modified: / 27-08-2017 / 15:38:08 / cg"
 !
 
 readJBIGTiffImageData
@@ -257,9 +1033,24 @@
 !
 
 readJPEGTiffImageData
-    ^ self fileFormatError:'jpeg compression not implemented'.
-
-    "Modified: / 3.2.1998 / 18:05:12 / cg"
+    |nBytes compressedData|
+    
+    stripByteCounts size == 1 ifTrue:[
+        "/ single strip
+        self positionToStrip:1.
+        nBytes := stripByteCounts at:1.
+        compressedData := ByteArray uninitializedNew:nBytes.
+        (inStream nextBytes:nBytes into:compressedData) == nBytes ifFalse:[ self error:'short read' ].
+        "/ pngOrJPGImage := JPEGReader fromStream:compressedData readStream.
+        "/ self halt.
+    ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
+    
+    ^ self fileFormatError:'jpeg (old) compression not implemented'.
+
+    "Modified: / 27-08-2017 / 15:38:23 / cg"
 !
 
 readLZWTiffImageData
@@ -286,7 +1077,7 @@
         bytesPerRow := width * samplesPerPixel.
     ] ifFalse:[
         (nPlanes == 2) ifTrue:[
-            (planarConfiguration ~~ 2) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
                 ^ self fileFormatError:'only separate planes are supported'.
             ].
             'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -297,6 +1088,9 @@
         ].
         bytesPerRow := (width * (bitsPerSample at:1) + 7) // 8.
     ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
 
     "/ 'TIFFReader: decompressing LZW ...' infoPrintNL.
 
@@ -321,7 +1115,7 @@
             compressedStrip := ByteArray uninitializedNew:nBytes.
             prevSize := nBytes
         ].
-        inStream nextBytes:nBytes into:compressedStrip.
+        (inStream nextBytes:nBytes into:compressedStrip) == nBytes ifFalse:[ self fileFormatError:'short file' ].
         self class 
             decompressLZWFrom:compressedStrip count:nBytes
             into:data startingAt:offset.
@@ -329,11 +1123,15 @@
         row := row + rowsPerStrip
     ].
 
-    (predictor == 2) ifTrue:[
-        self class decodeDelta:nPlanes in:data width:width height:height
+    predictor ~~ 1 ifTrue:[
+        (predictor == 2) ifTrue:[
+            self class decodeDelta:nPlanes in:data width:width height:height
+        ] ifFalse:[
+            self fileFormatError:'unsupported predictor'
+        ]
     ]
 
-    "Modified: / 25-08-2017 / 10:09:03 / cg"
+    "Modified: / 27-08-2017 / 15:38:30 / cg"
 !
 
 readNeXTJPEGTiffImageData
@@ -359,9 +1157,7 @@
      stripNr       "{ Class: SmallInteger }"
      offset        "{ Class: SmallInteger }"
      row           "{ Class: SmallInteger }" 
-     nBytes        "{ Class: SmallInteger }"
-     nDecompressedBytes  "{ Class: SmallInteger }"
-     bitsPerPixel overAllBytes buffer|
+     nBytes        "{ Class: SmallInteger }" bitsPerPixel overAllBytes buffer|
 
     nPlanes := samplesPerPixel.
 
@@ -370,7 +1166,7 @@
      or rgb - if non separate planes and no alpha"
 
     (nPlanes == 2) ifTrue:[
-        (planarConfiguration ~~ 2) ifTrue:[
+        (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
             ^ self fileFormatError:'with alpha, only separate planes supported'.
         ].
         'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -380,7 +1176,7 @@
         samplesPerPixel := 1.
     ] ifFalse:[
         (nPlanes == 3) ifTrue:[
-            (planarConfiguration ~~ 1) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_CONTIG) ifTrue:[
                 ^ self fileFormatError:'only non separate planes supported'.
             ].
             bitsPerSample ~= #(8 8 8) ifTrue:[
@@ -394,6 +1190,9 @@
             bitsPerPixel := bitsPerSample at:1.
         ]
     ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
 
     bitsPerRow := width * bitsPerPixel.
     bytesPerRow := bitsPerRow // 8.
@@ -409,12 +1208,11 @@
     ].
 
     offset := 1.
-    stripNr := 0.
+    stripNr := 1.
 
     buffer := nil.
     row := 1.
     [row <= height] whileTrue:[
-        stripNr := stripNr + 1.
         nBytes := stripByteCounts at:stripNr.
         self positionToStrip:stripNr.
 
@@ -422,15 +1220,18 @@
             "/ realloc
             buffer := ByteArray uninitializedNew:nBytes.
         ].
-        inStream nextBytes:nBytes into:buffer.
-        nDecompressedBytes := self class decompressPackBitsFrom:buffer at:1 to:data at:offset count:nBytes.
+        (inStream nextBytes:nBytes into:buffer) == nBytes ifFalse:[
+            self fileFormatError:'short file read'
+        ].    
+        self class decompressTiffPackBitsFrom:buffer to:data at:offset count:(bytesPerRow * rowsPerStrip).
         "/ nDecompressedBytes := self class decompressPackBits:nBytes from:buffer to:data startingAt:offset.
 
-        offset := offset + nDecompressedBytes.
-        row := row + rowsPerStrip
+        offset := offset + (bytesPerRow * rowsPerStrip).
+        row := row + rowsPerStrip.
+        stripNr := stripNr + 1.
     ]
 
-    "Modified: / 25-08-2017 / 02:02:20 / cg"
+    "Modified: / 27-08-2017 / 15:38:37 / cg"
 !
 
 readPixarFilmTiffImageData
@@ -471,7 +1272,7 @@
     nPlanes := samplesPerPixel.
 
     (nPlanes == 2) ifTrue:[
-        (planarConfiguration ~~ 2) ifTrue:[
+        (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
             ^ self fileFormatError:'only separate planes are supported'.
         ].
         'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -483,6 +1284,10 @@
     (bitsPerSample at:1) == 4 ifFalse:[
         ^ self fileFormatError:('unsupported bitsPerSample: %1 (only 4 supported)' bindWith:(bitsPerSample at:1)).
     ].    
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
+
     bytesPerRow := (width * (bitsPerSample at:1) + 7) // 8.
 
     "/ 'TIFFReader: decompressing ThunderScan ...' infoPrintNL.
@@ -586,79 +1391,103 @@
         ^ self fileFormatError:('unsupported predictor: %1' bindWith:predictor).
     ].
 
-    "Modified: / 25-08-2017 / 17:43:00 / cg"
+    "Modified: / 27-08-2017 / 15:38:47 / cg"
 !
 
 readTiffImageData
-    (compression == 1) ifTrue:[
-        ^ self readUncompressedTiffImageData.
+    (compression == COMPRESSION_NONE " 1 " ) ifTrue:[
+        self readUncompressedTiffImageData.
+        ^ self
     ].
-    (compression == 2) ifTrue:[
-        ^ self readCCITT3RLETiffImageData.
+    (compression == COMPRESSION_CCITTRLE " 2 ") ifTrue:[
+        self readCCITT3RLETiffImageData.
+        ^ self
     ].
-    (compression == 3) ifTrue:[
-        ^ self readCCITTGroup3TiffImageData.
+    (compression == COMPRESSION_CCITTFAX3 " 3 ") ifTrue:[
+        self readCCITTGroup3TiffImageData.
+        ^ self
     ]. 
-    (compression == 4) ifTrue:[
-        ^ self readCCITTGroup4TiffImageData.
+    (compression == COMPRESSION_CCITTFAX4 " 4 ") ifTrue:[
+        self readCCITTGroup4TiffImageData.
+        ^ self
     ]. 
-    (compression == 5) ifTrue:[
-        ^ self readLZWTiffImageData.
+    (compression == COMPRESSION_LZW " 5 ") ifTrue:[
+        self readLZWTiffImageData.
+        ^ self
     ].
-    (compression == 6) ifTrue:[
-        ^ self readJPEGTiffImageData.
+    (compression == COMPRESSION_OJPEG " 6 ") ifTrue:[
+        self readJPEGTiffImageData.
+        ^ self
+    ].
+    (compression == COMPRESSION_JPEG " 7 ") ifTrue:[
+        self readNewJPEGTiffImageData.
+        ^ self
     ].
-    (compression == 7) ifTrue:[
-        ^ self readNewJPEGTiffImageData.
+    (compression == COMPRESSION_ADOBE_DEFLATE " 8 ") ifTrue:[
+        self readAdobeDeflateTiffImageData.
+        ^ self
     ].
 
-    (compression == 32766) ifTrue:[
-        ^ self readNeXTRLE2TiffImageData.
+    (compression == COMPRESSION_NEXT " 32766 ") ifTrue:[
+        self readNeXTRLE2TiffImageData.
+        ^ self
     ].
-    (compression == 32771) ifTrue:[
-        ^ self readCCITTRLEWTiffImageData.
+    (compression == COMPRESSION_CCITTRLEW " 32771 ") ifTrue:[
+        self readCCITTRLEWTiffImageData.
+        ^ self
     ].
-    (compression == 32773) ifTrue:[
-        ^ self readPackbitsTiffImageData.
+    (compression == COMPRESSION_PACKBITS " 32773 ") ifTrue:[
+        self readPackbitsTiffImageData.
+        ^ self
     ].
-    (compression == 32809) ifTrue:[
-        ^ self readThunderScanTiffImageData.
+    (compression == COMPRESSION_THUNDERSCAN " 32809 ") ifTrue:[
+        self readThunderScanTiffImageData.
+        ^ self
     ].
-    (compression == 32908) ifTrue:[
-        ^ self readPixarFilmTiffImageData.
+    (compression == COMPRESSION_PIXARFILM " 32908 ") ifTrue:[
+        self readPixarFilmTiffImageData.
+        ^ self
     ].
-    (compression == 32909) ifTrue:[
-        ^ self readPixarLogTiffImageData.
+    (compression == COMPRESSION_PIXARLOG " 32909 ") ifTrue:[
+        self readPixarLogTiffImageData.
+        ^ self
     ].
-    (compression == 32946) ifTrue:[
-        ^ self readDeflateTiffImageData.
+    (compression == COMPRESSION_DEFLATE " 32946 ") ifTrue:[
+        self readDeflateTiffImageData.
+        ^ self
     ].
-    (compression == 32947) ifTrue:[
-        ^ self readDCSTiffImageData.
+    (compression == COMPRESSION_DCS " 32947 ") ifTrue:[
+        self readDCSTiffImageData.
+        ^ self
     ].
-    (compression == 32865) ifTrue:[
-        ^ self readNeXTJPEGTiffImageData.
-    ].
-    (compression == 34661) ifTrue:[
-        ^ self readJBIGTiffImageData.
+    (compression == COMPRESSION_NEXT_JPEG " 32865 ") ifTrue:[
+        self readNeXTJPEGTiffImageData.
+        ^ self
     ].
-    (compression == 34676) ifTrue:[
-        ^ self readSGI32TiffImageData.
+    (compression == COMPRESSION_JBIG " 34661 ") ifTrue:[
+        self readJBIGTiffImageData.
+        ^ self
     ].
-    (compression == 34677) ifTrue:[
-        ^ self readSGI24TiffImageData.
+    (compression == COMPRESSION_SGILOG " 34676 ") ifTrue:[
+        self readSGI32TiffImageData.
+        ^ self
     ].
-
-    ^ self fileFormatError:('compression type ' , compression printString , ' not known').
+    (compression == COMPRESSION_SGILOG24 " 34677 ") ifTrue:[
+        self readSGI24TiffImageData.
+        ^ self
+    ].
+
+    self fileFormatError:('compression type ' , compression printString , ' not known').
 
     "Created: / 11-04-1997 / 00:19:44 / cg"
-    "Modified: / 25-08-2017 / 11:17:25 / cg"
+    "Modified: / 26-08-2017 / 21:46:56 / cg"
 !
 
 readTiledJPEGTiffImageData
-    ^ self fileFormatError:'jpeg compression not implemented (in tile mode)'.
+    ^ self fileFormatError:'tiled jpeg (old) compression not implemented'.
 
     "Created: / 25-08-2017 / 16:27:28 / cg"
+    "Modified: / 26-08-2017 / 13:39:04 / cg"
 !
 
 readTiledLZWTiffImageData
@@ -667,21 +1496,34 @@
     "Created: / 25-08-2017 / 01:05:13 / cg"
 !
 
+readTiledNewJPEGTiffImageData
+    ^ self fileFormatError:'tiled new jpeg compression not implemented'.
+
+    "Created: / 26-08-2017 / 13:37:51 / cg"
+!
+
 readTiledTiffImageData
-    (compression == 1) ifTrue:[
-        ^ self readTiledUncompressedTiffImageData.
+    (compression == COMPRESSION_NONE " 1 ") ifTrue:[
+        self readTiledUncompressedTiffImageData.
+        ^ self
     ].
-    (compression == 5) ifTrue:[
-        ^ self readTiledLZWTiffImageData.
+    (compression == COMPRESSION_LZW " 5 ") ifTrue:[
+        self readTiledLZWTiffImageData.
+        ^ self
     ].
-    (compression == 6) ifTrue:[
-        ^ self readTiledJPEGTiffImageData.
+    (compression == COMPRESSION_OJPEG " 6 ") ifTrue:[
+        self readTiledJPEGTiffImageData.
+        ^ self
     ].
-
-    ^ self fileFormatError:('compression type ' , compression printString , ' not supported (in tile mode)').
+    (compression == COMPRESSION_JPEG " 7 ") ifTrue:[
+        self readTiledNewJPEGTiffImageData.
+        ^ self
+    ].
+
+    self fileFormatError:('tiled compression type ' , compression printString , ' not supported').
 
     "Created: / 25-08-2017 / 00:19:14 / cg"
-    "Modified: / 25-08-2017 / 16:27:40 / cg"
+    "Modified: / 26-08-2017 / 13:39:15 / cg"
 !
 
 readTiledUncompressedTiffImageData
@@ -703,20 +1545,14 @@
      imageOffset     "{ Class: SmallInteger }" 
      tileOffset      "{ Class: SmallInteger }"   
      dataOffset      "{ Class: SmallInteger }"   
-     tilePos tile     
-     tileWidth tileLength tileOffsets tileByteCounts|
-
-    tileWidth := metaData at:#TileWidth.
-    tileLength := metaData at:#TileLength.
-    tileOffsets := metaData at:#TileOffsets.
-    tileByteCounts := metaData at:#TileByteCounts.
+     tilePos tile tH tW tb|
 
     nPlanes := samplesPerPixel.
 
     "/ not all formats are supported here,
 
     (nPlanes == 2) ifTrue:[
-        (planarConfiguration ~~ 2) ifTrue:[
+        (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
             ^ self fileFormatError:'with alpha, only separate planes supported'.
         ].
         'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -726,7 +1562,7 @@
         samplesPerPixel := 1.
     ] ifFalse:[
         (nPlanes == 4) ifTrue:[
-            (planarConfiguration ~~ 1) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_CONTIG) ifTrue:[
                 ^ self fileFormatError:'only non separate planes supported'.
             ].
             bitsPerSample ~= #(8 8 8 8) ifTrue:[
@@ -735,7 +1571,7 @@
             bitsPerPixel := 32.
         ] ifFalse:[
             (nPlanes == 3) ifTrue:[
-                (planarConfiguration ~~ 1) ifTrue:[
+                (planarConfiguration ~~ PLANARCONFIG_CONTIG) ifTrue:[
                     ^ self fileFormatError:'only non separate planes supported'.
                 ].
                 bitsPerSample ~= #(8 8 8) ifTrue:[
@@ -750,18 +1586,15 @@
             ]
         ]
     ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
 
     bitsPerRow := width * bitsPerPixel.
-    bytesPerRow := bitsPerRow // 8.
-    ((bitsPerRow \\ 8) ~~ 0) ifTrue:[
-        bytesPerRow := bytesPerRow + 1
-    ].
+    bytesPerRow := (bitsPerRow + 7) // 8.
     
     bitsPerTileRow := tileWidth * bitsPerPixel.
-    bytesPerTileRow := bitsPerTileRow // 8.
-    ((bitsPerTileRow \\ 8) ~~ 0) ifTrue:[
-        bytesPerTileRow := bytesPerTileRow + 1
-    ].
+    bytesPerTileRow := (bitsPerTileRow + 7) // 8.
 
     overAllBytes := bytesPerRow * height.
     data := ByteArray new:overAllBytes.
@@ -771,6 +1604,10 @@
     y := 0.
     imageRowOffset := 1.
     [ y < height ] whileTrue:[
+        tH := tileLength.
+        (y+tileLength) > height ifTrue:[
+            tH := height - y.
+        ].    
         x := 0.
         imageOffset := imageRowOffset.
         [ x < width ] whileTrue:[
@@ -788,8 +1625,14 @@
             "/ copy the tile.
             tileOffset := 1.
             dataOffset := imageOffset. 
-            1 to:tileLength do:[:yT |
-                data replaceFrom:dataOffset to:dataOffset+bytesPerTileRow-1 with:tile startingAt:tileOffset.
+            tW := tileWidth.
+            tb := bytesPerTileRow.
+            (x+tileWidth) > width ifTrue:[
+                tW := width-x.
+                tb := ((bitsPerPixel * bitsPerPixel) + 7) // 8.
+            ].    
+            1 to:tH do:[:yT |
+                data replaceFrom:dataOffset to:dataOffset+tb-1 with:tile startingAt:tileOffset.
                 dataOffset := dataOffset + bytesPerRow.
                 tileOffset := tileOffset + bytesPerTileRow.
             ].
@@ -798,14 +1641,15 @@
             "/ row := row + rowsPerStrip.
             where := where + nBytes.
 
-            x := x + tileWidth.
+            x := x + tW.
             imageOffset := imageOffset + bytesPerTileRow.
         ].
-        y := y + tileLength.
-        imageRowOffset := imageRowOffset + (bytesPerRow*tileLength).
+        y := y + tH.
+        imageRowOffset := imageRowOffset + (bytesPerRow*tH).
     ].
 
     "Created: / 25-08-2017 / 00:22:31 / cg"
+    "Modified: / 27-08-2017 / 15:39:02 / cg"
 !
 
 readUncompressedTiffImageData
@@ -826,7 +1670,7 @@
     "/ not all formats are supported here,
 
     (nPlanes == 2) ifTrue:[
-        (planarConfiguration ~~ 2) ifTrue:[
+        (planarConfiguration ~~ PLANARCONFIG_SEPARATE) ifTrue:[
             ^ self fileFormatError:'with alpha, only separate planes supported'.
         ].
         'TIFFReader [info]: ignoring alpha plane' infoPrintCR.
@@ -836,22 +1680,26 @@
         samplesPerPixel := 1.
     ] ifFalse:[
         (nPlanes == 4) ifTrue:[
-            (planarConfiguration ~~ 1) ifTrue:[
+            (planarConfiguration ~~ PLANARCONFIG_CONTIG) ifTrue:[
                 ^ self fileFormatError:'only non separate planes supported'.
             ].
             bitsPerSample ~= #(8 8 8 8) ifTrue:[
-                ^ self fileFormatError:'only 8/8/8/8 cmyk images supported'.
+                bitsPerSample ~= #(16 16 16 16) ifTrue:[
+                    ^ self fileFormatError:'only 8/8/8/8 and 16/16/16/16 images supported'.
+                ].
             ].
-            bitsPerPixel := 32.
+            bitsPerPixel := bitsPerSample sum.
         ] ifFalse:[
             (nPlanes == 3) ifTrue:[
                 (planarConfiguration ~~ 1) ifTrue:[
                     ^ self fileFormatError:'only non separate planes supported'.
                 ].
                 bitsPerSample ~= #(8 8 8) ifTrue:[
-                    ^ self fileFormatError:'only 8/8/8 rgb images supported (is: ' , bitsPerSample printString , ')'.
+                    bitsPerSample ~= #(16 16 16) ifTrue:[
+                        ^ self fileFormatError:'only 8/8/8 and 16/16/16 images supported; is: ' , bitsPerSample printString.
+                    ].
                 ].
-                bitsPerPixel := 24
+                bitsPerPixel := bitsPerSample sum.
             ] ifFalse:[
                 (nPlanes ~~ 1) ifTrue:[
                     ^ self fileFormatError:('unsupported format: nplanes=' , nPlanes printString).
@@ -860,6 +1708,9 @@
             ]
         ]
     ].
+    stripRowCounts notNil ifTrue:[
+        ^ self fileFormatError:'stripRowCounts not supported'.
+    ].
 
     bitsPerRow := width * bitsPerPixel.
     bytesPerRow := bitsPerRow // 8.
@@ -900,11 +1751,171 @@
         where := where + nBytes.
     ].
 
-    "Modified: / 12.8.1998 / 13:57:14 / cg"
+    "Modified: / 27-08-2017 / 15:39:09 / cg"
 ! !
 
 !TIFFReader methodsFor:'private-reading'!
 
+decodePhotoshopImageResourceBlock:bytes
+    "8BIM is the signature for Photoshop Image Resource Block (IRB). 
+     See http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_38034.
+     
+     This kind of information could be found in images such as TIFF, JPEG, Photoshop native image format etc. 
+     It could also be found in non-image documents such as in PDF.
+     The structure of the IRB is as follows:
+     Each IRB block starts with 4 bytes signature which translates to string '8BIM.' 
+     After that, is a 2 bytes unique identifier denoting the kind of resource for this IRB. 
+     For example: 
+        0x040c for thumbnail; 
+        0x041a for slices; 
+        0x0408 for grid information; 
+        0x040f for ICC Profile etc.
+
+     After the identifier is a variable length string for name. 
+     The first byte of the string tells the length of the string (excluding the first length byte). 
+     After the first byte comes the string itself. 
+     There is a requirement that the length of the whole string (including the length byte) should be even. 
+     Otherwise, pad one more byte after the string.
+
+     The next 4 bytes specifies the size of the actual data for this resource block followed by the data with the specified length. 
+     The total length of the data also should be an even number. So if the size of the data is odd, pad another one byte. 
+     This finishes a whole 8BIM.
+
+     There could be more than one IRBs but they all conform to the same structure as described above. 
+     How to interpret the data depends on the unique identifier.
+
+     Now let's see how the IRBs are include in images. 
+     For a JPEG image, metadata could be present as one of the application (APPn) segment. 
+     Since different application could use the same APPn segment to store it's own metadata, 
+     there must be some kind of identifier to let the image reader know what kind of information is contained inside the APPn. 
+     Photoshop uses APP13 as it's IRB container and the APP13 contains 'Photoshop 3.0' as it's identifier.
+
+     For TIFF image which is tag based and arranged in a directory structure. 
+     There is a private tag 16r8649 called 'PHOTOSHOP' to insert IRB information.
+
+    0x03E8 (Obsolete--Photoshop 2.0 only ) Contains five 2-byte values: number of channels, rows, columns, depth, and mode
+    0x03E9 Macintosh print manager print info record
+    0x03EA Macintosh page format information. No longer read by Photoshop. (Obsolete)
+    0x03EB Obsolete--Photoshop 2.0 only ) Indexed color table
+    0x03ED ResolutionInfo structure. See Appendix A in Photoshop API Guide.pdf.
+    0x03EE Names of the alpha channels as a series of Pascal strings.
+    0x03EF (Obsolete) See ID 1077DisplayInfo structure. See Appendix A in Photoshop API Guide.pdf.
+    0x03F0 The caption as a Pascal string.
+    0x03F1 Border information. Contains a fixed number (2 bytes real, 2 bytes fraction) for the border width, and 2 bytes for border units (1 = inches, 2 = cm, 3 = points, 4 = picas, 5 = columns).
+    0x03F2 Background color. See See Color structure.
+    0x03F3 Print flags. A series of one-byte boolean values (see Page Setup dialog): labels, crop marks, color bars, registration marks, negative, flip, interpolate, caption, print flags.
+    0x03F4 Grayscale and multichannel halftoning information
+    0x03F5 Color halftoning information
+    0x03F6 Duotone halftoning information
+    0x03F7 Grayscale and multichannel transfer function
+    0x03F8 Color transfer functions
+    0x03F9 Duotone transfer functions
+    0x03FA Duotone image information
+    0x03FB Two bytes for the effective black and white values for the dot range
+    0x03FC (Obsolete)
+    0x03FD EPS options
+    0x03FE Quick Mask information. 2 bytes containing Quick Mask channel ID; 1- byte boolean indicating whether the mask was initially empty.
+    0x03FF (Obsolete)
+    0x0400 Layer state information. 2 bytes containing the index of target layer (0 = bottom layer).
+    0x0401 Working path (not saved). See See Path resource format.
+    0x0402 Layers group information. 2 bytes per layer containing a group ID for the dragging groups. Layers in a group have the same group ID.
+    0x0403 (Obsolete)
+    0x0404 IPTC-NAA record. Contains the File Info... information. See the documentation in the IPTC folder of the Documentation folder.
+    0x0405 Image mode for raw format files
+    0x0406 JPEG quality. Private.
+    0x0408 (Photoshop 4.0) Grid and guides information. See See Grid and guides resource format.
+    0x0409 (Photoshop 4.0) Thumbnail resource for Photoshop 4.0 only. See See Thumbnail resource format.
+    0x040A (Photoshop 4.0) Copyright flag. Boolean indicating whether image is copyrighted. Can be set via Property suite or by user in File Info...
+    0x040B (Photoshop 4.0) URL. Handle of a text string with uniform resource locator. Can be set via Property suite or by user in File Info...
+    0x040C (Photoshop 5.0) Thumbnail resource (supersedes resource 1033). See See Thumbnail resource format.
+    0x040D (Photoshop 5.0) Global Angle. 4 bytes that contain an integer between 0 and 359, which is the global lighting angle for effects layer. If not present, assumed to be 30.
+    0x040E (Obsolete) See ID 1073 below. (Photoshop 5.0) Color samplers resource. See See Color samplers resource format.
+    0x040F (Photoshop 5.0) ICC Profile. The raw bytes of an ICC (International Color Consortium) format profile. See ICC1v42_2006-05.pdf in the Documentation folder and icProfileHeader.h in Sample Code\Common\Includes .
+    0x0410 (Photoshop 5.0) Watermark. One byte.
+    0x0411 (Photoshop 5.0) ICC Untagged Profile. 1 byte that disables any assumed profile handling when opening the file. 1 = intentionally untagged.
+    0x0412 (Photoshop 5.0) Effects visible. 1-byte global flag to show/hide all the effects layer. Only present when they are hidden.
+    0x0413 (Photoshop 5.0) Spot Halftone. 4 bytes for version, 4 bytes for length, and the variable length data.
+    0x0414 (Photoshop 5.0) Document-specific IDs seed number. 4 bytes: Base value, starting at which layer IDs will be generated (or a greater value if existing IDs already exceed it). Its purpose is to avoid the case where we add layers, flatten, save, open, and then add more layers that end up with the same IDs as the first set.
+    0x0415 (Photoshop 5.0) Unicode Alpha Names. Unicode string
+    0x0416 (Photoshop 6.0) Indexed Color Table Count. 2 bytes for the number of colors in table that are actually defined
+    0x0417 (Photoshop 6.0) Transparency Index. 2 bytes for the index of transparent color, if any.
+    0x0419 (Photoshop 6.0) Global Altitude. 4 byte entry for altitude
+    0x041A (Photoshop 6.0) Slices. See See Slices resource format.
+    0x041B (Photoshop 6.0) Workflow URL. Unicode string
+    0x041C (Photoshop 6.0) Jump To XPEP. 2 bytes major version, 2 bytes minor version, 4 bytes count. Following is repeated for count: 4 bytes block size, 4 bytes key, if key = 'jtDd' , then next is a Boolean for the dirty flag; otherwise it's a 4 byte entry for the mod date.
+    0x041D (Photoshop 6.0) Alpha Identifiers. 4 bytes of length, followed by 4 bytes each for every alpha identifier.
+    0x041E (Photoshop 6.0) URL List. 4 byte count of URLs, followed by 4 byte long, 4 byte ID, and Unicode string for each count.
+    0x0421 (Photoshop 6.0) Version Info. 4 bytes version, 1 byte hasRealMergedData , Unicode string: writer name, Unicode string: reader name, 4 bytes file version.
+    0x0422 (Photoshop 7.0) EXIF data 1. See http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf
+    0x0423 (Photoshop 7.0) EXIF data 3. See http://www.kodak.com/global/plugins/acrobat/en/service/digCam/exifStandard2.pdf
+    0x0424 (Photoshop 7.0) XMP metadata. File info as XML description. See http://www.adobe.com/devnet/xmp/
+    0x0425 (Photoshop 7.0) Caption digest. 16 bytes: RSA Data Security, MD5 message-digest algorithm
+    0x0426 (Photoshop 7.0) Print scale. 2 bytes style (0 = centered, 1 = size to fit, 2 = user defined). 4 bytes x location (floating point). 4 bytes y location (floating point). 4 bytes scale (floating point)
+    0x0428 (Photoshop CS) Pixel Aspect Ratio. 4 bytes (version = 1 or 2), 8 bytes double, x / y of a pixel. Version 2, attempting to correct values for NTSC and PAL, previously off by a factor of approx. 5%.
+    0x0429 (Photoshop CS) Layer Comps. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure)
+    0x042A (Photoshop CS) Alternate Duotone Colors. 2 bytes (version = 1), 2 bytes count, following is repeated for each count: [ Color: 2 bytes for space followed by 4 * 2 byte color component ], following this is another 2 byte count, usually 256, followed by Lab colors one byte each for L, a, b. This resource is not read or used by Photoshop.
+    0x042B (Photoshop CS)Alternate Spot Colors. 2 bytes (version = 1), 2 bytes channel count, following is repeated for each count: 4 bytes channel ID, Color: 2 bytes for space followed by 4 * 2 byte color component. This resource is not read or used by Photoshop.
+    0x042D (Photoshop CS2) Layer Selection ID(s). 2 bytes count, following is repeated for each count: 4 bytes layer ID
+    0x042E (Photoshop CS2) HDR Toning information
+    0x042F (Photoshop CS2) Print info
+    0x0430 (Photoshop CS2) Layer Group(s) Enabled ID. 1 byte for each layer in the document, repeated by length of the resource. NOTE: Layer groups have start and end markers
+    0x0431 (Photoshop CS3) Color samplers resource. Also see ID 1038 for old format. See See Color samplers resource format.
+    0x0432 (Photoshop CS3) Measurement Scale. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure)
+    0x0433 (Photoshop CS3) Timeline Information. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure)
+    0x0434 (Photoshop CS3) Sheet Disclosure. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure)
+    0x0435 (Photoshop CS3) DisplayInfo structure to support floating point clors. Also see ID 1007. See Appendix A in Photoshop API Guide.pdf .
+    0x0436 (Photoshop CS3) Onion Skins. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure)
+    0x0438 (Photoshop CS4) Count Information. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure) Information about the count in the document. See the Count Tool.
+    0x043A (Photoshop CS5) Print Information. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure) Information about the current print settings in the document. The color management options.
+    0x043B (Photoshop CS5) Print Style. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure) Information about the current print style in the document. The printing marks, labels, ornaments, etc.
+    0x043C (Photoshop CS5) Macintosh NSPrintInfo. Variable OS specific info for Macintosh. NSPrintInfo. It is recommened that you do not interpret or use this data.
+    0x043D (Photoshop CS5) Windows DEVMODE. Variable OS specific info for Windows. DEVMODE. It is recommened that you do not interpret or use this data.
+    0x043E (Photoshop CS6) Auto Save File Path. Unicode string. It is recommened that you do not interpret or use this data.
+    0x043F (Photoshop CS6) Auto Save Format. Unicode string. It is recommened that you do not interpret or use this data.
+    0x0440 (Photoshop CC) Path Selection State. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure) Information about the current path selection state.
+    0x07D0-0x0BB6 Path Information (saved paths). See See Path resource format.
+    0x0BB7 Name of clipping path. See See Path resource format.
+    0x0BB8 (Photoshop CC) Origin Path Info. 4 bytes (descriptor version = 16), Descriptor (see See Descriptor structure) Information about the origin path data.
+    0x0FA0-0x1387 Plug-In resource(s). Resources added by a plug-in. See the plug-in API found in the SDK documentation
+    0x1B58 Image Ready variables. XML representation of variables definition
+    0x1B59 Image Ready data sets
+    0x1B5A Image Ready default selected state
+    0x1B5B Image Ready 7 rollover expanded state
+    0x1B5C Image Ready rollover expanded state
+    0x1B5D Image Ready save layer settings
+    0x1B5E Image Ready version
+    0x1F40 (Photoshop CS3) Lightroom workflow, if present the document is in the middle of a Lightroom workflow.
+    0x2710 Print flags information. 2 bytes version ( = 1), 1 byte center crop marks, 1 byte ( = 0), 4 bytes bleed width value, 2 bytes bleed width scale.
+    "
+
+    |s id name len resource record|
+
+    record := OrderedCollection new.
+    
+    s := bytes readStream.
+    [s atEnd] whileFalse:[
+        (s next:4) asString = '8BIM' ifTrue:[
+            id := s nextUnsignedInt16MSB.
+            name := s upTo:0.
+            name size odd ifFalse:[ s next ]. "/ padding
+            len := s nextUnsignedInt32MSB.
+            resource := s next:len.
+            Verbose == true ifTrue:[
+                Transcript showCR:('      8BIM-%1: %2' bindWith:(id hexPrintString:4) with:resource).
+            ].
+            record add:(Dictionary new
+                            at:#id put:id;
+                            at:#name put:name;
+                            at:#resource put:resource;
+                            yourself).                    
+        ].    
+    ].
+    metaData at:#'PhotoshopIRB' put:record.
+
+    "Created: / 27-08-2017 / 17:12:25 / cg"
+    "Modified: / 27-08-2017 / 18:14:56 / cg"
+!
+
 decodeTiffTag:tagType numberType:numberType length:length
     |offset value valueArray 
      val scaleFactor rV gV bV
@@ -1071,19 +2082,50 @@
             "/      JBIG2           -> 34715 
             compression := value.
 
-            Verbose == true ifTrue:[ 
-                Logger info:'      compression: %1' with:value 
+            Verbose == true ifTrue:[
+                |s|
+                s := (Dictionary withKeyValuePairs:
+                        #( (1 uncompressed)
+                            (2 CCITTRLE)
+                            (3 CCITTFAX3)
+                            (4 CCITTFAX4)
+                            (5 LZW)
+                            (6 OJPEG)
+                            (7 JPEG)
+                            (8 ADOBE_DEFLATE)
+                            (9 JBIG_T85)
+                            (10 JBIG_T43)
+                            (32766 NEXT)
+                            (32771 CCITTRLEW)
+                            (32773 PACKBITS)
+                            (32809 THUNDERSCAN)
+                            (32895 IT8CTPAD)
+                            (32896 IT8LW)
+                            (32897 IT8MP)
+                            (32898 IT8BL)
+                            (32908 PIXARFILM)
+                            (32909 PIXARLOG)
+                            (32946 DEFLATE)
+                            (32947 DCS)
+                            (34661 JBIG)
+                            (34676 SGI32)
+                            (34677 SGI24)
+                            (34712 JPEG2000)
+                            (34713 NIKON_NEF)
+                            (34715 JBIG2) 
+                        )) at:value ifAbsent:'???'.
+                Logger info:'      compression: %1 (=%2)' with:value with:s.
             ].
             ^ self
         ].
 
         (tagType == 262) ifTrue:[
             "photometric"
-	    |p|
+            |p|
 
             (value between:0 and:10) ifTrue:[
                 p := 
-		    #(
+                    #(
                         whiteIs0            "/  0 - grayscale or monochrome; faxes
                         blackIs0            "/  1 - grayscale or monochrome; faxes
                         rgb                 "/  2
@@ -1110,9 +2152,9 @@
                     p := #LinearRaw           "/ camera rw format
                 ].
             ].
-	    photometric := p.
+            photometric := p.
             Verbose == true ifTrue:[ 
-                Logger info:'      photometric: %1 (%2)' with:photometric with:value
+                Logger info:'      photometric: %1 (=%2)' with:value with:photometric
             ].
             ^ self
         ].
@@ -1132,7 +2174,6 @@
             "CellWidth"
             "/ 'cellWidth ' print. value printNewline.
             metaData at:#CellWidth put:value.
-
             ^ self
         ].
         (tagType == 265) ifTrue:[
@@ -1144,27 +2185,33 @@
         (tagType == 266) ifTrue:[
             "fillOrder"
             (value == 1) ifTrue:[
-              fillOrder := #msb
+                fillOrder := #msb
             ] ifFalse:[
-              (value == 2) ifTrue:[
-                fillOrder := #lsb
-              ] ifFalse:[
-                fillOrder := nil
-              ]
+                (value == 2) ifTrue:[
+                    fillOrder := #lsb
+                ] ifFalse:[
+                    fillOrder := nil
+                ]
             ].
-            "/ 'fillorder ' print. fillOrder printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      fillorder: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 269) ifTrue:[
             "documentName - info only"
-            "/ 'documentName ' print. value printNewline.
             metaData at:#DocumentName put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      documentName: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 270) ifTrue:[
             "imageDescription - info only"
-            "/ 'imageDescription ' print. value printNewline.
             metaData at:#ImageDescription put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      imageDescription: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 271) ifTrue:[
@@ -1179,7 +2226,7 @@
             "model - info only"
             metaData at:#Model put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      model: %1' with:value 
+                Logger info:'      model: %1' with:value
             ].
             ^ self
         ].
@@ -1196,17 +2243,17 @@
 
             orientation :=
                             #( nil          "/ 1 normal (topLeft)
-                               unsupported  "/ 2 horizontal flip
-                               unsupported  "/ 3 horizontal & vertical flip
+                               hFlip        "/ 2 horizontal flip
+                               hvFlip       "/ 3 horizontal & vertical flip
                                vFlip        "/ 4 vertical flip
-                               unsupported  "/ 5 rot 90' counter clock-wise
-                               unsupported  "/ 6 rot 90' clock-wise
-                               unsupported  "/ 7 rot 90' & flip
-                               unsupported  "/ 8 rot 90' ccw & flip
+                               rot90ccw     "/ 5 rot 90' counter clock-wise
+                               rot90        "/ 6 rot 90' clock-wise
+                               rot90flip    "/ 7 rot 90' & flip
+                               rot90ccwFlip "/ 8 rot 90' ccw & flip
                              ) at:value ifAbsent:#unsupported.
             metaData at:#Orientation put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      orientation: %1' with:value 
+                Logger info:'      orientation: %1 (=%2)' with:value with:(orientation ? #normal)
             ].
             ^ self
         ].
@@ -1236,20 +2283,26 @@
             ^ self
         ].
         (tagType == 280) ifTrue:[
-            "/ 'minSampleValue ' print. value printNewline.
+            "/ minSampleValue
             metaData at:#MinSampleValue put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      minSampleValue: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 281) ifTrue:[
-            "/ 'maxSampleValue ' print. value printNewline.
+            "/ maxSampleValue
             metaData at:#MaxSampleValue put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      maxSampleValue: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 282) ifTrue:[
             "/ xResolution
             metaData at:#ResolutionX put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      xResolution: %1' with:value 
+                Logger info:'      xResolution: %1 (%2)' with:value with:value asFloat 
             ].
             ^ self
         ].
@@ -1257,16 +2310,16 @@
             "/ yResolution
             metaData at:#ResolutionY put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      yResolution: %1' with:value 
+                Logger info:'      yResolution: %1 (%2)' with:value with:value asFloat 
             ].
             ^ self
         ].
         (tagType == 284) ifTrue:[
             (value == 1) ifTrue:[
-                planarConfiguration := 1
+                planarConfiguration := PLANARCONFIG_CONTIG
             ] ifFalse:[
                 (value == 2) ifTrue:[
-                    planarConfiguration := 2
+                    planarConfiguration := PLANARCONFIG_SEPARATE
                 ] ifFalse:[
                     planarConfiguration := nil
                 ]
@@ -1282,13 +2335,19 @@
             ^ self
         ].
         (tagType == 286) ifTrue:[
-            "/ 'xPosition ' print. value printNewline.
+            "/ xPosition
             metaData at:#PositionX put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      xPosition: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 287) ifTrue:[
-            "/ 'yPosition ' print. value printNewline.
+            "/ yPosition
             metaData at:#PositionY put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      yPosition: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 288) ifTrue:[
@@ -1316,15 +2375,19 @@
             "/      FILLBITS        -> 4
 
             group3options := value.
-            "/ 'group3options ' print. group3options printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      group3options: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 293) ifTrue:[
             "/ group4options (now called T6Options)
             "/      UNCOMPRESSED    -> 2
 
-            "group4options := value."
-            "/ 'group4options ' print. value printNewline.
+            "/ group4options := value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      group4options: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 296) ifTrue:[
@@ -1352,6 +2415,9 @@
         (tagType == 297) ifTrue:[
             "/ 'pageNumber ' print. value printNewline.
             metaData at:#PageNumber put:value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      PageNumber: %1' with:value 
+            ].
             ^ self
         ].
     ].
@@ -1369,38 +2435,38 @@
         ].
         (tagType == 305) ifTrue:[
             "software - info only"
-            metaData at:#Software put:value asString.
+            metaData at:#Software put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      software: %1' with:value asString
+                Logger info:'      software: %1' with:value
             ].
             ^ self
         ].
         (tagType == 306) ifTrue:[
             "dateTime - info only"
-            metaData at:#DateTime put:value asString.
+            metaData at:#DateTime put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      dateTime: %1' with:value asString
+                Logger info:'      dateTime: %1' with:value
             ].
             ^ self
         ].
         (tagType == 315) ifTrue:[
             "artist - info only"
-            metaData at:#Artist put:value asString.
+            metaData at:#Artist put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      artist: %1' with:value asString
+                Logger info:'      artist: %1' with:value
             ].
             ^ self
         ].
         (tagType == 316) ifTrue:[
             "host computer - info only"
-            metaData at:#HostComputer put:value asString.
+            metaData at:#HostComputer put:value.
             Verbose == true ifTrue:[ 
-                Logger info:'      host: %1' with:value asString
+                Logger info:'      host: %1' with:value
             ].
             ^ self
         ].
         (tagType == 317) ifTrue:[
-            "/ 'predictor ' print. predictor printNewline.
+            "/ predictor
             "/ 1 -> no predictor
             "/ 2 -> horiz. difference (see tiff spec 6.0)
             "/ 3 -> flt pnt (see adobe tech notes)
@@ -1409,15 +2475,18 @@
             "/ 34894 -> flt pnt x2
             "/ 34895 -> flt pnt x4
             predictor := value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      predictor: %1' with:value
+            ].
             ^ self
         ].
         (tagType == 318) ifTrue:[
-            "/ 'whitePoint ' print. value printNewline.
+            "/ whitePoint
             metaData at:#WhitePoint put:value.
             ^ self
         ].
         (tagType == 319) ifTrue:[
-            "/ 'primaryChromatics ' print. value printNewline.
+            "/ primaryChromatics
             metaData at:#PrimaryChromatics put:value.
             ^ self
         ].
@@ -1447,66 +2516,95 @@
                 i3 := i3 + 1.
             ].
             colorMap := MappedPalette redVector:rV greenVector:gV blueVector:bV.
+            Verbose == true ifTrue:[ 
+                Logger info:'      colormap: ...'
+            ].
             ^ self
         ].
         (tagType == 321) ifTrue:[
-            "/ 'halftonehints' print. value printNewline.
+            "/ halftonehints
             metaData at:#HalftoneHints put:value.
             ^ self
         ].
         (tagType == 322) ifTrue:[
-            "/ 'tilewidth' print. value printNewline.
-            metaData at:#TileWidth put:value.
+            "/ tilewidth
+            tileWidth := value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      tileWidth: %1' with:value 
+            ].
+            (tileWidth \\ 16) == 0 ifFalse:[
+                Logger warning:'TIFFReader: tile width is not a multiple of 16'.
+            ].    
             ^ self
         ].
         (tagType == 323) ifTrue:[
-            "/ 'tilelength' print. value printNewline.
-            metaData at:#TileLength put:value.
+            "/ tilelength (height)
+            tileLength := value.
+            Verbose == true ifTrue:[ 
+                Logger info:'      tileLength: %1' with:value 
+            ].
+            (tileLength \\ 16) == 0 ifFalse:[
+                Logger warning:'TIFFReader: tile height is not a multiple of 16'.
+            ].    
             ^ self
         ].
         (tagType == 324) ifTrue:[
-            "/ 'tileoffsets' print. value printNewline.
-            metaData at:#TileOffsets put:valueArray.
+            "/ tileoffsets
+            tileOffsets := valueArray.
+            Verbose == true ifTrue:[ 
+                Logger info:'      tileOffsets: %1' with:valueArray 
+            ].
             ^ self
         ].
         (tagType == 325) ifTrue:[
-            "/ 'tilebytecounts' print. value printNewline.
-            metaData at:#TileByteCounts put:valueArray.
+            "/ tilebytecounts
+            tileByteCounts := valueArray.
+            Verbose == true ifTrue:[ 
+                Logger info:'      tileByteCounts: %1' with:valueArray 
+            ].
             ^ self
         ].
         (tagType == 326) ifTrue:[
-            "/ 'badFaxLines' print. value printNewline.
+            "/ badFaxLines
+            Verbose == true ifTrue:[ 
+                Logger info:'      badFaxLines: %1' with:valueArray 
+            ].
             ^ self
         ].
         (tagType == 327) ifTrue:[
             "CleanFaxData"
-
-            "/        'cleanfaxdata' print. value printNewline.
-            "/        (value == 0) ifTrue:[
-            "/            'no lines with incorrect pixel counts' printNewline
-            "/        ] ifFalse:[
-            "/            (value == 1) ifTrue:[
-            "/                'incorrect lines were regenerated' printNewline
-            "/            ] ifFalse:[
-            "/                (value == 2) ifTrue:[
-            "/                    'incorrect lines were not regenerated' printNewline
-            "/                ] ifFalse:[
-            "/                    'cleanfaxdata invalid' printNewline
-            "/                ]
-            "/            ]
-            "/        ].
-
+            Verbose == true ifTrue:[ 
+                "/        'cleanfaxdata' print. value printNewline.
+                "/        (value == 0) ifTrue:[
+                "/            'no lines with incorrect pixel counts' printNewline
+                "/        ] ifFalse:[
+                "/            (value == 1) ifTrue:[
+                "/                'incorrect lines were regenerated' printNewline
+                "/            ] ifFalse:[
+                "/                (value == 2) ifTrue:[
+                "/                    'incorrect lines were not regenerated' printNewline
+                "/                ] ifFalse:[
+                "/                    'cleanfaxdata invalid' printNewline
+                "/                ]
+                "/            ]
+                "/        ].
+                Logger info:'      cleanfaxdata: %1' with:value  
+            ].
             ^ self
         ].
         (tagType == 328) ifTrue:[
-            "/ 'consecutiveBadFaxLines' print. value printNewline.
+            "/ consecutiveBadFaxLines
+            Verbose == true ifTrue:[ 
+                Logger info:'      consecutiveBadFaxLines: %1' with:valueArray 
+            ].
             ^ self
         ].
         (tagType == 330) ifTrue:[
             "/ subifd
             Verbose == true ifTrue:[ 
-                Logger info:'      subifd: %1' with:value 
+                Logger info:'      subifd: %1' with:valueArray 
             ].
+            subIfds := valueArray. 
             ^ self
         ].
         (tagType == 332) ifTrue:[
@@ -1532,18 +2630,35 @@
         ].
         (tagType == 338) ifTrue:[
             "/ 'extrasamples' print. value printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      extrasamples: %1' with:value 
+            ].
             ^ self
         ].
         (tagType == 339) ifTrue:[
             "/ 'sample format' print. value printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      sample format: %1 (=%2)' 
+                            with:value 
+                            with:(#( uint int float undef ) at:value ifAbsent:'???')
+            ].
+            sampleFormat := value.
             ^ self
         ].
         (tagType == 340) ifTrue:[
             "/ 'min sample value' print. value printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      min sample value: %1' with:value 
+            ].
+            minSampleValue := value.
             ^ self
         ].
         (tagType == 341) ifTrue:[
             "/ 'max sample value' print. value printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      max sample value: %1' with:value 
+            ].
+            maxSampleValue := value.
             ^ self
         ].
         (tagType == 342) ifTrue:[
@@ -1562,10 +2677,18 @@
             "/ 'yclip path units' print. value printNewline.
             ^ self
         ].
+        (tagType == 346) ifTrue:[
+            "/ 'indexed' print. value printNewline.
+            ^ self
+        ].
         (tagType == 347) ifTrue:[
             "/ 'jpegtables' print. value printNewline.
             ^ self
         ].
+        (tagType == 351) ifTrue:[
+            "/ opiproxy
+            ^ self
+        ].
     ].
 
     (tagType between:400 and:499) ifTrue:[
@@ -1672,14 +2795,20 @@
             ^ self
         ].
         (tagType == 559) ifTrue:[
-            "/ 'stripRowCounts' print. value printNewline.
+            "/ stripRowCounts
+            "/ Defined in the Mixed Raster Content part of RFC 2301, 
+            "/ used to replace RowsPerStrip for IFDs with variable-sized strips.
+            Verbose == true ifTrue:[ 
+                Logger info:'      stripRowCounts: %1' with:valueArray 
+            ].
+            stripRowCounts := valueArray.
             ^ self
         ].
     ].
 
     (tagType between:700 and:799) ifTrue:[
         (tagType == 700) ifTrue:[
-            "XMLPACKET"
+            "XMP metadata (xml)"
 
             "/ In TIFF files, the XML Packet containing XMP metadata is pointed to
             "/ by an entry in the Image File Directory (IFD). That entry has a Tag
@@ -1693,6 +2822,17 @@
         ].
     ].
     
+    (tagType between:18000 and:18999) ifTrue:[
+        (tagType == 18246) ifTrue:[
+            "/ Image Rating by windows
+            ^ self
+        ].
+        (tagType == 18249) ifTrue:[
+            "/ Image Rating Percent by windows
+            ^ self
+        ].
+    ].
+
     (tagType between:32000 and:32999) ifTrue:[
         (tagType == 32781) ifTrue:[
             "/'imageid' print. value printNewline.
@@ -1727,16 +2867,26 @@
             "/ 'matteing' print. value printNewline.
             ^ self
         ].
+        
         (tagType == 32996) ifTrue:[
-            "/ 'datatype' print. value printNewline.
+            "/ datatype
+            Verbose == true ifTrue:[ 
+                Logger info:'      datatype: %1' with:value
+            ].
             ^ self
         ].
         (tagType == 32997) ifTrue:[
-            "/ 'imagedepth' print. value printNewline.
+            "/ imagedepth
+            Verbose == true ifTrue:[ 
+                Logger info:'      imagedepth: %1' with:value
+            ].
             ^ self
         ].
         (tagType == 32998) ifTrue:[
-            "/ 'tiledepth' print. value printNewline.
+            "/ tiledepth
+            Verbose == true ifTrue:[ 
+                Logger info:'      tiledepth: %1' with:value
+            ].
             ^ self
         ].
     ].
@@ -1758,7 +2908,24 @@
             ^ self
         ].
 
-        "/ unknown
+        (tagType == 33421) ifTrue:[
+            "/ CFARepeatPatternDim - For camera raw files from sensors with CFA overlay
+            Verbose == true ifTrue:[ 
+                Logger info:'      CFARepeatPatternDim: %1' with:value
+            ].
+            ^ self
+        ].
+        (tagType == 33422) ifTrue:[
+            "/ CFAPattern - For camera raw files from sensors with CFA overlay
+            Verbose == true ifTrue:[ 
+                Logger info:'      CFAPattern: %1' with:value
+            ].
+            ^ self
+        ].
+        (tagType == 33423) ifTrue:[
+            "/ BatteryLevel - Encodes camera battery level at time of image capture
+            ^ self
+        ].
         (tagType == 33432) ifTrue:[
             "/ 'copyright' print. value printNewline.
             ^ self
@@ -1773,12 +2940,89 @@
             "/ 'RICHTIFFIPTC' print. value printNewline.
             ^ self
         ].
+
+
+        (tagType == 33920) ifTrue:[
+            "/ 'geotiff IntergraphMatrixTag' print. value printNewline.
+            ^ self
+        ].
+        (tagType == 33922) ifTrue:[
+            "/ 'geotiff ModelTiepointTag' print. value printNewline.
+            ^ self
+        ].
+
     ].
-    
+
     (tagType between:34000 and:34999) ifTrue:[
-        "/ Private Texas instruments
-        (tagType == 34232) ifTrue:[
-            "/ 'sequence frame count' print. value printNewline.
+        (tagType == 34016) ifTrue:[
+            "/ Site
+            Verbose == true ifTrue:[ 
+                Logger info:'      site: %1' with:value 
+            ].
+            ^ self
+        ].
+        (tagType == 34017) ifTrue:[
+            "/ colorSequence
+            ^ self
+        ].
+        (tagType == 34018) ifTrue:[
+            "/ it8header
+            ^ self
+        ].
+        (tagType == 34019) ifTrue:[
+            "/ rasterPadding
+            ^ self
+        ].
+        (tagType == 34020) ifTrue:[
+            "/ bitsPerRunLength
+            ^ self
+        ].
+        (tagType == 34021) ifTrue:[
+            "/ bitsPerExtendedRunLength
+            ^ self
+        ].
+        (tagType == 34022) ifTrue:[
+            "/ colorTable
+            ^ self
+        ].
+        (tagType == 34023) ifTrue:[
+            "/ imageColorIndicator
+            ^ self
+        ].
+        (tagType == 34024) ifTrue:[
+            "/ backgroundColorIndicator
+            ^ self
+        ].
+        (tagType == 34025) ifTrue:[
+            "/ imageColorValue
+            ^ self
+        ].
+        (tagType == 34026) ifTrue:[
+            "/ backgroundColorValue
+            ^ self
+        ].
+        (tagType == 34027) ifTrue:[
+            "/ pixelIntensityRange
+            ^ self
+        ].
+        (tagType == 34028) ifTrue:[
+            "/ transparencyIndicator
+            ^ self
+        ].
+        (tagType == 34029) ifTrue:[
+            "/ colorCharacterization
+            ^ self
+        ].
+        (tagType == 34030) ifTrue:[
+            "/ hcUsage
+            ^ self
+        ].
+        (tagType == 34031) ifTrue:[
+            "/ trapIndicator
+            ^ self
+        ].
+        (tagType == 34032) ifTrue:[
+            "/ cmykEquivalent
             ^ self
         ].
 
@@ -1788,11 +3032,28 @@
             ^ self
         ].
 
+        (tagType == 34264) ifTrue:[
+            "/ 'geotiff ModelTransformationTag' print. value printNewline.
+            ^ self
+        ].
         "/ private Photoshop
         (tagType == 34377) ifTrue:[
-            "/ 'photoshop RICHTIFFIPTC' print. value printNewline.
+            "/ RICHTIFFIPTC
+            "/ IPTC (International Press Telecommunications Council) metadata.
+            "/ (see http://www.iptc.org/std/photometadata/specification/IPTC-PhotoMetadata)
+            Verbose == true ifTrue:[ 
+                Logger info:'      RICHTIFFIPTC: %1' with:value
+            ].
+            decodeMetaTags == true ifTrue:[
+                self decodePhotoshopImageResourceBlock:value.
+            ] ifFalse:[
+                Verbose == true ifTrue:[ 
+                    Logger info:'      skipped decoding of IPTC-PhotoMetadata'
+                ].
+            ].    
             ^ self
         ].
+
         (tagType == 34665) ifTrue:[
             "/ EXIFIFD
             Verbose == true ifTrue:[ 
@@ -1809,11 +3070,26 @@
             "/ 'ImageLayer' print. value printNewline.
             ^ self
         ].
+
+        (tagType == 34735) ifTrue:[
+            "/ 'geotiff GeoKeyDirectoryTag' print. value printNewline.
+            ^ self
+        ].
+        (tagType == 34736) ifTrue:[
+            "/ 'geotiff GeoDoubleParamsTag' print. value printNewline.
+            ^ self
+        ].
+        (tagType == 34737) ifTrue:[
+            "/ 'geotiff GeoAsciiParamsTag' print. value printNewline.
+            ^ self
+        ].
+
+        
         (tagType == 34859) ifTrue:[
             "/ '???' print. value printNewline.
-            Verbose == true ifTrue:[ 
-                Logger info:'      ?: %1' with:value 
-            ].
+            "/ Verbose == true ifTrue:[ 
+            "/     Logger info:'      ?: %1' with:value 
+            "/ ].
             ^ self
         ].
         
@@ -1861,6 +3137,9 @@
     (tagType between:42000 and:42999) ifTrue:[
         (tagType == 42112) ifTrue:[
             "/ 'GDAL_METADATA' print. value printNewline.
+            Verbose == true ifTrue:[ 
+                Logger info:'      GDAL_METADATA: %1' with:value
+            ].
             ^ self
         ].
     ].
@@ -1872,6 +3151,7 @@
             Verbose == true ifTrue:[ 
                 Logger info:'      DNGVersion: %1' with:value
             ].
+            isDNGImage := true.
             ^ self
         ].
         (tagType == 50707) ifTrue:[
@@ -1881,14 +3161,14 @@
         (tagType == 50708) ifTrue:[
             "/ UniqueCameraModel
             Verbose == true ifTrue:[ 
-                Logger info:'      UniqueCameraModel: %1' with:value asString
+                Logger info:'      UniqueCameraModel: %1' with:value
             ].
             ^ self
         ].
         (tagType == 50709) ifTrue:[
             "/ LocalizedCameraModel
             Verbose == true ifTrue:[ 
-                Logger info:'      LocalizedCameraModel: %1' with:value asString
+                Logger info:'      LocalizedCameraModel: %1' with:value
             ].
             ^ self
         ].
@@ -1995,7 +3275,7 @@
         (tagType == 50735) ifTrue:[
             "/ 'CameraSerialNumber' print. value printNewline.
             Verbose == true ifTrue:[ 
-                Logger info:'      CameraSerialNumber: %1' with:value asString
+                Logger info:'      CameraSerialNumber: %1' with:value
             ].
             ^ self
         ].
@@ -2023,6 +3303,7 @@
             "/ 'MakerNoteSafety' print. value printNewline.
             ^ self
         ].
+        
         (tagType == 50778) ifTrue:[
             "/ 'CalibrationIlluminant1' print. value printNewline.
             ^ self
@@ -2039,6 +3320,7 @@
             "/ 'RawDataUniqueID' print. value printNewline.
             ^ self
         ].
+        
         (tagType == 50827) ifTrue:[
             "/ 'OriginalRawFileName' print. value printNewline.
             ^ self
@@ -2053,7 +3335,7 @@
     'TIFFReader [warning]: unknown tag type ' errorPrint. tagType errorPrintCR
 
     "Modified (format): / 23-05-2017 / 16:12:58 / mawalch"
-    "Modified (format): / 25-08-2017 / 17:02:57 / cg"
+    "Modified: / 27-08-2017 / 19:57:55 / cg"
 !
 
 positionToStrip:stripNr
@@ -2071,9 +3353,14 @@
 
     |oldPos offset bytes nInline|
 
-    n == 0 ifTrue:[^ ''].
-
     nInline := isBigTiff ifTrue:[8] ifFalse:[4].
+
+    n == 0 ifTrue:[
+        "/ even in this case, one WORD is to be skipped.
+        inStream skip:nInline.
+        ^ ''
+    ].
+
     bytes := (isSigned ifTrue:[Array] ifFalse:[ByteArray]) new:n.
     (n <= nInline) ifTrue:[
         isSigned ifTrue:[
@@ -2097,7 +3384,7 @@
     ].
     ^ bytes
 
-    "Modified: / 24-08-2017 / 23:25:30 / cg"
+    "Modified: / 27-08-2017 / 19:56:23 / cg"
 !
 
 readChars:n
@@ -2105,18 +3392,24 @@
 
     |oldPos offset string nInline|
 
-    n == 0 ifTrue:[^ ''].
-
     nInline := isBigTiff ifTrue:[8] ifFalse:[4].
-    
+
+    n == 0 ifTrue:[
+        "/ even in this case, one WORD is to be skipped.
+        inStream skip:nInline.
+        ^ ''
+    ].
+
     string := String new:(n - 1).
     (n <= nInline) ifTrue:[
         inStream nextBytes:(n - 1) into:string.
+        inStream next. "/ skip the 0-byte.
+
         (n < nInline) ifTrue:[
             inStream skip:(nInline - n).
         ]
     ] ifFalse:[
-        offset := inStream nextInt32MSB:(byteOrder ~~ #lsb).
+        offset := inStream nextInt32MSB:(byteOrder == #msb).
         oldPos := inStream position.
         inStream position:offset.
         inStream nextBytes:(n - 1) into:string.
@@ -2124,7 +3417,7 @@
     ].
     ^ string
 
-    "Modified: / 24-08-2017 / 23:25:03 / cg"
+    "Modified: / 27-08-2017 / 19:55:15 / cg"
 !
 
 readDoubles:nFloats
@@ -2342,6 +3635,42 @@
     ^ values
 
     "Modified: / 24-08-2017 / 23:33:09 / cg"
+!
+
+readSingleTagFrom:aStream
+    |msb tagType numberType length|
+
+    msb := (byteOrder == #msb).
+    
+    tagType := aStream nextUnsignedInt16MSB:msb.
+    numberType := aStream nextUnsignedInt16MSB:msb.
+
+    isBigTiff ifFalse:[
+        length := aStream nextInt32MSB:msb.
+    ] ifTrue:[
+        length := aStream nextInt64MSB:msb.
+    ].
+    self decodeTiffTag:tagType numberType:numberType length:length.
+
+    "Created: / 26-08-2017 / 11:04:50 / cg"
+    "Modified (format): / 26-08-2017 / 22:37:58 / cg"
+!
+
+readTagsFrom:aStream
+    |numberOfTags msb|
+
+    msb := (byteOrder == #msb).
+    
+    isBigTiff ifFalse:[
+        numberOfTags := aStream nextUnsignedInt16MSB:msb.
+    ] ifTrue:[
+        numberOfTags := aStream nextUnsignedInt64MSB:msb.
+    ].
+    1 to:numberOfTags do:[:index |
+        self readSingleTagFrom:aStream.
+    ].
+
+    "Created: / 26-08-2017 / 11:03:45 / cg"
 ! !
 
 !TIFFReader methodsFor:'private-writing'!
@@ -2729,14 +4058,8 @@
      Leave image description in instance variables.
      (i.e. to get the image, ask with image)."
 
-    |char1 char2 version 
-     numberOfTags "{ Class: SmallInteger }"
-     tagType      "{ Class: SmallInteger }"
-     numberType   "{ Class: SmallInteger }"
-     length       "{ Class: SmallInteger }"
-     result offset msb
-     bytesPerRow offset1 offset2 tmp
-     pos1|
+    |char1 char2 version offset msb
+     bytesPerRow img moreIfds|
 
     inStream := aStream.
     aStream binary.
@@ -2760,12 +4083,10 @@
             ^ self fileFormatError:'not a tiff file'.
         ]
     ].
-    isBigTiff := false.
     
     version := aStream nextUnsignedInt16MSB:msb.
     (version == 42) ifTrue:[
-        offset := aStream nextUnsignedInt32MSB:msb.
-        aStream position:offset.
+        isBigTiff := false.
     ] ifFalse:[
        (version == 43) ifTrue:[
             |byteSizeOfOffsets always0|
@@ -2780,124 +4101,148 @@
             always0 == 0 ifFalse:[
                 ^ self fileFormatError:'version of bigtiff-file not supported'.
             ].
-            offset := aStream nextUnsignedInt64MSB:msb.
-            aStream position:offset.
         ] ifFalse:[    
             ^ self fileFormatError:'version of tiff-file not supported'.
         ].
     ].
 
-    "setup default values"
-    metaData := TIFFMetaData new.
+    imageSequence := ImageSequence new.
+    isDNGImage := false.
+
+    isBigTiff ifFalse:[
+        offset := aStream nextUnsignedInt32MSB:msb.
+    ] ifTrue:[
+        offset := aStream nextUnsignedInt64MSB:msb.
+    ].    
+
+    [ offset ~~ 0 ] whileTrue:[    
+        Verbose == true ifTrue:[
+            Logger info:'------------------ reading image #%1 ------------------' with:imageSequence size+1.
+        ].    
+        
+        aStream position:offset.
+
+        "setup default values"
+        metaData := TIFFMetaData new.
+
+        compression := 1. "none"
+        fillOrder := #msb.
+        planarConfiguration := PLANARCONFIG_CONTIG.
+        photometric := nil.
+        bitsPerSample := 1.
+        samplesPerPixel := 1.
+        width := height := nil.
+        stripOffsets := stripByteCounts := rowsPerStrip := nil.
+        "resolutionUnit := 2."
+        predictor := 1.
+        group3options := nil.
+        orientation := nil.
+        subFileType := subIfds := nil.
+        sampleFormat := minSampleValue := maxSampleValue := nil.
+        tileWidth := tileLength := tileOffsets := tileByteCounts := nil.
+        
+        self readTagsFrom:aStream.
+        "/ read the next offset now,
+        "/ because the stream's position will be changed when the image-data is read
+        isBigTiff ifFalse:[
+            offset := aStream nextUnsignedInt32MSB:msb.
+        ] ifTrue:[
+            offset := aStream nextUnsignedInt64MSB:msb.
+        ].    
+
+        "check for required tags"
+        width isNil ifTrue:[ ^ self fileFormatError:'missing width tag' ].
+        height isNil ifTrue:[ ^ self fileFormatError:'missing length tag' ].
+        photometric isNil ifTrue:[ ^ self fileFormatError:'missing photometric tag' ].
+
+        "given all the information, read the bits"
+        tileWidth notNil ifTrue:[
+            tileOffsets := tileOffsets ? stripOffsets.
+            tileByteCounts := tileByteCounts ? stripByteCounts.
+            (tileOffsets notNil 
+                and:[tileLength notNil
+                and:[tileByteCounts notNil ]]
+            ) ifFalse:[    
+                ^ self fileFormatError:'missing stripOffsets (or tileOffsets)'.
+            ].
+            self reportDimension.
+            self readTiledTiffImageData.
+        ] ifFalse:[
+            stripByteCounts isNil ifTrue:[
+                stripOffsets size == 1 ifTrue:[
+                    stripByteCounts := Array with:(self bitsPerPixel // 8) * width * height
+                ] ifFalse:[
+                    ^ self fileFormatError:'missing stripByteCounts'.
+                ].    
+            ].
+            rowsPerStrip isNil ifTrue:[
+                rowsPerStrip := height
+            ].
+            self reportDimension.
+            self readTiffImageData.
+        ].
     
-    compression := 1. "none"
-    fillOrder := #msb.
-    planarConfiguration := 1.
-    photometric := nil.
-    bitsPerSample := 1.
-    samplesPerPixel := 1.
-    width := nil.
-    height := nil.
-    stripOffsets := nil.
-    rowsPerStrip := nil.
-    "resolutionUnit := 2."
-    predictor := 1.
-    orientation := nil.
-
-    (version == 42) ifTrue:[
-        numberOfTags := aStream nextUnsignedInt16MSB:msb.
-
-        1 to:numberOfTags do:[:index |
-            tagType := aStream nextUnsignedInt16MSB:msb.
-            numberType := aStream nextUnsignedInt16MSB:msb.
-            length := aStream nextInt32MSB:msb.
-            self decodeTiffTag:tagType numberType:numberType length:length
-        ].
-        offset := aStream nextInt32MSB:msb.
-    ] ifFalse:[
-        numberOfTags := aStream nextUnsignedInt64MSB:msb.
-
-        1 to:numberOfTags do:[:index |
-            tagType := aStream nextUnsignedInt16MSB:msb.
-            numberType := aStream nextUnsignedInt16MSB:msb.
-            length := aStream nextInt64MSB:msb.
-            pos1 := aStream position.
-            self decodeTiffTag:tagType numberType:numberType length:length.
-        ].
-        offset := aStream nextInt32MSB:msb.
-    ].
-    (offset ~~ 0) ifTrue:[
-        'TIFFReader [info]: more tags ignored' infoPrintCR
-    ].
-
-    "check for required tags"
-    width isNil ifTrue:[
-        ^ self fileFormatError:'missing width tag'.
-    ].
-
-    height isNil ifTrue:[
-        ^ self fileFormatError:'missing length tag'.
-    ].
-
-    photometric isNil ifTrue:[
-        ^ self fileFormatError:'missing photometric tag'.
+        orientation == #unsupported ifTrue:[
+            'TIFFReader [warning]: unsupported orientation' errorPrintCR
+        ] ifFalse:[
+            orientation == #vFlip ifTrue:[
+                |tmp offset1 offset2|
+                
+                "/ reverse rows to top-to bottom 
+                "/ (oops - depends on side-effecting the data array)
+
+                bytesPerRow := self bytesPerRow.
+                tmp := ByteArray new:bytesPerRow.
+                offset1 := 1.
+                offset2 := (height-1)*bytesPerRow + 1.
+                0 to:((height-1)//2) do:[:row |
+                    tmp replaceFrom:1 to:bytesPerRow with:data startingAt:offset1.
+                    data replaceFrom:offset1 to:(offset1+bytesPerRow-1) with:data startingAt:offset2.
+                    data replaceFrom:offset2 to:(offset2+bytesPerRow-1) with:tmp startingAt:1.
+                    offset1 := offset1 + bytesPerRow.
+                    offset2 := offset2 - bytesPerRow.
+                ].
+            ].
+        ].
+
+        "/ fixup photoetric
+        photometric == #rgb ifTrue:[
+            samplesPerPixel == 4 ifTrue:[
+                photometric := #rgba
+            ].    
+        ].
+        
+        img := self makeImage.
+        img imageSequence:imageSequence.
+        imageSequence add:(ImageFrame new image:img).
+
+        offset == 0 ifTrue:[
+            moreIfds isNil ifTrue:[
+                subIfds notNil ifTrue:[
+                    (isDNGImage not or:[loadFullResolutionImage == true]) ifTrue:[
+                        moreIfds := OrderedCollection withAll:subIfds.
+                        subIfds := nil.
+                    ] ifFalse:[
+                        Verbose == true ifTrue:[
+                            Logger info:'skip high resolution images (use loadFullResolutionImage is false)'
+                        ].    
+                    ].    
+                ].
+            ].
+            moreIfds notEmptyOrNil ifTrue:[
+                offset := moreIfds removeFirst
+            ].    
+        ].    
     ].
 
-    "given all the information, read the bits"
-    stripOffsets isNil ifTrue:[
-        (metaData notNil 
-            and:[(metaData includesKey:#TileWidth) 
-            and:[(metaData includesKey:#TileLength)
-            and:[(metaData includesKey:#TileOffsets)
-            and:[(metaData includesKey:#TileByteCounts) ]]]]
-        ) ifFalse:[    
-            ^ self fileFormatError:'missing stripOffsets or tileOffsets tag'.
-        ].
-        self reportDimension.
-        result := self readTiledTiffImageData.
-    ] ifFalse:[
-        stripByteCounts isNil ifTrue:[
-            stripOffsets size == 1 ifTrue:[
-                stripByteCounts := Array with:(self bitsPerPixel // 8) * width * height
-            ] ifFalse:[
-                ^ self fileFormatError:'missing stripByteCounts'.
-            ].    
-        ].
-        self reportDimension.
-        rowsPerStrip isNil ifTrue:[
-            rowsPerStrip := height
-        ].
-
-        result := self readTiffImageData.
-    ].
-    
-    result isNil ifTrue:[
-        "/ unsupported format.
-        ^ nil
-    ].
-
-    orientation == #vFlip ifTrue:[
-        "/ reverse rows to top-to bottom
-
-        bytesPerRow := self bytesPerRow.
-        tmp := ByteArray new:bytesPerRow.
-        offset1 := 1.
-        offset2 := (height-1)*bytesPerRow + 1.
-        0 to:((height-1)//2) do:[:row |
-            tmp replaceFrom:1 to:bytesPerRow with:data startingAt:offset1.
-            data replaceFrom:offset1 to:(offset1+bytesPerRow-1) with:data startingAt:offset2.
-            data replaceFrom:offset2 to:(offset2+bytesPerRow-1) with:tmp startingAt:1.
-            offset1 := offset1 + bytesPerRow.
-            offset2 := offset2 - bytesPerRow.
-        ].
-    ].
-    orientation == #unsupported ifTrue:[
-        'TIFFReader [warning]: unsupported orientation' errorPrintCR
-    ].
-
-    ^ result
-
-    "Modified: / 25-08-2017 / 10:08:30 / cg"
+    imageSequence size > 1 ifTrue:[
+        Verbose == true ifTrue:[
+            Logger info:'read %1 images' with:imageSequence size
+        ].    
+    ].    
+    ^ self
+
+    "Modified: / 27-08-2017 / 18:45:40 / cg"
 ! !
 
 !TIFFReader methodsFor:'writing'!
@@ -2930,7 +4275,7 @@
     bitsPerSample := image bitsPerSample.
 
     colorMap := image colorMap.
-    planarConfiguration := 1.
+    planarConfiguration := PLANARCONFIG_CONTIG.
     compression := 1.   "none"
     data := image bits.
 
@@ -2990,6 +4335,8 @@
         self writeTag:320            "colorMap"
     ].
     self writeLong:0.                "end of tags mark"
+
+    "Modified: / 27-08-2017 / 13:36:35 / cg"
 ! !
 
 !TIFFReader class methodsFor:'documentation'!