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