Home | History | Annotate | Download | only in coders
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                        TTTTT  IIIII  FFFFF  FFFFF                           %
      7 %                          T      I    F      F                               %
      8 %                          T      I    FFF    FFF                             %
      9 %                          T      I    F      F                               %
     10 %                          T    IIIII  F      F                               %
     11 %                                                                             %
     12 %                                                                             %
     13 %                        Read/Write TIFF Image Format                         %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                                   Cristy                                    %
     17 %                                 July 1992                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 */
     38 
     39 #ifdef __VMS
     41 #define JPEG_SUPPORT 1
     42 #endif
     43 
     44 /*
     45   Include declarations.
     46 */
     47 #include "MagickCore/studio.h"
     48 #include "MagickCore/artifact.h"
     49 #include "MagickCore/attribute.h"
     50 #include "MagickCore/blob.h"
     51 #include "MagickCore/blob-private.h"
     52 #include "MagickCore/cache.h"
     53 #include "MagickCore/color.h"
     54 #include "MagickCore/color-private.h"
     55 #include "MagickCore/colormap.h"
     56 #include "MagickCore/colorspace.h"
     57 #include "MagickCore/colorspace-private.h"
     58 #include "MagickCore/constitute.h"
     59 #include "MagickCore/enhance.h"
     60 #include "MagickCore/exception.h"
     61 #include "MagickCore/exception-private.h"
     62 #include "MagickCore/geometry.h"
     63 #include "MagickCore/image.h"
     64 #include "MagickCore/image-private.h"
     65 #include "MagickCore/list.h"
     66 #include "MagickCore/log.h"
     67 #include "MagickCore/magick.h"
     68 #include "MagickCore/memory_.h"
     69 #include "MagickCore/memory-private.h"
     70 #include "MagickCore/module.h"
     71 #include "MagickCore/monitor.h"
     72 #include "MagickCore/monitor-private.h"
     73 #include "MagickCore/option.h"
     74 #include "MagickCore/pixel-accessor.h"
     75 #include "MagickCore/pixel-private.h"
     76 #include "MagickCore/property.h"
     77 #include "MagickCore/quantum.h"
     78 #include "MagickCore/quantum-private.h"
     79 #include "MagickCore/profile.h"
     80 #include "MagickCore/resize.h"
     81 #include "MagickCore/resource_.h"
     82 #include "MagickCore/semaphore.h"
     83 #include "MagickCore/splay-tree.h"
     84 #include "MagickCore/static.h"
     85 #include "MagickCore/statistic.h"
     86 #include "MagickCore/string_.h"
     87 #include "MagickCore/string-private.h"
     88 #include "MagickCore/thread_.h"
     89 #include "MagickCore/token.h"
     90 #include "MagickCore/utility.h"
     91 #if defined(MAGICKCORE_TIFF_DELEGATE)
     92 # if defined(MAGICKCORE_HAVE_TIFFCONF_H)
     93 #  include "tiffconf.h"
     94 # endif
     95 # include "tiff.h"
     96 # include "tiffio.h"
     97 # if !defined(COMPRESSION_ADOBE_DEFLATE)
     98 #  define COMPRESSION_ADOBE_DEFLATE  8
     99 # endif
    100 # if !defined(PREDICTOR_HORIZONTAL)
    101 # define PREDICTOR_HORIZONTAL  2
    102 # endif
    103 # if !defined(TIFFTAG_COPYRIGHT)
    104 #  define TIFFTAG_COPYRIGHT  33432
    105 # endif
    106 # if !defined(TIFFTAG_OPIIMAGEID)
    107 #  define TIFFTAG_OPIIMAGEID  32781
    108 # endif
    109 #include "psd-private.h"
    110 
    111 /*
    112   Typedef declarations.
    113 */
    114 typedef enum
    115 {
    116   ReadSingleSampleMethod,
    117   ReadRGBAMethod,
    118   ReadCMYKAMethod,
    119   ReadYCCKMethod,
    120   ReadStripMethod,
    121   ReadTileMethod,
    122   ReadGenericMethod
    123 } TIFFMethodType;
    124 
    125 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
    126 typedef struct _ExifInfo
    127 {
    128   unsigned int
    129     tag,
    130     type,
    131     variable_length;
    132 
    133   const char
    134     *property;
    135 } ExifInfo;
    136 
    137 static const ExifInfo
    138   exif_info[] = {
    139     { EXIFTAG_EXPOSURETIME, TIFF_RATIONAL, 0, "exif:ExposureTime" },
    140     { EXIFTAG_FNUMBER, TIFF_RATIONAL, 0, "exif:FNumber" },
    141     { EXIFTAG_EXPOSUREPROGRAM, TIFF_SHORT, 0, "exif:ExposureProgram" },
    142     { EXIFTAG_SPECTRALSENSITIVITY, TIFF_ASCII, 0, "exif:SpectralSensitivity" },
    143     { EXIFTAG_ISOSPEEDRATINGS, TIFF_SHORT, 1, "exif:ISOSpeedRatings" },
    144     { EXIFTAG_OECF, TIFF_NOTYPE, 0, "exif:OptoelectricConversionFactor" },
    145     { EXIFTAG_EXIFVERSION, TIFF_NOTYPE, 0, "exif:ExifVersion" },
    146     { EXIFTAG_DATETIMEORIGINAL, TIFF_ASCII, 0, "exif:DateTimeOriginal" },
    147     { EXIFTAG_DATETIMEDIGITIZED, TIFF_ASCII, 0, "exif:DateTimeDigitized" },
    148     { EXIFTAG_COMPONENTSCONFIGURATION, TIFF_NOTYPE, 0, "exif:ComponentsConfiguration" },
    149     { EXIFTAG_COMPRESSEDBITSPERPIXEL, TIFF_RATIONAL, 0, "exif:CompressedBitsPerPixel" },
    150     { EXIFTAG_SHUTTERSPEEDVALUE, TIFF_SRATIONAL, 0, "exif:ShutterSpeedValue" },
    151     { EXIFTAG_APERTUREVALUE, TIFF_RATIONAL, 0, "exif:ApertureValue" },
    152     { EXIFTAG_BRIGHTNESSVALUE, TIFF_SRATIONAL, 0, "exif:BrightnessValue" },
    153     { EXIFTAG_EXPOSUREBIASVALUE, TIFF_SRATIONAL, 0, "exif:ExposureBiasValue" },
    154     { EXIFTAG_MAXAPERTUREVALUE, TIFF_RATIONAL, 0, "exif:MaxApertureValue" },
    155     { EXIFTAG_SUBJECTDISTANCE, TIFF_RATIONAL, 0, "exif:SubjectDistance" },
    156     { EXIFTAG_METERINGMODE, TIFF_SHORT, 0, "exif:MeteringMode" },
    157     { EXIFTAG_LIGHTSOURCE, TIFF_SHORT, 0, "exif:LightSource" },
    158     { EXIFTAG_FLASH, TIFF_SHORT, 0, "exif:Flash" },
    159     { EXIFTAG_FOCALLENGTH, TIFF_RATIONAL, 0, "exif:FocalLength" },
    160     { EXIFTAG_SUBJECTAREA, TIFF_NOTYPE, 0, "exif:SubjectArea" },
    161     { EXIFTAG_MAKERNOTE, TIFF_NOTYPE, 0, "exif:MakerNote" },
    162     { EXIFTAG_USERCOMMENT, TIFF_NOTYPE, 0, "exif:UserComment" },
    163     { EXIFTAG_SUBSECTIME, TIFF_ASCII, 0, "exif:SubSecTime" },
    164     { EXIFTAG_SUBSECTIMEORIGINAL, TIFF_ASCII, 0, "exif:SubSecTimeOriginal" },
    165     { EXIFTAG_SUBSECTIMEDIGITIZED, TIFF_ASCII, 0, "exif:SubSecTimeDigitized" },
    166     { EXIFTAG_FLASHPIXVERSION, TIFF_NOTYPE, 0, "exif:FlashpixVersion" },
    167     { EXIFTAG_PIXELXDIMENSION, TIFF_LONG, 0, "exif:PixelXDimension" },
    168     { EXIFTAG_PIXELYDIMENSION, TIFF_LONG, 0, "exif:PixelYDimension" },
    169     { EXIFTAG_RELATEDSOUNDFILE, TIFF_ASCII, 0, "exif:RelatedSoundFile" },
    170     { EXIFTAG_FLASHENERGY, TIFF_RATIONAL, 0, "exif:FlashEnergy" },
    171     { EXIFTAG_SPATIALFREQUENCYRESPONSE, TIFF_NOTYPE, 0, "exif:SpatialFrequencyResponse" },
    172     { EXIFTAG_FOCALPLANEXRESOLUTION, TIFF_RATIONAL, 0, "exif:FocalPlaneXResolution" },
    173     { EXIFTAG_FOCALPLANEYRESOLUTION, TIFF_RATIONAL, 0, "exif:FocalPlaneYResolution" },
    174     { EXIFTAG_FOCALPLANERESOLUTIONUNIT, TIFF_SHORT, 0, "exif:FocalPlaneResolutionUnit" },
    175     { EXIFTAG_SUBJECTLOCATION, TIFF_SHORT, 0, "exif:SubjectLocation" },
    176     { EXIFTAG_EXPOSUREINDEX, TIFF_RATIONAL, 0, "exif:ExposureIndex" },
    177     { EXIFTAG_SENSINGMETHOD, TIFF_SHORT, 0, "exif:SensingMethod" },
    178     { EXIFTAG_FILESOURCE, TIFF_NOTYPE, 0, "exif:FileSource" },
    179     { EXIFTAG_SCENETYPE, TIFF_NOTYPE, 0, "exif:SceneType" },
    180     { EXIFTAG_CFAPATTERN, TIFF_NOTYPE, 0, "exif:CFAPattern" },
    181     { EXIFTAG_CUSTOMRENDERED, TIFF_SHORT, 0, "exif:CustomRendered" },
    182     { EXIFTAG_EXPOSUREMODE, TIFF_SHORT, 0, "exif:ExposureMode" },
    183     { EXIFTAG_WHITEBALANCE, TIFF_SHORT, 0, "exif:WhiteBalance" },
    184     { EXIFTAG_DIGITALZOOMRATIO, TIFF_RATIONAL, 0, "exif:DigitalZoomRatio" },
    185     { EXIFTAG_FOCALLENGTHIN35MMFILM, TIFF_SHORT, 0, "exif:FocalLengthIn35mmFilm" },
    186     { EXIFTAG_SCENECAPTURETYPE, TIFF_SHORT, 0, "exif:SceneCaptureType" },
    187     { EXIFTAG_GAINCONTROL, TIFF_RATIONAL, 0, "exif:GainControl" },
    188     { EXIFTAG_CONTRAST, TIFF_SHORT, 0, "exif:Contrast" },
    189     { EXIFTAG_SATURATION, TIFF_SHORT, 0, "exif:Saturation" },
    190     { EXIFTAG_SHARPNESS, TIFF_SHORT, 0, "exif:Sharpness" },
    191     { EXIFTAG_DEVICESETTINGDESCRIPTION, TIFF_NOTYPE, 0, "exif:DeviceSettingDescription" },
    192     { EXIFTAG_SUBJECTDISTANCERANGE, TIFF_SHORT, 0, "exif:SubjectDistanceRange" },
    193     { EXIFTAG_IMAGEUNIQUEID, TIFF_ASCII, 0, "exif:ImageUniqueID" },
    194     { 0, 0, 0, (char *) NULL }
    195 };
    196 #endif
    197 #endif  /* MAGICKCORE_TIFF_DELEGATE */
    198 
    199 /*
    201   Global declarations.
    202 */
    203 static MagickThreadKey
    204   tiff_exception;
    205 
    206 static SemaphoreInfo
    207   *tiff_semaphore = (SemaphoreInfo *) NULL;
    208 
    209 static TIFFErrorHandler
    210   error_handler,
    211   warning_handler;
    212 
    213 static volatile MagickBooleanType
    214   instantiate_key = MagickFalse;
    215 
    216 /*
    218   Forward declarations.
    219 */
    220 #if defined(MAGICKCORE_TIFF_DELEGATE)
    221 static Image *
    222   ReadTIFFImage(const ImageInfo *,ExceptionInfo *);
    223 
    224 static MagickBooleanType
    225   WriteGROUP4Image(const ImageInfo *,Image *,ExceptionInfo *),
    226   WritePTIFImage(const ImageInfo *,Image *,ExceptionInfo *),
    227   WriteTIFFImage(const ImageInfo *,Image *,ExceptionInfo *);
    228 #endif
    229 
    230 /*
    232 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    233 %                                                                             %
    234 %                                                                             %
    235 %                                                                             %
    236 %   I s T I F F                                                               %
    237 %                                                                             %
    238 %                                                                             %
    239 %                                                                             %
    240 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    241 %
    242 %  IsTIFF() returns MagickTrue if the image format type, identified by the
    243 %  magick string, is TIFF.
    244 %
    245 %  The format of the IsTIFF method is:
    246 %
    247 %      MagickBooleanType IsTIFF(const unsigned char *magick,const size_t length)
    248 %
    249 %  A description of each parameter follows:
    250 %
    251 %    o magick: compare image format pattern against these bytes.
    252 %
    253 %    o length: Specifies the length of the magick string.
    254 %
    255 */
    256 static MagickBooleanType IsTIFF(const unsigned char *magick,const size_t length)
    257 {
    258   if (length < 4)
    259     return(MagickFalse);
    260   if (memcmp(magick,"\115\115\000\052",4) == 0)
    261     return(MagickTrue);
    262   if (memcmp(magick,"\111\111\052\000",4) == 0)
    263     return(MagickTrue);
    264 #if defined(TIFF_VERSION_BIG)
    265   if (length < 8)
    266     return(MagickFalse);
    267   if (memcmp(magick,"\115\115\000\053\000\010\000\000",8) == 0)
    268     return(MagickTrue);
    269   if (memcmp(magick,"\111\111\053\000\010\000\000\000",8) == 0)
    270     return(MagickTrue);
    271 #endif
    272   return(MagickFalse);
    273 }
    274 
    275 #if defined(MAGICKCORE_TIFF_DELEGATE)
    277 /*
    278 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    279 %                                                                             %
    280 %                                                                             %
    281 %                                                                             %
    282 %   R e a d G R O U P 4 I m a g e                                             %
    283 %                                                                             %
    284 %                                                                             %
    285 %                                                                             %
    286 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    287 %
    288 %  ReadGROUP4Image() reads a raw CCITT Group 4 image file and returns it.  It
    289 %  allocates the memory necessary for the new Image structure and returns a
    290 %  pointer to the new image.
    291 %
    292 %  The format of the ReadGROUP4Image method is:
    293 %
    294 %      Image *ReadGROUP4Image(const ImageInfo *image_info,
    295 %        ExceptionInfo *exception)
    296 %
    297 %  A description of each parameter follows:
    298 %
    299 %    o image_info: the image info.
    300 %
    301 %    o exception: return any errors or warnings in this structure.
    302 %
    303 */
    304 
    305 static inline size_t WriteLSBLong(FILE *file,const size_t value)
    306 {
    307   unsigned char
    308     buffer[4];
    309 
    310   buffer[0]=(unsigned char) value;
    311   buffer[1]=(unsigned char) (value >> 8);
    312   buffer[2]=(unsigned char) (value >> 16);
    313   buffer[3]=(unsigned char) (value >> 24);
    314   return(fwrite(buffer,1,4,file));
    315 }
    316 
    317 static Image *ReadGROUP4Image(const ImageInfo *image_info,
    318   ExceptionInfo *exception)
    319 {
    320   char
    321     filename[MagickPathExtent];
    322 
    323   FILE
    324     *file;
    325 
    326   Image
    327     *image;
    328 
    329   ImageInfo
    330     *read_info;
    331 
    332   int
    333     c,
    334     unique_file;
    335 
    336   MagickBooleanType
    337     status;
    338 
    339   size_t
    340     length;
    341 
    342   ssize_t
    343     offset,
    344     strip_offset;
    345 
    346   /*
    347     Open image file.
    348   */
    349   assert(image_info != (const ImageInfo *) NULL);
    350   assert(image_info->signature == MagickCoreSignature);
    351   if (image_info->debug != MagickFalse)
    352     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    353       image_info->filename);
    354   assert(exception != (ExceptionInfo *) NULL);
    355   assert(exception->signature == MagickCoreSignature);
    356   image=AcquireImage(image_info,exception);
    357   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
    358   if (status == MagickFalse)
    359     {
    360       image=DestroyImageList(image);
    361       return((Image *) NULL);
    362     }
    363   /*
    364     Write raw CCITT Group 4 wrapped as a TIFF image file.
    365   */
    366   file=(FILE *) NULL;
    367   unique_file=AcquireUniqueFileResource(filename);
    368   if (unique_file != -1)
    369     file=fdopen(unique_file,"wb");
    370   if ((unique_file == -1) || (file == (FILE *) NULL))
    371     ThrowImageException(FileOpenError,"UnableToCreateTemporaryFile");
    372   length=fwrite("\111\111\052\000\010\000\000\000\016\000",1,10,file);
    373   length=fwrite("\376\000\003\000\001\000\000\000\000\000\000\000",1,12,file);
    374   length=fwrite("\000\001\004\000\001\000\000\000",1,8,file);
    375   length=WriteLSBLong(file,image->columns);
    376   length=fwrite("\001\001\004\000\001\000\000\000",1,8,file);
    377   length=WriteLSBLong(file,image->rows);
    378   length=fwrite("\002\001\003\000\001\000\000\000\001\000\000\000",1,12,file);
    379   length=fwrite("\003\001\003\000\001\000\000\000\004\000\000\000",1,12,file);
    380   length=fwrite("\006\001\003\000\001\000\000\000\000\000\000\000",1,12,file);
    381   length=fwrite("\021\001\003\000\001\000\000\000",1,8,file);
    382   strip_offset=10+(12*14)+4+8;
    383   length=WriteLSBLong(file,(size_t) strip_offset);
    384   length=fwrite("\022\001\003\000\001\000\000\000",1,8,file);
    385   length=WriteLSBLong(file,(size_t) image_info->orientation);
    386   length=fwrite("\025\001\003\000\001\000\000\000\001\000\000\000",1,12,file);
    387   length=fwrite("\026\001\004\000\001\000\000\000",1,8,file);
    388   length=WriteLSBLong(file,image->rows);
    389   length=fwrite("\027\001\004\000\001\000\000\000\000\000\000\000",1,12,file);
    390   offset=(ssize_t) ftell(file)-4;
    391   length=fwrite("\032\001\005\000\001\000\000\000",1,8,file);
    392   length=WriteLSBLong(file,(size_t) (strip_offset-8));
    393   length=fwrite("\033\001\005\000\001\000\000\000",1,8,file);
    394   length=WriteLSBLong(file,(size_t) (strip_offset-8));
    395   length=fwrite("\050\001\003\000\001\000\000\000\002\000\000\000",1,12,file);
    396   length=fwrite("\000\000\000\000",1,4,file);
    397   length=WriteLSBLong(file,(long) image->resolution.x);
    398   length=WriteLSBLong(file,1);
    399   status=MagickTrue;
    400   for (length=0; (c=ReadBlobByte(image)) != EOF; length++)
    401     if (fputc(c,file) != c)
    402       status=MagickFalse;
    403   offset=(ssize_t) fseek(file,(ssize_t) offset,SEEK_SET);
    404   length=WriteLSBLong(file,(unsigned int) length);
    405   (void) fclose(file);
    406   (void) CloseBlob(image);
    407   image=DestroyImage(image);
    408   /*
    409     Read TIFF image.
    410   */
    411   read_info=CloneImageInfo((ImageInfo *) NULL);
    412   (void) FormatLocaleString(read_info->filename,MagickPathExtent,"%s",filename);
    413   image=ReadTIFFImage(read_info,exception);
    414   read_info=DestroyImageInfo(read_info);
    415   if (image != (Image *) NULL)
    416     {
    417       (void) CopyMagickString(image->filename,image_info->filename,
    418         MagickPathExtent);
    419       (void) CopyMagickString(image->magick_filename,image_info->filename,
    420         MagickPathExtent);
    421       (void) CopyMagickString(image->magick,"GROUP4",MagickPathExtent);
    422     }
    423   (void) RelinquishUniqueFileResource(filename);
    424   if (status == MagickFalse)
    425     image=DestroyImage(image);
    426   return(image);
    427 }
    428 #endif
    429 
    430 #if defined(MAGICKCORE_TIFF_DELEGATE)
    432 /*
    433 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    434 %                                                                             %
    435 %                                                                             %
    436 %                                                                             %
    437 %   R e a d T I F F I m a g e                                                 %
    438 %                                                                             %
    439 %                                                                             %
    440 %                                                                             %
    441 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    442 %
    443 %  ReadTIFFImage() reads a Tagged image file and returns it.  It allocates the
    444 %  memory necessary for the new Image structure and returns a pointer to the
    445 %  new image.
    446 %
    447 %  The format of the ReadTIFFImage method is:
    448 %
    449 %      Image *ReadTIFFImage(const ImageInfo *image_info,
    450 %        ExceptionInfo *exception)
    451 %
    452 %  A description of each parameter follows:
    453 %
    454 %    o image_info: the image info.
    455 %
    456 %    o exception: return any errors or warnings in this structure.
    457 %
    458 */
    459 
    460 static inline unsigned char ClampYCC(double value)
    461 {
    462   value=255.0-value;
    463   if (value < 0.0)
    464     return((unsigned char)0);
    465   if (value > 255.0)
    466     return((unsigned char)255);
    467   return((unsigned char)(value));
    468 }
    469 
    470 static MagickBooleanType DecodeLabImage(Image *image,ExceptionInfo *exception)
    471 {
    472   CacheView
    473     *image_view;
    474 
    475   MagickBooleanType
    476     status;
    477 
    478   ssize_t
    479     y;
    480 
    481   status=MagickTrue;
    482   image_view=AcquireAuthenticCacheView(image,exception);
    483   for (y=0; y < (ssize_t) image->rows; y++)
    484   {
    485     register Quantum
    486       *magick_restrict q;
    487 
    488     register ssize_t
    489       x;
    490 
    491     if (status == MagickFalse)
    492       continue;
    493     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
    494     if (q == (Quantum *) NULL)
    495       {
    496         status=MagickFalse;
    497         continue;
    498       }
    499     for (x=0; x < (ssize_t) image->columns; x++)
    500     {
    501       double
    502         a,
    503         b;
    504 
    505       a=QuantumScale*GetPixela(image,q)+0.5;
    506       if (a > 1.0)
    507         a-=1.0;
    508       b=QuantumScale*GetPixelb(image,q)+0.5;
    509       if (b > 1.0)
    510         b-=1.0;
    511       SetPixela(image,QuantumRange*a,q);
    512       SetPixelb(image,QuantumRange*b,q);
    513       q+=GetPixelChannels(image);
    514     }
    515     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
    516       status=MagickFalse;
    517   }
    518   image_view=DestroyCacheView(image_view);
    519   return(status);
    520 }
    521 
    522 static MagickBooleanType ReadProfile(Image *image,const char *name,
    523   const unsigned char *datum,ssize_t length,ExceptionInfo *exception)
    524 {
    525   MagickBooleanType
    526     status;
    527 
    528   StringInfo
    529     *profile;
    530 
    531   if (length < 4)
    532     return(MagickFalse);
    533   profile=BlobToStringInfo(datum,(size_t) length);
    534   if (profile == (StringInfo *) NULL)
    535     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    536       image->filename);
    537   status=SetImageProfile(image,name,profile,exception);
    538   profile=DestroyStringInfo(profile);
    539   if (status == MagickFalse)
    540     ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
    541       image->filename);
    542   return(MagickTrue);
    543 }
    544 
    545 #if defined(__cplusplus) || defined(c_plusplus)
    546 extern "C" {
    547 #endif
    548 
    549 static int TIFFCloseBlob(thandle_t image)
    550 {
    551   (void) CloseBlob((Image *) image);
    552   return(0);
    553 }
    554 
    555 static void TIFFErrors(const char *module,const char *format,va_list error)
    556 {
    557   char
    558     message[MagickPathExtent];
    559 
    560   ExceptionInfo
    561     *exception;
    562 
    563 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
    564   (void) vsnprintf(message,MagickPathExtent,format,error);
    565 #else
    566   (void) vsprintf(message,format,error);
    567 #endif
    568   (void) ConcatenateMagickString(message,".",MagickPathExtent);
    569   exception=(ExceptionInfo *) GetMagickThreadValue(tiff_exception);
    570   if (exception != (ExceptionInfo *) NULL)
    571     (void) ThrowMagickException(exception,GetMagickModule(),CoderError,message,
    572       "`%s'",module);
    573 }
    574 
    575 static toff_t TIFFGetBlobSize(thandle_t image)
    576 {
    577   return((toff_t) GetBlobSize((Image *) image));
    578 }
    579 
    580 static void TIFFGetProfiles(TIFF *tiff,Image *image,MagickBooleanType ping,
    581   ExceptionInfo *exception)
    582 {
    583   uint32
    584     length;
    585 
    586   unsigned char
    587     *profile;
    588 
    589   length=0;
    590   if (ping == MagickFalse)
    591     {
    592 #if defined(TIFFTAG_ICCPROFILE)
    593       if ((TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&profile) == 1) &&
    594           (profile != (unsigned char *) NULL))
    595         (void) ReadProfile(image,"icc",profile,(ssize_t) length,exception);
    596 #endif
    597 #if defined(TIFFTAG_PHOTOSHOP)
    598       if ((TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&profile) == 1) &&
    599           (profile != (unsigned char *) NULL))
    600         (void) ReadProfile(image,"8bim",profile,(ssize_t) length,exception);
    601 #endif
    602 #if defined(TIFFTAG_RICHTIFFIPTC)
    603       if ((TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&profile) == 1) &&
    604           (profile != (unsigned char *) NULL))
    605         {
    606           if (TIFFIsByteSwapped(tiff) != 0)
    607             TIFFSwabArrayOfLong((uint32 *) profile,(size_t) length);
    608           (void) ReadProfile(image,"iptc",profile,4L*length,exception);
    609         }
    610 #endif
    611 #if defined(TIFFTAG_XMLPACKET)
    612       if ((TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&profile) == 1) &&
    613           (profile != (unsigned char *) NULL))
    614         (void) ReadProfile(image,"xmp",profile,(ssize_t) length,exception);
    615 #endif
    616       if ((TIFFGetField(tiff,34118,&length,&profile) == 1) &&
    617           (profile != (unsigned char *) NULL))
    618         (void) ReadProfile(image,"tiff:34118",profile,(ssize_t) length,
    619           exception);
    620     }
    621   if ((TIFFGetField(tiff,37724,&length,&profile) == 1) &&
    622       (profile != (unsigned char *) NULL))
    623     (void) ReadProfile(image,"tiff:37724",profile,(ssize_t) length,exception);
    624 }
    625 
    626 static void TIFFGetProperties(TIFF *tiff,Image *image,ExceptionInfo *exception)
    627 {
    628   char
    629     message[MagickPathExtent],
    630     *text;
    631 
    632   uint32
    633     count,
    634     length,
    635     type;
    636 
    637   unsigned long
    638     *tietz;
    639 
    640 
    641   if (TIFFGetField(tiff,TIFFTAG_ARTIST,&text) == 1)
    642     (void) SetImageProperty(image,"tiff:artist",text,exception);
    643   if (TIFFGetField(tiff,TIFFTAG_COPYRIGHT,&text) == 1)
    644     (void) SetImageProperty(image,"tiff:copyright",text,exception);
    645   if (TIFFGetField(tiff,TIFFTAG_DATETIME,&text) == 1)
    646     (void) SetImageProperty(image,"tiff:timestamp",text,exception);
    647   if (TIFFGetField(tiff,TIFFTAG_DOCUMENTNAME,&text) == 1)
    648     (void) SetImageProperty(image,"tiff:document",text,exception);
    649   if (TIFFGetField(tiff,TIFFTAG_HOSTCOMPUTER,&text) == 1)
    650     (void) SetImageProperty(image,"tiff:hostcomputer",text,exception);
    651   if (TIFFGetField(tiff,TIFFTAG_IMAGEDESCRIPTION,&text) == 1)
    652     (void) SetImageProperty(image,"comment",text,exception);
    653   if (TIFFGetField(tiff,TIFFTAG_MAKE,&text) == 1)
    654     (void) SetImageProperty(image,"tiff:make",text,exception);
    655   if (TIFFGetField(tiff,TIFFTAG_MODEL,&text) == 1)
    656     (void) SetImageProperty(image,"tiff:model",text,exception);
    657   if (TIFFGetField(tiff,TIFFTAG_OPIIMAGEID,&count,&text) == 1)
    658     {
    659       if (count >= MagickPathExtent)
    660         count=MagickPathExtent-1;
    661       (void) CopyMagickString(message,text,count+1);
    662       (void) SetImageProperty(image,"tiff:image-id",message,exception);
    663     }
    664   if (TIFFGetField(tiff,TIFFTAG_PAGENAME,&text) == 1)
    665     (void) SetImageProperty(image,"label",text,exception);
    666   if (TIFFGetField(tiff,TIFFTAG_SOFTWARE,&text) == 1)
    667     (void) SetImageProperty(image,"tiff:software",text,exception);
    668   if (TIFFGetField(tiff,33423,&count,&text) == 1)
    669     {
    670       if (count >= MagickPathExtent)
    671         count=MagickPathExtent-1;
    672       (void) CopyMagickString(message,text,count+1);
    673       (void) SetImageProperty(image,"tiff:kodak-33423",message,exception);
    674     }
    675   if (TIFFGetField(tiff,36867,&count,&text) == 1)
    676     {
    677       if (count >= MagickPathExtent)
    678         count=MagickPathExtent-1;
    679       (void) CopyMagickString(message,text,count+1);
    680       (void) SetImageProperty(image,"tiff:kodak-36867",message,exception);
    681     }
    682   if (TIFFGetField(tiff,TIFFTAG_SUBFILETYPE,&type) == 1)
    683     switch (type)
    684     {
    685       case 0x01:
    686       {
    687         (void) SetImageProperty(image,"tiff:subfiletype","REDUCEDIMAGE",
    688           exception);
    689         break;
    690       }
    691       case 0x02:
    692       {
    693         (void) SetImageProperty(image,"tiff:subfiletype","PAGE",exception);
    694         break;
    695       }
    696       case 0x04:
    697       {
    698         (void) SetImageProperty(image,"tiff:subfiletype","MASK",exception);
    699         break;
    700       }
    701       default:
    702         break;
    703     }
    704   if (TIFFGetField(tiff,37706,&length,&tietz) == 1)
    705     {
    706       (void) FormatLocaleString(message,MagickPathExtent,"%lu",tietz[0]);
    707       (void) SetImageProperty(image,"tiff:tietz_offset",message,exception);
    708     }
    709 }
    710 
    711 static void TIFFGetEXIFProperties(TIFF *tiff,Image *image,
    712   ExceptionInfo *exception)
    713 {
    714 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
    715   char
    716     value[MagickPathExtent];
    717 
    718   register ssize_t
    719     i;
    720 
    721   tdir_t
    722     directory;
    723 
    724 #if defined(TIFF_VERSION_BIG)
    725   uint64
    726 #else
    727   uint32
    728 #endif
    729     offset;
    730 
    731   void
    732     *sans;
    733 
    734   /*
    735     Read EXIF properties.
    736   */
    737   offset=0;
    738   if (TIFFGetField(tiff,TIFFTAG_EXIFIFD,&offset) != 1)
    739     return;
    740   directory=TIFFCurrentDirectory(tiff);
    741   if (TIFFReadEXIFDirectory(tiff,offset) != 1)
    742     {
    743       TIFFSetDirectory(tiff,directory);
    744       return;
    745     }
    746   sans=NULL;
    747   for (i=0; exif_info[i].tag != 0; i++)
    748   {
    749     *value='\0';
    750     switch (exif_info[i].type)
    751     {
    752       case TIFF_ASCII:
    753       {
    754         char
    755           *ascii;
    756 
    757         ascii=(char *) NULL;
    758         if ((TIFFGetField(tiff,exif_info[i].tag,&ascii,&sans,&sans) == 1) &&
    759             (ascii != (char *) NULL) && (*ascii != '\0'))
    760           (void) CopyMagickString(value,ascii,MagickPathExtent);
    761         break;
    762       }
    763       case TIFF_SHORT:
    764       {
    765         if (exif_info[i].variable_length == 0)
    766           {
    767             uint16
    768               shorty;
    769 
    770             shorty=0;
    771             if (TIFFGetField(tiff,exif_info[i].tag,&shorty,&sans,&sans) == 1)
    772               (void) FormatLocaleString(value,MagickPathExtent,"%d",shorty);
    773           }
    774         else
    775           {
    776             int
    777               tiff_status;
    778 
    779             uint16
    780               *shorty;
    781 
    782             uint16
    783               shorty_num;
    784 
    785             tiff_status=TIFFGetField(tiff,exif_info[i].tag,&shorty_num,&shorty,
    786               &sans,&sans);
    787             if (tiff_status == 1)
    788               (void) FormatLocaleString(value,MagickPathExtent,"%d",
    789                 shorty_num != 0 ? shorty[0] : 0);
    790           }
    791         break;
    792       }
    793       case TIFF_LONG:
    794       {
    795         uint32
    796           longy;
    797 
    798         longy=0;
    799         if (TIFFGetField(tiff,exif_info[i].tag,&longy,&sans,&sans) == 1)
    800           (void) FormatLocaleString(value,MagickPathExtent,"%d",longy);
    801         break;
    802       }
    803 #if defined(TIFF_VERSION_BIG)
    804       case TIFF_LONG8:
    805       {
    806         uint64
    807           long8y;
    808 
    809         long8y=0;
    810         if (TIFFGetField(tiff,exif_info[i].tag,&long8y,&sans,&sans) == 1)
    811           (void) FormatLocaleString(value,MagickPathExtent,"%.20g",(double)
    812             ((MagickOffsetType) long8y));
    813         break;
    814       }
    815 #endif
    816       case TIFF_RATIONAL:
    817       case TIFF_SRATIONAL:
    818       case TIFF_FLOAT:
    819       {
    820         float
    821           floaty;
    822 
    823         floaty=0.0;
    824         if (TIFFGetField(tiff,exif_info[i].tag,&floaty,&sans,&sans) == 1)
    825           (void) FormatLocaleString(value,MagickPathExtent,"%g",(double)
    826             floaty);
    827         break;
    828       }
    829       case TIFF_DOUBLE:
    830       {
    831         double
    832           doubley;
    833 
    834         doubley=0.0;
    835         if (TIFFGetField(tiff,exif_info[i].tag,&doubley,&sans,&sans) == 1)
    836           (void) FormatLocaleString(value,MagickPathExtent,"%g",doubley);
    837         break;
    838       }
    839       default:
    840         break;
    841     }
    842     if (*value != '\0')
    843       (void) SetImageProperty(image,exif_info[i].property,value,exception);
    844   }
    845   TIFFSetDirectory(tiff,directory);
    846 #else
    847   (void) tiff;
    848   (void) image;
    849 #endif
    850 }
    851 
    852 static int TIFFMapBlob(thandle_t image,tdata_t *base,toff_t *size)
    853 {
    854   *base=(tdata_t *) GetBlobStreamData((Image *) image);
    855   if (*base != (tdata_t *) NULL)
    856     *size=(toff_t) GetBlobSize((Image *) image);
    857   if (*base != (tdata_t *) NULL)
    858     return(1);
    859   return(0);
    860 }
    861 
    862 static tsize_t TIFFReadBlob(thandle_t image,tdata_t data,tsize_t size)
    863 {
    864   tsize_t
    865     count;
    866 
    867   count=(tsize_t) ReadBlob((Image *) image,(size_t) size,
    868     (unsigned char *) data);
    869   return(count);
    870 }
    871 
    872 static int32 TIFFReadPixels(TIFF *tiff,size_t bits_per_sample,
    873   tsample_t sample,ssize_t row,tdata_t scanline)
    874 {
    875   int32
    876     status;
    877 
    878   (void) bits_per_sample;
    879   status=TIFFReadScanline(tiff,scanline,(uint32) row,sample);
    880   return(status);
    881 }
    882 
    883 static toff_t TIFFSeekBlob(thandle_t image,toff_t offset,int whence)
    884 {
    885   return((toff_t) SeekBlob((Image *) image,(MagickOffsetType) offset,whence));
    886 }
    887 
    888 static void TIFFUnmapBlob(thandle_t image,tdata_t base,toff_t size)
    889 {
    890   (void) image;
    891   (void) base;
    892   (void) size;
    893 }
    894 
    895 static void TIFFWarnings(const char *module,const char *format,va_list warning)
    896 {
    897   char
    898     message[MagickPathExtent];
    899 
    900   ExceptionInfo
    901     *exception;
    902 
    903 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
    904   (void) vsnprintf(message,MagickPathExtent,format,warning);
    905 #else
    906   (void) vsprintf(message,format,warning);
    907 #endif
    908   (void) ConcatenateMagickString(message,".",MagickPathExtent);
    909   exception=(ExceptionInfo *) GetMagickThreadValue(tiff_exception);
    910   if (exception != (ExceptionInfo *) NULL)
    911     (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
    912       message,"`%s'",module);
    913 }
    914 
    915 static tsize_t TIFFWriteBlob(thandle_t image,tdata_t data,tsize_t size)
    916 {
    917   tsize_t
    918     count;
    919 
    920   count=(tsize_t) WriteBlob((Image *) image,(size_t) size,
    921     (unsigned char *) data);
    922   return(count);
    923 }
    924 
    925 static TIFFMethodType GetJPEGMethod(Image* image,TIFF *tiff,uint16 photometric,
    926   uint16 bits_per_sample,uint16 samples_per_pixel)
    927 {
    928 #define BUFFER_SIZE 2048
    929 
    930   MagickOffsetType
    931     position,
    932     offset;
    933 
    934   register size_t
    935     i;
    936 
    937   TIFFMethodType
    938     method;
    939 
    940 #if defined(TIFF_VERSION_BIG)
    941   uint64
    942 #else
    943   uint32
    944 #endif
    945     **value;
    946 
    947   unsigned char
    948     buffer[BUFFER_SIZE+32];
    949 
    950   unsigned short
    951     length;
    952 
    953   /* only support 8 bit for now */
    954   if ((photometric != PHOTOMETRIC_SEPARATED) || (bits_per_sample != 8) ||
    955       (samples_per_pixel != 4))
    956     return(ReadGenericMethod);
    957   /* Search for Adobe APP14 JPEG Marker */
    958   if (!TIFFGetField(tiff,TIFFTAG_STRIPOFFSETS,&value))
    959     return(ReadRGBAMethod);
    960   position=TellBlob(image);
    961   offset=(MagickOffsetType) (value[0]);
    962   if (SeekBlob(image,offset,SEEK_SET) != offset)
    963     return(ReadRGBAMethod);
    964   method=ReadRGBAMethod;
    965   if (ReadBlob(image,BUFFER_SIZE,buffer) == BUFFER_SIZE)
    966     {
    967       for (i=0; i < BUFFER_SIZE; i++)
    968       {
    969         while (i < BUFFER_SIZE)
    970         {
    971           if (buffer[i++] == 255)
    972            break;
    973         }
    974         while (i < BUFFER_SIZE)
    975         {
    976           if (buffer[++i] != 255)
    977            break;
    978         }
    979         if (buffer[i++] == 216) /* JPEG_MARKER_SOI */
    980           continue;
    981         length=(unsigned short) (((unsigned int) (buffer[i] << 8) |
    982           (unsigned int) buffer[i+1]) & 0xffff);
    983         if (i+(size_t) length >= BUFFER_SIZE)
    984           break;
    985         if (buffer[i-1] == 238) /* JPEG_MARKER_APP0+14 */
    986           {
    987             if (length != 14)
    988               break;
    989             /* 0 == CMYK, 1 == YCbCr, 2 = YCCK */
    990             if (buffer[i+13] == 2)
    991               method=ReadYCCKMethod;
    992             break;
    993           }
    994         i+=(size_t) length;
    995       }
    996     }
    997   (void) SeekBlob(image,position,SEEK_SET);
    998   return(method);
    999 }
   1000 
   1001 static void TIFFReadPhotoshopLayers(Image* image,const ImageInfo *image_info,
   1002   ExceptionInfo *exception)
   1003 {
   1004   const char
   1005     *option;
   1006 
   1007   const StringInfo
   1008     *layer_info;
   1009 
   1010   Image
   1011     *layers;
   1012 
   1013   PSDInfo
   1014     info;
   1015 
   1016   register ssize_t
   1017     i;
   1018 
   1019   if (GetImageListLength(image) != 1)
   1020     return;
   1021   if ((image_info->number_scenes == 1) && (image_info->scene == 0))
   1022     return;
   1023   option=GetImageOption(image_info,"tiff:ignore-layers");
   1024   if (option != (const char * ) NULL)
   1025     return;
   1026   layer_info=GetImageProfile(image,"tiff:37724");
   1027   if (layer_info == (const StringInfo *) NULL)
   1028     return;
   1029   for (i=0; i < (ssize_t) layer_info->length-8; i++)
   1030   {
   1031     if (LocaleNCompare((const char *) (layer_info->datum+i),
   1032         image->endian == MSBEndian ? "8BIM" : "MIB8",4) != 0)
   1033       continue;
   1034     i+=4;
   1035     if ((LocaleNCompare((const char *) (layer_info->datum+i),
   1036          image->endian == MSBEndian ? "Layr" : "ryaL",4) == 0) ||
   1037         (LocaleNCompare((const char *) (layer_info->datum+i),
   1038          image->endian == MSBEndian ? "LMsk" : "ksML",4) == 0) ||
   1039         (LocaleNCompare((const char *) (layer_info->datum+i),
   1040          image->endian == MSBEndian ? "Lr16" : "61rL",4) == 0) ||
   1041         (LocaleNCompare((const char *) (layer_info->datum+i),
   1042          image->endian == MSBEndian ? "Lr32" : "23rL",4) == 0))
   1043       break;
   1044   }
   1045   i+=4;
   1046   if (i >= (ssize_t) (layer_info->length-8))
   1047     return;
   1048   layers=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
   1049   (void) DeleteImageProfile(layers,"tiff:37724");
   1050   AttachBlob(layers->blob,layer_info->datum,layer_info->length);
   1051   SeekBlob(layers,(MagickOffsetType) i,SEEK_SET);
   1052   info.version=1;
   1053   info.columns=layers->columns;
   1054   info.rows=layers->rows;
   1055   info.channels=(unsigned short) layers->number_channels;
   1056   /* Setting the mode to a value that won't change the colorspace */
   1057   info.mode=10;
   1058   ReadPSDLayers(layers,image_info,&info,MagickFalse,exception);
   1059   DeleteImageFromList(&layers);
   1060   if (layers != (Image *) NULL)
   1061     {
   1062       SetImageArtifact(image,"tiff:has-layers","true");
   1063       AppendImageToList(&image,layers);
   1064       while (layers != (Image *) NULL)
   1065       {
   1066         SetImageArtifact(layers,"tiff:has-layers","true");
   1067         DetachBlob(layers->blob);
   1068         layers=GetNextImageInList(layers);
   1069       }
   1070     }
   1071 }
   1072 
   1073 #if defined(__cplusplus) || defined(c_plusplus)
   1074 }
   1075 #endif
   1076 
   1077 static Image *ReadTIFFImage(const ImageInfo *image_info,
   1078   ExceptionInfo *exception)
   1079 {
   1080   const char
   1081     *option;
   1082 
   1083   float
   1084     *chromaticity,
   1085     x_position,
   1086     y_position,
   1087     x_resolution,
   1088     y_resolution;
   1089 
   1090   Image
   1091     *image;
   1092 
   1093   int
   1094     tiff_status;
   1095 
   1096   MagickBooleanType
   1097     status;
   1098 
   1099   MagickSizeType
   1100     number_pixels;
   1101 
   1102   QuantumInfo
   1103     *quantum_info;
   1104 
   1105   QuantumType
   1106     quantum_type;
   1107 
   1108   register ssize_t
   1109     i;
   1110 
   1111   size_t
   1112     pad;
   1113 
   1114   ssize_t
   1115     y;
   1116 
   1117   TIFF
   1118     *tiff;
   1119 
   1120   TIFFMethodType
   1121     method;
   1122 
   1123   uint16
   1124     compress_tag,
   1125     bits_per_sample,
   1126     endian,
   1127     extra_samples,
   1128     interlace,
   1129     max_sample_value,
   1130     min_sample_value,
   1131     orientation,
   1132     pages,
   1133     photometric,
   1134     *sample_info,
   1135     sample_format,
   1136     samples_per_pixel,
   1137     units,
   1138     value;
   1139 
   1140   uint32
   1141     height,
   1142     rows_per_strip,
   1143     width;
   1144 
   1145   unsigned char
   1146     *pixels;
   1147 
   1148   /*
   1149     Open image.
   1150   */
   1151   assert(image_info != (const ImageInfo *) NULL);
   1152   assert(image_info->signature == MagickCoreSignature);
   1153   if (image_info->debug != MagickFalse)
   1154     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
   1155       image_info->filename);
   1156   assert(exception != (ExceptionInfo *) NULL);
   1157   assert(exception->signature == MagickCoreSignature);
   1158   image=AcquireImage(image_info,exception);
   1159   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
   1160   if (status == MagickFalse)
   1161     {
   1162       image=DestroyImageList(image);
   1163       return((Image *) NULL);
   1164     }
   1165   (void) SetMagickThreadValue(tiff_exception,exception);
   1166   tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) image,TIFFReadBlob,
   1167     TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
   1168     TIFFUnmapBlob);
   1169   if (tiff == (TIFF *) NULL)
   1170     {
   1171       image=DestroyImageList(image);
   1172       return((Image *) NULL);
   1173     }
   1174   if (image_info->number_scenes != 0)
   1175     {
   1176       /*
   1177         Generate blank images for subimage specification (e.g. image.tif[4].
   1178         We need to check the number of directores because it is possible that
   1179         the subimage(s) are stored in the photoshop profile.
   1180       */
   1181       if (image_info->scene < (size_t) TIFFNumberOfDirectories(tiff))
   1182         {
   1183           for (i=0; i < (ssize_t) image_info->scene; i++)
   1184           {
   1185             status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
   1186             if (status == MagickFalse)
   1187               {
   1188                 TIFFClose(tiff);
   1189                 image=DestroyImageList(image);
   1190                 return((Image *) NULL);
   1191               }
   1192             AcquireNextImage(image_info,image,exception);
   1193             if (GetNextImageInList(image) == (Image *) NULL)
   1194               {
   1195                 TIFFClose(tiff);
   1196                 image=DestroyImageList(image);
   1197                 return((Image *) NULL);
   1198               }
   1199             image=SyncNextImageInList(image);
   1200           }
   1201       }
   1202   }
   1203   do
   1204   {
   1205 DisableMSCWarning(4127)
   1206     if (0 && (image_info->verbose != MagickFalse))
   1207       TIFFPrintDirectory(tiff,stdout,MagickFalse);
   1208 RestoreMSCWarning
   1209     if ((TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) != 1) ||
   1210         (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&height) != 1) ||
   1211         (TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag) != 1) ||
   1212         (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian) != 1) ||
   1213         (TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace) != 1) ||
   1214         (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,&samples_per_pixel) != 1) ||
   1215         (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample) != 1) ||
   1216         (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format) != 1) ||
   1217         (TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value) != 1) ||
   1218         (TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value) != 1) ||
   1219         (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric) != 1))
   1220       {
   1221         TIFFClose(tiff);
   1222         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
   1223       }
   1224     if (sample_format == SAMPLEFORMAT_IEEEFP)
   1225       (void) SetImageProperty(image,"quantum:format","floating-point",
   1226         exception);
   1227     switch (photometric)
   1228     {
   1229       case PHOTOMETRIC_MINISBLACK:
   1230       {
   1231         (void) SetImageProperty(image,"tiff:photometric","min-is-black",
   1232           exception);
   1233         break;
   1234       }
   1235       case PHOTOMETRIC_MINISWHITE:
   1236       {
   1237         (void) SetImageProperty(image,"tiff:photometric","min-is-white",
   1238           exception);
   1239         break;
   1240       }
   1241       case PHOTOMETRIC_PALETTE:
   1242       {
   1243         (void) SetImageProperty(image,"tiff:photometric","palette",exception);
   1244         break;
   1245       }
   1246       case PHOTOMETRIC_RGB:
   1247       {
   1248         (void) SetImageProperty(image,"tiff:photometric","RGB",exception);
   1249         break;
   1250       }
   1251       case PHOTOMETRIC_CIELAB:
   1252       {
   1253         (void) SetImageProperty(image,"tiff:photometric","CIELAB",exception);
   1254         break;
   1255       }
   1256       case PHOTOMETRIC_LOGL:
   1257       {
   1258         (void) SetImageProperty(image,"tiff:photometric","CIE Log2(L)",
   1259           exception);
   1260         break;
   1261       }
   1262       case PHOTOMETRIC_LOGLUV:
   1263       {
   1264         (void) SetImageProperty(image,"tiff:photometric","LOGLUV",exception);
   1265         break;
   1266       }
   1267 #if defined(PHOTOMETRIC_MASK)
   1268       case PHOTOMETRIC_MASK:
   1269       {
   1270         (void) SetImageProperty(image,"tiff:photometric","MASK",exception);
   1271         break;
   1272       }
   1273 #endif
   1274       case PHOTOMETRIC_SEPARATED:
   1275       {
   1276         (void) SetImageProperty(image,"tiff:photometric","separated",exception);
   1277         break;
   1278       }
   1279       case PHOTOMETRIC_YCBCR:
   1280       {
   1281         (void) SetImageProperty(image,"tiff:photometric","YCBCR",exception);
   1282         break;
   1283       }
   1284       default:
   1285       {
   1286         (void) SetImageProperty(image,"tiff:photometric","unknown",exception);
   1287         break;
   1288       }
   1289     }
   1290     if (image->debug != MagickFalse)
   1291       {
   1292         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %ux%u",
   1293           (unsigned int) width,(unsigned int) height);
   1294         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Interlace: %u",
   1295           interlace);
   1296         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1297           "Bits per sample: %u",bits_per_sample);
   1298         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1299           "Min sample value: %u",min_sample_value);
   1300         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1301           "Max sample value: %u",max_sample_value);
   1302         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Photometric "
   1303           "interpretation: %s",GetImageProperty(image,"tiff:photometric",
   1304           exception));
   1305       }
   1306     image->columns=(size_t) width;
   1307     image->rows=(size_t) height;
   1308     image->depth=(size_t) bits_per_sample;
   1309     if (image->debug != MagickFalse)
   1310       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
   1311         (double) image->depth);
   1312     image->endian=MSBEndian;
   1313     if (endian == FILLORDER_LSB2MSB)
   1314       image->endian=LSBEndian;
   1315 #if defined(MAGICKCORE_HAVE_TIFFISBIGENDIAN)
   1316     if (TIFFIsBigEndian(tiff) == 0)
   1317       {
   1318         (void) SetImageProperty(image,"tiff:endian","lsb",exception);
   1319         image->endian=LSBEndian;
   1320       }
   1321     else
   1322       {
   1323         (void) SetImageProperty(image,"tiff:endian","msb",exception);
   1324         image->endian=MSBEndian;
   1325       }
   1326 #endif
   1327     if ((photometric == PHOTOMETRIC_MINISBLACK) ||
   1328         (photometric == PHOTOMETRIC_MINISWHITE))
   1329       SetImageColorspace(image,GRAYColorspace,exception);
   1330     if (photometric == PHOTOMETRIC_SEPARATED)
   1331       SetImageColorspace(image,CMYKColorspace,exception);
   1332     if (photometric == PHOTOMETRIC_CIELAB)
   1333       SetImageColorspace(image,LabColorspace,exception);
   1334     TIFFGetProfiles(tiff,image,image_info->ping,exception);
   1335     TIFFGetProperties(tiff,image,exception);
   1336     option=GetImageOption(image_info,"tiff:exif-properties");
   1337     if (IsStringFalse(option) == MagickFalse) /* enabled by default */
   1338       TIFFGetEXIFProperties(tiff,image,exception);
   1339     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
   1340       &samples_per_pixel);
   1341     if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XRESOLUTION,&x_resolution) == 1) &&
   1342         (TIFFGetFieldDefaulted(tiff,TIFFTAG_YRESOLUTION,&y_resolution) == 1))
   1343       {
   1344         image->resolution.x=x_resolution;
   1345         image->resolution.y=y_resolution;
   1346       }
   1347     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units) == 1)
   1348       {
   1349         if (units == RESUNIT_INCH)
   1350           image->units=PixelsPerInchResolution;
   1351         if (units == RESUNIT_CENTIMETER)
   1352           image->units=PixelsPerCentimeterResolution;
   1353       }
   1354     if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XPOSITION,&x_position) == 1) &&
   1355         (TIFFGetFieldDefaulted(tiff,TIFFTAG_YPOSITION,&y_position) == 1))
   1356       {
   1357         image->page.x=(ssize_t) ceil(x_position*image->resolution.x-0.5);
   1358         image->page.y=(ssize_t) ceil(y_position*image->resolution.y-0.5);
   1359       }
   1360     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation) == 1)
   1361       image->orientation=(OrientationType) orientation;
   1362     if (TIFFGetField(tiff,TIFFTAG_WHITEPOINT,&chromaticity) == 1)
   1363       {
   1364         if (chromaticity != (float *) NULL)
   1365           {
   1366             image->chromaticity.white_point.x=chromaticity[0];
   1367             image->chromaticity.white_point.y=chromaticity[1];
   1368           }
   1369       }
   1370     if (TIFFGetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,&chromaticity) == 1)
   1371       {
   1372         if (chromaticity != (float *) NULL)
   1373           {
   1374             image->chromaticity.red_primary.x=chromaticity[0];
   1375             image->chromaticity.red_primary.y=chromaticity[1];
   1376             image->chromaticity.green_primary.x=chromaticity[2];
   1377             image->chromaticity.green_primary.y=chromaticity[3];
   1378             image->chromaticity.blue_primary.x=chromaticity[4];
   1379             image->chromaticity.blue_primary.y=chromaticity[5];
   1380           }
   1381       }
   1382 #if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
   1383     if ((compress_tag != COMPRESSION_NONE) &&
   1384         (TIFFIsCODECConfigured(compress_tag) == 0))
   1385       {
   1386         TIFFClose(tiff);
   1387         ThrowReaderException(CoderError,"CompressNotSupported");
   1388       }
   1389 #endif
   1390     switch (compress_tag)
   1391     {
   1392       case COMPRESSION_NONE: image->compression=NoCompression; break;
   1393       case COMPRESSION_CCITTFAX3: image->compression=FaxCompression; break;
   1394       case COMPRESSION_CCITTFAX4: image->compression=Group4Compression; break;
   1395       case COMPRESSION_JPEG:
   1396       {
   1397          image->compression=JPEGCompression;
   1398 #if defined(JPEG_SUPPORT)
   1399          {
   1400            char
   1401              sampling_factor[MagickPathExtent];
   1402 
   1403            int
   1404              tiff_status;
   1405 
   1406            uint16
   1407              horizontal,
   1408              vertical;
   1409 
   1410            tiff_status=TIFFGetFieldDefaulted(tiff,TIFFTAG_YCBCRSUBSAMPLING,
   1411              &horizontal,&vertical);
   1412            if (tiff_status == 1)
   1413              {
   1414                (void) FormatLocaleString(sampling_factor,MagickPathExtent,
   1415                  "%dx%d",horizontal,vertical);
   1416                (void) SetImageProperty(image,"jpeg:sampling-factor",
   1417                  sampling_factor,exception);
   1418                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1419                  "Sampling Factors: %s",sampling_factor);
   1420              }
   1421          }
   1422 #endif
   1423         break;
   1424       }
   1425       case COMPRESSION_OJPEG: image->compression=JPEGCompression; break;
   1426 #if defined(COMPRESSION_LZMA)
   1427       case COMPRESSION_LZMA: image->compression=LZMACompression; break;
   1428 #endif
   1429       case COMPRESSION_LZW: image->compression=LZWCompression; break;
   1430       case COMPRESSION_DEFLATE: image->compression=ZipCompression; break;
   1431       case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break;
   1432       default: image->compression=RLECompression; break;
   1433     }
   1434     /*
   1435       Allocate memory for the image and pixel buffer.
   1436     */
   1437     quantum_info=AcquireQuantumInfo(image_info,image);
   1438     if (quantum_info == (QuantumInfo *) NULL)
   1439       {
   1440         TIFFClose(tiff);
   1441         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1442       }
   1443     if (sample_format == SAMPLEFORMAT_UINT)
   1444       status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat);
   1445     if (sample_format == SAMPLEFORMAT_INT)
   1446       status=SetQuantumFormat(image,quantum_info,SignedQuantumFormat);
   1447     if (sample_format == SAMPLEFORMAT_IEEEFP)
   1448       status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
   1449     if (status == MagickFalse)
   1450       {
   1451         TIFFClose(tiff);
   1452         quantum_info=DestroyQuantumInfo(quantum_info);
   1453         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1454       }
   1455     status=MagickTrue;
   1456     switch (photometric)
   1457     {
   1458       case PHOTOMETRIC_MINISBLACK:
   1459       {
   1460         quantum_info->min_is_white=MagickFalse;
   1461         break;
   1462       }
   1463       case PHOTOMETRIC_MINISWHITE:
   1464       {
   1465         quantum_info->min_is_white=MagickTrue;
   1466         break;
   1467       }
   1468       default:
   1469         break;
   1470     }
   1471     tiff_status=TIFFGetFieldDefaulted(tiff,TIFFTAG_EXTRASAMPLES,&extra_samples,
   1472       &sample_info);
   1473     if (tiff_status == 1)
   1474       {
   1475         (void) SetImageProperty(image,"tiff:alpha","unspecified",exception);
   1476         if (extra_samples == 0)
   1477           {
   1478             if ((samples_per_pixel == 4) && (photometric == PHOTOMETRIC_RGB))
   1479               image->alpha_trait=BlendPixelTrait;
   1480           }
   1481         else
   1482           for (i=0; i < extra_samples; i++)
   1483           {
   1484             image->alpha_trait=BlendPixelTrait;
   1485             if (sample_info[i] == EXTRASAMPLE_ASSOCALPHA)
   1486               {
   1487                 SetQuantumAlphaType(quantum_info,DisassociatedQuantumAlpha);
   1488                 (void) SetImageProperty(image,"tiff:alpha","associated",
   1489                   exception);
   1490               }
   1491             else
   1492               if (sample_info[i] == EXTRASAMPLE_UNASSALPHA)
   1493                 (void) SetImageProperty(image,"tiff:alpha","unassociated",
   1494                   exception);
   1495           }
   1496       }
   1497     if ((photometric == PHOTOMETRIC_PALETTE) &&
   1498         (pow(2.0,1.0*bits_per_sample) <= MaxColormapSize))
   1499       {
   1500         size_t
   1501           colors;
   1502 
   1503         colors=(size_t) GetQuantumRange(bits_per_sample)+1;
   1504         if (AcquireImageColormap(image,colors,exception) == MagickFalse)
   1505           {
   1506             TIFFClose(tiff);
   1507             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1508           }
   1509       }
   1510     value=(unsigned short) image->scene;
   1511     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&value,&pages) == 1)
   1512       image->scene=value;
   1513     if (image->storage_class == PseudoClass)
   1514       {
   1515         int
   1516           tiff_status;
   1517 
   1518         size_t
   1519           range;
   1520 
   1521         uint16
   1522           *blue_colormap,
   1523           *green_colormap,
   1524           *red_colormap;
   1525 
   1526         /*
   1527           Initialize colormap.
   1528         */
   1529         tiff_status=TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap,
   1530           &green_colormap,&blue_colormap);
   1531         if (tiff_status == 1)
   1532           {
   1533             if ((red_colormap != (uint16 *) NULL) &&
   1534                 (green_colormap != (uint16 *) NULL) &&
   1535                 (blue_colormap != (uint16 *) NULL))
   1536               {
   1537                 range=255;  /* might be old style 8-bit colormap */
   1538                 for (i=0; i < (ssize_t) image->colors; i++)
   1539                   if ((red_colormap[i] >= 256) || (green_colormap[i] >= 256) ||
   1540                       (blue_colormap[i] >= 256))
   1541                     {
   1542                       range=65535;
   1543                       break;
   1544                     }
   1545                 for (i=0; i < (ssize_t) image->colors; i++)
   1546                 {
   1547                   image->colormap[i].red=ClampToQuantum(((double)
   1548                     QuantumRange*red_colormap[i])/range);
   1549                   image->colormap[i].green=ClampToQuantum(((double)
   1550                     QuantumRange*green_colormap[i])/range);
   1551                   image->colormap[i].blue=ClampToQuantum(((double)
   1552                     QuantumRange*blue_colormap[i])/range);
   1553                 }
   1554               }
   1555           }
   1556         if (image->alpha_trait == UndefinedPixelTrait)
   1557           image->depth=GetImageDepth(image,exception);
   1558       }
   1559     if (image_info->ping != MagickFalse)
   1560       {
   1561         if (image_info->number_scenes != 0)
   1562           if (image->scene >= (image_info->scene+image_info->number_scenes-1))
   1563             {
   1564               quantum_info=DestroyQuantumInfo(quantum_info);
   1565               break;
   1566             }
   1567         goto next_tiff_frame;
   1568       }
   1569     status=SetImageExtent(image,image->columns,image->rows,exception);
   1570     if (status == MagickFalse)
   1571       return(DestroyImageList(image));
   1572     method=ReadGenericMethod;
   1573     if (TIFFGetField(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1)
   1574       {
   1575         char
   1576           value[MagickPathExtent];
   1577 
   1578         method=ReadStripMethod;
   1579         (void) FormatLocaleString(value,MagickPathExtent,"%u",
   1580           (unsigned int) rows_per_strip);
   1581         (void) SetImageProperty(image,"tiff:rows-per-strip",value,exception);
   1582       }
   1583     if ((samples_per_pixel >= 2) && (interlace == PLANARCONFIG_CONTIG))
   1584       method=ReadRGBAMethod;
   1585     if ((samples_per_pixel >= 2) && (interlace == PLANARCONFIG_SEPARATE))
   1586       method=ReadCMYKAMethod;
   1587     if ((photometric != PHOTOMETRIC_RGB) &&
   1588         (photometric != PHOTOMETRIC_CIELAB) &&
   1589         (photometric != PHOTOMETRIC_SEPARATED))
   1590       method=ReadGenericMethod;
   1591     if (image->storage_class == PseudoClass)
   1592       method=ReadSingleSampleMethod;
   1593     if ((photometric == PHOTOMETRIC_MINISBLACK) ||
   1594         (photometric == PHOTOMETRIC_MINISWHITE))
   1595       method=ReadSingleSampleMethod;
   1596     if ((photometric != PHOTOMETRIC_SEPARATED) &&
   1597         (interlace == PLANARCONFIG_SEPARATE) && (bits_per_sample < 64))
   1598       method=ReadGenericMethod;
   1599     if (image->compression == JPEGCompression)
   1600       method=GetJPEGMethod(image,tiff,photometric,bits_per_sample,
   1601         samples_per_pixel);
   1602     if (compress_tag == COMPRESSION_JBIG)
   1603       method=ReadStripMethod;
   1604     if (TIFFIsTiled(tiff) != MagickFalse)
   1605       method=ReadTileMethod;
   1606     quantum_info->endian=LSBEndian;
   1607     quantum_type=RGBQuantum;
   1608     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   1609     switch (method)
   1610     {
   1611       case ReadSingleSampleMethod:
   1612       {
   1613         /*
   1614           Convert TIFF image to PseudoClass MIFF image.
   1615         */
   1616         quantum_type=IndexQuantum;
   1617         pad=(size_t) MagickMax((size_t) samples_per_pixel-1,0);
   1618         if (image->alpha_trait != UndefinedPixelTrait)
   1619           {
   1620             if (image->storage_class != PseudoClass)
   1621               {
   1622                 quantum_type=samples_per_pixel == 1 ? AlphaQuantum :
   1623                   GrayAlphaQuantum;
   1624                 pad=(size_t) MagickMax((size_t) samples_per_pixel-2,0);
   1625               }
   1626             else
   1627               {
   1628                 quantum_type=IndexAlphaQuantum;
   1629                 pad=(size_t) MagickMax((size_t) samples_per_pixel-2,0);
   1630               }
   1631           }
   1632         else
   1633           if (image->storage_class != PseudoClass)
   1634             {
   1635               quantum_type=GrayQuantum;
   1636               pad=(size_t) MagickMax((size_t) samples_per_pixel-1,0);
   1637             }
   1638         status=SetQuantumPad(image,quantum_info,pad*pow(2,ceil(log(
   1639           bits_per_sample)/log(2))));
   1640         if (status == MagickFalse)
   1641           {
   1642             TIFFClose(tiff);
   1643             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1644           }
   1645         pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   1646         for (y=0; y < (ssize_t) image->rows; y++)
   1647         {
   1648           int
   1649             status;
   1650 
   1651           register Quantum
   1652             *magick_restrict q;
   1653 
   1654           status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) pixels);
   1655           if (status == -1)
   1656             break;
   1657           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
   1658           if (q == (Quantum *) NULL)
   1659             break;
   1660           (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   1661             quantum_type,pixels,exception);
   1662           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1663             break;
   1664           if (image->previous == (Image *) NULL)
   1665             {
   1666               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1667                 image->rows);
   1668               if (status == MagickFalse)
   1669                 break;
   1670             }
   1671         }
   1672         break;
   1673       }
   1674       case ReadRGBAMethod:
   1675       {
   1676         /*
   1677           Convert TIFF image to DirectClass MIFF image.
   1678         */
   1679         pad=(size_t) MagickMax((size_t) samples_per_pixel-3,0);
   1680         quantum_type=RGBQuantum;
   1681         if (image->alpha_trait != UndefinedPixelTrait)
   1682           {
   1683             quantum_type=RGBAQuantum;
   1684             pad=(size_t) MagickMax((size_t) samples_per_pixel-4,0);
   1685           }
   1686         if (image->colorspace == CMYKColorspace)
   1687           {
   1688             pad=(size_t) MagickMax((size_t) samples_per_pixel-4,0);
   1689             quantum_type=CMYKQuantum;
   1690             if (image->alpha_trait != UndefinedPixelTrait)
   1691               {
   1692                 quantum_type=CMYKAQuantum;
   1693                 pad=(size_t) MagickMax((size_t) samples_per_pixel-5,0);
   1694               }
   1695           }
   1696         status=SetQuantumPad(image,quantum_info,pad*((bits_per_sample+7) >> 3));
   1697         if (status == MagickFalse)
   1698           {
   1699             TIFFClose(tiff);
   1700             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1701           }
   1702         pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   1703         for (y=0; y < (ssize_t) image->rows; y++)
   1704         {
   1705           int
   1706             status;
   1707 
   1708           register Quantum
   1709             *magick_restrict q;
   1710 
   1711           status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) pixels);
   1712           if (status == -1)
   1713             break;
   1714           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
   1715           if (q == (Quantum *) NULL)
   1716             break;
   1717           (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   1718             quantum_type,pixels,exception);
   1719           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1720             break;
   1721           if (image->previous == (Image *) NULL)
   1722             {
   1723               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1724                 image->rows);
   1725               if (status == MagickFalse)
   1726                 break;
   1727             }
   1728         }
   1729         break;
   1730       }
   1731       case ReadCMYKAMethod:
   1732       {
   1733         /*
   1734           Convert TIFF image to DirectClass MIFF image.
   1735         */
   1736         for (i=0; i < (ssize_t) samples_per_pixel; i++)
   1737         {
   1738           for (y=0; y < (ssize_t) image->rows; y++)
   1739           {
   1740             register Quantum
   1741               *magick_restrict q;
   1742 
   1743             int
   1744               status;
   1745 
   1746             status=TIFFReadPixels(tiff,bits_per_sample,(tsample_t) i,y,(char *)
   1747               pixels);
   1748             if (status == -1)
   1749               break;
   1750             q=GetAuthenticPixels(image,0,y,image->columns,1,exception);
   1751             if (q == (Quantum *) NULL)
   1752               break;
   1753             if (image->colorspace != CMYKColorspace)
   1754               switch (i)
   1755               {
   1756                 case 0: quantum_type=RedQuantum; break;
   1757                 case 1: quantum_type=GreenQuantum; break;
   1758                 case 2: quantum_type=BlueQuantum; break;
   1759                 case 3: quantum_type=AlphaQuantum; break;
   1760                 default: quantum_type=UndefinedQuantum; break;
   1761               }
   1762             else
   1763               switch (i)
   1764               {
   1765                 case 0: quantum_type=CyanQuantum; break;
   1766                 case 1: quantum_type=MagentaQuantum; break;
   1767                 case 2: quantum_type=YellowQuantum; break;
   1768                 case 3: quantum_type=BlackQuantum; break;
   1769                 case 4: quantum_type=AlphaQuantum; break;
   1770                 default: quantum_type=UndefinedQuantum; break;
   1771               }
   1772             (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   1773               quantum_type,pixels,exception);
   1774             if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1775               break;
   1776           }
   1777           if (image->previous == (Image *) NULL)
   1778             {
   1779               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1780                 image->rows);
   1781               if (status == MagickFalse)
   1782                 break;
   1783             }
   1784         }
   1785         break;
   1786       }
   1787       case ReadYCCKMethod:
   1788       {
   1789         pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   1790         for (y=0; y < (ssize_t) image->rows; y++)
   1791         {
   1792           int
   1793             status;
   1794 
   1795           register Quantum
   1796             *magick_restrict q;
   1797 
   1798           register ssize_t
   1799             x;
   1800 
   1801           unsigned char
   1802             *p;
   1803 
   1804           status=TIFFReadPixels(tiff,bits_per_sample,0,y,(char *) pixels);
   1805           if (status == -1)
   1806             break;
   1807           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
   1808           if (q == (Quantum *) NULL)
   1809             break;
   1810           p=pixels;
   1811           for (x=0; x < (ssize_t) image->columns; x++)
   1812           {
   1813             SetPixelCyan(image,ScaleCharToQuantum(ClampYCC((double) *p+
   1814               (1.402*(double) *(p+2))-179.456)),q);
   1815             SetPixelMagenta(image,ScaleCharToQuantum(ClampYCC((double) *p-
   1816               (0.34414*(double) *(p+1))-(0.71414*(double ) *(p+2))+
   1817               135.45984)),q);
   1818             SetPixelYellow(image,ScaleCharToQuantum(ClampYCC((double) *p+
   1819               (1.772*(double) *(p+1))-226.816)),q);
   1820             SetPixelBlack(image,ScaleCharToQuantum((unsigned char) *(p+3)),q);
   1821             q+=GetPixelChannels(image);
   1822             p+=4;
   1823           }
   1824           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1825             break;
   1826           if (image->previous == (Image *) NULL)
   1827             {
   1828               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1829                 image->rows);
   1830               if (status == MagickFalse)
   1831                 break;
   1832             }
   1833         }
   1834         break;
   1835       }
   1836       case ReadStripMethod:
   1837       {
   1838         register uint32
   1839           *p;
   1840 
   1841         /*
   1842           Convert stripped TIFF image to DirectClass MIFF image.
   1843         */
   1844         i=0;
   1845         p=(uint32 *) NULL;
   1846         for (y=0; y < (ssize_t) image->rows; y++)
   1847         {
   1848           register ssize_t
   1849             x;
   1850 
   1851           register Quantum
   1852             *magick_restrict q;
   1853 
   1854           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
   1855           if (q == (Quantum *) NULL)
   1856             break;
   1857           if (i == 0)
   1858             {
   1859               if (TIFFReadRGBAStrip(tiff,(tstrip_t) y,(uint32 *) pixels) == 0)
   1860                 break;
   1861               i=(ssize_t) MagickMin((ssize_t) rows_per_strip,(ssize_t)
   1862                 image->rows-y);
   1863             }
   1864           i--;
   1865           p=((uint32 *) pixels)+image->columns*i;
   1866           for (x=0; x < (ssize_t) image->columns; x++)
   1867           {
   1868             SetPixelRed(image,ScaleCharToQuantum((unsigned char)
   1869               (TIFFGetR(*p))),q);
   1870             SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
   1871               (TIFFGetG(*p))),q);
   1872             SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
   1873               (TIFFGetB(*p))),q);
   1874             if (image->alpha_trait != UndefinedPixelTrait)
   1875               SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
   1876                 (TIFFGetA(*p))),q);
   1877             p++;
   1878             q+=GetPixelChannels(image);
   1879           }
   1880           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1881             break;
   1882           if (image->previous == (Image *) NULL)
   1883             {
   1884               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1885                 image->rows);
   1886               if (status == MagickFalse)
   1887                 break;
   1888             }
   1889         }
   1890         break;
   1891       }
   1892       case ReadTileMethod:
   1893       {
   1894         register uint32
   1895           *p;
   1896 
   1897         uint32
   1898           *tile_pixels,
   1899           columns,
   1900           rows;
   1901 
   1902         /*
   1903           Convert tiled TIFF image to DirectClass MIFF image.
   1904         */
   1905         if ((TIFFGetField(tiff,TIFFTAG_TILEWIDTH,&columns) != 1) ||
   1906             (TIFFGetField(tiff,TIFFTAG_TILELENGTH,&rows) != 1))
   1907           {
   1908             TIFFClose(tiff);
   1909             ThrowReaderException(CoderError,"ImageIsNotTiled");
   1910           }
   1911         (void) SetImageStorageClass(image,DirectClass,exception);
   1912         number_pixels=(MagickSizeType) columns*rows;
   1913         if (HeapOverflowSanityCheck(rows,sizeof(*tile_pixels)) != MagickFalse)
   1914           {
   1915             TIFFClose(tiff);
   1916             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1917           }
   1918         tile_pixels=(uint32 *) AcquireQuantumMemory(columns,rows*
   1919           sizeof(*tile_pixels));
   1920         if (tile_pixels == (uint32 *) NULL)
   1921           {
   1922             TIFFClose(tiff);
   1923             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   1924           }
   1925         for (y=0; y < (ssize_t) image->rows; y+=rows)
   1926         {
   1927           register ssize_t
   1928             x;
   1929 
   1930           register Quantum
   1931             *magick_restrict q,
   1932             *magick_restrict tile;
   1933 
   1934           size_t
   1935             columns_remaining,
   1936             rows_remaining;
   1937 
   1938           rows_remaining=image->rows-y;
   1939           if ((ssize_t) (y+rows) < (ssize_t) image->rows)
   1940             rows_remaining=rows;
   1941           tile=QueueAuthenticPixels(image,0,y,image->columns,rows_remaining,
   1942             exception);
   1943           if (tile == (Quantum *) NULL)
   1944             break;
   1945           for (x=0; x < (ssize_t) image->columns; x+=columns)
   1946           {
   1947             size_t
   1948               column,
   1949               row;
   1950 
   1951             if (TIFFReadRGBATile(tiff,(uint32) x,(uint32) y,tile_pixels) == 0)
   1952               break;
   1953             columns_remaining=image->columns-x;
   1954             if ((ssize_t) (x+columns) < (ssize_t) image->columns)
   1955               columns_remaining=columns;
   1956             p=tile_pixels+(rows-rows_remaining)*columns;
   1957             q=tile+GetPixelChannels(image)*(image->columns*(rows_remaining-1)+
   1958               x);
   1959             for (row=rows_remaining; row > 0; row--)
   1960             {
   1961               if (image->alpha_trait != UndefinedPixelTrait)
   1962                 for (column=columns_remaining; column > 0; column--)
   1963                 {
   1964                   SetPixelRed(image,ScaleCharToQuantum((unsigned char)
   1965                     TIFFGetR(*p)),q);
   1966                   SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
   1967                     TIFFGetG(*p)),q);
   1968                   SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
   1969                     TIFFGetB(*p)),q);
   1970                   SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
   1971                     TIFFGetA(*p)),q);
   1972                   p++;
   1973                   q+=GetPixelChannels(image);
   1974                 }
   1975               else
   1976                 for (column=columns_remaining; column > 0; column--)
   1977                 {
   1978                   SetPixelRed(image,ScaleCharToQuantum((unsigned char)
   1979                     TIFFGetR(*p)),q);
   1980                   SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
   1981                     TIFFGetG(*p)),q);
   1982                   SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
   1983                     TIFFGetB(*p)),q);
   1984                   p++;
   1985                   q+=GetPixelChannels(image);
   1986                 }
   1987               p+=columns-columns_remaining;
   1988               q-=GetPixelChannels(image)*(image->columns+columns_remaining);
   1989             }
   1990           }
   1991           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   1992             break;
   1993           if (image->previous == (Image *) NULL)
   1994             {
   1995               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   1996                 image->rows);
   1997               if (status == MagickFalse)
   1998                 break;
   1999             }
   2000         }
   2001         tile_pixels=(uint32 *) RelinquishMagickMemory(tile_pixels);
   2002         break;
   2003       }
   2004       case ReadGenericMethod:
   2005       default:
   2006       {
   2007         MemoryInfo
   2008           *pixel_info;
   2009 
   2010         register uint32
   2011           *p;
   2012 
   2013         uint32
   2014           *pixels;
   2015 
   2016         /*
   2017           Convert TIFF image to DirectClass MIFF image.
   2018         */
   2019         number_pixels=(MagickSizeType) image->columns*image->rows;
   2020         if (HeapOverflowSanityCheck(image->rows,sizeof(*pixels)) != MagickFalse)
   2021           {
   2022             TIFFClose(tiff);
   2023             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   2024           }
   2025         pixel_info=AcquireVirtualMemory(image->columns,image->rows*
   2026           sizeof(uint32));
   2027         if (pixel_info == (MemoryInfo *) NULL)
   2028           {
   2029             TIFFClose(tiff);
   2030             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
   2031           }
   2032         pixels=(uint32 *) GetVirtualMemoryBlob(pixel_info);
   2033         (void) TIFFReadRGBAImage(tiff,(uint32) image->columns,(uint32)
   2034           image->rows,(uint32 *) pixels,0);
   2035         /*
   2036           Convert image to DirectClass pixel packets.
   2037         */
   2038         p=pixels+number_pixels-1;
   2039         for (y=0; y < (ssize_t) image->rows; y++)
   2040         {
   2041           register ssize_t
   2042             x;
   2043 
   2044           register Quantum
   2045             *magick_restrict q;
   2046 
   2047           q=QueueAuthenticPixels(image,0,y,image->columns,1,exception);
   2048           if (q == (Quantum *) NULL)
   2049             break;
   2050           q+=GetPixelChannels(image)*(image->columns-1);
   2051           for (x=0; x < (ssize_t) image->columns; x++)
   2052           {
   2053             SetPixelRed(image,ScaleCharToQuantum((unsigned char)
   2054               TIFFGetR(*p)),q);
   2055             SetPixelGreen(image,ScaleCharToQuantum((unsigned char)
   2056               TIFFGetG(*p)),q);
   2057             SetPixelBlue(image,ScaleCharToQuantum((unsigned char)
   2058               TIFFGetB(*p)),q);
   2059             if (image->alpha_trait != UndefinedPixelTrait)
   2060               SetPixelAlpha(image,ScaleCharToQuantum((unsigned char)
   2061                 TIFFGetA(*p)),q);
   2062             p--;
   2063             q-=GetPixelChannels(image);
   2064           }
   2065           if (SyncAuthenticPixels(image,exception) == MagickFalse)
   2066             break;
   2067           if (image->previous == (Image *) NULL)
   2068             {
   2069               status=SetImageProgress(image,LoadImageTag,(MagickOffsetType) y,
   2070                 image->rows);
   2071               if (status == MagickFalse)
   2072                 break;
   2073             }
   2074         }
   2075         pixel_info=RelinquishVirtualMemory(pixel_info);
   2076         break;
   2077       }
   2078     }
   2079     SetQuantumImageType(image,quantum_type);
   2080   next_tiff_frame:
   2081     quantum_info=DestroyQuantumInfo(quantum_info);
   2082     if (photometric == PHOTOMETRIC_CIELAB)
   2083       DecodeLabImage(image,exception);
   2084     if ((photometric == PHOTOMETRIC_LOGL) ||
   2085         (photometric == PHOTOMETRIC_MINISBLACK) ||
   2086         (photometric == PHOTOMETRIC_MINISWHITE))
   2087       {
   2088         image->type=GrayscaleType;
   2089         if (bits_per_sample == 1)
   2090           image->type=BilevelType;
   2091       }
   2092     /*
   2093       Proceed to next image.
   2094     */
   2095     if (image_info->number_scenes != 0)
   2096       if (image->scene >= (image_info->scene+image_info->number_scenes-1))
   2097         break;
   2098     status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
   2099     if (status != MagickFalse)
   2100       {
   2101         /*
   2102           Allocate next image structure.
   2103         */
   2104         AcquireNextImage(image_info,image,exception);
   2105         if (GetNextImageInList(image) == (Image *) NULL)
   2106           {
   2107             image=DestroyImageList(image);
   2108             return((Image *) NULL);
   2109           }
   2110         image=SyncNextImageInList(image);
   2111         status=SetImageProgress(image,LoadImagesTag,image->scene-1,
   2112           image->scene);
   2113         if (status == MagickFalse)
   2114           break;
   2115       }
   2116   } while (status != MagickFalse);
   2117   TIFFClose(tiff);
   2118   TIFFReadPhotoshopLayers(image,image_info,exception);
   2119   if (image_info->number_scenes != 0)
   2120     {
   2121       if (image_info->scene >= GetImageListLength(image))
   2122         {
   2123           /* Subimage was not found in the Photoshop layer */
   2124           image=DestroyImageList(image);
   2125           return((Image *)NULL);
   2126         }
   2127     }
   2128   return(GetFirstImageInList(image));
   2129 }
   2130 #endif
   2131 
   2132 /*
   2134 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2135 %                                                                             %
   2136 %                                                                             %
   2137 %                                                                             %
   2138 %   R e g i s t e r T I F F I m a g e                                         %
   2139 %                                                                             %
   2140 %                                                                             %
   2141 %                                                                             %
   2142 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2143 %
   2144 %  RegisterTIFFImage() adds properties for the TIFF image format to
   2145 %  the list of supported formats.  The properties include the image format
   2146 %  tag, a method to read and/or write the format, whether the format
   2147 %  supports the saving of more than one frame to the same file or blob,
   2148 %  whether the format supports native in-memory I/O, and a brief
   2149 %  description of the format.
   2150 %
   2151 %  The format of the RegisterTIFFImage method is:
   2152 %
   2153 %      size_t RegisterTIFFImage(void)
   2154 %
   2155 */
   2156 
   2157 #if defined(MAGICKCORE_HAVE_TIFFMERGEFIELDINFO) && defined(MAGICKCORE_HAVE_TIFFSETTAGEXTENDER)
   2158 static TIFFExtendProc
   2159   tag_extender = (TIFFExtendProc) NULL;
   2160 
   2161 static void TIFFIgnoreTags(TIFF *tiff)
   2162 {
   2163   char
   2164     *q;
   2165 
   2166   const char
   2167     *p,
   2168     *tags;
   2169 
   2170   Image
   2171    *image;
   2172 
   2173   register ssize_t
   2174     i;
   2175 
   2176   size_t
   2177     count;
   2178 
   2179   TIFFFieldInfo
   2180     *ignore;
   2181 
   2182   if (TIFFGetReadProc(tiff) != TIFFReadBlob)
   2183     return;
   2184   image=(Image *)TIFFClientdata(tiff);
   2185   tags=GetImageArtifact(image,"tiff:ignore-tags");
   2186   if (tags == (const char *) NULL)
   2187     return;
   2188   count=0;
   2189   p=tags;
   2190   while (*p != '\0')
   2191   {
   2192     while ((isspace((int) ((unsigned char) *p)) != 0))
   2193       p++;
   2194 
   2195     (void) strtol(p,&q,10);
   2196     if (p == q)
   2197       return;
   2198 
   2199     p=q;
   2200     count++;
   2201 
   2202     while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
   2203       p++;
   2204   }
   2205   if (count == 0)
   2206     return;
   2207   i=0;
   2208   p=tags;
   2209   ignore=(TIFFFieldInfo *) AcquireQuantumMemory(count,sizeof(*ignore));
   2210   /* This also sets field_bit to 0 (FIELD_IGNORE) */
   2211   ResetMagickMemory(ignore,0,count*sizeof(*ignore));
   2212   while (*p != '\0')
   2213   {
   2214     while ((isspace((int) ((unsigned char) *p)) != 0))
   2215       p++;
   2216 
   2217     ignore[i].field_tag=(ttag_t) strtol(p,&q,10);
   2218 
   2219     p=q;
   2220     i++;
   2221 
   2222     while ((isspace((int) ((unsigned char) *p)) != 0) || (*p == ','))
   2223       p++;
   2224   }
   2225   (void) TIFFMergeFieldInfo(tiff,ignore,(uint32) count);
   2226   ignore=(TIFFFieldInfo *) RelinquishMagickMemory(ignore);
   2227 }
   2228 
   2229 static void TIFFTagExtender(TIFF *tiff)
   2230 {
   2231   static const TIFFFieldInfo
   2232     TIFFExtensions[] =
   2233     {
   2234       { 37724, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, 1, 1,
   2235         (char *) "PhotoshopLayerData" },
   2236       { 34118, -3, -3, TIFF_UNDEFINED, FIELD_CUSTOM, 1, 1,
   2237         (char *) "Microscope" }
   2238     };
   2239 
   2240   TIFFMergeFieldInfo(tiff,TIFFExtensions,sizeof(TIFFExtensions)/
   2241     sizeof(*TIFFExtensions));
   2242   if (tag_extender != (TIFFExtendProc) NULL)
   2243     (*tag_extender)(tiff);
   2244   TIFFIgnoreTags(tiff);
   2245 }
   2246 #endif
   2247 
   2248 ModuleExport size_t RegisterTIFFImage(void)
   2249 {
   2250 #define TIFFDescription  "Tagged Image File Format"
   2251 
   2252   char
   2253     version[MagickPathExtent];
   2254 
   2255   MagickInfo
   2256     *entry;
   2257 
   2258   if (tiff_semaphore == (SemaphoreInfo *) NULL)
   2259     ActivateSemaphoreInfo(&tiff_semaphore);
   2260   LockSemaphoreInfo(tiff_semaphore);
   2261   if (instantiate_key == MagickFalse)
   2262     {
   2263       if (CreateMagickThreadKey(&tiff_exception,NULL) == MagickFalse)
   2264         ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   2265       error_handler=TIFFSetErrorHandler(TIFFErrors);
   2266       warning_handler=TIFFSetWarningHandler(TIFFWarnings);
   2267 #if defined(MAGICKCORE_HAVE_TIFFMERGEFIELDINFO) && defined(MAGICKCORE_HAVE_TIFFSETTAGEXTENDER)
   2268       if (tag_extender == (TIFFExtendProc) NULL)
   2269         tag_extender=TIFFSetTagExtender(TIFFTagExtender);
   2270 #endif
   2271       instantiate_key=MagickTrue;
   2272     }
   2273   UnlockSemaphoreInfo(tiff_semaphore);
   2274   *version='\0';
   2275 #if defined(TIFF_VERSION)
   2276   (void) FormatLocaleString(version,MagickPathExtent,"%d",TIFF_VERSION);
   2277 #endif
   2278 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2279   {
   2280     const char
   2281       *p;
   2282 
   2283     register ssize_t
   2284       i;
   2285 
   2286     p=TIFFGetVersion();
   2287     for (i=0; (i < (MagickPathExtent-1)) && (*p != 0) && (*p != '\n'); i++)
   2288       version[i]=(*p++);
   2289     version[i]='\0';
   2290   }
   2291 #endif
   2292 
   2293   entry=AcquireMagickInfo("TIFF","GROUP4","Raw CCITT Group4");
   2294 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2295   entry->decoder=(DecodeImageHandler *) ReadGROUP4Image;
   2296   entry->encoder=(EncodeImageHandler *) WriteGROUP4Image;
   2297 #endif
   2298   entry->flags|=CoderRawSupportFlag;
   2299   entry->flags|=CoderEndianSupportFlag;
   2300   entry->flags|=CoderSeekableStreamFlag;
   2301   entry->flags^=CoderAdjoinFlag;
   2302   entry->flags^=CoderUseExtensionFlag;
   2303   entry->format_type=ImplicitFormatType;
   2304   entry->mime_type=ConstantString("image/tiff");
   2305   (void) RegisterMagickInfo(entry);
   2306   entry=AcquireMagickInfo("TIFF","PTIF","Pyramid encoded TIFF");
   2307 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2308   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
   2309   entry->encoder=(EncodeImageHandler *) WritePTIFImage;
   2310 #endif
   2311   entry->flags|=CoderEndianSupportFlag;
   2312   entry->flags|=CoderSeekableStreamFlag;
   2313   entry->flags^=CoderUseExtensionFlag;
   2314   entry->mime_type=ConstantString("image/tiff");
   2315   (void) RegisterMagickInfo(entry);
   2316   entry=AcquireMagickInfo("TIFF","TIF",TIFFDescription);
   2317 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2318   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
   2319   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
   2320 #endif
   2321   entry->flags|=CoderEndianSupportFlag;
   2322   entry->flags|=CoderSeekableStreamFlag;
   2323   entry->flags|=CoderStealthFlag;
   2324   entry->flags^=CoderUseExtensionFlag;
   2325   if (*version != '\0')
   2326     entry->version=ConstantString(version);
   2327   entry->mime_type=ConstantString("image/tiff");
   2328   (void) RegisterMagickInfo(entry);
   2329   entry=AcquireMagickInfo("TIFF","TIFF",TIFFDescription);
   2330 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2331   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
   2332   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
   2333 #endif
   2334   entry->magick=(IsImageFormatHandler *) IsTIFF;
   2335   entry->flags|=CoderEndianSupportFlag;
   2336   entry->flags|=CoderSeekableStreamFlag;
   2337   entry->flags^=CoderUseExtensionFlag;
   2338   if (*version != '\0')
   2339     entry->version=ConstantString(version);
   2340   entry->mime_type=ConstantString("image/tiff");
   2341   (void) RegisterMagickInfo(entry);
   2342   entry=AcquireMagickInfo("TIFF","TIFF64","Tagged Image File Format (64-bit)");
   2343 #if defined(TIFF_VERSION_BIG)
   2344   entry->decoder=(DecodeImageHandler *) ReadTIFFImage;
   2345   entry->encoder=(EncodeImageHandler *) WriteTIFFImage;
   2346 #endif
   2347   entry->flags|=CoderEndianSupportFlag;
   2348   entry->flags|=CoderSeekableStreamFlag;
   2349   entry->flags^=CoderAdjoinFlag;
   2350   entry->flags^=CoderUseExtensionFlag;
   2351   if (*version != '\0')
   2352     entry->version=ConstantString(version);
   2353   entry->mime_type=ConstantString("image/tiff");
   2354   (void) RegisterMagickInfo(entry);
   2355   return(MagickImageCoderSignature);
   2356 }
   2357 
   2358 /*
   2360 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2361 %                                                                             %
   2362 %                                                                             %
   2363 %                                                                             %
   2364 %   U n r e g i s t e r T I F F I m a g e                                     %
   2365 %                                                                             %
   2366 %                                                                             %
   2367 %                                                                             %
   2368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2369 %
   2370 %  UnregisterTIFFImage() removes format registrations made by the TIFF module
   2371 %  from the list of supported formats.
   2372 %
   2373 %  The format of the UnregisterTIFFImage method is:
   2374 %
   2375 %      UnregisterTIFFImage(void)
   2376 %
   2377 */
   2378 ModuleExport void UnregisterTIFFImage(void)
   2379 {
   2380   (void) UnregisterMagickInfo("TIFF64");
   2381   (void) UnregisterMagickInfo("TIFF");
   2382   (void) UnregisterMagickInfo("TIF");
   2383   (void) UnregisterMagickInfo("PTIF");
   2384   if (tiff_semaphore == (SemaphoreInfo *) NULL)
   2385     ActivateSemaphoreInfo(&tiff_semaphore);
   2386   LockSemaphoreInfo(tiff_semaphore);
   2387   if (instantiate_key != MagickFalse)
   2388     {
   2389 #if defined(MAGICKCORE_HAVE_TIFFMERGEFIELDINFO) && defined(MAGICKCORE_HAVE_TIFFSETTAGEXTENDER)
   2390       if (tag_extender == (TIFFExtendProc) NULL)
   2391         (void) TIFFSetTagExtender(tag_extender);
   2392 #endif
   2393       if (DeleteMagickThreadKey(tiff_exception) == MagickFalse)
   2394         ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
   2395       (void) TIFFSetWarningHandler(warning_handler);
   2396       (void) TIFFSetErrorHandler(error_handler);
   2397       instantiate_key=MagickFalse;
   2398     }
   2399   UnlockSemaphoreInfo(tiff_semaphore);
   2400   RelinquishSemaphoreInfo(&tiff_semaphore);
   2401 }
   2402 
   2403 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2405 /*
   2406 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2407 %                                                                             %
   2408 %                                                                             %
   2409 %                                                                             %
   2410 %   W r i t e G R O U P 4 I m a g e                                           %
   2411 %                                                                             %
   2412 %                                                                             %
   2413 %                                                                             %
   2414 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2415 %
   2416 %  WriteGROUP4Image() writes an image in the raw CCITT Group 4 image format.
   2417 %
   2418 %  The format of the WriteGROUP4Image method is:
   2419 %
   2420 %      MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
   2421 %        Image *image,ExceptionInfo *)
   2422 %
   2423 %  A description of each parameter follows:
   2424 %
   2425 %    o image_info: the image info.
   2426 %
   2427 %    o image:  The image.
   2428 %
   2429 %    o exception: return any errors or warnings in this structure.
   2430 %
   2431 */
   2432 static MagickBooleanType WriteGROUP4Image(const ImageInfo *image_info,
   2433   Image *image,ExceptionInfo *exception)
   2434 {
   2435   char
   2436     filename[MagickPathExtent];
   2437 
   2438   FILE
   2439     *file;
   2440 
   2441   Image
   2442     *huffman_image;
   2443 
   2444   ImageInfo
   2445     *write_info;
   2446 
   2447   int
   2448     unique_file;
   2449 
   2450   MagickBooleanType
   2451     status;
   2452 
   2453   register ssize_t
   2454     i;
   2455 
   2456   ssize_t
   2457     count;
   2458 
   2459   TIFF
   2460     *tiff;
   2461 
   2462   toff_t
   2463     *byte_count,
   2464     strip_size;
   2465 
   2466   unsigned char
   2467     *buffer;
   2468 
   2469   /*
   2470     Write image as CCITT Group4 TIFF image to a temporary file.
   2471   */
   2472   assert(image_info != (const ImageInfo *) NULL);
   2473   assert(image_info->signature == MagickCoreSignature);
   2474   assert(image != (Image *) NULL);
   2475   assert(image->signature == MagickCoreSignature);
   2476   if (image->debug != MagickFalse)
   2477     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   2478   assert(exception != (ExceptionInfo *) NULL);
   2479   assert(exception->signature == MagickCoreSignature);
   2480   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   2481   if (status == MagickFalse)
   2482     return(status);
   2483   huffman_image=CloneImage(image,0,0,MagickTrue,exception);
   2484   if (huffman_image == (Image *) NULL)
   2485     {
   2486       (void) CloseBlob(image);
   2487       return(MagickFalse);
   2488     }
   2489   huffman_image->endian=MSBEndian;
   2490   file=(FILE *) NULL;
   2491   unique_file=AcquireUniqueFileResource(filename);
   2492   if (unique_file != -1)
   2493     file=fdopen(unique_file,"wb");
   2494   if ((unique_file == -1) || (file == (FILE *) NULL))
   2495     {
   2496       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
   2497         filename);
   2498       return(MagickFalse);
   2499     }
   2500   (void) FormatLocaleString(huffman_image->filename,MagickPathExtent,"tiff:%s",
   2501     filename);
   2502   (void) SetImageType(huffman_image,BilevelType,exception);
   2503   write_info=CloneImageInfo((ImageInfo *) NULL);
   2504   SetImageInfoFile(write_info,file);
   2505   (void) SetImageType(image,BilevelType,exception);
   2506   (void) SetImageDepth(image,1,exception);
   2507   write_info->compression=Group4Compression;
   2508   write_info->type=BilevelType;
   2509   (void) SetImageOption(write_info,"quantum:polarity","min-is-white");
   2510   status=WriteTIFFImage(write_info,huffman_image,exception);
   2511   (void) fflush(file);
   2512   write_info=DestroyImageInfo(write_info);
   2513   if (status == MagickFalse)
   2514     {
   2515       huffman_image=DestroyImage(huffman_image);
   2516       (void) fclose(file);
   2517       (void) RelinquishUniqueFileResource(filename);
   2518       return(MagickFalse);
   2519     }
   2520   tiff=TIFFOpen(filename,"rb");
   2521   if (tiff == (TIFF *) NULL)
   2522     {
   2523       huffman_image=DestroyImage(huffman_image);
   2524       (void) fclose(file);
   2525       (void) RelinquishUniqueFileResource(filename);
   2526       ThrowFileException(exception,FileOpenError,"UnableToOpenFile",
   2527         image_info->filename);
   2528       return(MagickFalse);
   2529     }
   2530   /*
   2531     Allocate raw strip buffer.
   2532   */
   2533   if (TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count) != 1)
   2534     {
   2535       TIFFClose(tiff);
   2536       huffman_image=DestroyImage(huffman_image);
   2537       (void) fclose(file);
   2538       (void) RelinquishUniqueFileResource(filename);
   2539       return(MagickFalse);
   2540     }
   2541   strip_size=byte_count[0];
   2542   for (i=1; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
   2543     if (byte_count[i] > strip_size)
   2544       strip_size=byte_count[i];
   2545   buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size,
   2546     sizeof(*buffer));
   2547   if (buffer == (unsigned char *) NULL)
   2548     {
   2549       TIFFClose(tiff);
   2550       huffman_image=DestroyImage(huffman_image);
   2551       (void) fclose(file);
   2552       (void) RelinquishUniqueFileResource(filename);
   2553       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
   2554         image_info->filename);
   2555     }
   2556   /*
   2557     Compress runlength encoded to 2D Huffman pixels.
   2558   */
   2559   for (i=0; i < (ssize_t) TIFFNumberOfStrips(tiff); i++)
   2560   {
   2561     count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,strip_size);
   2562     if (WriteBlob(image,(size_t) count,buffer) != count)
   2563       status=MagickFalse;
   2564   }
   2565   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
   2566   TIFFClose(tiff);
   2567   huffman_image=DestroyImage(huffman_image);
   2568   (void) fclose(file);
   2569   (void) RelinquishUniqueFileResource(filename);
   2570   (void) CloseBlob(image);
   2571   return(status);
   2572 }
   2573 #endif
   2574 
   2575 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2577 /*
   2578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2579 %                                                                             %
   2580 %                                                                             %
   2581 %                                                                             %
   2582 %   W r i t e P T I F I m a g e                                               %
   2583 %                                                                             %
   2584 %                                                                             %
   2585 %                                                                             %
   2586 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2587 %
   2588 %  WritePTIFImage() writes an image in the pyrimid-encoded Tagged image file
   2589 %  format.
   2590 %
   2591 %  The format of the WritePTIFImage method is:
   2592 %
   2593 %      MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
   2594 %        Image *image,ExceptionInfo *exception)
   2595 %
   2596 %  A description of each parameter follows:
   2597 %
   2598 %    o image_info: the image info.
   2599 %
   2600 %    o image:  The image.
   2601 %
   2602 %    o exception: return any errors or warnings in this structure.
   2603 %
   2604 */
   2605 static MagickBooleanType WritePTIFImage(const ImageInfo *image_info,
   2606   Image *image,ExceptionInfo *exception)
   2607 {
   2608   Image
   2609     *images,
   2610     *next,
   2611     *pyramid_image;
   2612 
   2613   ImageInfo
   2614     *write_info;
   2615 
   2616   MagickBooleanType
   2617     status;
   2618 
   2619   PointInfo
   2620     resolution;
   2621 
   2622   size_t
   2623     columns,
   2624     rows;
   2625 
   2626   /*
   2627     Create pyramid-encoded TIFF image.
   2628   */
   2629   images=NewImageList();
   2630   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
   2631   {
   2632     Image
   2633       *clone_image;
   2634 
   2635     clone_image=CloneImage(next,0,0,MagickFalse,exception);
   2636     if (clone_image == (Image *) NULL)
   2637       break;
   2638     clone_image->previous=NewImageList();
   2639     clone_image->next=NewImageList();
   2640     (void) SetImageProperty(clone_image,"tiff:subfiletype","none",exception);
   2641     AppendImageToList(&images,clone_image);
   2642     columns=next->columns;
   2643     rows=next->rows;
   2644     resolution=next->resolution;
   2645     while ((columns > 64) && (rows > 64))
   2646     {
   2647       columns/=2;
   2648       rows/=2;
   2649       resolution.x/=2;
   2650       resolution.y/=2;
   2651       pyramid_image=ResizeImage(next,columns,rows,image->filter,exception);
   2652       if (pyramid_image == (Image *) NULL)
   2653         break;
   2654       pyramid_image->resolution=resolution;
   2655       (void) SetImageProperty(pyramid_image,"tiff:subfiletype","REDUCEDIMAGE",
   2656         exception);
   2657       AppendImageToList(&images,pyramid_image);
   2658     }
   2659   }
   2660   images=GetFirstImageInList(images);
   2661   /*
   2662     Write pyramid-encoded TIFF image.
   2663   */
   2664   write_info=CloneImageInfo(image_info);
   2665   write_info->adjoin=MagickTrue;
   2666   (void) CopyMagickString(write_info->magick,"TIFF",MagickPathExtent);
   2667   (void) CopyMagickString(images->magick,"TIFF",MagickPathExtent);
   2668   status=WriteTIFFImage(write_info,images,exception);
   2669   images=DestroyImageList(images);
   2670   write_info=DestroyImageInfo(write_info);
   2671   return(status);
   2672 }
   2673 #endif
   2674 
   2675 #if defined(MAGICKCORE_TIFF_DELEGATE)
   2677 /*
   2678 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2679 %                                                                             %
   2680 %                                                                             %
   2681 %   W r i t e T I F F I m a g e                                               %
   2682 %                                                                             %
   2683 %                                                                             %
   2684 %                                                                             %
   2685 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   2686 %
   2687 %  WriteTIFFImage() writes an image in the Tagged image file format.
   2688 %
   2689 %  The format of the WriteTIFFImage method is:
   2690 %
   2691 %      MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   2692 %        Image *image,ExceptionInfo *exception)
   2693 %
   2694 %  A description of each parameter follows:
   2695 %
   2696 %    o image_info: the image info.
   2697 %
   2698 %    o image:  The image.
   2699 %
   2700 %    o exception: return any errors or warnings in this structure.
   2701 %
   2702 */
   2703 
   2704 typedef struct _TIFFInfo
   2705 {
   2706   RectangleInfo
   2707     tile_geometry;
   2708 
   2709   unsigned char
   2710     *scanline,
   2711     *scanlines,
   2712     *pixels;
   2713 } TIFFInfo;
   2714 
   2715 static void DestroyTIFFInfo(TIFFInfo *tiff_info)
   2716 {
   2717   assert(tiff_info != (TIFFInfo *) NULL);
   2718   if (tiff_info->scanlines != (unsigned char *) NULL)
   2719     tiff_info->scanlines=(unsigned char *) RelinquishMagickMemory(
   2720       tiff_info->scanlines);
   2721   if (tiff_info->pixels != (unsigned char *) NULL)
   2722     tiff_info->pixels=(unsigned char *) RelinquishMagickMemory(
   2723       tiff_info->pixels);
   2724 }
   2725 
   2726 static MagickBooleanType EncodeLabImage(Image *image,ExceptionInfo *exception)
   2727 {
   2728   CacheView
   2729     *image_view;
   2730 
   2731   MagickBooleanType
   2732     status;
   2733 
   2734   ssize_t
   2735     y;
   2736 
   2737   status=MagickTrue;
   2738   image_view=AcquireAuthenticCacheView(image,exception);
   2739   for (y=0; y < (ssize_t) image->rows; y++)
   2740   {
   2741     register Quantum
   2742       *magick_restrict q;
   2743 
   2744     register ssize_t
   2745       x;
   2746 
   2747     if (status == MagickFalse)
   2748       continue;
   2749     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
   2750     if (q == (Quantum *) NULL)
   2751       {
   2752         status=MagickFalse;
   2753         continue;
   2754       }
   2755     for (x=0; x < (ssize_t) image->columns; x++)
   2756     {
   2757       double
   2758         a,
   2759         b;
   2760 
   2761       a=QuantumScale*GetPixela(image,q)-0.5;
   2762       if (a < 0.0)
   2763         a+=1.0;
   2764       b=QuantumScale*GetPixelb(image,q)-0.5;
   2765       if (b < 0.0)
   2766         b+=1.0;
   2767       SetPixela(image,QuantumRange*a,q);
   2768       SetPixelb(image,QuantumRange*b,q);
   2769       q+=GetPixelChannels(image);
   2770     }
   2771     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
   2772       status=MagickFalse;
   2773   }
   2774   image_view=DestroyCacheView(image_view);
   2775   return(status);
   2776 }
   2777 
   2778 static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,
   2779   TIFF *tiff,TIFFInfo *tiff_info)
   2780 {
   2781   const char
   2782     *option;
   2783 
   2784   MagickStatusType
   2785     flags;
   2786 
   2787   uint32
   2788     tile_columns,
   2789     tile_rows;
   2790 
   2791   assert(tiff_info != (TIFFInfo *) NULL);
   2792   (void) ResetMagickMemory(tiff_info,0,sizeof(*tiff_info));
   2793   option=GetImageOption(image_info,"tiff:tile-geometry");
   2794   if (option == (const char *) NULL)
   2795     return(MagickTrue);
   2796   flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
   2797   if ((flags & HeightValue) == 0)
   2798     tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
   2799   tile_columns=(uint32) tiff_info->tile_geometry.width;
   2800   tile_rows=(uint32) tiff_info->tile_geometry.height;
   2801   TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
   2802   (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
   2803   (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
   2804   tiff_info->tile_geometry.width=tile_columns;
   2805   tiff_info->tile_geometry.height=tile_rows;
   2806   tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
   2807     tile_rows*TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
   2808   tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
   2809     tile_rows*TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
   2810   if ((tiff_info->scanlines == (unsigned char *) NULL) ||
   2811       (tiff_info->pixels == (unsigned char *) NULL))
   2812     {
   2813       DestroyTIFFInfo(tiff_info);
   2814       return(MagickFalse);
   2815     }
   2816   return(MagickTrue);
   2817 }
   2818 
   2819 static int32 TIFFWritePixels(TIFF *tiff,TIFFInfo *tiff_info,ssize_t row,
   2820   tsample_t sample,Image *image)
   2821 {
   2822   int32
   2823     status;
   2824 
   2825   register ssize_t
   2826     i;
   2827 
   2828   register unsigned char
   2829     *p,
   2830     *q;
   2831 
   2832   size_t
   2833     number_tiles,
   2834     tile_width;
   2835 
   2836   ssize_t
   2837     bytes_per_pixel,
   2838     j,
   2839     k,
   2840     l;
   2841 
   2842   if (TIFFIsTiled(tiff) == 0)
   2843     return(TIFFWriteScanline(tiff,tiff_info->scanline,(uint32) row,sample));
   2844   /*
   2845     Fill scanlines to tile height.
   2846   */
   2847   i=(ssize_t) (row % tiff_info->tile_geometry.height)*TIFFScanlineSize(tiff);
   2848   (void) CopyMagickMemory(tiff_info->scanlines+i,(char *) tiff_info->scanline,
   2849     (size_t) TIFFScanlineSize(tiff));
   2850   if (((size_t) (row % tiff_info->tile_geometry.height) !=
   2851       (tiff_info->tile_geometry.height-1)) &&
   2852       (row != (ssize_t) (image->rows-1)))
   2853     return(0);
   2854   /*
   2855     Write tile to TIFF image.
   2856   */
   2857   status=0;
   2858   bytes_per_pixel=TIFFTileSize(tiff)/(ssize_t) (
   2859     tiff_info->tile_geometry.height*tiff_info->tile_geometry.width);
   2860   number_tiles=(image->columns+tiff_info->tile_geometry.width)/
   2861     tiff_info->tile_geometry.width;
   2862   for (i=0; i < (ssize_t) number_tiles; i++)
   2863   {
   2864     tile_width=(i == (ssize_t) (number_tiles-1)) ? image->columns-(i*
   2865       tiff_info->tile_geometry.width) : tiff_info->tile_geometry.width;
   2866     for (j=0; j < (ssize_t) ((row % tiff_info->tile_geometry.height)+1); j++)
   2867       for (k=0; k < (ssize_t) tile_width; k++)
   2868       {
   2869         if (bytes_per_pixel == 0)
   2870           {
   2871             p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
   2872               tiff_info->tile_geometry.width+k)/8);
   2873             q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k/8);
   2874             *q++=(*p++);
   2875             continue;
   2876           }
   2877         p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
   2878           tiff_info->tile_geometry.width+k)*bytes_per_pixel);
   2879         q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k*bytes_per_pixel);
   2880         for (l=0; l < bytes_per_pixel; l++)
   2881           *q++=(*p++);
   2882       }
   2883     if ((i*tiff_info->tile_geometry.width) != image->columns)
   2884       status=TIFFWriteTile(tiff,tiff_info->pixels,(uint32) (i*
   2885         tiff_info->tile_geometry.width),(uint32) ((row/
   2886         tiff_info->tile_geometry.height)*tiff_info->tile_geometry.height),0,
   2887         sample);
   2888     if (status < 0)
   2889       break;
   2890   }
   2891   return(status);
   2892 }
   2893 
   2894 static void TIFFSetProfiles(TIFF *tiff,Image *image)
   2895 {
   2896   const char
   2897     *name;
   2898 
   2899   const StringInfo
   2900     *profile;
   2901 
   2902   if (image->profiles == (void *) NULL)
   2903     return;
   2904   ResetImageProfileIterator(image);
   2905   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
   2906   {
   2907     profile=GetImageProfile(image,name);
   2908     if (GetStringInfoLength(profile) == 0)
   2909       {
   2910         name=GetNextImageProfile(image);
   2911         continue;
   2912       }
   2913 #if defined(TIFFTAG_XMLPACKET)
   2914     if (LocaleCompare(name,"xmp") == 0)
   2915       (void) TIFFSetField(tiff,TIFFTAG_XMLPACKET,(uint32) GetStringInfoLength(
   2916         profile),GetStringInfoDatum(profile));
   2917 #endif
   2918 #if defined(TIFFTAG_ICCPROFILE)
   2919     if (LocaleCompare(name,"icc") == 0)
   2920       (void) TIFFSetField(tiff,TIFFTAG_ICCPROFILE,(uint32) GetStringInfoLength(
   2921         profile),GetStringInfoDatum(profile));
   2922 #endif
   2923     if (LocaleCompare(name,"iptc") == 0)
   2924       {
   2925         size_t
   2926           length;
   2927 
   2928         StringInfo
   2929           *iptc_profile;
   2930 
   2931         iptc_profile=CloneStringInfo(profile);
   2932         length=GetStringInfoLength(profile)+4-(GetStringInfoLength(profile) &
   2933           0x03);
   2934         SetStringInfoLength(iptc_profile,length);
   2935         if (TIFFIsByteSwapped(tiff))
   2936           TIFFSwabArrayOfLong((uint32 *) GetStringInfoDatum(iptc_profile),
   2937             (unsigned long) (length/4));
   2938         (void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
   2939           GetStringInfoLength(iptc_profile)/4,GetStringInfoDatum(iptc_profile));
   2940         iptc_profile=DestroyStringInfo(iptc_profile);
   2941       }
   2942 #if defined(TIFFTAG_PHOTOSHOP)
   2943     if (LocaleCompare(name,"8bim") == 0)
   2944       (void) TIFFSetField(tiff,TIFFTAG_PHOTOSHOP,(uint32)
   2945         GetStringInfoLength(profile),GetStringInfoDatum(profile));
   2946 #endif
   2947     if (LocaleCompare(name,"tiff:37724") == 0)
   2948       (void) TIFFSetField(tiff,37724,(uint32) GetStringInfoLength(profile),
   2949         GetStringInfoDatum(profile));
   2950     if (LocaleCompare(name,"tiff:34118") == 0)
   2951       (void) TIFFSetField(tiff,34118,(uint32) GetStringInfoLength(profile),
   2952         GetStringInfoDatum(profile));
   2953     name=GetNextImageProfile(image);
   2954   }
   2955 }
   2956 
   2957 static void TIFFSetProperties(TIFF *tiff,const ImageInfo *image_info,
   2958   Image *image,ExceptionInfo *exception)
   2959 {
   2960   const char
   2961     *value;
   2962 
   2963   value=GetImageArtifact(image,"tiff:document");
   2964   if (value != (const char *) NULL)
   2965     (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,value);
   2966   value=GetImageArtifact(image,"tiff:hostcomputer");
   2967   if (value != (const char *) NULL)
   2968     (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
   2969   value=GetImageArtifact(image,"tiff:artist");
   2970   if (value != (const char *) NULL)
   2971     (void) TIFFSetField(tiff,TIFFTAG_ARTIST,value);
   2972   value=GetImageArtifact(image,"tiff:timestamp");
   2973   if (value != (const char *) NULL)
   2974     (void) TIFFSetField(tiff,TIFFTAG_DATETIME,value);
   2975   value=GetImageArtifact(image,"tiff:make");
   2976   if (value != (const char *) NULL)
   2977     (void) TIFFSetField(tiff,TIFFTAG_MAKE,value);
   2978   value=GetImageArtifact(image,"tiff:model");
   2979   if (value != (const char *) NULL)
   2980     (void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
   2981   value=GetImageArtifact(image,"tiff:software");
   2982   if (value != (const char *) NULL)
   2983     (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
   2984   value=GetImageArtifact(image,"tiff:copyright");
   2985   if (value != (const char *) NULL)
   2986     (void) TIFFSetField(tiff,TIFFTAG_COPYRIGHT,value);
   2987   value=GetImageArtifact(image,"kodak-33423");
   2988   if (value != (const char *) NULL)
   2989     (void) TIFFSetField(tiff,33423,value);
   2990   value=GetImageArtifact(image,"kodak-36867");
   2991   if (value != (const char *) NULL)
   2992     (void) TIFFSetField(tiff,36867,value);
   2993   value=GetImageProperty(image,"label",exception);
   2994   if (value != (const char *) NULL)
   2995     (void) TIFFSetField(tiff,TIFFTAG_PAGENAME,value);
   2996   value=GetImageProperty(image,"comment",exception);
   2997   if (value != (const char *) NULL)
   2998     (void) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,value);
   2999   value=GetImageArtifact(image,"tiff:subfiletype");
   3000   if (value != (const char *) NULL)
   3001     {
   3002       if (LocaleCompare(value,"REDUCEDIMAGE") == 0)
   3003         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
   3004       else
   3005         if (LocaleCompare(value,"PAGE") == 0)
   3006           (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
   3007         else
   3008           if (LocaleCompare(value,"MASK") == 0)
   3009             (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_MASK);
   3010     }
   3011   else
   3012     {
   3013       uint16
   3014         page,
   3015         pages;
   3016 
   3017       page=(uint16) image->scene;
   3018       pages=(uint16) GetImageListLength(image);
   3019       if ((image_info->adjoin != MagickFalse) && (pages > 1))
   3020         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
   3021       (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
   3022     }
   3023 }
   3024 
   3025 static void TIFFSetEXIFProperties(TIFF *tiff,Image *image,
   3026   ExceptionInfo *exception)
   3027 {
   3028 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
   3029   const char
   3030     *value;
   3031 
   3032   register ssize_t
   3033     i;
   3034 
   3035   uint32
   3036     offset;
   3037 
   3038   /*
   3039     Write EXIF properties.
   3040   */
   3041   offset=0;
   3042   (void) TIFFSetField(tiff,TIFFTAG_SUBIFD,1,&offset);
   3043   for (i=0; exif_info[i].tag != 0; i++)
   3044   {
   3045     value=GetImageProperty(image,exif_info[i].property,exception);
   3046     if (value == (const char *) NULL)
   3047       continue;
   3048     switch (exif_info[i].type)
   3049     {
   3050       case TIFF_ASCII:
   3051       {
   3052         (void) TIFFSetField(tiff,exif_info[i].tag,value);
   3053         break;
   3054       }
   3055       case TIFF_SHORT:
   3056       {
   3057         uint16
   3058           field;
   3059 
   3060         field=(uint16) StringToLong(value);
   3061         (void) TIFFSetField(tiff,exif_info[i].tag,field);
   3062         break;
   3063       }
   3064       case TIFF_LONG:
   3065       {
   3066         uint16
   3067           field;
   3068 
   3069         field=(uint16) StringToLong(value);
   3070         (void) TIFFSetField(tiff,exif_info[i].tag,field);
   3071         break;
   3072       }
   3073       case TIFF_RATIONAL:
   3074       case TIFF_SRATIONAL:
   3075       {
   3076         float
   3077           field;
   3078 
   3079         field=StringToDouble(value,(char **) NULL);
   3080         (void) TIFFSetField(tiff,exif_info[i].tag,field);
   3081         break;
   3082       }
   3083       default:
   3084         break;
   3085     }
   3086   }
   3087   /* (void) TIFFSetField(tiff,TIFFTAG_EXIFIFD,offset); */
   3088 #else
   3089   (void) tiff;
   3090   (void) image;
   3091 #endif
   3092 }
   3093 
   3094 static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
   3095   Image *image,ExceptionInfo *exception)
   3096 {
   3097 #if !defined(TIFFDefaultStripSize)
   3098 #define TIFFDefaultStripSize(tiff,request)  (8192UL/TIFFScanlineSize(tiff))
   3099 #endif
   3100 
   3101   const char
   3102     *mode,
   3103     *option;
   3104 
   3105   CompressionType
   3106     compression;
   3107 
   3108   EndianType
   3109     endian_type;
   3110 
   3111   MagickBooleanType
   3112     debug,
   3113     status;
   3114 
   3115   MagickOffsetType
   3116     scene;
   3117 
   3118   QuantumInfo
   3119     *quantum_info;
   3120 
   3121   QuantumType
   3122     quantum_type;
   3123 
   3124   register ssize_t
   3125     i;
   3126 
   3127   size_t
   3128     length;
   3129 
   3130   ssize_t
   3131     y;
   3132 
   3133   TIFF
   3134     *tiff;
   3135 
   3136   TIFFInfo
   3137     tiff_info;
   3138 
   3139   uint16
   3140     bits_per_sample,
   3141     compress_tag,
   3142     endian,
   3143     photometric;
   3144 
   3145   uint32
   3146     rows_per_strip;
   3147 
   3148   unsigned char
   3149     *pixels;
   3150 
   3151   /*
   3152     Open TIFF file.
   3153   */
   3154   assert(image_info != (const ImageInfo *) NULL);
   3155   assert(image_info->signature == MagickCoreSignature);
   3156   assert(image != (Image *) NULL);
   3157   assert(image->signature == MagickCoreSignature);
   3158   if (image->debug != MagickFalse)
   3159     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
   3160   assert(exception != (ExceptionInfo *) NULL);
   3161   assert(exception->signature == MagickCoreSignature);
   3162   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
   3163   if (status == MagickFalse)
   3164     return(status);
   3165   (void) SetMagickThreadValue(tiff_exception,exception);
   3166   endian_type=UndefinedEndian;
   3167   option=GetImageOption(image_info,"tiff:endian");
   3168   if (option != (const char *) NULL)
   3169     {
   3170       if (LocaleNCompare(option,"msb",3) == 0)
   3171         endian_type=MSBEndian;
   3172       if (LocaleNCompare(option,"lsb",3) == 0)
   3173         endian_type=LSBEndian;;
   3174     }
   3175   switch (endian_type)
   3176   {
   3177     case LSBEndian: mode="wl"; break;
   3178     case MSBEndian: mode="wb"; break;
   3179     default: mode="w"; break;
   3180   }
   3181 #if defined(TIFF_VERSION_BIG)
   3182   if (LocaleCompare(image_info->magick,"TIFF64") == 0)
   3183     switch (endian_type)
   3184     {
   3185       case LSBEndian: mode="wl8"; break;
   3186       case MSBEndian: mode="wb8"; break;
   3187       default: mode="w8"; break;
   3188     }
   3189 #endif
   3190   tiff=TIFFClientOpen(image->filename,mode,(thandle_t) image,TIFFReadBlob,
   3191     TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
   3192     TIFFUnmapBlob);
   3193   if (tiff == (TIFF *) NULL)
   3194     return(MagickFalse);
   3195   scene=0;
   3196   debug=IsEventLogging();
   3197   (void) debug;
   3198   do
   3199   {
   3200     /*
   3201       Initialize TIFF fields.
   3202     */
   3203     if ((image_info->type != UndefinedType) &&
   3204         (image_info->type != OptimizeType))
   3205       (void) SetImageType(image,image_info->type,exception);
   3206     compression=UndefinedCompression;
   3207     if (image->compression != JPEGCompression)
   3208       compression=image->compression;
   3209     if (image_info->compression != UndefinedCompression)
   3210       compression=image_info->compression;
   3211     switch (compression)
   3212     {
   3213       case FaxCompression:
   3214       case Group4Compression:
   3215       {
   3216         (void) SetImageType(image,BilevelType,exception);
   3217         (void) SetImageDepth(image,1,exception);
   3218         break;
   3219       }
   3220       case JPEGCompression:
   3221       {
   3222         (void) SetImageStorageClass(image,DirectClass,exception);
   3223         (void) SetImageDepth(image,8,exception);
   3224         break;
   3225       }
   3226       default:
   3227         break;
   3228     }
   3229     quantum_info=AcquireQuantumInfo(image_info,image);
   3230     if (quantum_info == (QuantumInfo *) NULL)
   3231       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   3232     if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
   3233         (quantum_info->format == UndefinedQuantumFormat) &&
   3234         (IsHighDynamicRangeImage(image,exception) != MagickFalse))
   3235       {
   3236         status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
   3237         if (status == MagickFalse)
   3238           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   3239       }
   3240     if ((LocaleCompare(image_info->magick,"PTIF") == 0) &&
   3241         (GetPreviousImageInList(image) != (Image *) NULL))
   3242       (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
   3243     if ((image->columns != (uint32) image->columns) ||
   3244         (image->rows != (uint32) image->rows))
   3245       ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
   3246     (void) TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
   3247     (void) TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
   3248     switch (compression)
   3249     {
   3250       case FaxCompression:
   3251       {
   3252         compress_tag=COMPRESSION_CCITTFAX3;
   3253         SetQuantumMinIsWhite(quantum_info,MagickTrue);
   3254         break;
   3255       }
   3256       case Group4Compression:
   3257       {
   3258         compress_tag=COMPRESSION_CCITTFAX4;
   3259         SetQuantumMinIsWhite(quantum_info,MagickTrue);
   3260         break;
   3261       }
   3262 #if defined(COMPRESSION_JBIG)
   3263       case JBIG1Compression:
   3264       {
   3265         compress_tag=COMPRESSION_JBIG;
   3266         break;
   3267       }
   3268 #endif
   3269       case JPEGCompression:
   3270       {
   3271         compress_tag=COMPRESSION_JPEG;
   3272         break;
   3273       }
   3274 #if defined(COMPRESSION_LZMA)
   3275       case LZMACompression:
   3276       {
   3277         compress_tag=COMPRESSION_LZMA;
   3278         break;
   3279       }
   3280 #endif
   3281       case LZWCompression:
   3282       {
   3283         compress_tag=COMPRESSION_LZW;
   3284         break;
   3285       }
   3286       case RLECompression:
   3287       {
   3288         compress_tag=COMPRESSION_PACKBITS;
   3289         break;
   3290       }
   3291       case ZipCompression:
   3292       {
   3293         compress_tag=COMPRESSION_ADOBE_DEFLATE;
   3294         break;
   3295       }
   3296       case NoCompression:
   3297       default:
   3298       {
   3299         compress_tag=COMPRESSION_NONE;
   3300         break;
   3301       }
   3302     }
   3303 #if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
   3304     if ((compress_tag != COMPRESSION_NONE) &&
   3305         (TIFFIsCODECConfigured(compress_tag) == 0))
   3306       {
   3307         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
   3308           "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
   3309           MagickCompressOptions,(ssize_t) compression));
   3310         compress_tag=COMPRESSION_NONE;
   3311         compression=NoCompression;
   3312       }
   3313 #else
   3314       switch (compress_tag)
   3315       {
   3316 #if defined(CCITT_SUPPORT)
   3317         case COMPRESSION_CCITTFAX3:
   3318         case COMPRESSION_CCITTFAX4:
   3319 #endif
   3320 #if defined(YCBCR_SUPPORT) && defined(JPEG_SUPPORT)
   3321         case COMPRESSION_JPEG:
   3322 #endif
   3323 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
   3324         case COMPRESSION_LZMA:
   3325 #endif
   3326 #if defined(LZW_SUPPORT)
   3327         case COMPRESSION_LZW:
   3328 #endif
   3329 #if defined(PACKBITS_SUPPORT)
   3330         case COMPRESSION_PACKBITS:
   3331 #endif
   3332 #if defined(ZIP_SUPPORT)
   3333         case COMPRESSION_ADOBE_DEFLATE:
   3334 #endif
   3335         case COMPRESSION_NONE:
   3336           break;
   3337         default:
   3338         {
   3339           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
   3340             "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
   3341               MagickCompressOptions,(ssize_t) compression));
   3342           compress_tag=COMPRESSION_NONE;
   3343           compression=NoCompression;
   3344           break;
   3345         }
   3346       }
   3347 #endif
   3348     if (image->colorspace == CMYKColorspace)
   3349       {
   3350         photometric=PHOTOMETRIC_SEPARATED;
   3351         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,4);
   3352         (void) TIFFSetField(tiff,TIFFTAG_INKSET,INKSET_CMYK);
   3353       }
   3354     else
   3355       {
   3356         /*
   3357           Full color TIFF raster.
   3358         */
   3359         if (image->colorspace == LabColorspace)
   3360           {
   3361             photometric=PHOTOMETRIC_CIELAB;
   3362             EncodeLabImage(image,exception);
   3363           }
   3364         else
   3365           if (image->colorspace == YCbCrColorspace)
   3366             {
   3367               photometric=PHOTOMETRIC_YCBCR;
   3368               (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
   3369               (void) SetImageStorageClass(image,DirectClass,exception);
   3370               (void) SetImageDepth(image,8,exception);
   3371             }
   3372           else
   3373             photometric=PHOTOMETRIC_RGB;
   3374         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,3);
   3375         if ((image_info->type != TrueColorType) &&
   3376             (image_info->type != TrueColorAlphaType))
   3377           {
   3378             if ((image_info->type != PaletteType) &&
   3379                 (SetImageGray(image,exception) != MagickFalse))
   3380               {
   3381                 photometric=(uint16) (quantum_info->min_is_white !=
   3382                   MagickFalse ? PHOTOMETRIC_MINISWHITE :
   3383                   PHOTOMETRIC_MINISBLACK);
   3384                 (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
   3385                 if ((image->depth == 1) &&
   3386                     (image->alpha_trait == UndefinedPixelTrait))
   3387                   SetImageMonochrome(image,exception);
   3388               }
   3389             else
   3390               if (image->storage_class == PseudoClass)
   3391                 {
   3392                   size_t
   3393                     depth;
   3394 
   3395                   /*
   3396                     Colormapped TIFF raster.
   3397                   */
   3398                   (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
   3399                   photometric=PHOTOMETRIC_PALETTE;
   3400                   depth=1;
   3401                   while ((GetQuantumRange(depth)+1) < image->colors)
   3402                     depth<<=1;
   3403                   status=SetQuantumDepth(image,quantum_info,depth);
   3404                   if (status == MagickFalse)
   3405                     ThrowWriterException(ResourceLimitError,
   3406                       "MemoryAllocationFailed");
   3407                 }
   3408           }
   3409       }
   3410     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian);
   3411     if ((compress_tag == COMPRESSION_CCITTFAX3) &&
   3412         (photometric != PHOTOMETRIC_MINISWHITE))
   3413       {
   3414         compress_tag=COMPRESSION_NONE;
   3415         endian=FILLORDER_MSB2LSB;
   3416       }
   3417     else
   3418       if ((compress_tag == COMPRESSION_CCITTFAX4) &&
   3419          (photometric != PHOTOMETRIC_MINISWHITE))
   3420        {
   3421          compress_tag=COMPRESSION_NONE;
   3422          endian=FILLORDER_MSB2LSB;
   3423        }
   3424     option=GetImageOption(image_info,"tiff:fill-order");
   3425     if (option != (const char *) NULL)
   3426       {
   3427         if (LocaleNCompare(option,"msb",3) == 0)
   3428           endian=FILLORDER_MSB2LSB;
   3429         if (LocaleNCompare(option,"lsb",3) == 0)
   3430           endian=FILLORDER_LSB2MSB;
   3431       }
   3432     (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
   3433     (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
   3434     (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
   3435     if (image->alpha_trait != UndefinedPixelTrait)
   3436       {
   3437         uint16
   3438           extra_samples,
   3439           sample_info[1],
   3440           samples_per_pixel;
   3441 
   3442         /*
   3443           TIFF has a matte channel.
   3444         */
   3445         extra_samples=1;
   3446         sample_info[0]=EXTRASAMPLE_UNASSALPHA;
   3447         option=GetImageOption(image_info,"tiff:alpha");
   3448         if (option != (const char *) NULL)
   3449           {
   3450             if (LocaleCompare(option,"associated") == 0)
   3451               sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
   3452             else
   3453               if (LocaleCompare(option,"unspecified") == 0)
   3454                 sample_info[0]=EXTRASAMPLE_UNSPECIFIED;
   3455           }
   3456         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
   3457           &samples_per_pixel);
   3458         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,samples_per_pixel+1);
   3459         (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples,
   3460           &sample_info);
   3461         if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA)
   3462           SetQuantumAlphaType(quantum_info,AssociatedQuantumAlpha);
   3463       }
   3464     (void) TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
   3465     switch (quantum_info->format)
   3466     {
   3467       case FloatingPointQuantumFormat:
   3468       {
   3469         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
   3470         (void) TIFFSetField(tiff,TIFFTAG_SMINSAMPLEVALUE,quantum_info->minimum);
   3471         (void) TIFFSetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,quantum_info->maximum);
   3472         break;
   3473       }
   3474       case SignedQuantumFormat:
   3475       {
   3476         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
   3477         break;
   3478       }
   3479       case UnsignedQuantumFormat:
   3480       {
   3481         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
   3482         break;
   3483       }
   3484       default:
   3485         break;
   3486     }
   3487     (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
   3488     (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
   3489     if (photometric == PHOTOMETRIC_RGB)
   3490       if ((image_info->interlace == PlaneInterlace) ||
   3491           (image_info->interlace == PartitionInterlace))
   3492         (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
   3493      rows_per_strip=TIFFDefaultStripSize(tiff,0);
   3494     option=GetImageOption(image_info,"tiff:rows-per-strip");
   3495     if (option != (const char *) NULL)
   3496       rows_per_strip=(size_t) strtol(option,(char **) NULL,10);
   3497     switch (compress_tag)
   3498     {
   3499       case COMPRESSION_JPEG:
   3500       {
   3501 #if defined(JPEG_SUPPORT)
   3502         const char
   3503           *sampling_factor;
   3504 
   3505         GeometryInfo
   3506           geometry_info;
   3507 
   3508         MagickStatusType
   3509           flags;
   3510 
   3511         rows_per_strip+=(16-(rows_per_strip % 16));
   3512         if (image_info->quality != UndefinedCompressionQuality)
   3513           (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality);
   3514         (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RAW);
   3515         if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
   3516           {
   3517             const char
   3518               *value;
   3519 
   3520             (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB);
   3521             sampling_factor=(const char *) NULL;
   3522             value=GetImageProperty(image,"jpeg:sampling-factor",exception);
   3523             if (value != (char *) NULL)
   3524               {
   3525                 sampling_factor=value;
   3526                 if (image->debug != MagickFalse)
   3527                   (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   3528                     "  Input sampling-factors=%s",sampling_factor);
   3529               }
   3530             if (image_info->sampling_factor != (char *) NULL)
   3531               sampling_factor=image_info->sampling_factor;
   3532             if (sampling_factor != (const char *) NULL)
   3533               {
   3534                 flags=ParseGeometry(sampling_factor,&geometry_info);
   3535                 if ((flags & SigmaValue) == 0)
   3536                   geometry_info.sigma=geometry_info.rho;
   3537                 if (image->colorspace == YCbCrColorspace)
   3538                   (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
   3539                     geometry_info.rho,(uint16) geometry_info.sigma);
   3540               }
   3541           }
   3542         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
   3543           &bits_per_sample);
   3544         if (bits_per_sample == 12)
   3545           (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT);
   3546 #endif
   3547         break;
   3548       }
   3549       case COMPRESSION_ADOBE_DEFLATE:
   3550       {
   3551         rows_per_strip=(uint32) image->rows;
   3552         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
   3553           &bits_per_sample);
   3554         if (((photometric == PHOTOMETRIC_RGB) ||
   3555              (photometric == PHOTOMETRIC_MINISBLACK)) &&
   3556             ((bits_per_sample == 8) || (bits_per_sample == 16)))
   3557           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
   3558         (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,(long) (
   3559           image_info->quality == UndefinedCompressionQuality ? 7 :
   3560           MagickMin((ssize_t) image_info->quality/10,9)));
   3561         break;
   3562       }
   3563       case COMPRESSION_CCITTFAX3:
   3564       {
   3565         /*
   3566           Byte-aligned EOL.
   3567         */
   3568         rows_per_strip=(uint32) image->rows;
   3569         (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,4);
   3570         break;
   3571       }
   3572       case COMPRESSION_CCITTFAX4:
   3573       {
   3574         rows_per_strip=(uint32) image->rows;
   3575         break;
   3576       }
   3577 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
   3578       case COMPRESSION_LZMA:
   3579       {
   3580         if (((photometric == PHOTOMETRIC_RGB) ||
   3581              (photometric == PHOTOMETRIC_MINISBLACK)) &&
   3582             ((bits_per_sample == 8) || (bits_per_sample == 16)))
   3583           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
   3584         (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,(long) (
   3585           image_info->quality == UndefinedCompressionQuality ? 7 :
   3586           MagickMin((ssize_t) image_info->quality/10,9)));
   3587         break;
   3588       }
   3589 #endif
   3590       case COMPRESSION_LZW:
   3591       {
   3592         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
   3593           &bits_per_sample);
   3594         if (((photometric == PHOTOMETRIC_RGB) ||
   3595              (photometric == PHOTOMETRIC_MINISBLACK)) &&
   3596             ((bits_per_sample == 8) || (bits_per_sample == 16)))
   3597           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
   3598         break;
   3599       }
   3600       default:
   3601         break;
   3602     }
   3603     if (rows_per_strip < 1)
   3604       rows_per_strip=1;
   3605     if ((image->rows/rows_per_strip) >= (1UL << 15))
   3606       rows_per_strip=(uint32) (image->rows >> 15);
   3607     (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
   3608     if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0))
   3609       {
   3610         unsigned short
   3611           units;
   3612 
   3613         /*
   3614           Set image resolution.
   3615         */
   3616         units=RESUNIT_NONE;
   3617         if (image->units == PixelsPerInchResolution)
   3618           units=RESUNIT_INCH;
   3619         if (image->units == PixelsPerCentimeterResolution)
   3620           units=RESUNIT_CENTIMETER;
   3621         (void) TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units);
   3622         (void) TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->resolution.x);
   3623         (void) TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->resolution.y);
   3624         if ((image->page.x < 0) || (image->page.y < 0))
   3625           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
   3626             "TIFF: negative image positions unsupported","%s",image->filename);
   3627         if ((image->page.x > 0) && (image->resolution.x > 0.0))
   3628           {
   3629             /*
   3630               Set horizontal image position.
   3631             */
   3632             (void) TIFFSetField(tiff,TIFFTAG_XPOSITION,(float) image->page.x/
   3633               image->resolution.x);
   3634           }
   3635         if ((image->page.y > 0) && (image->resolution.y > 0.0))
   3636           {
   3637             /*
   3638               Set vertical image position.
   3639             */
   3640             (void) TIFFSetField(tiff,TIFFTAG_YPOSITION,(float) image->page.y/
   3641               image->resolution.y);
   3642           }
   3643       }
   3644     if (image->chromaticity.white_point.x != 0.0)
   3645       {
   3646         float
   3647           chromaticity[6];
   3648 
   3649         /*
   3650           Set image chromaticity.
   3651         */
   3652         chromaticity[0]=(float) image->chromaticity.red_primary.x;
   3653         chromaticity[1]=(float) image->chromaticity.red_primary.y;
   3654         chromaticity[2]=(float) image->chromaticity.green_primary.x;
   3655         chromaticity[3]=(float) image->chromaticity.green_primary.y;
   3656         chromaticity[4]=(float) image->chromaticity.blue_primary.x;
   3657         chromaticity[5]=(float) image->chromaticity.blue_primary.y;
   3658         (void) TIFFSetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,chromaticity);
   3659         chromaticity[0]=(float) image->chromaticity.white_point.x;
   3660         chromaticity[1]=(float) image->chromaticity.white_point.y;
   3661         (void) TIFFSetField(tiff,TIFFTAG_WHITEPOINT,chromaticity);
   3662       }
   3663     if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
   3664         (image_info->adjoin != MagickFalse) && (GetImageListLength(image) > 1))
   3665       {
   3666         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
   3667         if (image->scene != 0)
   3668           (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,(uint16) image->scene,
   3669             GetImageListLength(image));
   3670       }
   3671     if (image->orientation != UndefinedOrientation)
   3672       (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,(uint16) image->orientation);
   3673     (void) TIFFSetProfiles(tiff,image);
   3674     {
   3675       uint16
   3676         page,
   3677         pages;
   3678 
   3679       page=(uint16) scene;
   3680       pages=(uint16) GetImageListLength(image);
   3681       if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
   3682           (image_info->adjoin != MagickFalse) && (pages > 1))
   3683         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
   3684       (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
   3685     }
   3686     (void) TIFFSetProperties(tiff,image_info,image,exception);
   3687 DisableMSCWarning(4127)
   3688     if (0)
   3689 RestoreMSCWarning
   3690       (void) TIFFSetEXIFProperties(tiff,image,exception);
   3691     /*
   3692       Write image scanlines.
   3693     */
   3694     if (GetTIFFInfo(image_info,tiff,&tiff_info) == MagickFalse)
   3695       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   3696     quantum_info->endian=LSBEndian;
   3697     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
   3698     tiff_info.scanline=(unsigned char *) GetQuantumPixels(quantum_info);
   3699     switch (photometric)
   3700     {
   3701       case PHOTOMETRIC_CIELAB:
   3702       case PHOTOMETRIC_YCBCR:
   3703       case PHOTOMETRIC_RGB:
   3704       {
   3705         /*
   3706           RGB TIFF image.
   3707         */
   3708         switch (image_info->interlace)
   3709         {
   3710           case NoInterlace:
   3711           default:
   3712           {
   3713             quantum_type=RGBQuantum;
   3714             if (image->alpha_trait != UndefinedPixelTrait)
   3715               quantum_type=RGBAQuantum;
   3716             for (y=0; y < (ssize_t) image->rows; y++)
   3717             {
   3718               register const Quantum
   3719                 *magick_restrict p;
   3720 
   3721               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3722               if (p == (const Quantum *) NULL)
   3723                 break;
   3724               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3725                 quantum_type,pixels,exception);
   3726               (void) length;
   3727               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
   3728                 break;
   3729               if (image->previous == (Image *) NULL)
   3730                 {
   3731                   status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
   3732                     y,image->rows);
   3733                   if (status == MagickFalse)
   3734                     break;
   3735                 }
   3736             }
   3737             break;
   3738           }
   3739           case PlaneInterlace:
   3740           case PartitionInterlace:
   3741           {
   3742             /*
   3743               Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
   3744             */
   3745             for (y=0; y < (ssize_t) image->rows; y++)
   3746             {
   3747               register const Quantum
   3748                 *magick_restrict p;
   3749 
   3750               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3751               if (p == (const Quantum *) NULL)
   3752                 break;
   3753               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3754                 RedQuantum,pixels,exception);
   3755               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
   3756                 break;
   3757             }
   3758             if (image->previous == (Image *) NULL)
   3759               {
   3760                 status=SetImageProgress(image,SaveImageTag,100,400);
   3761                 if (status == MagickFalse)
   3762                   break;
   3763               }
   3764             for (y=0; y < (ssize_t) image->rows; y++)
   3765             {
   3766               register const Quantum
   3767                 *magick_restrict p;
   3768 
   3769               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3770               if (p == (const Quantum *) NULL)
   3771                 break;
   3772               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3773                 GreenQuantum,pixels,exception);
   3774               if (TIFFWritePixels(tiff,&tiff_info,y,1,image) == -1)
   3775                 break;
   3776             }
   3777             if (image->previous == (Image *) NULL)
   3778               {
   3779                 status=SetImageProgress(image,SaveImageTag,200,400);
   3780                 if (status == MagickFalse)
   3781                   break;
   3782               }
   3783             for (y=0; y < (ssize_t) image->rows; y++)
   3784             {
   3785               register const Quantum
   3786                 *magick_restrict p;
   3787 
   3788               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3789               if (p == (const Quantum *) NULL)
   3790                 break;
   3791               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3792                 BlueQuantum,pixels,exception);
   3793               if (TIFFWritePixels(tiff,&tiff_info,y,2,image) == -1)
   3794                 break;
   3795             }
   3796             if (image->previous == (Image *) NULL)
   3797               {
   3798                 status=SetImageProgress(image,SaveImageTag,300,400);
   3799                 if (status == MagickFalse)
   3800                   break;
   3801               }
   3802             if (image->alpha_trait != UndefinedPixelTrait)
   3803               for (y=0; y < (ssize_t) image->rows; y++)
   3804               {
   3805                 register const Quantum
   3806                   *magick_restrict p;
   3807 
   3808                 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3809                 if (p == (const Quantum *) NULL)
   3810                   break;
   3811                 length=ExportQuantumPixels(image,(CacheView *) NULL,
   3812                   quantum_info,AlphaQuantum,pixels,exception);
   3813                 if (TIFFWritePixels(tiff,&tiff_info,y,3,image) == -1)
   3814                   break;
   3815               }
   3816             if (image->previous == (Image *) NULL)
   3817               {
   3818                 status=SetImageProgress(image,SaveImageTag,400,400);
   3819                 if (status == MagickFalse)
   3820                   break;
   3821               }
   3822             break;
   3823           }
   3824         }
   3825         break;
   3826       }
   3827       case PHOTOMETRIC_SEPARATED:
   3828       {
   3829         /*
   3830           CMYK TIFF image.
   3831         */
   3832         quantum_type=CMYKQuantum;
   3833         if (image->alpha_trait != UndefinedPixelTrait)
   3834           quantum_type=CMYKAQuantum;
   3835         if (image->colorspace != CMYKColorspace)
   3836           (void) TransformImageColorspace(image,CMYKColorspace,exception);
   3837         for (y=0; y < (ssize_t) image->rows; y++)
   3838         {
   3839           register const Quantum
   3840             *magick_restrict p;
   3841 
   3842           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3843           if (p == (const Quantum *) NULL)
   3844             break;
   3845           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3846             quantum_type,pixels,exception);
   3847           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
   3848             break;
   3849           if (image->previous == (Image *) NULL)
   3850             {
   3851               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
   3852                 image->rows);
   3853               if (status == MagickFalse)
   3854                 break;
   3855             }
   3856         }
   3857         break;
   3858       }
   3859       case PHOTOMETRIC_PALETTE:
   3860       {
   3861         uint16
   3862           *blue,
   3863           *green,
   3864           *red;
   3865 
   3866         /*
   3867           Colormapped TIFF image.
   3868         */
   3869         red=(uint16 *) AcquireQuantumMemory(65536,sizeof(*red));
   3870         green=(uint16 *) AcquireQuantumMemory(65536,sizeof(*green));
   3871         blue=(uint16 *) AcquireQuantumMemory(65536,sizeof(*blue));
   3872         if ((red == (uint16 *) NULL) || (green == (uint16 *) NULL) ||
   3873             (blue == (uint16 *) NULL))
   3874           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
   3875         /*
   3876           Initialize TIFF colormap.
   3877         */
   3878         (void) ResetMagickMemory(red,0,65536*sizeof(*red));
   3879         (void) ResetMagickMemory(green,0,65536*sizeof(*green));
   3880         (void) ResetMagickMemory(blue,0,65536*sizeof(*blue));
   3881         for (i=0; i < (ssize_t) image->colors; i++)
   3882         {
   3883           red[i]=ScaleQuantumToShort(image->colormap[i].red);
   3884           green[i]=ScaleQuantumToShort(image->colormap[i].green);
   3885           blue[i]=ScaleQuantumToShort(image->colormap[i].blue);
   3886         }
   3887         (void) TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
   3888         red=(uint16 *) RelinquishMagickMemory(red);
   3889         green=(uint16 *) RelinquishMagickMemory(green);
   3890         blue=(uint16 *) RelinquishMagickMemory(blue);
   3891       }
   3892       default:
   3893       {
   3894         /*
   3895           Convert PseudoClass packets to contiguous grayscale scanlines.
   3896         */
   3897         quantum_type=IndexQuantum;
   3898         if (image->alpha_trait != UndefinedPixelTrait)
   3899           {
   3900             if (photometric != PHOTOMETRIC_PALETTE)
   3901               quantum_type=GrayAlphaQuantum;
   3902             else
   3903               quantum_type=IndexAlphaQuantum;
   3904            }
   3905          else
   3906            if (photometric != PHOTOMETRIC_PALETTE)
   3907              quantum_type=GrayQuantum;
   3908         for (y=0; y < (ssize_t) image->rows; y++)
   3909         {
   3910           register const Quantum
   3911             *magick_restrict p;
   3912 
   3913           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
   3914           if (p == (const Quantum *) NULL)
   3915             break;
   3916           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
   3917             quantum_type,pixels,exception);
   3918           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
   3919             break;
   3920           if (image->previous == (Image *) NULL)
   3921             {
   3922               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
   3923                 image->rows);
   3924               if (status == MagickFalse)
   3925                 break;
   3926             }
   3927         }
   3928         break;
   3929       }
   3930     }
   3931     quantum_info=DestroyQuantumInfo(quantum_info);
   3932     if (image->colorspace == LabColorspace)
   3933       DecodeLabImage(image,exception);
   3934     DestroyTIFFInfo(&tiff_info);
   3935 DisableMSCWarning(4127)
   3936     if (0 && (image_info->verbose != MagickFalse))
   3937 RestoreMSCWarning
   3938       TIFFPrintDirectory(tiff,stdout,MagickFalse);
   3939     (void) TIFFWriteDirectory(tiff);
   3940     image=SyncNextImageInList(image);
   3941     if (image == (Image *) NULL)
   3942       break;
   3943     status=SetImageProgress(image,SaveImagesTag,scene++,
   3944       GetImageListLength(image));
   3945     if (status == MagickFalse)
   3946       break;
   3947   } while (image_info->adjoin != MagickFalse);
   3948   TIFFClose(tiff);
   3949   return(MagickTrue);
   3950 }
   3951 #endif
   3952