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