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