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