]> granicus.if.org Git - imagemagick/blob - coders/tiff.c
...
[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 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
28 %  Unless required by applicable law or agreed to in writing, software        %
29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
31 %  See the License for the specific language governing permissions and        %
32 %  limitations under the License.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 #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,MagickBooleanType ping,
582   ExceptionInfo *exception)
583 {
584   uint32
585     length;
586
587   unsigned char
588     *profile;
589
590   length=0;
591   if (ping == MagickFalse)
592     {
593 #if defined(TIFFTAG_ICCPROFILE)
594       if ((TIFFGetField(tiff,TIFFTAG_ICCPROFILE,&length,&profile) == 1) &&
595           (profile != (unsigned char *) NULL))
596         (void) ReadProfile(image,"icc",profile,(ssize_t) length,exception);
597 #endif
598 #if defined(TIFFTAG_PHOTOSHOP)
599       if ((TIFFGetField(tiff,TIFFTAG_PHOTOSHOP,&length,&profile) == 1) &&
600           (profile != (unsigned char *) NULL))
601         (void) ReadProfile(image,"8bim",profile,(ssize_t) length,exception);
602 #endif
603 #if defined(TIFFTAG_RICHTIFFIPTC)
604       if ((TIFFGetField(tiff,TIFFTAG_RICHTIFFIPTC,&length,&profile) == 1) &&
605           (profile != (unsigned char *) NULL))
606         {
607           if (TIFFIsByteSwapped(tiff) != 0)
608             TIFFSwabArrayOfLong((uint32 *) profile,(size_t) length);
609           (void) ReadProfile(image,"iptc",profile,4L*length,exception);
610         }
611 #endif
612 #if defined(TIFFTAG_XMLPACKET)
613       if ((TIFFGetField(tiff,TIFFTAG_XMLPACKET,&length,&profile) == 1) &&
614           (profile != (unsigned char *) NULL))
615         (void) ReadProfile(image,"xmp",profile,(ssize_t) length,exception);
616 #endif
617       if ((TIFFGetField(tiff,34118,&length,&profile) == 1) &&
618           (profile != (unsigned char *) NULL))
619         (void) ReadProfile(image,"tiff:34118",profile,(ssize_t) length,
620           exception);
621     }
622   if ((TIFFGetField(tiff,37724,&length,&profile) == 1) &&
623       (profile != (unsigned char *) NULL))
624     (void) ReadProfile(image,"tiff:37724",profile,(ssize_t) length,exception);
625 }
626
627 static void TIFFGetProperties(TIFF *tiff,Image *image,ExceptionInfo *exception)
628 {
629   char
630     message[MagickPathExtent],
631     *text;
632
633   uint32
634     count,
635     length,
636     type;
637
638   unsigned long
639     *tietz;
640
641   if ((TIFFGetField(tiff,TIFFTAG_ARTIST,&text) == 1) &&
642       (text != (char *) NULL))
643     (void) SetImageProperty(image,"tiff:artist",text,exception);
644   if ((TIFFGetField(tiff,TIFFTAG_COPYRIGHT,&text) == 1) &&
645       (text != (char *) NULL))
646     (void) SetImageProperty(image,"tiff:copyright",text,exception);
647   if ((TIFFGetField(tiff,TIFFTAG_DATETIME,&text) == 1) &&
648       (text != (char *) NULL))
649     (void) SetImageProperty(image,"tiff:timestamp",text,exception);
650   if ((TIFFGetField(tiff,TIFFTAG_DOCUMENTNAME,&text) == 1) &&
651       (text != (char *) NULL))
652     (void) SetImageProperty(image,"tiff:document",text,exception);
653   if ((TIFFGetField(tiff,TIFFTAG_HOSTCOMPUTER,&text) == 1) &&
654       (text != (char *) NULL))
655     (void) SetImageProperty(image,"tiff:hostcomputer",text,exception);
656   if ((TIFFGetField(tiff,TIFFTAG_IMAGEDESCRIPTION,&text) == 1) &&
657       (text != (char *) NULL))
658     (void) SetImageProperty(image,"comment",text,exception);
659   if ((TIFFGetField(tiff,TIFFTAG_MAKE,&text) == 1) &&
660       (text != (char *) NULL))
661     (void) SetImageProperty(image,"tiff:make",text,exception);
662   if ((TIFFGetField(tiff,TIFFTAG_MODEL,&text) == 1) &&
663       (text != (char *) NULL))
664     (void) SetImageProperty(image,"tiff:model",text,exception);
665   if ((TIFFGetField(tiff,TIFFTAG_OPIIMAGEID,&count,&text) == 1) &&
666       (text != (char *) NULL))
667     {
668       if (count >= MagickPathExtent)
669         count=MagickPathExtent-1;
670       (void) CopyMagickString(message,text,count+1);
671       (void) SetImageProperty(image,"tiff:image-id",message,exception);
672     }
673   if ((TIFFGetField(tiff,TIFFTAG_PAGENAME,&text) == 1) &&
674       (text != (char *) NULL))
675     (void) SetImageProperty(image,"label",text,exception);
676   if ((TIFFGetField(tiff,TIFFTAG_SOFTWARE,&text) == 1) &&
677       (text != (char *) NULL))
678     (void) SetImageProperty(image,"tiff:software",text,exception);
679   if ((TIFFGetField(tiff,33423,&count,&text) == 1) &&
680       (text != (char *) NULL))
681     {
682       if (count >= MagickPathExtent)
683         count=MagickPathExtent-1;
684       (void) CopyMagickString(message,text,count+1);
685       (void) SetImageProperty(image,"tiff:kodak-33423",message,exception);
686     }
687   if ((TIFFGetField(tiff,36867,&count,&text) == 1) &&
688       (text != (char *) NULL))
689     {
690       if (count >= MagickPathExtent)
691         count=MagickPathExtent-1;
692       (void) CopyMagickString(message,text,count+1);
693       (void) SetImageProperty(image,"tiff:kodak-36867",message,exception);
694     }
695   if (TIFFGetField(tiff,TIFFTAG_SUBFILETYPE,&type) == 1)
696     switch (type)
697     {
698       case 0x01:
699       {
700         (void) SetImageProperty(image,"tiff:subfiletype","REDUCEDIMAGE",
701           exception);
702         break;
703       }
704       case 0x02:
705       {
706         (void) SetImageProperty(image,"tiff:subfiletype","PAGE",exception);
707         break;
708       }
709       case 0x04:
710       {
711         (void) SetImageProperty(image,"tiff:subfiletype","MASK",exception);
712         break;
713       }
714       default:
715         break;
716     }
717   if ((TIFFGetField(tiff,37706,&length,&tietz) == 1) &&
718       (tietz != (unsigned long *) NULL))
719     {
720       (void) FormatLocaleString(message,MagickPathExtent,"%lu",tietz[0]);
721       (void) SetImageProperty(image,"tiff:tietz_offset",message,exception);
722     }
723 }
724
725 static void TIFFGetEXIFProperties(TIFF *tiff,Image *image,
726   ExceptionInfo *exception)
727 {
728 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
729   char
730     value[MagickPathExtent];
731
732   register ssize_t
733     i;
734
735   tdir_t
736     directory;
737
738 #if defined(TIFF_VERSION_BIG)
739   uint64
740 #else
741   uint32
742 #endif
743     offset;
744
745   void
746     *sans;
747
748   /*
749     Read EXIF properties.
750   */
751   offset=0;
752   if (TIFFGetField(tiff,TIFFTAG_EXIFIFD,&offset) != 1)
753     return;
754   directory=TIFFCurrentDirectory(tiff);
755   if (TIFFReadEXIFDirectory(tiff,offset) != 1)
756     {
757       TIFFSetDirectory(tiff,directory);
758       return;
759     }
760   sans=NULL;
761   for (i=0; exif_info[i].tag != 0; i++)
762   {
763     *value='\0';
764     switch (exif_info[i].type)
765     {
766       case TIFF_ASCII:
767       {
768         char
769           *ascii;
770
771         ascii=(char *) NULL;
772         if ((TIFFGetField(tiff,exif_info[i].tag,&ascii,&sans,&sans) == 1) &&
773             (ascii != (char *) NULL) && (*ascii != '\0'))
774           (void) CopyMagickString(value,ascii,MagickPathExtent);
775         break;
776       }
777       case TIFF_SHORT:
778       {
779         if (exif_info[i].variable_length == 0)
780           {
781             uint16
782               shorty;
783
784             shorty=0;
785             if (TIFFGetField(tiff,exif_info[i].tag,&shorty,&sans,&sans) == 1)
786               (void) FormatLocaleString(value,MagickPathExtent,"%d",shorty);
787           }
788         else
789           {
790             int
791               tiff_status;
792
793             uint16
794               *shorty;
795
796             uint16
797               shorty_num;
798
799             tiff_status=TIFFGetField(tiff,exif_info[i].tag,&shorty_num,&shorty,
800               &sans,&sans);
801             if (tiff_status == 1)
802               (void) FormatLocaleString(value,MagickPathExtent,"%d",
803                 shorty_num != 0 ? shorty[0] : 0);
804           }
805         break;
806       }
807       case TIFF_LONG:
808       {
809         uint32
810           longy;
811
812         longy=0;
813         if (TIFFGetField(tiff,exif_info[i].tag,&longy,&sans,&sans) == 1)
814           (void) FormatLocaleString(value,MagickPathExtent,"%d",longy);
815         break;
816       }
817 #if defined(TIFF_VERSION_BIG)
818       case TIFF_LONG8:
819       {
820         uint64
821           long8y;
822
823         long8y=0;
824         if (TIFFGetField(tiff,exif_info[i].tag,&long8y,&sans,&sans) == 1)
825           (void) FormatLocaleString(value,MagickPathExtent,"%.20g",(double)
826             ((MagickOffsetType) long8y));
827         break;
828       }
829 #endif
830       case TIFF_RATIONAL:
831       case TIFF_SRATIONAL:
832       case TIFF_FLOAT:
833       {
834         float
835           floaty;
836
837         floaty=0.0;
838         if (TIFFGetField(tiff,exif_info[i].tag,&floaty,&sans,&sans) == 1)
839           (void) FormatLocaleString(value,MagickPathExtent,"%g",(double)
840             floaty);
841         break;
842       }
843       case TIFF_DOUBLE:
844       {
845         double
846           doubley;
847
848         doubley=0.0;
849         if (TIFFGetField(tiff,exif_info[i].tag,&doubley,&sans,&sans) == 1)
850           (void) FormatLocaleString(value,MagickPathExtent,"%g",doubley);
851         break;
852       }
853       default:
854         break;
855     }
856     if (*value != '\0')
857       (void) SetImageProperty(image,exif_info[i].property,value,exception);
858   }
859   TIFFSetDirectory(tiff,directory);
860 #else
861   (void) tiff;
862   (void) image;
863 #endif
864 }
865
866 static int TIFFMapBlob(thandle_t image,tdata_t *base,toff_t *size)
867 {
868   *base=(tdata_t *) GetBlobStreamData((Image *) image);
869   if (*base != (tdata_t *) NULL)
870     *size=(toff_t) GetBlobSize((Image *) image);
871   if (*base != (tdata_t *) NULL)
872     return(1);
873   return(0);
874 }
875
876 static tsize_t TIFFReadBlob(thandle_t image,tdata_t data,tsize_t size)
877 {
878   tsize_t
879     count;
880
881   count=(tsize_t) ReadBlob((Image *) image,(size_t) size,
882     (unsigned char *) data);
883   return(count);
884 }
885
886 static int32 TIFFReadPixels(TIFF *tiff,size_t bits_per_sample,
887   tsample_t sample,ssize_t row,tdata_t scanline)
888 {
889   int32
890     status;
891
892   (void) bits_per_sample;
893   status=TIFFReadScanline(tiff,scanline,(uint32) row,sample);
894   return(status);
895 }
896
897 static toff_t TIFFSeekBlob(thandle_t image,toff_t offset,int whence)
898 {
899   return((toff_t) SeekBlob((Image *) image,(MagickOffsetType) offset,whence));
900 }
901
902 static void TIFFUnmapBlob(thandle_t image,tdata_t base,toff_t size)
903 {
904   (void) image;
905   (void) base;
906   (void) size;
907 }
908
909 static void TIFFWarnings(const char *module,const char *format,va_list warning)
910 {
911   char
912     message[MagickPathExtent];
913
914   ExceptionInfo
915     *exception;
916
917 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
918   (void) vsnprintf(message,MagickPathExtent,format,warning);
919 #else
920   (void) vsprintf(message,format,warning);
921 #endif
922   (void) ConcatenateMagickString(message,".",MagickPathExtent);
923   exception=(ExceptionInfo *) GetMagickThreadValue(tiff_exception);
924   if (exception != (ExceptionInfo *) NULL)
925     (void) ThrowMagickException(exception,GetMagickModule(),CoderWarning,
926       message,"`%s'",module);
927 }
928
929 static tsize_t TIFFWriteBlob(thandle_t image,tdata_t data,tsize_t size)
930 {
931   tsize_t
932     count;
933
934   count=(tsize_t) WriteBlob((Image *) image,(size_t) size,
935     (unsigned char *) data);
936   return(count);
937 }
938
939 static TIFFMethodType GetJPEGMethod(Image* image,TIFF *tiff,uint16 photometric,
940   uint16 bits_per_sample,uint16 samples_per_pixel)
941 {
942 #define BUFFER_SIZE 2048
943
944   MagickOffsetType
945     position,
946     offset;
947
948   register size_t
949     i;
950
951   TIFFMethodType
952     method;
953
954 #if defined(TIFF_VERSION_BIG)
955   uint64
956 #else
957   uint32
958 #endif
959     **value;
960
961   unsigned char
962     buffer[BUFFER_SIZE+32];
963
964   unsigned short
965     length;
966
967   /* only support 8 bit for now */
968   if ((photometric != PHOTOMETRIC_SEPARATED) || (bits_per_sample != 8) ||
969       (samples_per_pixel != 4))
970     return(ReadGenericMethod);
971   /* Search for Adobe APP14 JPEG Marker */
972   if (!TIFFGetField(tiff,TIFFTAG_STRIPOFFSETS,&value))
973     return(ReadRGBAMethod);
974   position=TellBlob(image);
975   offset=(MagickOffsetType) (value[0]);
976   if (SeekBlob(image,offset,SEEK_SET) != offset)
977     return(ReadRGBAMethod);
978   method=ReadRGBAMethod;
979   if (ReadBlob(image,BUFFER_SIZE,buffer) == BUFFER_SIZE)
980     {
981       for (i=0; i < BUFFER_SIZE; i++)
982       {
983         while (i < BUFFER_SIZE)
984         {
985           if (buffer[i++] == 255)
986            break;
987         }
988         while (i < BUFFER_SIZE)
989         {
990           if (buffer[++i] != 255)
991            break;
992         }
993         if (buffer[i++] == 216) /* JPEG_MARKER_SOI */
994           continue;
995         length=(unsigned short) (((unsigned int) (buffer[i] << 8) |
996           (unsigned int) buffer[i+1]) & 0xffff);
997         if (i+(size_t) length >= BUFFER_SIZE)
998           break;
999         if (buffer[i-1] == 238) /* JPEG_MARKER_APP0+14 */
1000           {
1001             if (length != 14)
1002               break;
1003             /* 0 == CMYK, 1 == YCbCr, 2 = YCCK */
1004             if (buffer[i+13] == 2)
1005               method=ReadYCCKMethod;
1006             break;
1007           }
1008         i+=(size_t) length;
1009       }
1010     }
1011   (void) SeekBlob(image,position,SEEK_SET);
1012   return(method);
1013 }
1014
1015 static void TIFFReadPhotoshopLayers(Image* image,const ImageInfo *image_info,
1016   ExceptionInfo *exception)
1017 {
1018   const char
1019     *option;
1020
1021   const StringInfo
1022     *layer_info;
1023
1024   Image
1025     *layers;
1026
1027   PSDInfo
1028     info;
1029
1030   register ssize_t
1031     i;
1032
1033   if (GetImageListLength(image) != 1)
1034     return;
1035   if ((image_info->number_scenes == 1) && (image_info->scene == 0))
1036     return;
1037   option=GetImageOption(image_info,"tiff:ignore-layers");
1038   if (option != (const char * ) NULL)
1039     return;
1040   layer_info=GetImageProfile(image,"tiff:37724");
1041   if (layer_info == (const StringInfo *) NULL)
1042     return;
1043   for (i=0; i < (ssize_t) layer_info->length-8; i++)
1044   {
1045     if (LocaleNCompare((const char *) (layer_info->datum+i),
1046         image->endian == MSBEndian ? "8BIM" : "MIB8",4) != 0)
1047       continue;
1048     i+=4;
1049     if ((LocaleNCompare((const char *) (layer_info->datum+i),
1050          image->endian == MSBEndian ? "Layr" : "ryaL",4) == 0) ||
1051         (LocaleNCompare((const char *) (layer_info->datum+i),
1052          image->endian == MSBEndian ? "LMsk" : "ksML",4) == 0) ||
1053         (LocaleNCompare((const char *) (layer_info->datum+i),
1054          image->endian == MSBEndian ? "Lr16" : "61rL",4) == 0) ||
1055         (LocaleNCompare((const char *) (layer_info->datum+i),
1056          image->endian == MSBEndian ? "Lr32" : "23rL",4) == 0))
1057       break;
1058   }
1059   i+=4;
1060   if (i >= (ssize_t) (layer_info->length-8))
1061     return;
1062   layers=CloneImage(image,image->columns,image->rows,MagickTrue,exception);
1063   (void) DeleteImageProfile(layers,"tiff:37724");
1064   AttachBlob(layers->blob,layer_info->datum,layer_info->length);
1065   SeekBlob(layers,(MagickOffsetType) i,SEEK_SET);
1066   info.version=1;
1067   info.columns=layers->columns;
1068   info.rows=layers->rows;
1069   info.channels=(unsigned short) layers->number_channels;
1070   /* Setting the mode to a value that won't change the colorspace */
1071   info.mode=10;
1072   ReadPSDLayers(layers,image_info,&info,MagickFalse,exception);
1073   DeleteImageFromList(&layers);
1074   if (layers != (Image *) NULL)
1075     {
1076       SetImageArtifact(image,"tiff:has-layers","true");
1077       AppendImageToList(&image,layers);
1078       while (layers != (Image *) NULL)
1079       {
1080         SetImageArtifact(layers,"tiff:has-layers","true");
1081         DetachBlob(layers->blob);
1082         layers=GetNextImageInList(layers);
1083       }
1084     }
1085 }
1086
1087 #if defined(__cplusplus) || defined(c_plusplus)
1088 }
1089 #endif
1090
1091 static Image *ReadTIFFImage(const ImageInfo *image_info,
1092   ExceptionInfo *exception)
1093 {
1094   const char
1095     *option;
1096
1097   float
1098     *chromaticity,
1099     x_position,
1100     y_position,
1101     x_resolution,
1102     y_resolution;
1103
1104   Image
1105     *image;
1106
1107   int
1108     tiff_status;
1109
1110   MagickBooleanType
1111     status;
1112
1113   MagickSizeType
1114     number_pixels;
1115
1116   QuantumInfo
1117     *quantum_info;
1118
1119   QuantumType
1120     quantum_type;
1121
1122   register ssize_t
1123     i;
1124
1125   size_t
1126     pad;
1127
1128   ssize_t
1129     y;
1130
1131   TIFF
1132     *tiff;
1133
1134   TIFFMethodType
1135     method;
1136
1137   uint16
1138     compress_tag,
1139     bits_per_sample,
1140     endian,
1141     extra_samples,
1142     interlace,
1143     max_sample_value,
1144     min_sample_value,
1145     orientation,
1146     pages,
1147     photometric,
1148     *sample_info,
1149     sample_format,
1150     samples_per_pixel,
1151     units,
1152     value;
1153
1154   uint32
1155     height,
1156     rows_per_strip,
1157     width;
1158
1159   unsigned char
1160     *tiff_pixels;
1161
1162   /*
1163     Open image.
1164   */
1165   assert(image_info != (const ImageInfo *) NULL);
1166   assert(image_info->signature == MagickCoreSignature);
1167   if (image_info->debug != MagickFalse)
1168     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
1169       image_info->filename);
1170   assert(exception != (ExceptionInfo *) NULL);
1171   assert(exception->signature == MagickCoreSignature);
1172   image=AcquireImage(image_info,exception);
1173   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
1174   if (status == MagickFalse)
1175     {
1176       image=DestroyImageList(image);
1177       return((Image *) NULL);
1178     }
1179   (void) SetMagickThreadValue(tiff_exception,exception);
1180   tiff=TIFFClientOpen(image->filename,"rb",(thandle_t) image,TIFFReadBlob,
1181     TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
1182     TIFFUnmapBlob);
1183   if (tiff == (TIFF *) NULL)
1184     {
1185       image=DestroyImageList(image);
1186       return((Image *) NULL);
1187     }
1188   if (image_info->number_scenes != 0)
1189     {
1190       /*
1191         Generate blank images for subimage specification (e.g. image.tif[4].
1192         We need to check the number of directores because it is possible that
1193         the subimage(s) are stored in the photoshop profile.
1194       */
1195       if (image_info->scene < (size_t) TIFFNumberOfDirectories(tiff))
1196         {
1197           for (i=0; i < (ssize_t) image_info->scene; i++)
1198           {
1199             status=TIFFReadDirectory(tiff) != 0 ? MagickTrue : MagickFalse;
1200             if (status == MagickFalse)
1201               {
1202                 TIFFClose(tiff);
1203                 image=DestroyImageList(image);
1204                 return((Image *) NULL);
1205               }
1206             AcquireNextImage(image_info,image,exception);
1207             if (GetNextImageInList(image) == (Image *) NULL)
1208               {
1209                 TIFFClose(tiff);
1210                 image=DestroyImageList(image);
1211                 return((Image *) NULL);
1212               }
1213             image=SyncNextImageInList(image);
1214           }
1215       }
1216   }
1217   do
1218   {
1219 DisableMSCWarning(4127)
1220     if (0 && (image_info->verbose != MagickFalse))
1221       TIFFPrintDirectory(tiff,stdout,MagickFalse);
1222 RestoreMSCWarning
1223     if ((TIFFGetField(tiff,TIFFTAG_IMAGEWIDTH,&width) != 1) ||
1224         (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&height) != 1) ||
1225         (TIFFGetFieldDefaulted(tiff,TIFFTAG_COMPRESSION,&compress_tag) != 1) ||
1226         (TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian) != 1) ||
1227         (TIFFGetFieldDefaulted(tiff,TIFFTAG_PLANARCONFIG,&interlace) != 1) ||
1228         (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,&samples_per_pixel) != 1) ||
1229         (TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,&bits_per_sample) != 1) ||
1230         (TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLEFORMAT,&sample_format) != 1) ||
1231         (TIFFGetFieldDefaulted(tiff,TIFFTAG_MINSAMPLEVALUE,&min_sample_value) != 1) ||
1232         (TIFFGetFieldDefaulted(tiff,TIFFTAG_MAXSAMPLEVALUE,&max_sample_value) != 1) ||
1233         (TIFFGetFieldDefaulted(tiff,TIFFTAG_PHOTOMETRIC,&photometric) != 1))
1234       {
1235         TIFFClose(tiff);
1236         ThrowReaderException(CorruptImageError,"ImproperImageHeader");
1237       }
1238     if (sample_format == SAMPLEFORMAT_IEEEFP)
1239       (void) SetImageProperty(image,"quantum:format","floating-point",
1240         exception);
1241     switch (photometric)
1242     {
1243       case PHOTOMETRIC_MINISBLACK:
1244       {
1245         (void) SetImageProperty(image,"tiff:photometric","min-is-black",
1246           exception);
1247         break;
1248       }
1249       case PHOTOMETRIC_MINISWHITE:
1250       {
1251         (void) SetImageProperty(image,"tiff:photometric","min-is-white",
1252           exception);
1253         break;
1254       }
1255       case PHOTOMETRIC_PALETTE:
1256       {
1257         (void) SetImageProperty(image,"tiff:photometric","palette",exception);
1258         break;
1259       }
1260       case PHOTOMETRIC_RGB:
1261       {
1262         (void) SetImageProperty(image,"tiff:photometric","RGB",exception);
1263         break;
1264       }
1265       case PHOTOMETRIC_CIELAB:
1266       {
1267         (void) SetImageProperty(image,"tiff:photometric","CIELAB",exception);
1268         break;
1269       }
1270       case PHOTOMETRIC_LOGL:
1271       {
1272         (void) SetImageProperty(image,"tiff:photometric","CIE Log2(L)",
1273           exception);
1274         break;
1275       }
1276       case PHOTOMETRIC_LOGLUV:
1277       {
1278         (void) SetImageProperty(image,"tiff:photometric","LOGLUV",exception);
1279         break;
1280       }
1281 #if defined(PHOTOMETRIC_MASK)
1282       case PHOTOMETRIC_MASK:
1283       {
1284         (void) SetImageProperty(image,"tiff:photometric","MASK",exception);
1285         break;
1286       }
1287 #endif
1288       case PHOTOMETRIC_SEPARATED:
1289       {
1290         (void) SetImageProperty(image,"tiff:photometric","separated",exception);
1291         break;
1292       }
1293       case PHOTOMETRIC_YCBCR:
1294       {
1295         (void) SetImageProperty(image,"tiff:photometric","YCBCR",exception);
1296         break;
1297       }
1298       default:
1299       {
1300         (void) SetImageProperty(image,"tiff:photometric","unknown",exception);
1301         break;
1302       }
1303     }
1304     if (image->debug != MagickFalse)
1305       {
1306         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Geometry: %ux%u",
1307           (unsigned int) width,(unsigned int) height);
1308         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Interlace: %u",
1309           interlace);
1310         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1311           "Bits per sample: %u",bits_per_sample);
1312         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1313           "Min sample value: %u",min_sample_value);
1314         (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1315           "Max sample value: %u",max_sample_value);
1316         (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Photometric "
1317           "interpretation: %s",GetImageProperty(image,"tiff:photometric",
1318           exception));
1319       }
1320     image->columns=(size_t) width;
1321     image->rows=(size_t) height;
1322     image->depth=(size_t) bits_per_sample;
1323     if (image->debug != MagickFalse)
1324       (void) LogMagickEvent(CoderEvent,GetMagickModule(),"Image depth: %.20g",
1325         (double) image->depth);
1326     image->endian=MSBEndian;
1327     if (endian == FILLORDER_LSB2MSB)
1328       image->endian=LSBEndian;
1329 #if defined(MAGICKCORE_HAVE_TIFFISBIGENDIAN)
1330     if (TIFFIsBigEndian(tiff) == 0)
1331       {
1332         (void) SetImageProperty(image,"tiff:endian","lsb",exception);
1333         image->endian=LSBEndian;
1334       }
1335     else
1336       {
1337         (void) SetImageProperty(image,"tiff:endian","msb",exception);
1338         image->endian=MSBEndian;
1339       }
1340 #endif
1341     if ((photometric == PHOTOMETRIC_MINISBLACK) ||
1342         (photometric == PHOTOMETRIC_MINISWHITE))
1343       SetImageColorspace(image,GRAYColorspace,exception);
1344     if (photometric == PHOTOMETRIC_SEPARATED)
1345       SetImageColorspace(image,CMYKColorspace,exception);
1346     if (photometric == PHOTOMETRIC_CIELAB)
1347       SetImageColorspace(image,LabColorspace,exception);
1348     TIFFGetProfiles(tiff,image,image_info->ping,exception);
1349     TIFFGetProperties(tiff,image,exception);
1350     option=GetImageOption(image_info,"tiff:exif-properties");
1351     if (IsStringFalse(option) == MagickFalse) /* enabled by default */
1352       TIFFGetEXIFProperties(tiff,image,exception);
1353     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
1354       &samples_per_pixel);
1355     if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XRESOLUTION,&x_resolution) == 1) &&
1356         (TIFFGetFieldDefaulted(tiff,TIFFTAG_YRESOLUTION,&y_resolution) == 1))
1357       {
1358         image->resolution.x=x_resolution;
1359         image->resolution.y=y_resolution;
1360       }
1361     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_RESOLUTIONUNIT,&units) == 1)
1362       {
1363         if (units == RESUNIT_INCH)
1364           image->units=PixelsPerInchResolution;
1365         if (units == RESUNIT_CENTIMETER)
1366           image->units=PixelsPerCentimeterResolution;
1367       }
1368     if ((TIFFGetFieldDefaulted(tiff,TIFFTAG_XPOSITION,&x_position) == 1) &&
1369         (TIFFGetFieldDefaulted(tiff,TIFFTAG_YPOSITION,&y_position) == 1))
1370       {
1371         image->page.x=(ssize_t) ceil(x_position*image->resolution.x-0.5);
1372         image->page.y=(ssize_t) ceil(y_position*image->resolution.y-0.5);
1373       }
1374     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_ORIENTATION,&orientation) == 1)
1375       image->orientation=(OrientationType) orientation;
1376     if (TIFFGetField(tiff,TIFFTAG_WHITEPOINT,&chromaticity) == 1)
1377       {
1378         if (chromaticity != (float *) NULL)
1379           {
1380             image->chromaticity.white_point.x=chromaticity[0];
1381             image->chromaticity.white_point.y=chromaticity[1];
1382           }
1383       }
1384     if (TIFFGetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,&chromaticity) == 1)
1385       {
1386         if (chromaticity != (float *) NULL)
1387           {
1388             image->chromaticity.red_primary.x=chromaticity[0];
1389             image->chromaticity.red_primary.y=chromaticity[1];
1390             image->chromaticity.green_primary.x=chromaticity[2];
1391             image->chromaticity.green_primary.y=chromaticity[3];
1392             image->chromaticity.blue_primary.x=chromaticity[4];
1393             image->chromaticity.blue_primary.y=chromaticity[5];
1394           }
1395       }
1396 #if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
1397     if ((compress_tag != COMPRESSION_NONE) &&
1398         (TIFFIsCODECConfigured(compress_tag) == 0))
1399       {
1400         TIFFClose(tiff);
1401         ThrowReaderException(CoderError,"CompressNotSupported");
1402       }
1403 #endif
1404     switch (compress_tag)
1405     {
1406       case COMPRESSION_NONE: image->compression=NoCompression; break;
1407       case COMPRESSION_CCITTFAX3: image->compression=FaxCompression; break;
1408       case COMPRESSION_CCITTFAX4: image->compression=Group4Compression; break;
1409       case COMPRESSION_JPEG:
1410       {
1411          image->compression=JPEGCompression;
1412 #if defined(JPEG_SUPPORT)
1413          {
1414            char
1415              sampling_factor[MagickPathExtent];
1416
1417            int
1418              tiff_status;
1419
1420            uint16
1421              horizontal,
1422              vertical;
1423
1424            tiff_status=TIFFGetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,&horizontal,
1425              &vertical);
1426            if (tiff_status == 1)
1427              {
1428                (void) FormatLocaleString(sampling_factor,MagickPathExtent,
1429                  "%dx%d",horizontal,vertical);
1430                (void) SetImageProperty(image,"jpeg:sampling-factor",
1431                  sampling_factor,exception);
1432                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
1433                  "Sampling Factors: %s",sampling_factor);
1434              }
1435          }
1436 #endif
1437         break;
1438       }
1439       case COMPRESSION_OJPEG: image->compression=JPEGCompression; break;
1440 #if defined(COMPRESSION_LZMA)
1441       case COMPRESSION_LZMA: image->compression=LZMACompression; break;
1442 #endif
1443       case COMPRESSION_LZW: image->compression=LZWCompression; break;
1444       case COMPRESSION_DEFLATE: image->compression=ZipCompression; break;
1445       case COMPRESSION_ADOBE_DEFLATE: image->compression=ZipCompression; break;
1446       default: image->compression=RLECompression; break;
1447     }
1448     quantum_info=(QuantumInfo *) NULL;
1449     if ((photometric == PHOTOMETRIC_PALETTE) &&
1450         (pow(2.0,1.0*bits_per_sample) <= MaxColormapSize))
1451       {
1452         size_t
1453           colors;
1454
1455         colors=(size_t) GetQuantumRange(bits_per_sample)+1;
1456         if (AcquireImageColormap(image,colors,exception) == MagickFalse)
1457           {
1458             TIFFClose(tiff);
1459             ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1460           }
1461       }
1462     value=(unsigned short) image->scene;
1463     if (TIFFGetFieldDefaulted(tiff,TIFFTAG_PAGENUMBER,&value,&pages) == 1)
1464       image->scene=value;
1465     if (image->storage_class == PseudoClass)
1466       {
1467         int
1468           tiff_status;
1469
1470         size_t
1471           range;
1472
1473         uint16
1474           *blue_colormap,
1475           *green_colormap,
1476           *red_colormap;
1477
1478         /*
1479           Initialize colormap.
1480         */
1481         tiff_status=TIFFGetField(tiff,TIFFTAG_COLORMAP,&red_colormap,
1482           &green_colormap,&blue_colormap);
1483         if (tiff_status == 1)
1484           {
1485             if ((red_colormap != (uint16 *) NULL) &&
1486                 (green_colormap != (uint16 *) NULL) &&
1487                 (blue_colormap != (uint16 *) NULL))
1488               {
1489                 range=255;  /* might be old style 8-bit colormap */
1490                 for (i=0; i < (ssize_t) image->colors; i++)
1491                   if ((red_colormap[i] >= 256) || (green_colormap[i] >= 256) ||
1492                       (blue_colormap[i] >= 256))
1493                     {
1494                       range=65535;
1495                       break;
1496                     }
1497                 for (i=0; i < (ssize_t) image->colors; i++)
1498                 {
1499                   image->colormap[i].red=ClampToQuantum(((double)
1500                     QuantumRange*red_colormap[i])/range);
1501                   image->colormap[i].green=ClampToQuantum(((double)
1502                     QuantumRange*green_colormap[i])/range);
1503                   image->colormap[i].blue=ClampToQuantum(((double)
1504                     QuantumRange*blue_colormap[i])/range);
1505                 }
1506               }
1507           }
1508       }
1509     if (image_info->ping != MagickFalse)
1510       {
1511         if (image_info->number_scenes != 0)
1512           if (image->scene >= (image_info->scene+image_info->number_scenes-1))
1513             break;
1514         goto next_tiff_frame;
1515       }
1516     status=SetImageExtent(image,image->columns,image->rows,exception);
1517     if (status == MagickFalse)
1518       return(DestroyImageList(image));
1519     /*
1520       Allocate memory for the image and pixel buffer.
1521     */
1522     quantum_info=AcquireQuantumInfo(image_info,image);
1523     if (quantum_info == (QuantumInfo *) NULL)
1524       {
1525         TIFFClose(tiff);
1526         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1527       }
1528     if (sample_format == SAMPLEFORMAT_UINT)
1529       status=SetQuantumFormat(image,quantum_info,UnsignedQuantumFormat);
1530     if (sample_format == SAMPLEFORMAT_INT)
1531       status=SetQuantumFormat(image,quantum_info,SignedQuantumFormat);
1532     if (sample_format == SAMPLEFORMAT_IEEEFP)
1533       status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
1534     if (status == MagickFalse)
1535       {
1536         TIFFClose(tiff);
1537         quantum_info=DestroyQuantumInfo(quantum_info);
1538         ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed");
1539       }
1540     status=MagickTrue;
1541     switch (photometric)
1542     {
1543       case PHOTOMETRIC_MINISBLACK:
1544       {
1545         quantum_info->min_is_white=MagickFalse;
1546         break;
1547       }
1548       case PHOTOMETRIC_MINISWHITE:
1549       {
1550         quantum_info->min_is_white=MagickTrue;
1551         break;
1552       }
1553       default:
1554         break;
1555     }
1556     tiff_status=TIFFGetFieldDefaulted(tiff,TIFFTAG_EXTRASAMPLES,&extra_samples,
1557       &sample_info);
1558     if (tiff_status == 1)
1559       {
1560         (void) SetImageProperty(image,"tiff:alpha","unspecified",exception);
1561         if (extra_samples == 0)
1562           {
1563             if ((samples_per_pixel == 4) && (photometric == PHOTOMETRIC_RGB))
1564               image->alpha_trait=BlendPixelTrait;
1565           }
1566         else
1567           for (i=0; i < extra_samples; i++)
1568           {
1569             image->alpha_trait=BlendPixelTrait;
1570             if (sample_info[i] == EXTRASAMPLE_ASSOCALPHA)
1571               {
1572                 SetQuantumAlphaType(quantum_info,DisassociatedQuantumAlpha);
1573                 (void) SetImageProperty(image,"tiff:alpha","associated",
1574                   exception);
1575               }
1576             else
1577               if (sample_info[i] == EXTRASAMPLE_UNASSALPHA)
1578                 (void) SetImageProperty(image,"tiff:alpha","unassociated",
1579                   exception);
1580           }
1581       }
1582     method=ReadGenericMethod;
1583     if (TIFFGetField(tiff,TIFFTAG_ROWSPERSTRIP,&rows_per_strip) == 1)
1584       {
1585         char
1586           value[MagickPathExtent];
1587
1588         method=ReadStripMethod;
1589         (void) FormatLocaleString(value,MagickPathExtent,"%u",
1590           (unsigned int) rows_per_strip);
1591         (void) SetImageProperty(image,"tiff:rows-per-strip",value,exception);
1592       }
1593     if ((samples_per_pixel >= 3) && (interlace == PLANARCONFIG_CONTIG))
1594       method=ReadRGBAMethod;
1595     if ((samples_per_pixel >= 4) && (interlace == PLANARCONFIG_SEPARATE))
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),(size_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   images=GetFirstImageInList(images);
2678   /*
2679     Write pyramid-encoded TIFF image.
2680   */
2681   write_info=CloneImageInfo(image_info);
2682   write_info->adjoin=MagickTrue;
2683   (void) CopyMagickString(write_info->magick,"TIFF",MagickPathExtent);
2684   (void) CopyMagickString(images->magick,"TIFF",MagickPathExtent);
2685   status=WriteTIFFImage(write_info,images,exception);
2686   images=DestroyImageList(images);
2687   write_info=DestroyImageInfo(write_info);
2688   return(status);
2689 }
2690 #endif
2691 \f
2692 #if defined(MAGICKCORE_TIFF_DELEGATE)
2693 /*
2694 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2695 %                                                                             %
2696 %                                                                             %
2697 %   W r i t e T I F F I m a g e                                               %
2698 %                                                                             %
2699 %                                                                             %
2700 %                                                                             %
2701 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2702 %
2703 %  WriteTIFFImage() writes an image in the Tagged image file format.
2704 %
2705 %  The format of the WriteTIFFImage method is:
2706 %
2707 %      MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
2708 %        Image *image,ExceptionInfo *exception)
2709 %
2710 %  A description of each parameter follows:
2711 %
2712 %    o image_info: the image info.
2713 %
2714 %    o image:  The image.
2715 %
2716 %    o exception: return any errors or warnings in this structure.
2717 %
2718 */
2719
2720 typedef struct _TIFFInfo
2721 {
2722   RectangleInfo
2723     tile_geometry;
2724
2725   unsigned char
2726     *scanline,
2727     *scanlines,
2728     *pixels;
2729 } TIFFInfo;
2730
2731 static void DestroyTIFFInfo(TIFFInfo *tiff_info)
2732 {
2733   assert(tiff_info != (TIFFInfo *) NULL);
2734   if (tiff_info->scanlines != (unsigned char *) NULL)
2735     tiff_info->scanlines=(unsigned char *) RelinquishMagickMemory(
2736       tiff_info->scanlines);
2737   if (tiff_info->pixels != (unsigned char *) NULL)
2738     tiff_info->pixels=(unsigned char *) RelinquishMagickMemory(
2739       tiff_info->pixels);
2740 }
2741
2742 static MagickBooleanType EncodeLabImage(Image *image,ExceptionInfo *exception)
2743 {
2744   CacheView
2745     *image_view;
2746
2747   MagickBooleanType
2748     status;
2749
2750   ssize_t
2751     y;
2752
2753   status=MagickTrue;
2754   image_view=AcquireAuthenticCacheView(image,exception);
2755   for (y=0; y < (ssize_t) image->rows; y++)
2756   {
2757     register Quantum
2758       *magick_restrict q;
2759
2760     register ssize_t
2761       x;
2762
2763     if (status == MagickFalse)
2764       continue;
2765     q=GetCacheViewAuthenticPixels(image_view,0,y,image->columns,1,exception);
2766     if (q == (Quantum *) NULL)
2767       {
2768         status=MagickFalse;
2769         continue;
2770       }
2771     for (x=0; x < (ssize_t) image->columns; x++)
2772     {
2773       double
2774         a,
2775         b;
2776
2777       a=QuantumScale*GetPixela(image,q)-0.5;
2778       if (a < 0.0)
2779         a+=1.0;
2780       b=QuantumScale*GetPixelb(image,q)-0.5;
2781       if (b < 0.0)
2782         b+=1.0;
2783       SetPixela(image,QuantumRange*a,q);
2784       SetPixelb(image,QuantumRange*b,q);
2785       q+=GetPixelChannels(image);
2786     }
2787     if (SyncCacheViewAuthenticPixels(image_view,exception) == MagickFalse)
2788       status=MagickFalse;
2789   }
2790   image_view=DestroyCacheView(image_view);
2791   return(status);
2792 }
2793
2794 static MagickBooleanType GetTIFFInfo(const ImageInfo *image_info,
2795   TIFF *tiff,TIFFInfo *tiff_info)
2796 {
2797   const char
2798     *option;
2799
2800   MagickStatusType
2801     flags;
2802
2803   uint32
2804     tile_columns,
2805     tile_rows;
2806
2807   assert(tiff_info != (TIFFInfo *) NULL);
2808   (void) ResetMagickMemory(tiff_info,0,sizeof(*tiff_info));
2809   option=GetImageOption(image_info,"tiff:tile-geometry");
2810   if (option == (const char *) NULL)
2811     {
2812       uint32
2813         rows_per_strip;
2814
2815       option=GetImageOption(image_info,"tiff:rows-per-strip");
2816       if (option != (const char *) NULL)
2817         rows_per_strip=(size_t) strtol(option,(char **) NULL,10);
2818       else
2819         if (TIFFGetField(tiff,TIFFTAG_IMAGELENGTH,&rows_per_strip) == 0)
2820           rows_per_strip=0;  /* use default */
2821       rows_per_strip=TIFFDefaultStripSize(tiff,rows_per_strip);
2822       (void) TIFFSetField(tiff,TIFFTAG_ROWSPERSTRIP,rows_per_strip);
2823       return(MagickTrue);
2824     }
2825   /*
2826     Create tiled TIFF, ignore "tiff:rows-per-strip".
2827   */
2828   flags=ParseAbsoluteGeometry(option,&tiff_info->tile_geometry);
2829   if ((flags & HeightValue) == 0)
2830     tiff_info->tile_geometry.height=tiff_info->tile_geometry.width;
2831   tile_columns=(uint32) tiff_info->tile_geometry.width;
2832   tile_rows=(uint32) tiff_info->tile_geometry.height;
2833   TIFFDefaultTileSize(tiff,&tile_columns,&tile_rows);
2834   (void) TIFFSetField(tiff,TIFFTAG_TILEWIDTH,tile_columns);
2835   (void) TIFFSetField(tiff,TIFFTAG_TILELENGTH,tile_rows);
2836   tiff_info->tile_geometry.width=tile_columns;
2837   tiff_info->tile_geometry.height=tile_rows;
2838   tiff_info->scanlines=(unsigned char *) AcquireQuantumMemory((size_t)
2839     tile_rows*TIFFScanlineSize(tiff),sizeof(*tiff_info->scanlines));
2840   tiff_info->pixels=(unsigned char *) AcquireQuantumMemory((size_t)
2841     tile_rows*TIFFTileSize(tiff),sizeof(*tiff_info->scanlines));
2842   if ((tiff_info->scanlines == (unsigned char *) NULL) ||
2843       (tiff_info->pixels == (unsigned char *) NULL))
2844     {
2845       DestroyTIFFInfo(tiff_info);
2846       return(MagickFalse);
2847     }
2848   return(MagickTrue);
2849 }
2850
2851 static int32 TIFFWritePixels(TIFF *tiff,TIFFInfo *tiff_info,ssize_t row,
2852   tsample_t sample,Image *image)
2853 {
2854   int32
2855     status;
2856
2857   register ssize_t
2858     i;
2859
2860   register unsigned char
2861     *p,
2862     *q;
2863
2864   size_t
2865     number_tiles,
2866     tile_width;
2867
2868   ssize_t
2869     bytes_per_pixel,
2870     j,
2871     k,
2872     l;
2873
2874   if (TIFFIsTiled(tiff) == 0)
2875     return(TIFFWriteScanline(tiff,tiff_info->scanline,(uint32) row,sample));
2876   /*
2877     Fill scanlines to tile height.
2878   */
2879   i=(ssize_t) (row % tiff_info->tile_geometry.height)*TIFFScanlineSize(tiff);
2880   (void) CopyMagickMemory(tiff_info->scanlines+i,(char *) tiff_info->scanline,
2881     (size_t) TIFFScanlineSize(tiff));
2882   if (((size_t) (row % tiff_info->tile_geometry.height) !=
2883       (tiff_info->tile_geometry.height-1)) &&
2884       (row != (ssize_t) (image->rows-1)))
2885     return(0);
2886   /*
2887     Write tile to TIFF image.
2888   */
2889   status=0;
2890   bytes_per_pixel=TIFFTileSize(tiff)/(ssize_t) (
2891     tiff_info->tile_geometry.height*tiff_info->tile_geometry.width);
2892   number_tiles=(image->columns+tiff_info->tile_geometry.width)/
2893     tiff_info->tile_geometry.width;
2894   for (i=0; i < (ssize_t) number_tiles; i++)
2895   {
2896     tile_width=(i == (ssize_t) (number_tiles-1)) ? image->columns-(i*
2897       tiff_info->tile_geometry.width) : tiff_info->tile_geometry.width;
2898     for (j=0; j < (ssize_t) ((row % tiff_info->tile_geometry.height)+1); j++)
2899       for (k=0; k < (ssize_t) tile_width; k++)
2900       {
2901         if (bytes_per_pixel == 0)
2902           {
2903             p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
2904               tiff_info->tile_geometry.width+k)/8);
2905             q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k/8);
2906             *q++=(*p++);
2907             continue;
2908           }
2909         p=tiff_info->scanlines+(j*TIFFScanlineSize(tiff)+(i*
2910           tiff_info->tile_geometry.width+k)*bytes_per_pixel);
2911         q=tiff_info->pixels+(j*TIFFTileRowSize(tiff)+k*bytes_per_pixel);
2912         for (l=0; l < bytes_per_pixel; l++)
2913           *q++=(*p++);
2914       }
2915     if ((i*tiff_info->tile_geometry.width) != image->columns)
2916       status=TIFFWriteTile(tiff,tiff_info->pixels,(uint32) (i*
2917         tiff_info->tile_geometry.width),(uint32) ((row/
2918         tiff_info->tile_geometry.height)*tiff_info->tile_geometry.height),0,
2919         sample);
2920     if (status < 0)
2921       break;
2922   }
2923   return(status);
2924 }
2925
2926 static void TIFFSetProfiles(TIFF *tiff,Image *image)
2927 {
2928   const char
2929     *name;
2930
2931   const StringInfo
2932     *profile;
2933
2934   if (image->profiles == (void *) NULL)
2935     return;
2936   ResetImageProfileIterator(image);
2937   for (name=GetNextImageProfile(image); name != (const char *) NULL; )
2938   {
2939     profile=GetImageProfile(image,name);
2940     if (GetStringInfoLength(profile) == 0)
2941       {
2942         name=GetNextImageProfile(image);
2943         continue;
2944       }
2945 #if defined(TIFFTAG_XMLPACKET)
2946     if (LocaleCompare(name,"xmp") == 0)
2947       (void) TIFFSetField(tiff,TIFFTAG_XMLPACKET,(uint32) GetStringInfoLength(
2948         profile),GetStringInfoDatum(profile));
2949 #endif
2950 #if defined(TIFFTAG_ICCPROFILE)
2951     if (LocaleCompare(name,"icc") == 0)
2952       (void) TIFFSetField(tiff,TIFFTAG_ICCPROFILE,(uint32) GetStringInfoLength(
2953         profile),GetStringInfoDatum(profile));
2954 #endif
2955     if (LocaleCompare(name,"iptc") == 0)
2956       {
2957         size_t
2958           length;
2959
2960         StringInfo
2961           *iptc_profile;
2962
2963         iptc_profile=CloneStringInfo(profile);
2964         length=GetStringInfoLength(profile)+4-(GetStringInfoLength(profile) &
2965           0x03);
2966         SetStringInfoLength(iptc_profile,length);
2967         if (TIFFIsByteSwapped(tiff))
2968           TIFFSwabArrayOfLong((uint32 *) GetStringInfoDatum(iptc_profile),
2969             (unsigned long) (length/4));
2970         (void) TIFFSetField(tiff,TIFFTAG_RICHTIFFIPTC,(uint32)
2971           GetStringInfoLength(iptc_profile)/4,GetStringInfoDatum(iptc_profile));
2972         iptc_profile=DestroyStringInfo(iptc_profile);
2973       }
2974 #if defined(TIFFTAG_PHOTOSHOP)
2975     if (LocaleCompare(name,"8bim") == 0)
2976       (void) TIFFSetField(tiff,TIFFTAG_PHOTOSHOP,(uint32)
2977         GetStringInfoLength(profile),GetStringInfoDatum(profile));
2978 #endif
2979     if (LocaleCompare(name,"tiff:37724") == 0)
2980       (void) TIFFSetField(tiff,37724,(uint32) GetStringInfoLength(profile),
2981         GetStringInfoDatum(profile));
2982     if (LocaleCompare(name,"tiff:34118") == 0)
2983       (void) TIFFSetField(tiff,34118,(uint32) GetStringInfoLength(profile),
2984         GetStringInfoDatum(profile));
2985     name=GetNextImageProfile(image);
2986   }
2987 }
2988
2989 static void TIFFSetProperties(TIFF *tiff,const ImageInfo *image_info,
2990   Image *image,ExceptionInfo *exception)
2991 {
2992   const char
2993     *value;
2994
2995   value=GetImageArtifact(image,"tiff:document");
2996   if (value != (const char *) NULL)
2997     (void) TIFFSetField(tiff,TIFFTAG_DOCUMENTNAME,value);
2998   value=GetImageArtifact(image,"tiff:hostcomputer");
2999   if (value != (const char *) NULL)
3000     (void) TIFFSetField(tiff,TIFFTAG_HOSTCOMPUTER,value);
3001   value=GetImageArtifact(image,"tiff:artist");
3002   if (value != (const char *) NULL)
3003     (void) TIFFSetField(tiff,TIFFTAG_ARTIST,value);
3004   value=GetImageArtifact(image,"tiff:timestamp");
3005   if (value != (const char *) NULL)
3006     (void) TIFFSetField(tiff,TIFFTAG_DATETIME,value);
3007   value=GetImageArtifact(image,"tiff:make");
3008   if (value != (const char *) NULL)
3009     (void) TIFFSetField(tiff,TIFFTAG_MAKE,value);
3010   value=GetImageArtifact(image,"tiff:model");
3011   if (value != (const char *) NULL)
3012     (void) TIFFSetField(tiff,TIFFTAG_MODEL,value);
3013   value=GetImageArtifact(image,"tiff:software");
3014   if (value != (const char *) NULL)
3015     (void) TIFFSetField(tiff,TIFFTAG_SOFTWARE,value);
3016   value=GetImageArtifact(image,"tiff:copyright");
3017   if (value != (const char *) NULL)
3018     (void) TIFFSetField(tiff,TIFFTAG_COPYRIGHT,value);
3019   value=GetImageArtifact(image,"kodak-33423");
3020   if (value != (const char *) NULL)
3021     (void) TIFFSetField(tiff,33423,value);
3022   value=GetImageArtifact(image,"kodak-36867");
3023   if (value != (const char *) NULL)
3024     (void) TIFFSetField(tiff,36867,value);
3025   value=GetImageProperty(image,"label",exception);
3026   if (value != (const char *) NULL)
3027     (void) TIFFSetField(tiff,TIFFTAG_PAGENAME,value);
3028   value=GetImageProperty(image,"comment",exception);
3029   if (value != (const char *) NULL)
3030     (void) TIFFSetField(tiff,TIFFTAG_IMAGEDESCRIPTION,value);
3031   value=GetImageArtifact(image,"tiff:subfiletype");
3032   if (value != (const char *) NULL)
3033     {
3034       if (LocaleCompare(value,"REDUCEDIMAGE") == 0)
3035         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
3036       else
3037         if (LocaleCompare(value,"PAGE") == 0)
3038           (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3039         else
3040           if (LocaleCompare(value,"MASK") == 0)
3041             (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_MASK);
3042     }
3043   else
3044     {
3045       uint16
3046         page,
3047         pages;
3048
3049       page=(uint16) image->scene;
3050       pages=(uint16) GetImageListLength(image);
3051       if ((image_info->adjoin != MagickFalse) && (pages > 1))
3052         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3053       (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
3054     }
3055 }
3056
3057 static void TIFFSetEXIFProperties(TIFF *tiff,Image *image,
3058   ExceptionInfo *exception)
3059 {
3060 #if defined(MAGICKCORE_HAVE_TIFFREADEXIFDIRECTORY)
3061   const char
3062     *value;
3063
3064   register ssize_t
3065     i;
3066
3067   uint32
3068     offset;
3069
3070   /*
3071     Write EXIF properties.
3072   */
3073   offset=0;
3074   (void) TIFFSetField(tiff,TIFFTAG_SUBIFD,1,&offset);
3075   for (i=0; exif_info[i].tag != 0; i++)
3076   {
3077     value=GetImageProperty(image,exif_info[i].property,exception);
3078     if (value == (const char *) NULL)
3079       continue;
3080     switch (exif_info[i].type)
3081     {
3082       case TIFF_ASCII:
3083       {
3084         (void) TIFFSetField(tiff,exif_info[i].tag,value);
3085         break;
3086       }
3087       case TIFF_SHORT:
3088       {
3089         uint16
3090           field;
3091
3092         field=(uint16) StringToLong(value);
3093         (void) TIFFSetField(tiff,exif_info[i].tag,field);
3094         break;
3095       }
3096       case TIFF_LONG:
3097       {
3098         uint16
3099           field;
3100
3101         field=(uint16) StringToLong(value);
3102         (void) TIFFSetField(tiff,exif_info[i].tag,field);
3103         break;
3104       }
3105       case TIFF_RATIONAL:
3106       case TIFF_SRATIONAL:
3107       {
3108         float
3109           field;
3110
3111         field=StringToDouble(value,(char **) NULL);
3112         (void) TIFFSetField(tiff,exif_info[i].tag,field);
3113         break;
3114       }
3115       default:
3116         break;
3117     }
3118   }
3119   /* (void) TIFFSetField(tiff,TIFFTAG_EXIFIFD,offset); */
3120 #else
3121   (void) tiff;
3122   (void) image;
3123 #endif
3124 }
3125
3126 static MagickBooleanType WriteTIFFImage(const ImageInfo *image_info,
3127   Image *image,ExceptionInfo *exception)
3128 {
3129   const char
3130     *mode,
3131     *option;
3132
3133   CompressionType
3134     compression;
3135
3136   EndianType
3137     endian_type;
3138
3139   MagickBooleanType
3140     debug,
3141     status;
3142
3143   MagickOffsetType
3144     scene;
3145
3146   QuantumInfo
3147     *quantum_info;
3148
3149   QuantumType
3150     quantum_type;
3151
3152   register ssize_t
3153     i;
3154
3155   size_t
3156     length;
3157
3158   ssize_t
3159     y;
3160
3161   TIFF
3162     *tiff;
3163
3164   TIFFInfo
3165     tiff_info;
3166
3167   uint16
3168     bits_per_sample,
3169     compress_tag,
3170     endian,
3171     photometric;
3172
3173   unsigned char
3174     *pixels;
3175
3176   /*
3177     Open TIFF file.
3178   */
3179   assert(image_info != (const ImageInfo *) NULL);
3180   assert(image_info->signature == MagickCoreSignature);
3181   assert(image != (Image *) NULL);
3182   assert(image->signature == MagickCoreSignature);
3183   if (image->debug != MagickFalse)
3184     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
3185   assert(exception != (ExceptionInfo *) NULL);
3186   assert(exception->signature == MagickCoreSignature);
3187   status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
3188   if (status == MagickFalse)
3189     return(status);
3190   (void) SetMagickThreadValue(tiff_exception,exception);
3191   endian_type=UndefinedEndian;
3192   option=GetImageOption(image_info,"tiff:endian");
3193   if (option != (const char *) NULL)
3194     {
3195       if (LocaleNCompare(option,"msb",3) == 0)
3196         endian_type=MSBEndian;
3197       if (LocaleNCompare(option,"lsb",3) == 0)
3198         endian_type=LSBEndian;;
3199     }
3200   switch (endian_type)
3201   {
3202     case LSBEndian: mode="wl"; break;
3203     case MSBEndian: mode="wb"; break;
3204     default: mode="w"; break;
3205   }
3206 #if defined(TIFF_VERSION_BIG)
3207   if (LocaleCompare(image_info->magick,"TIFF64") == 0)
3208     switch (endian_type)
3209     {
3210       case LSBEndian: mode="wl8"; break;
3211       case MSBEndian: mode="wb8"; break;
3212       default: mode="w8"; break;
3213     }
3214 #endif
3215   tiff=TIFFClientOpen(image->filename,mode,(thandle_t) image,TIFFReadBlob,
3216     TIFFWriteBlob,TIFFSeekBlob,TIFFCloseBlob,TIFFGetBlobSize,TIFFMapBlob,
3217     TIFFUnmapBlob);
3218   if (tiff == (TIFF *) NULL)
3219     return(MagickFalse);
3220   scene=0;
3221   debug=IsEventLogging();
3222   (void) debug;
3223   do
3224   {
3225     /*
3226       Initialize TIFF fields.
3227     */
3228     if ((image_info->type != UndefinedType) &&
3229         (image_info->type != OptimizeType))
3230       (void) SetImageType(image,image_info->type,exception);
3231     compression=UndefinedCompression;
3232     if (image->compression != JPEGCompression)
3233       compression=image->compression;
3234     if (image_info->compression != UndefinedCompression)
3235       compression=image_info->compression;
3236     switch (compression)
3237     {
3238       case FaxCompression:
3239       case Group4Compression:
3240       {
3241         (void) SetImageType(image,BilevelType,exception);
3242         (void) SetImageDepth(image,1,exception);
3243         break;
3244       }
3245       case JPEGCompression:
3246       {
3247         (void) SetImageStorageClass(image,DirectClass,exception);
3248         (void) SetImageDepth(image,8,exception);
3249         break;
3250       }
3251       default:
3252         break;
3253     }
3254     quantum_info=AcquireQuantumInfo(image_info,image);
3255     if (quantum_info == (QuantumInfo *) NULL)
3256       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3257     if ((image->storage_class != PseudoClass) && (image->depth >= 32) &&
3258         (quantum_info->format == UndefinedQuantumFormat) &&
3259         (IsHighDynamicRangeImage(image,exception) != MagickFalse))
3260       {
3261         status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat);
3262         if (status == MagickFalse)
3263           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3264       }
3265     if ((LocaleCompare(image_info->magick,"PTIF") == 0) &&
3266         (GetPreviousImageInList(image) != (Image *) NULL))
3267       (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_REDUCEDIMAGE);
3268     if ((image->columns != (uint32) image->columns) ||
3269         (image->rows != (uint32) image->rows))
3270       ThrowWriterException(ImageError,"WidthOrHeightExceedsLimit");
3271     (void) TIFFSetField(tiff,TIFFTAG_IMAGELENGTH,(uint32) image->rows);
3272     (void) TIFFSetField(tiff,TIFFTAG_IMAGEWIDTH,(uint32) image->columns);
3273     switch (compression)
3274     {
3275       case FaxCompression:
3276       {
3277         compress_tag=COMPRESSION_CCITTFAX3;
3278         SetQuantumMinIsWhite(quantum_info,MagickTrue);
3279         break;
3280       }
3281       case Group4Compression:
3282       {
3283         compress_tag=COMPRESSION_CCITTFAX4;
3284         SetQuantumMinIsWhite(quantum_info,MagickTrue);
3285         break;
3286       }
3287 #if defined(COMPRESSION_JBIG)
3288       case JBIG1Compression:
3289       {
3290         compress_tag=COMPRESSION_JBIG;
3291         break;
3292       }
3293 #endif
3294       case JPEGCompression:
3295       {
3296         compress_tag=COMPRESSION_JPEG;
3297         break;
3298       }
3299 #if defined(COMPRESSION_LZMA)
3300       case LZMACompression:
3301       {
3302         compress_tag=COMPRESSION_LZMA;
3303         break;
3304       }
3305 #endif
3306       case LZWCompression:
3307       {
3308         compress_tag=COMPRESSION_LZW;
3309         break;
3310       }
3311       case RLECompression:
3312       {
3313         compress_tag=COMPRESSION_PACKBITS;
3314         break;
3315       }
3316       case ZipCompression:
3317       {
3318         compress_tag=COMPRESSION_ADOBE_DEFLATE;
3319         break;
3320       }
3321       case NoCompression:
3322       default:
3323       {
3324         compress_tag=COMPRESSION_NONE;
3325         break;
3326       }
3327     }
3328 #if defined(MAGICKCORE_HAVE_TIFFISCODECCONFIGURED) || (TIFFLIB_VERSION > 20040919)
3329     if ((compress_tag != COMPRESSION_NONE) &&
3330         (TIFFIsCODECConfigured(compress_tag) == 0))
3331       {
3332         (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
3333           "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
3334           MagickCompressOptions,(ssize_t) compression));
3335         compress_tag=COMPRESSION_NONE;
3336         compression=NoCompression;
3337       }
3338 #else
3339       switch (compress_tag)
3340       {
3341 #if defined(CCITT_SUPPORT)
3342         case COMPRESSION_CCITTFAX3:
3343         case COMPRESSION_CCITTFAX4:
3344 #endif
3345 #if defined(YCBCR_SUPPORT) && defined(JPEG_SUPPORT)
3346         case COMPRESSION_JPEG:
3347 #endif
3348 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
3349         case COMPRESSION_LZMA:
3350 #endif
3351 #if defined(LZW_SUPPORT)
3352         case COMPRESSION_LZW:
3353 #endif
3354 #if defined(PACKBITS_SUPPORT)
3355         case COMPRESSION_PACKBITS:
3356 #endif
3357 #if defined(ZIP_SUPPORT)
3358         case COMPRESSION_ADOBE_DEFLATE:
3359 #endif
3360         case COMPRESSION_NONE:
3361           break;
3362         default:
3363         {
3364           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
3365             "CompressionNotSupported","`%s'",CommandOptionToMnemonic(
3366               MagickCompressOptions,(ssize_t) compression));
3367           compress_tag=COMPRESSION_NONE;
3368           compression=NoCompression;
3369           break;
3370         }
3371       }
3372 #endif
3373     if (image->colorspace == CMYKColorspace)
3374       {
3375         photometric=PHOTOMETRIC_SEPARATED;
3376         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,4);
3377         (void) TIFFSetField(tiff,TIFFTAG_INKSET,INKSET_CMYK);
3378       }
3379     else
3380       {
3381         /*
3382           Full color TIFF raster.
3383         */
3384         if (image->colorspace == LabColorspace)
3385           {
3386             photometric=PHOTOMETRIC_CIELAB;
3387             EncodeLabImage(image,exception);
3388           }
3389         else
3390           if (image->colorspace == YCbCrColorspace)
3391             {
3392               photometric=PHOTOMETRIC_YCBCR;
3393               (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,1,1);
3394               (void) SetImageStorageClass(image,DirectClass,exception);
3395               (void) SetImageDepth(image,8,exception);
3396             }
3397           else
3398             photometric=PHOTOMETRIC_RGB;
3399         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,3);
3400         if ((image_info->type != TrueColorType) &&
3401             (image_info->type != TrueColorAlphaType))
3402           {
3403             if ((image_info->type != PaletteType) &&
3404                 (SetImageGray(image,exception) != MagickFalse))
3405               {
3406                 photometric=(uint16) (quantum_info->min_is_white !=
3407                   MagickFalse ? PHOTOMETRIC_MINISWHITE :
3408                   PHOTOMETRIC_MINISBLACK);
3409                 (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
3410                 if ((image->depth == 1) &&
3411                     (image->alpha_trait == UndefinedPixelTrait))
3412                   SetImageMonochrome(image,exception);
3413               }
3414             else
3415               if (image->storage_class == PseudoClass)
3416                 {
3417                   size_t
3418                     depth;
3419
3420                   /*
3421                     Colormapped TIFF raster.
3422                   */
3423                   (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,1);
3424                   photometric=PHOTOMETRIC_PALETTE;
3425                   depth=1;
3426                   while ((GetQuantumRange(depth)+1) < image->colors)
3427                     depth<<=1;
3428                   status=SetQuantumDepth(image,quantum_info,depth);
3429                   if (status == MagickFalse)
3430                     ThrowWriterException(ResourceLimitError,
3431                       "MemoryAllocationFailed");
3432                 }
3433           }
3434       }
3435     (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&endian);
3436     if ((compress_tag == COMPRESSION_CCITTFAX3) &&
3437         (photometric != PHOTOMETRIC_MINISWHITE))
3438       {
3439         compress_tag=COMPRESSION_NONE;
3440         endian=FILLORDER_MSB2LSB;
3441       }
3442     else
3443       if ((compress_tag == COMPRESSION_CCITTFAX4) &&
3444          (photometric != PHOTOMETRIC_MINISWHITE))
3445        {
3446          compress_tag=COMPRESSION_NONE;
3447          endian=FILLORDER_MSB2LSB;
3448        }
3449     option=GetImageOption(image_info,"tiff:fill-order");
3450     if (option != (const char *) NULL)
3451       {
3452         if (LocaleNCompare(option,"msb",3) == 0)
3453           endian=FILLORDER_MSB2LSB;
3454         if (LocaleNCompare(option,"lsb",3) == 0)
3455           endian=FILLORDER_LSB2MSB;
3456       }
3457     (void) TIFFSetField(tiff,TIFFTAG_COMPRESSION,compress_tag);
3458     (void) TIFFSetField(tiff,TIFFTAG_FILLORDER,endian);
3459     (void) TIFFSetField(tiff,TIFFTAG_BITSPERSAMPLE,quantum_info->depth);
3460     if (image->alpha_trait != UndefinedPixelTrait)
3461       {
3462         uint16
3463           extra_samples,
3464           sample_info[1],
3465           samples_per_pixel;
3466
3467         /*
3468           TIFF has a matte channel.
3469         */
3470         extra_samples=1;
3471         sample_info[0]=EXTRASAMPLE_UNASSALPHA;
3472         option=GetImageOption(image_info,"tiff:alpha");
3473         if (option != (const char *) NULL)
3474           {
3475             if (LocaleCompare(option,"associated") == 0)
3476               sample_info[0]=EXTRASAMPLE_ASSOCALPHA;
3477             else
3478               if (LocaleCompare(option,"unspecified") == 0)
3479                 sample_info[0]=EXTRASAMPLE_UNSPECIFIED;
3480           }
3481         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_SAMPLESPERPIXEL,
3482           &samples_per_pixel);
3483         (void) TIFFSetField(tiff,TIFFTAG_SAMPLESPERPIXEL,samples_per_pixel+1);
3484         (void) TIFFSetField(tiff,TIFFTAG_EXTRASAMPLES,extra_samples,
3485           &sample_info);
3486         if (sample_info[0] == EXTRASAMPLE_ASSOCALPHA)
3487           SetQuantumAlphaType(quantum_info,AssociatedQuantumAlpha);
3488       }
3489     (void) TIFFSetField(tiff,TIFFTAG_PHOTOMETRIC,photometric);
3490     switch (quantum_info->format)
3491     {
3492       case FloatingPointQuantumFormat:
3493       {
3494         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_IEEEFP);
3495         (void) TIFFSetField(tiff,TIFFTAG_SMINSAMPLEVALUE,quantum_info->minimum);
3496         (void) TIFFSetField(tiff,TIFFTAG_SMAXSAMPLEVALUE,quantum_info->maximum);
3497         break;
3498       }
3499       case SignedQuantumFormat:
3500       {
3501         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_INT);
3502         break;
3503       }
3504       case UnsignedQuantumFormat:
3505       {
3506         (void) TIFFSetField(tiff,TIFFTAG_SAMPLEFORMAT,SAMPLEFORMAT_UINT);
3507         break;
3508       }
3509       default:
3510         break;
3511     }
3512     (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,ORIENTATION_TOPLEFT);
3513     (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_CONTIG);
3514     if (photometric == PHOTOMETRIC_RGB)
3515       if ((image_info->interlace == PlaneInterlace) ||
3516           (image_info->interlace == PartitionInterlace))
3517         (void) TIFFSetField(tiff,TIFFTAG_PLANARCONFIG,PLANARCONFIG_SEPARATE);
3518     switch (compress_tag)
3519     {
3520       case COMPRESSION_JPEG:
3521       {
3522 #if defined(JPEG_SUPPORT)
3523
3524
3525         if (image_info->quality != UndefinedCompressionQuality)
3526           (void) TIFFSetField(tiff,TIFFTAG_JPEGQUALITY,image_info->quality);
3527         (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RAW);
3528         if (IssRGBCompatibleColorspace(image->colorspace) != MagickFalse)
3529           {
3530             const char
3531               *value;
3532
3533             (void) TIFFSetField(tiff,TIFFTAG_JPEGCOLORMODE,JPEGCOLORMODE_RGB);
3534             if (image->colorspace == YCbCrColorspace)
3535               {
3536                 const char
3537                   *sampling_factor;
3538
3539                 GeometryInfo
3540                   geometry_info;
3541
3542                 MagickStatusType
3543                   flags;
3544
3545                 sampling_factor=(const char *) NULL;
3546                 value=GetImageProperty(image,"jpeg:sampling-factor",exception);
3547                 if (value != (char *) NULL)
3548                   {
3549                     sampling_factor=value;
3550                     if (image->debug != MagickFalse)
3551                       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
3552                         "  Input sampling-factors=%s",sampling_factor);
3553                   }
3554                 if (image_info->sampling_factor != (char *) NULL)
3555                   sampling_factor=image_info->sampling_factor;
3556                 if (sampling_factor != (const char *) NULL)
3557                   {
3558                     flags=ParseGeometry(sampling_factor,&geometry_info);
3559                     if ((flags & SigmaValue) == 0)
3560                       geometry_info.sigma=geometry_info.rho;
3561                     (void) TIFFSetField(tiff,TIFFTAG_YCBCRSUBSAMPLING,(uint16)
3562                       geometry_info.rho,(uint16) geometry_info.sigma);
3563                   }
3564                 }
3565           }
3566         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3567           &bits_per_sample);
3568         if (bits_per_sample == 12)
3569           (void) TIFFSetField(tiff,TIFFTAG_JPEGTABLESMODE,JPEGTABLESMODE_QUANT);
3570 #endif
3571         break;
3572       }
3573       case COMPRESSION_ADOBE_DEFLATE:
3574       {
3575         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3576           &bits_per_sample);
3577         if (((photometric == PHOTOMETRIC_RGB) ||
3578              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3579             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3580           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3581         (void) TIFFSetField(tiff,TIFFTAG_ZIPQUALITY,(long) (
3582           image_info->quality == UndefinedCompressionQuality ? 7 :
3583           MagickMin((ssize_t) image_info->quality/10,9)));
3584         break;
3585       }
3586       case COMPRESSION_CCITTFAX3:
3587       {
3588         /*
3589           Byte-aligned EOL.
3590         */
3591         (void) TIFFSetField(tiff,TIFFTAG_GROUP3OPTIONS,4);
3592         break;
3593       }
3594       case COMPRESSION_CCITTFAX4:
3595         break;
3596 #if defined(LZMA_SUPPORT) && defined(COMPRESSION_LZMA)
3597       case COMPRESSION_LZMA:
3598       {
3599         if (((photometric == PHOTOMETRIC_RGB) ||
3600              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3601             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3602           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3603         (void) TIFFSetField(tiff,TIFFTAG_LZMAPRESET,(long) (
3604           image_info->quality == UndefinedCompressionQuality ? 7 :
3605           MagickMin((ssize_t) image_info->quality/10,9)));
3606         break;
3607       }
3608 #endif
3609       case COMPRESSION_LZW:
3610       {
3611         (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_BITSPERSAMPLE,
3612           &bits_per_sample);
3613         if (((photometric == PHOTOMETRIC_RGB) ||
3614              (photometric == PHOTOMETRIC_MINISBLACK)) &&
3615             ((bits_per_sample == 8) || (bits_per_sample == 16)))
3616           (void) TIFFSetField(tiff,TIFFTAG_PREDICTOR,PREDICTOR_HORIZONTAL);
3617         break;
3618       }
3619       default:
3620         break;
3621     }
3622     if ((image->resolution.x != 0.0) && (image->resolution.y != 0.0))
3623       {
3624         unsigned short
3625           units;
3626
3627         /*
3628           Set image resolution.
3629         */
3630         units=RESUNIT_NONE;
3631         if (image->units == PixelsPerInchResolution)
3632           units=RESUNIT_INCH;
3633         if (image->units == PixelsPerCentimeterResolution)
3634           units=RESUNIT_CENTIMETER;
3635         (void) TIFFSetField(tiff,TIFFTAG_RESOLUTIONUNIT,(uint16) units);
3636         (void) TIFFSetField(tiff,TIFFTAG_XRESOLUTION,image->resolution.x);
3637         (void) TIFFSetField(tiff,TIFFTAG_YRESOLUTION,image->resolution.y);
3638         if ((image->page.x < 0) || (image->page.y < 0))
3639           (void) ThrowMagickException(exception,GetMagickModule(),CoderError,
3640             "TIFF: negative image positions unsupported","%s",image->filename);
3641         if ((image->page.x > 0) && (image->resolution.x > 0.0))
3642           {
3643             /*
3644               Set horizontal image position.
3645             */
3646             (void) TIFFSetField(tiff,TIFFTAG_XPOSITION,(float) image->page.x/
3647               image->resolution.x);
3648           }
3649         if ((image->page.y > 0) && (image->resolution.y > 0.0))
3650           {
3651             /*
3652               Set vertical image position.
3653             */
3654             (void) TIFFSetField(tiff,TIFFTAG_YPOSITION,(float) image->page.y/
3655               image->resolution.y);
3656           }
3657       }
3658     if (image->chromaticity.white_point.x != 0.0)
3659       {
3660         float
3661           chromaticity[6];
3662
3663         /*
3664           Set image chromaticity.
3665         */
3666         chromaticity[0]=(float) image->chromaticity.red_primary.x;
3667         chromaticity[1]=(float) image->chromaticity.red_primary.y;
3668         chromaticity[2]=(float) image->chromaticity.green_primary.x;
3669         chromaticity[3]=(float) image->chromaticity.green_primary.y;
3670         chromaticity[4]=(float) image->chromaticity.blue_primary.x;
3671         chromaticity[5]=(float) image->chromaticity.blue_primary.y;
3672         (void) TIFFSetField(tiff,TIFFTAG_PRIMARYCHROMATICITIES,chromaticity);
3673         chromaticity[0]=(float) image->chromaticity.white_point.x;
3674         chromaticity[1]=(float) image->chromaticity.white_point.y;
3675         (void) TIFFSetField(tiff,TIFFTAG_WHITEPOINT,chromaticity);
3676       }
3677     if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
3678         (image_info->adjoin != MagickFalse) && (GetImageListLength(image) > 1))
3679       {
3680         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3681         if (image->scene != 0)
3682           (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,(uint16) image->scene,
3683             GetImageListLength(image));
3684       }
3685     if (image->orientation != UndefinedOrientation)
3686       (void) TIFFSetField(tiff,TIFFTAG_ORIENTATION,(uint16) image->orientation);
3687     (void) TIFFSetProfiles(tiff,image);
3688     {
3689       uint16
3690         page,
3691         pages;
3692
3693       page=(uint16) scene;
3694       pages=(uint16) GetImageListLength(image);
3695       if ((LocaleCompare(image_info->magick,"PTIF") != 0) &&
3696           (image_info->adjoin != MagickFalse) && (pages > 1))
3697         (void) TIFFSetField(tiff,TIFFTAG_SUBFILETYPE,FILETYPE_PAGE);
3698       (void) TIFFSetField(tiff,TIFFTAG_PAGENUMBER,page,pages);
3699     }
3700     (void) TIFFSetProperties(tiff,image_info,image,exception);
3701 DisableMSCWarning(4127)
3702     if (0)
3703 RestoreMSCWarning
3704       (void) TIFFSetEXIFProperties(tiff,image,exception);
3705     /*
3706       Write image scanlines.
3707     */
3708     if (GetTIFFInfo(image_info,tiff,&tiff_info) == MagickFalse)
3709       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3710     quantum_info->endian=LSBEndian;
3711     pixels=(unsigned char *) GetQuantumPixels(quantum_info);
3712     tiff_info.scanline=(unsigned char *) GetQuantumPixels(quantum_info);
3713     switch (photometric)
3714     {
3715       case PHOTOMETRIC_CIELAB:
3716       case PHOTOMETRIC_YCBCR:
3717       case PHOTOMETRIC_RGB:
3718       {
3719         /*
3720           RGB TIFF image.
3721         */
3722         switch (image_info->interlace)
3723         {
3724           case NoInterlace:
3725           default:
3726           {
3727             quantum_type=RGBQuantum;
3728             if (image->alpha_trait != UndefinedPixelTrait)
3729               quantum_type=RGBAQuantum;
3730             for (y=0; y < (ssize_t) image->rows; y++)
3731             {
3732               register const Quantum
3733                 *magick_restrict p;
3734
3735               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3736               if (p == (const Quantum *) NULL)
3737                 break;
3738               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3739                 quantum_type,pixels,exception);
3740               (void) length;
3741               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3742                 break;
3743               if (image->previous == (Image *) NULL)
3744                 {
3745                   status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
3746                     y,image->rows);
3747                   if (status == MagickFalse)
3748                     break;
3749                 }
3750             }
3751             break;
3752           }
3753           case PlaneInterlace:
3754           case PartitionInterlace:
3755           {
3756             /*
3757               Plane interlacing:  RRRRRR...GGGGGG...BBBBBB...
3758             */
3759             for (y=0; y < (ssize_t) image->rows; y++)
3760             {
3761               register const Quantum
3762                 *magick_restrict p;
3763
3764               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3765               if (p == (const Quantum *) NULL)
3766                 break;
3767               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3768                 RedQuantum,pixels,exception);
3769               if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3770                 break;
3771             }
3772             if (image->previous == (Image *) NULL)
3773               {
3774                 status=SetImageProgress(image,SaveImageTag,100,400);
3775                 if (status == MagickFalse)
3776                   break;
3777               }
3778             for (y=0; y < (ssize_t) image->rows; y++)
3779             {
3780               register const Quantum
3781                 *magick_restrict p;
3782
3783               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3784               if (p == (const Quantum *) NULL)
3785                 break;
3786               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3787                 GreenQuantum,pixels,exception);
3788               if (TIFFWritePixels(tiff,&tiff_info,y,1,image) == -1)
3789                 break;
3790             }
3791             if (image->previous == (Image *) NULL)
3792               {
3793                 status=SetImageProgress(image,SaveImageTag,200,400);
3794                 if (status == MagickFalse)
3795                   break;
3796               }
3797             for (y=0; y < (ssize_t) image->rows; y++)
3798             {
3799               register const Quantum
3800                 *magick_restrict p;
3801
3802               p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3803               if (p == (const Quantum *) NULL)
3804                 break;
3805               length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3806                 BlueQuantum,pixels,exception);
3807               if (TIFFWritePixels(tiff,&tiff_info,y,2,image) == -1)
3808                 break;
3809             }
3810             if (image->previous == (Image *) NULL)
3811               {
3812                 status=SetImageProgress(image,SaveImageTag,300,400);
3813                 if (status == MagickFalse)
3814                   break;
3815               }
3816             if (image->alpha_trait != UndefinedPixelTrait)
3817               for (y=0; y < (ssize_t) image->rows; y++)
3818               {
3819                 register const Quantum
3820                   *magick_restrict p;
3821
3822                 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3823                 if (p == (const Quantum *) NULL)
3824                   break;
3825                 length=ExportQuantumPixels(image,(CacheView *) NULL,
3826                   quantum_info,AlphaQuantum,pixels,exception);
3827                 if (TIFFWritePixels(tiff,&tiff_info,y,3,image) == -1)
3828                   break;
3829               }
3830             if (image->previous == (Image *) NULL)
3831               {
3832                 status=SetImageProgress(image,SaveImageTag,400,400);
3833                 if (status == MagickFalse)
3834                   break;
3835               }
3836             break;
3837           }
3838         }
3839         break;
3840       }
3841       case PHOTOMETRIC_SEPARATED:
3842       {
3843         /*
3844           CMYK TIFF image.
3845         */
3846         quantum_type=CMYKQuantum;
3847         if (image->alpha_trait != UndefinedPixelTrait)
3848           quantum_type=CMYKAQuantum;
3849         if (image->colorspace != CMYKColorspace)
3850           (void) TransformImageColorspace(image,CMYKColorspace,exception);
3851         for (y=0; y < (ssize_t) image->rows; y++)
3852         {
3853           register const Quantum
3854             *magick_restrict p;
3855
3856           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3857           if (p == (const Quantum *) NULL)
3858             break;
3859           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3860             quantum_type,pixels,exception);
3861           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3862             break;
3863           if (image->previous == (Image *) NULL)
3864             {
3865               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
3866                 image->rows);
3867               if (status == MagickFalse)
3868                 break;
3869             }
3870         }
3871         break;
3872       }
3873       case PHOTOMETRIC_PALETTE:
3874       {
3875         uint16
3876           *blue,
3877           *green,
3878           *red;
3879
3880         /*
3881           Colormapped TIFF image.
3882         */
3883         red=(uint16 *) AcquireQuantumMemory(65536,sizeof(*red));
3884         green=(uint16 *) AcquireQuantumMemory(65536,sizeof(*green));
3885         blue=(uint16 *) AcquireQuantumMemory(65536,sizeof(*blue));
3886         if ((red == (uint16 *) NULL) || (green == (uint16 *) NULL) ||
3887             (blue == (uint16 *) NULL))
3888           ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
3889         /*
3890           Initialize TIFF colormap.
3891         */
3892         (void) ResetMagickMemory(red,0,65536*sizeof(*red));
3893         (void) ResetMagickMemory(green,0,65536*sizeof(*green));
3894         (void) ResetMagickMemory(blue,0,65536*sizeof(*blue));
3895         for (i=0; i < (ssize_t) image->colors; i++)
3896         {
3897           red[i]=ScaleQuantumToShort(image->colormap[i].red);
3898           green[i]=ScaleQuantumToShort(image->colormap[i].green);
3899           blue[i]=ScaleQuantumToShort(image->colormap[i].blue);
3900         }
3901         (void) TIFFSetField(tiff,TIFFTAG_COLORMAP,red,green,blue);
3902         red=(uint16 *) RelinquishMagickMemory(red);
3903         green=(uint16 *) RelinquishMagickMemory(green);
3904         blue=(uint16 *) RelinquishMagickMemory(blue);
3905       }
3906       default:
3907       {
3908         /*
3909           Convert PseudoClass packets to contiguous grayscale scanlines.
3910         */
3911         quantum_type=IndexQuantum;
3912         if (image->alpha_trait != UndefinedPixelTrait)
3913           {
3914             if (photometric != PHOTOMETRIC_PALETTE)
3915               quantum_type=GrayAlphaQuantum;
3916             else
3917               quantum_type=IndexAlphaQuantum;
3918            }
3919          else
3920            if (photometric != PHOTOMETRIC_PALETTE)
3921              quantum_type=GrayQuantum;
3922         for (y=0; y < (ssize_t) image->rows; y++)
3923         {
3924           register const Quantum
3925             *magick_restrict p;
3926
3927           p=GetVirtualPixels(image,0,y,image->columns,1,exception);
3928           if (p == (const Quantum *) NULL)
3929             break;
3930           length=ExportQuantumPixels(image,(CacheView *) NULL,quantum_info,
3931             quantum_type,pixels,exception);
3932           if (TIFFWritePixels(tiff,&tiff_info,y,0,image) == -1)
3933             break;
3934           if (image->previous == (Image *) NULL)
3935             {
3936               status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
3937                 image->rows);
3938               if (status == MagickFalse)
3939                 break;
3940             }
3941         }
3942         break;
3943       }
3944     }
3945     quantum_info=DestroyQuantumInfo(quantum_info);
3946     if (image->colorspace == LabColorspace)
3947       DecodeLabImage(image,exception);
3948     DestroyTIFFInfo(&tiff_info);
3949 DisableMSCWarning(4127)
3950     if (0 && (image_info->verbose != MagickFalse))
3951 RestoreMSCWarning
3952       TIFFPrintDirectory(tiff,stdout,MagickFalse);
3953     (void) TIFFWriteDirectory(tiff);
3954     image=SyncNextImageInList(image);
3955     if (image == (Image *) NULL)
3956       break;
3957     status=SetImageProgress(image,SaveImagesTag,scene++,
3958       GetImageListLength(image));
3959     if (status == MagickFalse)
3960       break;
3961   } while (image_info->adjoin != MagickFalse);
3962   TIFFClose(tiff);
3963   return(MagickTrue);
3964 }
3965 #endif