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