1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% M M IIIII FFFFF FFFFF % 7% MM MM I F F % 8% M M M I FFF FFF % 9% M M I F F % 10% M M IIIII F F % 11% % 12% % 13% Read/Write MIFF 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/* 40 Include declarations. 41*/ 42#include "MagickCore/studio.h" 43#include "MagickCore/attribute.h" 44#include "MagickCore/blob.h" 45#include "MagickCore/blob-private.h" 46#include "MagickCore/cache.h" 47#include "MagickCore/color.h" 48#include "MagickCore/color-private.h" 49#include "MagickCore/colormap.h" 50#include "MagickCore/colormap-private.h" 51#include "MagickCore/colorspace.h" 52#include "MagickCore/colorspace-private.h" 53#include "MagickCore/constitute.h" 54#include "MagickCore/exception.h" 55#include "MagickCore/exception-private.h" 56#include "MagickCore/geometry.h" 57#include "MagickCore/image.h" 58#include "MagickCore/image-private.h" 59#include "MagickCore/linked-list.h" 60#include "MagickCore/list.h" 61#include "MagickCore/magick.h" 62#include "MagickCore/memory_.h" 63#include "MagickCore/module.h" 64#include "MagickCore/monitor.h" 65#include "MagickCore/monitor-private.h" 66#include "MagickCore/option.h" 67#include "MagickCore/pixel.h" 68#include "MagickCore/pixel-accessor.h" 69#include "MagickCore/profile.h" 70#include "MagickCore/property.h" 71#include "MagickCore/quantum-private.h" 72#include "MagickCore/static.h" 73#include "MagickCore/statistic.h" 74#include "MagickCore/string_.h" 75#include "MagickCore/string-private.h" 76#if defined(MAGICKCORE_BZLIB_DELEGATE) 77#include "bzlib.h" 78#endif 79#if defined(MAGICKCORE_LZMA_DELEGATE) 80#include "lzma.h" 81#endif 82#if defined(MAGICKCORE_ZLIB_DELEGATE) 83#include "zlib.h" 84#endif 85 86/* 87 Define declarations. 88*/ 89#if !defined(LZMA_OK) 90#define LZMA_OK 0 91#endif 92 93/* 94 Forward declarations. 95*/ 96static MagickBooleanType 97 WriteMIFFImage(const ImageInfo *,Image *,ExceptionInfo *); 98 99/* 100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 101% % 102% % 103% % 104% I s M I F F % 105% % 106% % 107% % 108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 109% 110% IsMIFF() returns MagickTrue if the image format type, identified by the 111% magick string, is MIFF. 112% 113% The format of the IsMIFF method is: 114% 115% MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length) 116% 117% A description of each parameter follows: 118% 119% o magick: compare image format pattern against these bytes. 120% 121% o length: Specifies the length of the magick string. 122% 123*/ 124static MagickBooleanType IsMIFF(const unsigned char *magick,const size_t length) 125{ 126 if (length < 14) 127 return(MagickFalse); 128 if (LocaleNCompare((const char *) magick,"id=ImageMagick",14) == 0) 129 return(MagickTrue); 130 return(MagickFalse); 131} 132 133/* 134%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 135% % 136% % 137% % 138% R e a d M I F F I m a g e % 139% % 140% % 141% % 142%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 143% 144% ReadMIFFImage() reads a MIFF image file and returns it. It allocates the 145% memory necessary for the new Image structure and returns a pointer to the 146% new image. 147% 148% The format of the ReadMIFFImage method is: 149% 150% Image *ReadMIFFImage(const ImageInfo *image_info, 151% ExceptionInfo *exception) 152% 153% Decompression code contributed by Kyle Shorter. 154% 155% A description of each parameter follows: 156% 157% o image_info: the image info. 158% 159% o exception: return any errors or warnings in this structure. 160% 161*/ 162 163#if defined(MAGICKCORE_BZLIB_DELEGATE) 164static void *AcquireBZIPMemory(void *context,int items,int size) 165{ 166 (void) context; 167 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size)); 168} 169#endif 170 171#if defined(MAGICKCORE_LZMA_DELEGATE) 172static void *AcquireLZMAMemory(void *context,size_t items,size_t size) 173{ 174 (void) context; 175 return((void *) AcquireQuantumMemory((size_t) items,(size_t) size)); 176} 177#endif 178 179#if defined(MAGICKCORE_ZLIB_DELEGATE) 180static voidpf AcquireZIPMemory(voidpf context,unsigned int items, 181 unsigned int size) 182{ 183 (void) context; 184 return((voidpf) AcquireQuantumMemory(items,size)); 185} 186#endif 187 188static void PushRunlengthPacket(Image *image,const unsigned char *pixels, 189 size_t *length,PixelInfo *pixel,ExceptionInfo *exception) 190{ 191 const unsigned char 192 *p; 193 194 p=pixels; 195 if (image->storage_class == PseudoClass) 196 { 197 pixel->index=0; 198 switch (image->depth) 199 { 200 case 32: 201 { 202 pixel->index=ConstrainColormapIndex(image,((size_t) *p << 24) | 203 ((size_t) *(p+1) << 16) | ((size_t) *(p+2) << 8) | (size_t) *(p+3), 204 exception); 205 p+=4; 206 break; 207 } 208 case 16: 209 { 210 pixel->index=ConstrainColormapIndex(image,(*p << 8) | *(p+1), 211 exception); 212 p+=2; 213 break; 214 } 215 case 8: 216 { 217 pixel->index=ConstrainColormapIndex(image,*p,exception); 218 p++; 219 break; 220 } 221 default: 222 (void) ThrowMagickException(exception,GetMagickModule(), 223 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename); 224 } 225 switch (image->depth) 226 { 227 case 8: 228 { 229 unsigned char 230 quantum; 231 232 if (image->alpha_trait != UndefinedPixelTrait) 233 { 234 p=PushCharPixel(p,&quantum); 235 pixel->alpha=ScaleCharToQuantum(quantum); 236 } 237 break; 238 } 239 case 16: 240 { 241 unsigned short 242 quantum; 243 244 if (image->alpha_trait != UndefinedPixelTrait) 245 { 246 p=PushShortPixel(MSBEndian,p,&quantum); 247 pixel->alpha=(Quantum) (quantum >> (image->depth- 248 MAGICKCORE_QUANTUM_DEPTH)); 249 } 250 break; 251 } 252 case 32: 253 { 254 unsigned int 255 quantum; 256 257 if (image->alpha_trait != UndefinedPixelTrait) 258 { 259 p=PushLongPixel(MSBEndian,p,&quantum); 260 pixel->alpha=(Quantum) (quantum >> (image->depth- 261 MAGICKCORE_QUANTUM_DEPTH)); 262 } 263 break; 264 } 265 default: 266 (void) ThrowMagickException(exception,GetMagickModule(), 267 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename); 268 } 269 *length=(size_t) (*p++)+1; 270 return; 271 } 272 switch (image->depth) 273 { 274 case 8: 275 { 276 unsigned char 277 quantum; 278 279 p=PushCharPixel(p,&quantum); 280 pixel->red=ScaleCharToQuantum(quantum); 281 pixel->green=pixel->red; 282 pixel->blue=pixel->red; 283 if (IsGrayColorspace(image->colorspace) == MagickFalse) 284 { 285 p=PushCharPixel(p,&quantum); 286 pixel->green=ScaleCharToQuantum(quantum); 287 p=PushCharPixel(p,&quantum); 288 pixel->blue=ScaleCharToQuantum(quantum); 289 } 290 if (image->colorspace == CMYKColorspace) 291 { 292 p=PushCharPixel(p,&quantum); 293 pixel->black=ScaleCharToQuantum(quantum); 294 } 295 if (image->alpha_trait != UndefinedPixelTrait) 296 { 297 p=PushCharPixel(p,&quantum); 298 pixel->alpha=ScaleCharToQuantum(quantum); 299 } 300 break; 301 } 302 case 16: 303 { 304 unsigned short 305 quantum; 306 307 p=PushShortPixel(MSBEndian,p,&quantum); 308 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 309 pixel->green=pixel->red; 310 pixel->blue=pixel->red; 311 if (IsGrayColorspace(image->colorspace) == MagickFalse) 312 { 313 p=PushShortPixel(MSBEndian,p,&quantum); 314 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 315 p=PushShortPixel(MSBEndian,p,&quantum); 316 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 317 } 318 if (image->colorspace == CMYKColorspace) 319 { 320 p=PushShortPixel(MSBEndian,p,&quantum); 321 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 322 } 323 if (image->alpha_trait != UndefinedPixelTrait) 324 { 325 p=PushShortPixel(MSBEndian,p,&quantum); 326 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 327 } 328 break; 329 } 330 case 32: 331 { 332 unsigned int 333 quantum; 334 335 p=PushLongPixel(MSBEndian,p,&quantum); 336 pixel->red=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 337 pixel->green=pixel->red; 338 pixel->blue=pixel->red; 339 if (IsGrayColorspace(image->colorspace) == MagickFalse) 340 { 341 p=PushLongPixel(MSBEndian,p,&quantum); 342 pixel->green=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 343 p=PushLongPixel(MSBEndian,p,&quantum); 344 pixel->blue=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 345 } 346 if (image->colorspace == CMYKColorspace) 347 { 348 p=PushLongPixel(MSBEndian,p,&quantum); 349 pixel->black=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 350 } 351 if (image->alpha_trait != UndefinedPixelTrait) 352 { 353 p=PushLongPixel(MSBEndian,p,&quantum); 354 pixel->alpha=quantum >> (image->depth-MAGICKCORE_QUANTUM_DEPTH); 355 } 356 break; 357 } 358 default: 359 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, 360 "ImageDepthNotSupported","`%s'",image->filename); 361 } 362 *length=(size_t) (*p++)+1; 363} 364 365#if defined(MAGICKCORE_BZLIB_DELEGATE) 366static void RelinquishBZIPMemory(void *context,void *memory) 367{ 368 (void) context; 369 memory=RelinquishMagickMemory(memory); 370} 371#endif 372 373#if defined(MAGICKCORE_LZMA_DELEGATE) 374static void RelinquishLZMAMemory(void *context,void *memory) 375{ 376 (void) context; 377 memory=RelinquishMagickMemory(memory); 378} 379#endif 380 381#if defined(MAGICKCORE_ZLIB_DELEGATE) 382static void RelinquishZIPMemory(voidpf context,voidpf memory) 383{ 384 (void) context; 385 memory=RelinquishMagickMemory(memory); 386} 387#endif 388 389static Image *ReadMIFFImage(const ImageInfo *image_info, 390 ExceptionInfo *exception) 391{ 392#define BZipMaxExtent(x) ((x)+((x)/100)+600) 393#define LZMAMaxExtent(x) ((x)+((x)/3)+128) 394#define ZipMaxExtent(x) ((x)+(((x)+7) >> 3)+(((x)+63) >> 6)+11) 395 396#if defined(MAGICKCORE_BZLIB_DELEGATE) 397 bz_stream 398 bzip_info; 399#endif 400 401 char 402 id[MagickPathExtent], 403 keyword[MagickPathExtent], 404 *options; 405 406 const unsigned char 407 *p; 408 409 double 410 version; 411 412 GeometryInfo 413 geometry_info; 414 415 Image 416 *image; 417 418 int 419 c; 420 421 LinkedListInfo 422 *profiles; 423 424#if defined(MAGICKCORE_LZMA_DELEGATE) 425 lzma_stream 426 initialize_lzma = LZMA_STREAM_INIT, 427 lzma_info; 428 429 lzma_allocator 430 allocator; 431#endif 432 433 MagickBooleanType 434 status; 435 436 PixelInfo 437 pixel; 438 439 MagickStatusType 440 flags; 441 442 QuantumFormatType 443 quantum_format; 444 445 QuantumInfo 446 *quantum_info; 447 448 QuantumType 449 quantum_type; 450 451 register ssize_t 452 i; 453 454 size_t 455 compress_extent, 456 length, 457 packet_size; 458 459 ssize_t 460 count; 461 462 unsigned char 463 *compress_pixels, 464 *pixels; 465 466 size_t 467 colors; 468 469 ssize_t 470 y; 471 472#if defined(MAGICKCORE_ZLIB_DELEGATE) 473 z_stream 474 zip_info; 475#endif 476 477 /* 478 Open image file. 479 */ 480 assert(image_info != (const ImageInfo *) NULL); 481 assert(image_info->signature == MagickCoreSignature); 482 if (image_info->debug != MagickFalse) 483 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s", 484 image_info->filename); 485 assert(exception != (ExceptionInfo *) NULL); 486 assert(exception->signature == MagickCoreSignature); 487 image=AcquireImage(image_info,exception); 488 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception); 489 if (status == MagickFalse) 490 { 491 image=DestroyImageList(image); 492 return((Image *) NULL); 493 } 494 /* 495 Decode image header; header terminates one character beyond a ':'. 496 */ 497 c=ReadBlobByte(image); 498 if (c == EOF) 499 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 500 *id='\0'; 501 (void) ResetMagickMemory(keyword,0,sizeof(keyword)); 502 version=0.0; 503 (void) version; 504 do 505 { 506 /* 507 Decode image header; header terminates one character beyond a ':'. 508 */ 509 length=MagickPathExtent; 510 options=AcquireString((char *) NULL); 511 quantum_format=UndefinedQuantumFormat; 512 profiles=(LinkedListInfo *) NULL; 513 colors=0; 514 image->depth=8UL; 515 image->compression=NoCompression; 516 while ((isgraph(c) != MagickFalse) && (c != (int) ':')) 517 { 518 register char 519 *p; 520 521 if (c == (int) '{') 522 { 523 char 524 *comment; 525 526 /* 527 Read comment-- any text between { }. 528 */ 529 length=MagickPathExtent; 530 comment=AcquireString((char *) NULL); 531 for (p=comment; comment != (char *) NULL; p++) 532 { 533 c=ReadBlobByte(image); 534 if (c == (int) '\\') 535 c=ReadBlobByte(image); 536 else 537 if ((c == EOF) || (c == (int) '}')) 538 break; 539 if ((size_t) (p-comment+1) >= length) 540 { 541 *p='\0'; 542 length<<=1; 543 comment=(char *) ResizeQuantumMemory(comment,length+ 544 MagickPathExtent,sizeof(*comment)); 545 if (comment == (char *) NULL) 546 break; 547 p=comment+strlen(comment); 548 } 549 *p=(char) c; 550 } 551 if (comment == (char *) NULL) 552 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 553 *p='\0'; 554 (void) SetImageProperty(image,"comment",comment,exception); 555 comment=DestroyString(comment); 556 c=ReadBlobByte(image); 557 } 558 else 559 if (isalnum(c) != MagickFalse) 560 { 561 /* 562 Get the keyword. 563 */ 564 length=MagickPathExtent; 565 p=keyword; 566 do 567 { 568 if (c == (int) '=') 569 break; 570 if ((size_t) (p-keyword) < (MagickPathExtent-1)) 571 *p++=(char) c; 572 c=ReadBlobByte(image); 573 } while (c != EOF); 574 *p='\0'; 575 p=options; 576 while ((isspace((int) ((unsigned char) c)) != 0) && (c != EOF)) 577 c=ReadBlobByte(image); 578 if (c == (int) '=') 579 { 580 /* 581 Get the keyword value. 582 */ 583 c=ReadBlobByte(image); 584 while ((c != (int) '}') && (c != EOF)) 585 { 586 if ((size_t) (p-options+1) >= length) 587 { 588 *p='\0'; 589 length<<=1; 590 options=(char *) ResizeQuantumMemory(options,length+ 591 MagickPathExtent,sizeof(*options)); 592 if (options == (char *) NULL) 593 break; 594 p=options+strlen(options); 595 } 596 *p++=(char) c; 597 c=ReadBlobByte(image); 598 if (c == '\\') 599 { 600 c=ReadBlobByte(image); 601 if (c == (int) '}') 602 { 603 *p++=(char) c; 604 c=ReadBlobByte(image); 605 } 606 } 607 if (*options != '{') 608 if (isspace((int) ((unsigned char) c)) != 0) 609 break; 610 } 611 if (options == (char *) NULL) 612 ThrowReaderException(ResourceLimitError, 613 "MemoryAllocationFailed"); 614 } 615 *p='\0'; 616 if (*options == '{') 617 (void) CopyMagickString(options,options+1,strlen(options)); 618 /* 619 Assign a value to the specified keyword. 620 */ 621 switch (*keyword) 622 { 623 case 'a': 624 case 'A': 625 { 626 if (LocaleCompare(keyword,"alpha-color") == 0) 627 { 628 (void) QueryColorCompliance(options,AllCompliance, 629 &image->alpha_color,exception); 630 break; 631 } 632 if (LocaleCompare(keyword,"alpha-trait") == 0) 633 { 634 ssize_t 635 alpha_trait; 636 637 alpha_trait=ParseCommandOption(MagickPixelTraitOptions, 638 MagickFalse,options); 639 if (alpha_trait < 0) 640 break; 641 image->alpha_trait=(PixelTrait) alpha_trait; 642 break; 643 } 644 (void) SetImageProperty(image,keyword,options,exception); 645 break; 646 } 647 case 'b': 648 case 'B': 649 { 650 if (LocaleCompare(keyword,"background-color") == 0) 651 { 652 (void) QueryColorCompliance(options,AllCompliance, 653 &image->background_color,exception); 654 break; 655 } 656 if (LocaleCompare(keyword,"blue-primary") == 0) 657 { 658 flags=ParseGeometry(options,&geometry_info); 659 image->chromaticity.blue_primary.x=geometry_info.rho; 660 image->chromaticity.blue_primary.y=geometry_info.sigma; 661 if ((flags & SigmaValue) == 0) 662 image->chromaticity.blue_primary.y= 663 image->chromaticity.blue_primary.x; 664 break; 665 } 666 if (LocaleCompare(keyword,"border-color") == 0) 667 { 668 (void) QueryColorCompliance(options,AllCompliance, 669 &image->border_color,exception); 670 break; 671 } 672 (void) SetImageProperty(image,keyword,options,exception); 673 break; 674 } 675 case 'c': 676 case 'C': 677 { 678 if (LocaleCompare(keyword,"class") == 0) 679 { 680 ssize_t 681 storage_class; 682 683 storage_class=ParseCommandOption(MagickClassOptions, 684 MagickFalse,options); 685 if (storage_class < 0) 686 break; 687 image->storage_class=(ClassType) storage_class; 688 break; 689 } 690 if (LocaleCompare(keyword,"colors") == 0) 691 { 692 colors=StringToUnsignedLong(options); 693 break; 694 } 695 if (LocaleCompare(keyword,"colorspace") == 0) 696 { 697 ssize_t 698 colorspace; 699 700 colorspace=ParseCommandOption(MagickColorspaceOptions, 701 MagickFalse,options); 702 if (colorspace < 0) 703 break; 704 image->colorspace=(ColorspaceType) colorspace; 705 break; 706 } 707 if (LocaleCompare(keyword,"compression") == 0) 708 { 709 ssize_t 710 compression; 711 712 compression=ParseCommandOption(MagickCompressOptions, 713 MagickFalse,options); 714 if (compression < 0) 715 break; 716 image->compression=(CompressionType) compression; 717 break; 718 } 719 if (LocaleCompare(keyword,"columns") == 0) 720 { 721 image->columns=StringToUnsignedLong(options); 722 break; 723 } 724 (void) SetImageProperty(image,keyword,options,exception); 725 break; 726 } 727 case 'd': 728 case 'D': 729 { 730 if (LocaleCompare(keyword,"delay") == 0) 731 { 732 image->delay=StringToUnsignedLong(options); 733 break; 734 } 735 if (LocaleCompare(keyword,"depth") == 0) 736 { 737 image->depth=StringToUnsignedLong(options); 738 break; 739 } 740 if (LocaleCompare(keyword,"dispose") == 0) 741 { 742 ssize_t 743 dispose; 744 745 dispose=ParseCommandOption(MagickDisposeOptions,MagickFalse, 746 options); 747 if (dispose < 0) 748 break; 749 image->dispose=(DisposeType) dispose; 750 break; 751 } 752 (void) SetImageProperty(image,keyword,options,exception); 753 break; 754 } 755 case 'e': 756 case 'E': 757 { 758 if (LocaleCompare(keyword,"endian") == 0) 759 { 760 ssize_t 761 endian; 762 763 endian=ParseCommandOption(MagickEndianOptions,MagickFalse, 764 options); 765 if (endian < 0) 766 break; 767 image->endian=(EndianType) endian; 768 break; 769 } 770 (void) SetImageProperty(image,keyword,options,exception); 771 break; 772 } 773 case 'g': 774 case 'G': 775 { 776 if (LocaleCompare(keyword,"gamma") == 0) 777 { 778 image->gamma=StringToDouble(options,(char **) NULL); 779 break; 780 } 781 if (LocaleCompare(keyword,"gravity") == 0) 782 { 783 ssize_t 784 gravity; 785 786 gravity=ParseCommandOption(MagickGravityOptions,MagickFalse, 787 options); 788 if (gravity < 0) 789 break; 790 image->gravity=(GravityType) gravity; 791 break; 792 } 793 if (LocaleCompare(keyword,"green-primary") == 0) 794 { 795 flags=ParseGeometry(options,&geometry_info); 796 image->chromaticity.green_primary.x=geometry_info.rho; 797 image->chromaticity.green_primary.y=geometry_info.sigma; 798 if ((flags & SigmaValue) == 0) 799 image->chromaticity.green_primary.y= 800 image->chromaticity.green_primary.x; 801 break; 802 } 803 (void) SetImageProperty(image,keyword,options,exception); 804 break; 805 } 806 case 'i': 807 case 'I': 808 { 809 if (LocaleCompare(keyword,"id") == 0) 810 { 811 (void) CopyMagickString(id,options,MagickPathExtent); 812 break; 813 } 814 if (LocaleCompare(keyword,"iterations") == 0) 815 { 816 image->iterations=StringToUnsignedLong(options); 817 break; 818 } 819 (void) SetImageProperty(image,keyword,options,exception); 820 break; 821 } 822 case 'm': 823 case 'M': 824 { 825 if (LocaleCompare(keyword,"matte") == 0) 826 { 827 ssize_t 828 matte; 829 830 matte=ParseCommandOption(MagickBooleanOptions,MagickFalse, 831 options); 832 if (matte < 0) 833 break; 834 image->alpha_trait=matte == 0 ? UndefinedPixelTrait : 835 BlendPixelTrait; 836 break; 837 } 838 if (LocaleCompare(keyword,"montage") == 0) 839 { 840 (void) CloneString(&image->montage,options); 841 break; 842 } 843 (void) SetImageProperty(image,keyword,options,exception); 844 break; 845 } 846 case 'o': 847 case 'O': 848 { 849 if (LocaleCompare(keyword,"orientation") == 0) 850 { 851 ssize_t 852 orientation; 853 854 orientation=ParseCommandOption(MagickOrientationOptions, 855 MagickFalse,options); 856 if (orientation < 0) 857 break; 858 image->orientation=(OrientationType) orientation; 859 break; 860 } 861 (void) SetImageProperty(image,keyword,options,exception); 862 break; 863 } 864 case 'p': 865 case 'P': 866 { 867 if (LocaleCompare(keyword,"page") == 0) 868 { 869 char 870 *geometry; 871 872 geometry=GetPageGeometry(options); 873 (void) ParseAbsoluteGeometry(geometry,&image->page); 874 geometry=DestroyString(geometry); 875 break; 876 } 877 if (LocaleCompare(keyword,"pixel-intensity") == 0) 878 { 879 ssize_t 880 intensity; 881 882 intensity=ParseCommandOption(MagickPixelIntensityOptions, 883 MagickFalse,options); 884 if (intensity < 0) 885 break; 886 image->intensity=(PixelIntensityMethod) intensity; 887 break; 888 } 889 if ((LocaleNCompare(keyword,"profile:",8) == 0) || 890 (LocaleNCompare(keyword,"profile-",8) == 0)) 891 { 892 StringInfo 893 *profile; 894 895 if (profiles == (LinkedListInfo *) NULL) 896 profiles=NewLinkedList(0); 897 (void) AppendValueToLinkedList(profiles, 898 AcquireString(keyword+8)); 899 profile=BlobToStringInfo((const void *) NULL,(size_t) 900 StringToLong(options)); 901 if (profile == (StringInfo *) NULL) 902 ThrowReaderException(ResourceLimitError, 903 "MemoryAllocationFailed"); 904 (void) SetImageProfile(image,keyword+8,profile,exception); 905 profile=DestroyStringInfo(profile); 906 break; 907 } 908 (void) SetImageProperty(image,keyword,options,exception); 909 break; 910 } 911 case 'q': 912 case 'Q': 913 { 914 if (LocaleCompare(keyword,"quality") == 0) 915 { 916 image->quality=StringToUnsignedLong(options); 917 break; 918 } 919 if ((LocaleCompare(keyword,"quantum-format") == 0) || 920 (LocaleCompare(keyword,"quantum:format") == 0)) 921 { 922 ssize_t 923 format; 924 925 format=ParseCommandOption(MagickQuantumFormatOptions, 926 MagickFalse,options); 927 if (format < 0) 928 break; 929 quantum_format=(QuantumFormatType) format; 930 break; 931 } 932 (void) SetImageProperty(image,keyword,options,exception); 933 break; 934 } 935 case 'r': 936 case 'R': 937 { 938 if (LocaleCompare(keyword,"red-primary") == 0) 939 { 940 flags=ParseGeometry(options,&geometry_info); 941 image->chromaticity.red_primary.x=geometry_info.rho; 942 image->chromaticity.red_primary.y=geometry_info.sigma; 943 if ((flags & SigmaValue) == 0) 944 image->chromaticity.red_primary.y= 945 image->chromaticity.red_primary.x; 946 break; 947 } 948 if (LocaleCompare(keyword,"rendering-intent") == 0) 949 { 950 ssize_t 951 rendering_intent; 952 953 rendering_intent=ParseCommandOption(MagickIntentOptions, 954 MagickFalse,options); 955 if (rendering_intent < 0) 956 break; 957 image->rendering_intent=(RenderingIntent) rendering_intent; 958 break; 959 } 960 if (LocaleCompare(keyword,"resolution") == 0) 961 { 962 flags=ParseGeometry(options,&geometry_info); 963 image->resolution.x=geometry_info.rho; 964 image->resolution.y=geometry_info.sigma; 965 if ((flags & SigmaValue) == 0) 966 image->resolution.y=image->resolution.x; 967 break; 968 } 969 if (LocaleCompare(keyword,"rows") == 0) 970 { 971 image->rows=StringToUnsignedLong(options); 972 break; 973 } 974 (void) SetImageProperty(image,keyword,options,exception); 975 break; 976 } 977 case 's': 978 case 'S': 979 { 980 if (LocaleCompare(keyword,"scene") == 0) 981 { 982 image->scene=StringToUnsignedLong(options); 983 break; 984 } 985 (void) SetImageProperty(image,keyword,options,exception); 986 break; 987 } 988 case 't': 989 case 'T': 990 { 991 if (LocaleCompare(keyword,"ticks-per-second") == 0) 992 { 993 image->ticks_per_second=(ssize_t) StringToLong(options); 994 break; 995 } 996 if (LocaleCompare(keyword,"tile-offset") == 0) 997 { 998 char 999 *geometry; 1000 1001 geometry=GetPageGeometry(options); 1002 (void) ParseAbsoluteGeometry(geometry,&image->tile_offset); 1003 geometry=DestroyString(geometry); 1004 break; 1005 } 1006 if (LocaleCompare(keyword,"type") == 0) 1007 { 1008 ssize_t 1009 type; 1010 1011 type=ParseCommandOption(MagickTypeOptions,MagickFalse, 1012 options); 1013 if (type < 0) 1014 break; 1015 image->type=(ImageType) type; 1016 break; 1017 } 1018 (void) SetImageProperty(image,keyword,options,exception); 1019 break; 1020 } 1021 case 'u': 1022 case 'U': 1023 { 1024 if (LocaleCompare(keyword,"units") == 0) 1025 { 1026 ssize_t 1027 units; 1028 1029 units=ParseCommandOption(MagickResolutionOptions, 1030 MagickFalse,options); 1031 if (units < 0) 1032 break; 1033 image->units=(ResolutionType) units; 1034 break; 1035 } 1036 (void) SetImageProperty(image,keyword,options,exception); 1037 break; 1038 } 1039 case 'v': 1040 case 'V': 1041 { 1042 if (LocaleCompare(keyword,"version") == 0) 1043 { 1044 version=StringToDouble(options,(char **) NULL); 1045 break; 1046 } 1047 (void) SetImageProperty(image,keyword,options,exception); 1048 break; 1049 } 1050 case 'w': 1051 case 'W': 1052 { 1053 if (LocaleCompare(keyword,"white-point") == 0) 1054 { 1055 flags=ParseGeometry(options,&geometry_info); 1056 image->chromaticity.white_point.x=geometry_info.rho; 1057 image->chromaticity.white_point.y=geometry_info.sigma; 1058 if ((flags & SigmaValue) == 0) 1059 image->chromaticity.white_point.y= 1060 image->chromaticity.white_point.x; 1061 break; 1062 } 1063 (void) SetImageProperty(image,keyword,options,exception); 1064 break; 1065 } 1066 default: 1067 { 1068 (void) SetImageProperty(image,keyword,options,exception); 1069 break; 1070 } 1071 } 1072 } 1073 else 1074 c=ReadBlobByte(image); 1075 while (isspace((int) ((unsigned char) c)) != 0) 1076 c=ReadBlobByte(image); 1077 } 1078 options=DestroyString(options); 1079 (void) ReadBlobByte(image); 1080 /* 1081 Verify that required image information is defined. 1082 */ 1083 if ((LocaleCompare(id,"ImageMagick") != 0) || 1084 (image->storage_class == UndefinedClass) || 1085 (image->compression == UndefinedCompression) || 1086 (image->colorspace == UndefinedColorspace) || 1087 (image->columns == 0) || (image->rows == 0)) 1088 { 1089 if (image->previous == (Image *) NULL) 1090 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1091 (void) ThrowMagickException(exception,GetMagickModule(), 1092 CorruptImageError,"ImproperImageHeader","`%s'",image->filename); 1093 break; 1094 } 1095 if (image->montage != (char *) NULL) 1096 { 1097 register char 1098 *p; 1099 1100 /* 1101 Image directory. 1102 */ 1103 length=MagickPathExtent; 1104 image->directory=AcquireString((char *) NULL); 1105 p=image->directory; 1106 do 1107 { 1108 *p='\0'; 1109 if ((strlen(image->directory)+MagickPathExtent) >= length) 1110 { 1111 /* 1112 Allocate more memory for the image directory. 1113 */ 1114 length<<=1; 1115 image->directory=(char *) ResizeQuantumMemory(image->directory, 1116 length+MagickPathExtent,sizeof(*image->directory)); 1117 if (image->directory == (char *) NULL) 1118 ThrowReaderException(CorruptImageError,"UnableToReadImageData"); 1119 p=image->directory+strlen(image->directory); 1120 } 1121 c=ReadBlobByte(image); 1122 *p++=(char) c; 1123 } while (c != (int) '\0'); 1124 } 1125 if (profiles != (LinkedListInfo *) NULL) 1126 { 1127 const char 1128 *name; 1129 1130 const StringInfo 1131 *profile; 1132 1133 /* 1134 Read image profiles. 1135 */ 1136 ResetLinkedListIterator(profiles); 1137 name=(const char *) GetNextValueInLinkedList(profiles); 1138 while (name != (const char *) NULL) 1139 { 1140 profile=GetImageProfile(image,name); 1141 if (profile != (StringInfo *) NULL) 1142 { 1143 register unsigned char 1144 *p; 1145 1146 p=GetStringInfoDatum(profile); 1147 count=ReadBlob(image,GetStringInfoLength(profile),p); 1148 (void) count; 1149 } 1150 name=(const char *) GetNextValueInLinkedList(profiles); 1151 } 1152 profiles=DestroyLinkedList(profiles,RelinquishMagickMemory); 1153 } 1154 image->depth=GetImageQuantumDepth(image,MagickFalse); 1155 if (image->storage_class == PseudoClass) 1156 { 1157 /* 1158 Create image colormap. 1159 */ 1160 status=AcquireImageColormap(image,colors != 0 ? colors : 256,exception); 1161 if (status == MagickFalse) 1162 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1163 if (colors != 0) 1164 { 1165 size_t 1166 packet_size; 1167 1168 unsigned char 1169 *colormap; 1170 1171 /* 1172 Read image colormap from file. 1173 */ 1174 packet_size=(size_t) (3UL*image->depth/8UL); 1175 colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 1176 packet_size*sizeof(*colormap)); 1177 if (colormap == (unsigned char *) NULL) 1178 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1179 count=ReadBlob(image,packet_size*image->colors,colormap); 1180 p=colormap; 1181 switch (image->depth) 1182 { 1183 default: 1184 ThrowReaderException(CorruptImageError, 1185 "ImageDepthNotSupported"); 1186 case 8: 1187 { 1188 unsigned char 1189 pixel; 1190 1191 for (i=0; i < (ssize_t) image->colors; i++) 1192 { 1193 p=PushCharPixel(p,&pixel); 1194 image->colormap[i].red=ScaleCharToQuantum(pixel); 1195 p=PushCharPixel(p,&pixel); 1196 image->colormap[i].green=ScaleCharToQuantum(pixel); 1197 p=PushCharPixel(p,&pixel); 1198 image->colormap[i].blue=ScaleCharToQuantum(pixel); 1199 } 1200 break; 1201 } 1202 case 16: 1203 { 1204 unsigned short 1205 pixel; 1206 1207 for (i=0; i < (ssize_t) image->colors; i++) 1208 { 1209 p=PushShortPixel(MSBEndian,p,&pixel); 1210 image->colormap[i].red=ScaleShortToQuantum(pixel); 1211 p=PushShortPixel(MSBEndian,p,&pixel); 1212 image->colormap[i].green=ScaleShortToQuantum(pixel); 1213 p=PushShortPixel(MSBEndian,p,&pixel); 1214 image->colormap[i].blue=ScaleShortToQuantum(pixel); 1215 } 1216 break; 1217 } 1218 case 32: 1219 { 1220 unsigned int 1221 pixel; 1222 1223 for (i=0; i < (ssize_t) image->colors; i++) 1224 { 1225 p=PushLongPixel(MSBEndian,p,&pixel); 1226 image->colormap[i].red=ScaleLongToQuantum(pixel); 1227 p=PushLongPixel(MSBEndian,p,&pixel); 1228 image->colormap[i].green=ScaleLongToQuantum(pixel); 1229 p=PushLongPixel(MSBEndian,p,&pixel); 1230 image->colormap[i].blue=ScaleLongToQuantum(pixel); 1231 } 1232 break; 1233 } 1234 } 1235 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 1236 } 1237 } 1238 if ((image_info->ping != MagickFalse) && (image_info->number_scenes != 0)) 1239 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 1240 break; 1241 status=SetImageExtent(image,image->columns,image->rows,exception); 1242 if (status == MagickFalse) 1243 return(DestroyImageList(image)); 1244 /* 1245 Allocate image pixels. 1246 */ 1247 quantum_info=AcquireQuantumInfo(image_info,image); 1248 if (quantum_info == (QuantumInfo *) NULL) 1249 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1250 if (quantum_format != UndefinedQuantumFormat) 1251 { 1252 status=SetQuantumFormat(image,quantum_info,quantum_format); 1253 if (status == MagickFalse) 1254 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1255 } 1256 packet_size=(size_t) (quantum_info->depth/8); 1257 if (image->storage_class == DirectClass) 1258 packet_size=(size_t) (3*quantum_info->depth/8); 1259 if (IsGrayColorspace(image->colorspace) != MagickFalse) 1260 packet_size=quantum_info->depth/8; 1261 if (image->alpha_trait != UndefinedPixelTrait) 1262 packet_size+=quantum_info->depth/8; 1263 if (image->colorspace == CMYKColorspace) 1264 packet_size+=quantum_info->depth/8; 1265 if (image->compression == RLECompression) 1266 packet_size++; 1267 compress_extent=MagickMax(MagickMax(BZipMaxExtent(packet_size* 1268 image->columns),LZMAMaxExtent(packet_size*image->columns)), 1269 ZipMaxExtent(packet_size*image->columns)); 1270 compress_pixels=(unsigned char *) AcquireQuantumMemory(compress_extent, 1271 sizeof(*compress_pixels)); 1272 if (compress_pixels == (unsigned char *) NULL) 1273 ThrowReaderException(ResourceLimitError,"MemoryAllocationFailed"); 1274 /* 1275 Read image pixels. 1276 */ 1277 quantum_type=RGBQuantum; 1278 if (image->alpha_trait != UndefinedPixelTrait) 1279 quantum_type=RGBAQuantum; 1280 if (image->colorspace == CMYKColorspace) 1281 { 1282 quantum_type=CMYKQuantum; 1283 if (image->alpha_trait != UndefinedPixelTrait) 1284 quantum_type=CMYKAQuantum; 1285 } 1286 if (IsGrayColorspace(image->colorspace) != MagickFalse) 1287 { 1288 quantum_type=GrayQuantum; 1289 if (image->alpha_trait != UndefinedPixelTrait) 1290 quantum_type=GrayAlphaQuantum; 1291 } 1292 if (image->storage_class == PseudoClass) 1293 { 1294 quantum_type=IndexQuantum; 1295 if (image->alpha_trait != UndefinedPixelTrait) 1296 quantum_type=IndexAlphaQuantum; 1297 } 1298 status=MagickTrue; 1299 GetPixelInfo(image,&pixel); 1300#if defined(MAGICKCORE_BZLIB_DELEGATE) 1301 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info)); 1302#endif 1303#if defined(MAGICKCORE_LZMA_DELEGATE) 1304 (void) ResetMagickMemory(&allocator,0,sizeof(allocator)); 1305#endif 1306#if defined(MAGICKCORE_ZLIB_DELEGATE) 1307 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info)); 1308#endif 1309 switch (image->compression) 1310 { 1311#if defined(MAGICKCORE_BZLIB_DELEGATE) 1312 case BZipCompression: 1313 { 1314 int 1315 code; 1316 1317 bzip_info.bzalloc=AcquireBZIPMemory; 1318 bzip_info.bzfree=RelinquishBZIPMemory; 1319 bzip_info.opaque=(void *) NULL; 1320 code=BZ2_bzDecompressInit(&bzip_info,(int) image_info->verbose, 1321 MagickFalse); 1322 if (code != BZ_OK) 1323 status=MagickFalse; 1324 break; 1325 } 1326#endif 1327#if defined(MAGICKCORE_LZMA_DELEGATE) 1328 case LZMACompression: 1329 { 1330 int 1331 code; 1332 1333 allocator.alloc=AcquireLZMAMemory; 1334 allocator.free=RelinquishLZMAMemory; 1335 lzma_info=initialize_lzma; 1336 lzma_info.allocator=(&allocator); 1337 code=lzma_auto_decoder(&lzma_info,-1,0); 1338 if (code != LZMA_OK) 1339 status=MagickFalse; 1340 break; 1341 } 1342#endif 1343#if defined(MAGICKCORE_ZLIB_DELEGATE) 1344 case LZWCompression: 1345 case ZipCompression: 1346 { 1347 int 1348 code; 1349 1350 zip_info.zalloc=AcquireZIPMemory; 1351 zip_info.zfree=RelinquishZIPMemory; 1352 zip_info.opaque=(voidpf) NULL; 1353 code=inflateInit(&zip_info); 1354 if (code != Z_OK) 1355 status=MagickFalse; 1356 break; 1357 } 1358#endif 1359 case RLECompression: 1360 break; 1361 default: 1362 break; 1363 } 1364 pixels=(unsigned char *) GetQuantumPixels(quantum_info); 1365 length=0; 1366 for (y=0; y < (ssize_t) image->rows; y++) 1367 { 1368 register ssize_t 1369 x; 1370 1371 register Quantum 1372 *magick_restrict q; 1373 1374 if (status == MagickFalse) 1375 break; 1376 q=QueueAuthenticPixels(image,0,y,image->columns,1,exception); 1377 if (q == (Quantum *) NULL) 1378 break; 1379 switch (image->compression) 1380 { 1381#if defined(MAGICKCORE_BZLIB_DELEGATE) 1382 case BZipCompression: 1383 { 1384 bzip_info.next_out=(char *) pixels; 1385 bzip_info.avail_out=(unsigned int) (packet_size*image->columns); 1386 do 1387 { 1388 int 1389 code; 1390 1391 if (bzip_info.avail_in == 0) 1392 { 1393 bzip_info.next_in=(char *) compress_pixels; 1394 length=(size_t) BZipMaxExtent(packet_size*image->columns); 1395 if (version != 0.0) 1396 length=(size_t) ReadBlobMSBLong(image); 1397 if (length > compress_extent) 1398 { 1399 (void) BZ2_bzDecompressEnd(&bzip_info); 1400 ThrowReaderException(CorruptImageError, 1401 "UnableToReadImageData"); 1402 } 1403 bzip_info.avail_in=(unsigned int) ReadBlob(image,length, 1404 (unsigned char *) bzip_info.next_in); 1405 } 1406 code=BZ2_bzDecompress(&bzip_info); 1407 if (code < 0) 1408 { 1409 status=MagickFalse; 1410 break; 1411 } 1412 if (code == BZ_STREAM_END) 1413 break; 1414 } while (bzip_info.avail_out != 0); 1415 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1416 quantum_type,pixels,exception); 1417 break; 1418 } 1419#endif 1420#if defined(MAGICKCORE_LZMA_DELEGATE) 1421 case LZMACompression: 1422 { 1423 lzma_info.next_out=pixels; 1424 lzma_info.avail_out=packet_size*image->columns; 1425 do 1426 { 1427 int 1428 code; 1429 1430 if (lzma_info.avail_in == 0) 1431 { 1432 lzma_info.next_in=compress_pixels; 1433 length=(size_t) ReadBlobMSBLong(image); 1434 if (length > compress_extent) 1435 { 1436 lzma_end(&lzma_info); 1437 ThrowReaderException(CorruptImageError, 1438 "UnableToReadImageData"); 1439 } 1440 lzma_info.avail_in=(unsigned int) ReadBlob(image,length, 1441 (unsigned char *) lzma_info.next_in); 1442 } 1443 code=lzma_code(&lzma_info,LZMA_RUN); 1444 if (code < 0) 1445 { 1446 status=MagickFalse; 1447 break; 1448 } 1449 if (code == LZMA_STREAM_END) 1450 break; 1451 } while (lzma_info.avail_out != 0); 1452 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1453 quantum_type,pixels,exception); 1454 break; 1455 } 1456#endif 1457#if defined(MAGICKCORE_ZLIB_DELEGATE) 1458 case LZWCompression: 1459 case ZipCompression: 1460 { 1461 zip_info.next_out=pixels; 1462 zip_info.avail_out=(uInt) (packet_size*image->columns); 1463 do 1464 { 1465 int 1466 code; 1467 1468 if (zip_info.avail_in == 0) 1469 { 1470 zip_info.next_in=compress_pixels; 1471 length=(size_t) ZipMaxExtent(packet_size*image->columns); 1472 if (version != 0.0) 1473 length=(size_t) ReadBlobMSBLong(image); 1474 if (length > compress_extent) 1475 { 1476 (void) inflateEnd(&zip_info); 1477 ThrowReaderException(CorruptImageError, 1478 "UnableToReadImageData"); 1479 } 1480 zip_info.avail_in=(unsigned int) ReadBlob(image,length, 1481 zip_info.next_in); 1482 } 1483 code=inflate(&zip_info,Z_SYNC_FLUSH); 1484 if (code < 0) 1485 { 1486 status=MagickFalse; 1487 break; 1488 } 1489 if (code == Z_STREAM_END) 1490 break; 1491 } while (zip_info.avail_out != 0); 1492 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1493 quantum_type,pixels,exception); 1494 break; 1495 } 1496#endif 1497 case RLECompression: 1498 { 1499 for (x=0; x < (ssize_t) image->columns; x++) 1500 { 1501 if (length == 0) 1502 { 1503 count=ReadBlob(image,packet_size,pixels); 1504 PushRunlengthPacket(image,pixels,&length,&pixel,exception); 1505 } 1506 length--; 1507 if (image->storage_class == PseudoClass) 1508 SetPixelIndex(image,ClampToQuantum(pixel.index),q); 1509 else 1510 { 1511 SetPixelRed(image,ClampToQuantum(pixel.red),q); 1512 SetPixelGreen(image,ClampToQuantum(pixel.green),q); 1513 SetPixelBlue(image,ClampToQuantum(pixel.blue),q); 1514 if (image->colorspace == CMYKColorspace) 1515 SetPixelBlack(image,ClampToQuantum(pixel.black),q); 1516 } 1517 if (image->alpha_trait != UndefinedPixelTrait) 1518 SetPixelAlpha(image,ClampToQuantum(pixel.alpha),q); 1519 q+=GetPixelChannels(image); 1520 } 1521 break; 1522 } 1523 default: 1524 { 1525 count=ReadBlob(image,packet_size*image->columns,pixels); 1526 (void) ImportQuantumPixels(image,(CacheView *) NULL,quantum_info, 1527 quantum_type,pixels,exception); 1528 break; 1529 } 1530 } 1531 if (SyncAuthenticPixels(image,exception) == MagickFalse) 1532 break; 1533 } 1534 SetQuantumImageType(image,quantum_type); 1535 switch (image->compression) 1536 { 1537#if defined(MAGICKCORE_BZLIB_DELEGATE) 1538 case BZipCompression: 1539 { 1540 int 1541 code; 1542 1543 if (version == 0.0) 1544 { 1545 MagickOffsetType 1546 offset; 1547 1548 offset=SeekBlob(image,-((MagickOffsetType) 1549 bzip_info.avail_in),SEEK_CUR); 1550 if (offset < 0) 1551 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1552 } 1553 code=BZ2_bzDecompressEnd(&bzip_info); 1554 if (code != BZ_OK) 1555 status=MagickFalse; 1556 break; 1557 } 1558#endif 1559#if defined(MAGICKCORE_LZMA_DELEGATE) 1560 case LZMACompression: 1561 { 1562 int 1563 code; 1564 1565 code=lzma_code(&lzma_info,LZMA_FINISH); 1566 if ((code != LZMA_STREAM_END) && (code != LZMA_OK)) 1567 status=MagickFalse; 1568 lzma_end(&lzma_info); 1569 break; 1570 } 1571#endif 1572#if defined(MAGICKCORE_ZLIB_DELEGATE) 1573 case LZWCompression: 1574 case ZipCompression: 1575 { 1576 int 1577 code; 1578 1579 if (version == 0.0) 1580 { 1581 MagickOffsetType 1582 offset; 1583 1584 offset=SeekBlob(image,-((MagickOffsetType) zip_info.avail_in), 1585 SEEK_CUR); 1586 if (offset < 0) 1587 ThrowReaderException(CorruptImageError,"ImproperImageHeader"); 1588 } 1589 code=inflateEnd(&zip_info); 1590 if (code != LZMA_OK) 1591 status=MagickFalse; 1592 break; 1593 } 1594#endif 1595 default: 1596 break; 1597 } 1598 quantum_info=DestroyQuantumInfo(quantum_info); 1599 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels); 1600 if (((y != (ssize_t) image->rows)) || (status == MagickFalse)) 1601 { 1602 image=DestroyImageList(image); 1603 return((Image *) NULL); 1604 } 1605 if (EOFBlob(image) != MagickFalse) 1606 { 1607 ThrowFileException(exception,CorruptImageError,"UnexpectedEndOfFile", 1608 image->filename); 1609 break; 1610 } 1611 /* 1612 Proceed to next image. 1613 */ 1614 if (image_info->number_scenes != 0) 1615 if (image->scene >= (image_info->scene+image_info->number_scenes-1)) 1616 break; 1617 do 1618 { 1619 c=ReadBlobByte(image); 1620 } while ((isgraph(c) == MagickFalse) && (c != EOF)); 1621 if (c != EOF) 1622 { 1623 /* 1624 Allocate next image structure. 1625 */ 1626 AcquireNextImage(image_info,image,exception); 1627 if (GetNextImageInList(image) == (Image *) NULL) 1628 { 1629 image=DestroyImageList(image); 1630 return((Image *) NULL); 1631 } 1632 image=SyncNextImageInList(image); 1633 status=SetImageProgress(image,LoadImagesTag,TellBlob(image), 1634 GetBlobSize(image)); 1635 if (status == MagickFalse) 1636 break; 1637 } 1638 } while (c != EOF); 1639 (void) CloseBlob(image); 1640 return(GetFirstImageInList(image)); 1641} 1642 1643/* 1644%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1645% % 1646% % 1647% % 1648% R e g i s t e r M I F F I m a g e % 1649% % 1650% % 1651% % 1652%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1653% 1654% RegisterMIFFImage() adds properties for the MIFF image format to the list of 1655% supported formats. The properties include the image format tag, a method to 1656% read and/or write the format, whether the format supports the saving of more 1657% than one frame to the same file or blob, whether the format supports native 1658% in-memory I/O, and a brief description of the format. 1659% 1660% The format of the RegisterMIFFImage method is: 1661% 1662% size_t RegisterMIFFImage(void) 1663% 1664*/ 1665ModuleExport size_t RegisterMIFFImage(void) 1666{ 1667 char 1668 version[MagickPathExtent]; 1669 1670 MagickInfo 1671 *entry; 1672 1673 *version='\0'; 1674#if defined(MagickImageCoderSignatureText) 1675 (void) CopyMagickString(version,MagickLibVersionText,MagickPathExtent); 1676#if defined(ZLIB_VERSION) 1677 (void) ConcatenateMagickString(version," with Zlib ",MagickPathExtent); 1678 (void) ConcatenateMagickString(version,ZLIB_VERSION,MagickPathExtent); 1679#endif 1680#if defined(MAGICKCORE_BZLIB_DELEGATE) 1681 (void) ConcatenateMagickString(version," and BZlib",MagickPathExtent); 1682#endif 1683#endif 1684 entry=AcquireMagickInfo("MIFF","MIFF","Magick Image File Format"); 1685 entry->decoder=(DecodeImageHandler *) ReadMIFFImage; 1686 entry->encoder=(EncodeImageHandler *) WriteMIFFImage; 1687 entry->magick=(IsImageFormatHandler *) IsMIFF; 1688 entry->flags|=CoderSeekableStreamFlag; 1689 if (*version != '\0') 1690 entry->version=ConstantString(version); 1691 (void) RegisterMagickInfo(entry); 1692 return(MagickImageCoderSignature); 1693} 1694 1695/* 1696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1697% % 1698% % 1699% % 1700% U n r e g i s t e r M I F F I m a g e % 1701% % 1702% % 1703% % 1704%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1705% 1706% UnregisterMIFFImage() removes format registrations made by the MIFF module 1707% from the list of supported formats. 1708% 1709% The format of the UnregisterMIFFImage method is: 1710% 1711% UnregisterMIFFImage(void) 1712% 1713*/ 1714ModuleExport void UnregisterMIFFImage(void) 1715{ 1716 (void) UnregisterMagickInfo("MIFF"); 1717} 1718 1719/* 1720%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1721% % 1722% % 1723% % 1724% W r i t e M I F F I m a g e % 1725% % 1726% % 1727% % 1728%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1729% 1730% WriteMIFFImage() writes a MIFF image to a file. 1731% 1732% The format of the WriteMIFFImage method is: 1733% 1734% MagickBooleanType WriteMIFFImage(const ImageInfo *image_info, 1735% Image *image,ExceptionInfo *exception) 1736% 1737% Compression code contributed by Kyle Shorter. 1738% 1739% A description of each parameter follows: 1740% 1741% o image_info: the image info. 1742% 1743% o image: the image. 1744% 1745% o exception: return any errors or warnings in this structure. 1746% 1747*/ 1748 1749static unsigned char *PopRunlengthPacket(Image *image,unsigned char *pixels, 1750 size_t length,PixelInfo *pixel,ExceptionInfo *exception) 1751{ 1752 if (image->storage_class != DirectClass) 1753 { 1754 unsigned int 1755 value; 1756 1757 value=(unsigned int) ClampToQuantum(pixel->index); 1758 switch (image->depth) 1759 { 1760 case 32: 1761 { 1762 *pixels++=(unsigned char) (value >> 24); 1763 *pixels++=(unsigned char) (value >> 16); 1764 } 1765 case 16: 1766 *pixels++=(unsigned char) (value >> 8); 1767 case 8: 1768 { 1769 *pixels++=(unsigned char) value; 1770 break; 1771 } 1772 default: 1773 (void) ThrowMagickException(exception,GetMagickModule(), 1774 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename); 1775 } 1776 switch (image->depth) 1777 { 1778 case 32: 1779 { 1780 unsigned int 1781 value; 1782 1783 if (image->alpha_trait != UndefinedPixelTrait) 1784 { 1785 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha)); 1786 pixels=PopLongPixel(MSBEndian,value,pixels); 1787 } 1788 break; 1789 } 1790 case 16: 1791 { 1792 unsigned short 1793 value; 1794 1795 if (image->alpha_trait != UndefinedPixelTrait) 1796 { 1797 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha)); 1798 pixels=PopShortPixel(MSBEndian,value,pixels); 1799 } 1800 break; 1801 } 1802 case 8: 1803 { 1804 unsigned char 1805 value; 1806 1807 if (image->alpha_trait != UndefinedPixelTrait) 1808 { 1809 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum( 1810 pixel->alpha)); 1811 pixels=PopCharPixel(value,pixels); 1812 } 1813 break; 1814 } 1815 default: 1816 (void) ThrowMagickException(exception,GetMagickModule(), 1817 CorruptImageError,"ImageDepthNotSupported","`%s'",image->filename); 1818 } 1819 *pixels++=(unsigned char) length; 1820 return(pixels); 1821 } 1822 switch (image->depth) 1823 { 1824 case 32: 1825 { 1826 unsigned int 1827 value; 1828 1829 value=ScaleQuantumToLong(ClampToQuantum(pixel->red)); 1830 pixels=PopLongPixel(MSBEndian,value,pixels); 1831 if (IsGrayColorspace(image->colorspace) == MagickFalse) 1832 { 1833 value=ScaleQuantumToLong(ClampToQuantum(pixel->green)); 1834 pixels=PopLongPixel(MSBEndian,value,pixels); 1835 value=ScaleQuantumToLong(ClampToQuantum(pixel->blue)); 1836 pixels=PopLongPixel(MSBEndian,value,pixels); 1837 } 1838 if (image->colorspace == CMYKColorspace) 1839 { 1840 value=ScaleQuantumToLong(ClampToQuantum(pixel->black)); 1841 pixels=PopLongPixel(MSBEndian,value,pixels); 1842 } 1843 if (image->alpha_trait != UndefinedPixelTrait) 1844 { 1845 value=ScaleQuantumToLong(ClampToQuantum(pixel->alpha)); 1846 pixels=PopLongPixel(MSBEndian,value,pixels); 1847 } 1848 break; 1849 } 1850 case 16: 1851 { 1852 unsigned short 1853 value; 1854 1855 value=ScaleQuantumToShort(ClampToQuantum(pixel->red)); 1856 pixels=PopShortPixel(MSBEndian,value,pixels); 1857 if (IsGrayColorspace(image->colorspace) == MagickFalse) 1858 { 1859 value=ScaleQuantumToShort(ClampToQuantum(pixel->green)); 1860 pixels=PopShortPixel(MSBEndian,value,pixels); 1861 value=ScaleQuantumToShort(ClampToQuantum(pixel->blue)); 1862 pixels=PopShortPixel(MSBEndian,value,pixels); 1863 } 1864 if (image->colorspace == CMYKColorspace) 1865 { 1866 value=ScaleQuantumToShort(ClampToQuantum(pixel->black)); 1867 pixels=PopShortPixel(MSBEndian,value,pixels); 1868 } 1869 if (image->alpha_trait != UndefinedPixelTrait) 1870 { 1871 value=ScaleQuantumToShort(ClampToQuantum(pixel->alpha)); 1872 pixels=PopShortPixel(MSBEndian,value,pixels); 1873 } 1874 break; 1875 } 1876 case 8: 1877 { 1878 unsigned char 1879 value; 1880 1881 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->red)); 1882 pixels=PopCharPixel(value,pixels); 1883 if (IsGrayColorspace(image->colorspace) == MagickFalse) 1884 { 1885 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum( 1886 pixel->green)); 1887 pixels=PopCharPixel(value,pixels); 1888 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum(pixel->blue)); 1889 pixels=PopCharPixel(value,pixels); 1890 } 1891 if (image->colorspace == CMYKColorspace) 1892 { 1893 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum( 1894 pixel->black)); 1895 pixels=PopCharPixel(value,pixels); 1896 } 1897 if (image->alpha_trait != UndefinedPixelTrait) 1898 { 1899 value=(unsigned char) ScaleQuantumToChar(ClampToQuantum( 1900 pixel->alpha)); 1901 pixels=PopCharPixel(value,pixels); 1902 } 1903 break; 1904 } 1905 default: 1906 (void) ThrowMagickException(exception,GetMagickModule(),CorruptImageError, 1907 "ImageDepthNotSupported","`%s'",image->filename); 1908 } 1909 *pixels++=(unsigned char) length; 1910 return(pixels); 1911} 1912 1913static MagickBooleanType WriteMIFFImage(const ImageInfo *image_info, 1914 Image *image,ExceptionInfo *exception) 1915{ 1916#if defined(MAGICKCORE_BZLIB_DELEGATE) 1917 bz_stream 1918 bzip_info; 1919#endif 1920 1921 char 1922 buffer[MagickPathExtent]; 1923 1924 CompressionType 1925 compression; 1926 1927 const char 1928 *property, 1929 *value; 1930 1931#if defined(MAGICKCORE_LZMA_DELEGATE) 1932 lzma_allocator 1933 allocator; 1934 1935 lzma_stream 1936 initialize_lzma = LZMA_STREAM_INIT, 1937 lzma_info; 1938#endif 1939 1940 MagickBooleanType 1941 status; 1942 1943 MagickOffsetType 1944 scene; 1945 1946 PixelInfo 1947 pixel, 1948 target; 1949 1950 QuantumInfo 1951 *quantum_info; 1952 1953 QuantumType 1954 quantum_type; 1955 1956 register ssize_t 1957 i; 1958 1959 size_t 1960 length, 1961 packet_size; 1962 1963 ssize_t 1964 y; 1965 1966 unsigned char 1967 *compress_pixels, 1968 *pixels, 1969 *q; 1970 1971#if defined(MAGICKCORE_ZLIB_DELEGATE) 1972 z_stream 1973 zip_info; 1974#endif 1975 1976 /* 1977 Open output image file. 1978 */ 1979 assert(image_info != (const ImageInfo *) NULL); 1980 assert(image_info->signature == MagickCoreSignature); 1981 assert(image != (Image *) NULL); 1982 assert(image->signature == MagickCoreSignature); 1983 if (image->debug != MagickFalse) 1984 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 1985 assert(exception != (ExceptionInfo *) NULL); 1986 assert(exception->signature == MagickCoreSignature); 1987 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 1988 if (status == MagickFalse) 1989 return(status); 1990 scene=0; 1991 do 1992 { 1993 /* 1994 Allocate image pixels. 1995 */ 1996 if ((image->storage_class == PseudoClass) && 1997 (image->colors > (size_t) (GetQuantumRange(image->depth)+1))) 1998 (void) SetImageStorageClass(image,DirectClass,exception); 1999 image->depth=image->depth <= 8 ? 8UL : image->depth <= 16 ? 16UL : 2000 image->depth <= 32 ? 32UL : 64UL; 2001 quantum_info=AcquireQuantumInfo(image_info,image); 2002 if (quantum_info == (QuantumInfo *) NULL) 2003 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 2004 if ((image->storage_class != PseudoClass) && (image->depth >= 32) && 2005 (quantum_info->format == UndefinedQuantumFormat) && 2006 (IsHighDynamicRangeImage(image,exception) != MagickFalse)) 2007 { 2008 status=SetQuantumFormat(image,quantum_info,FloatingPointQuantumFormat); 2009 if (status == MagickFalse) 2010 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 2011 } 2012 compression=UndefinedCompression; 2013 if (image_info->compression != UndefinedCompression) 2014 compression=image_info->compression; 2015 switch (compression) 2016 { 2017#if !defined(MAGICKCORE_LZMA_DELEGATE) 2018 case LZMACompression: compression=NoCompression; break; 2019#endif 2020#if !defined(MAGICKCORE_ZLIB_DELEGATE) 2021 case LZWCompression: 2022 case ZipCompression: compression=NoCompression; break; 2023#endif 2024#if !defined(MAGICKCORE_BZLIB_DELEGATE) 2025 case BZipCompression: compression=NoCompression; break; 2026#endif 2027 case RLECompression: 2028 { 2029 if (quantum_info->format == FloatingPointQuantumFormat) 2030 compression=NoCompression; 2031 GetPixelInfo(image,&target); 2032 break; 2033 } 2034 default: 2035 break; 2036 } 2037 packet_size=(size_t) (quantum_info->depth/8); 2038 if (image->storage_class == DirectClass) 2039 packet_size=(size_t) (3*quantum_info->depth/8); 2040 if (IsGrayColorspace(image->colorspace) != MagickFalse) 2041 packet_size=(size_t) (quantum_info->depth/8); 2042 if (image->alpha_trait != UndefinedPixelTrait) 2043 packet_size+=quantum_info->depth/8; 2044 if (image->colorspace == CMYKColorspace) 2045 packet_size+=quantum_info->depth/8; 2046 if (compression == RLECompression) 2047 packet_size++; 2048 length=MagickMax(BZipMaxExtent(packet_size*image->columns),ZipMaxExtent( 2049 packet_size*image->columns)); 2050 if ((compression == BZipCompression) || (compression == ZipCompression)) 2051 if (length != (size_t) ((unsigned int) length)) 2052 compression=NoCompression; 2053 compress_pixels=(unsigned char *) AcquireQuantumMemory(length, 2054 sizeof(*compress_pixels)); 2055 if (compress_pixels == (unsigned char *) NULL) 2056 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 2057 /* 2058 Write MIFF header. 2059 */ 2060 (void) WriteBlobString(image,"id=ImageMagick version=1.0\n"); 2061 (void) FormatLocaleString(buffer,MagickPathExtent, 2062 "class=%s colors=%.20g alpha-trait=%s\n",CommandOptionToMnemonic( 2063 MagickClassOptions,image->storage_class),(double) image->colors, 2064 CommandOptionToMnemonic(MagickPixelTraitOptions,(ssize_t) 2065 image->alpha_trait)); 2066 (void) WriteBlobString(image,buffer); 2067 if (image->alpha_trait != UndefinedPixelTrait) 2068 (void) WriteBlobString(image,"matte=True\n"); 2069 (void) FormatLocaleString(buffer,MagickPathExtent, 2070 "columns=%.20g rows=%.20g depth=%.20g\n",(double) image->columns, 2071 (double) image->rows,(double) image->depth); 2072 (void) WriteBlobString(image,buffer); 2073 if (image->type != UndefinedType) 2074 { 2075 (void) FormatLocaleString(buffer,MagickPathExtent,"type=%s\n", 2076 CommandOptionToMnemonic(MagickTypeOptions,image->type)); 2077 (void) WriteBlobString(image,buffer); 2078 } 2079 if (image->colorspace != UndefinedColorspace) 2080 { 2081 (void) FormatLocaleString(buffer,MagickPathExtent,"colorspace=%s\n", 2082 CommandOptionToMnemonic(MagickColorspaceOptions,image->colorspace)); 2083 (void) WriteBlobString(image,buffer); 2084 } 2085 if (image->intensity != UndefinedPixelIntensityMethod) 2086 { 2087 (void) FormatLocaleString(buffer,MagickPathExtent, 2088 "pixel-intensity=%s\n",CommandOptionToMnemonic( 2089 MagickPixelIntensityOptions,image->intensity)); 2090 (void) WriteBlobString(image,buffer); 2091 } 2092 if (image->endian != UndefinedEndian) 2093 { 2094 (void) FormatLocaleString(buffer,MagickPathExtent,"endian=%s\n", 2095 CommandOptionToMnemonic(MagickEndianOptions,image->endian)); 2096 (void) WriteBlobString(image,buffer); 2097 } 2098 if (compression != UndefinedCompression) 2099 { 2100 (void) FormatLocaleString(buffer,MagickPathExtent,"compression=%s " 2101 "quality=%.20g\n",CommandOptionToMnemonic(MagickCompressOptions, 2102 compression),(double) image->quality); 2103 (void) WriteBlobString(image,buffer); 2104 } 2105 if (image->units != UndefinedResolution) 2106 { 2107 (void) FormatLocaleString(buffer,MagickPathExtent,"units=%s\n", 2108 CommandOptionToMnemonic(MagickResolutionOptions,image->units)); 2109 (void) WriteBlobString(image,buffer); 2110 } 2111 if ((image->resolution.x != 0) || (image->resolution.y != 0)) 2112 { 2113 (void) FormatLocaleString(buffer,MagickPathExtent, 2114 "resolution=%gx%g\n",image->resolution.x,image->resolution.y); 2115 (void) WriteBlobString(image,buffer); 2116 } 2117 if ((image->page.width != 0) || (image->page.height != 0)) 2118 { 2119 (void) FormatLocaleString(buffer,MagickPathExtent, 2120 "page=%.20gx%.20g%+.20g%+.20g\n",(double) image->page.width,(double) 2121 image->page.height,(double) image->page.x,(double) image->page.y); 2122 (void) WriteBlobString(image,buffer); 2123 } 2124 else 2125 if ((image->page.x != 0) || (image->page.y != 0)) 2126 { 2127 (void) FormatLocaleString(buffer,MagickPathExtent,"page=%+ld%+ld\n", 2128 (long) image->page.x,(long) image->page.y); 2129 (void) WriteBlobString(image,buffer); 2130 } 2131 if ((image->tile_offset.x != 0) || (image->tile_offset.y != 0)) 2132 { 2133 (void) FormatLocaleString(buffer,MagickPathExtent, 2134 "tile-offset=%+ld%+ld\n",(long) image->tile_offset.x,(long) 2135 image->tile_offset.y); 2136 (void) WriteBlobString(image,buffer); 2137 } 2138 if ((GetNextImageInList(image) != (Image *) NULL) || 2139 (GetPreviousImageInList(image) != (Image *) NULL)) 2140 { 2141 if (image->scene == 0) 2142 (void) FormatLocaleString(buffer,MagickPathExtent,"iterations=%.20g " 2143 "delay=%.20g ticks-per-second=%.20g\n",(double) image->iterations, 2144 (double) image->delay,(double) image->ticks_per_second); 2145 else 2146 (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g " 2147 "iterations=%.20g delay=%.20g ticks-per-second=%.20g\n",(double) 2148 image->scene,(double) image->iterations,(double) image->delay, 2149 (double) image->ticks_per_second); 2150 (void) WriteBlobString(image,buffer); 2151 } 2152 else 2153 { 2154 if (image->scene != 0) 2155 { 2156 (void) FormatLocaleString(buffer,MagickPathExtent,"scene=%.20g\n", 2157 (double) image->scene); 2158 (void) WriteBlobString(image,buffer); 2159 } 2160 if (image->iterations != 0) 2161 { 2162 (void) FormatLocaleString(buffer,MagickPathExtent, 2163 "iterations=%.20g\n",(double) image->iterations); 2164 (void) WriteBlobString(image,buffer); 2165 } 2166 if (image->delay != 0) 2167 { 2168 (void) FormatLocaleString(buffer,MagickPathExtent,"delay=%.20g\n", 2169 (double) image->delay); 2170 (void) WriteBlobString(image,buffer); 2171 } 2172 if (image->ticks_per_second != UndefinedTicksPerSecond) 2173 { 2174 (void) FormatLocaleString(buffer,MagickPathExtent, 2175 "ticks-per-second=%.20g\n",(double) image->ticks_per_second); 2176 (void) WriteBlobString(image,buffer); 2177 } 2178 } 2179 if (image->gravity != UndefinedGravity) 2180 { 2181 (void) FormatLocaleString(buffer,MagickPathExtent,"gravity=%s\n", 2182 CommandOptionToMnemonic(MagickGravityOptions,image->gravity)); 2183 (void) WriteBlobString(image,buffer); 2184 } 2185 if (image->dispose != UndefinedDispose) 2186 { 2187 (void) FormatLocaleString(buffer,MagickPathExtent,"dispose=%s\n", 2188 CommandOptionToMnemonic(MagickDisposeOptions,image->dispose)); 2189 (void) WriteBlobString(image,buffer); 2190 } 2191 if (image->rendering_intent != UndefinedIntent) 2192 { 2193 (void) FormatLocaleString(buffer,MagickPathExtent, 2194 "rendering-intent=%s\n",CommandOptionToMnemonic(MagickIntentOptions, 2195 image->rendering_intent)); 2196 (void) WriteBlobString(image,buffer); 2197 } 2198 if (image->gamma != 0.0) 2199 { 2200 (void) FormatLocaleString(buffer,MagickPathExtent,"gamma=%g\n", 2201 image->gamma); 2202 (void) WriteBlobString(image,buffer); 2203 } 2204 if (image->chromaticity.white_point.x != 0.0) 2205 { 2206 /* 2207 Note chomaticity points. 2208 */ 2209 (void) FormatLocaleString(buffer,MagickPathExtent,"red-primary=%g," 2210 "%g green-primary=%g,%g blue-primary=%g,%g\n", 2211 image->chromaticity.red_primary.x,image->chromaticity.red_primary.y, 2212 image->chromaticity.green_primary.x, 2213 image->chromaticity.green_primary.y, 2214 image->chromaticity.blue_primary.x, 2215 image->chromaticity.blue_primary.y); 2216 (void) WriteBlobString(image,buffer); 2217 (void) FormatLocaleString(buffer,MagickPathExtent, 2218 "white-point=%g,%g\n",image->chromaticity.white_point.x, 2219 image->chromaticity.white_point.y); 2220 (void) WriteBlobString(image,buffer); 2221 } 2222 if (image->orientation != UndefinedOrientation) 2223 { 2224 (void) FormatLocaleString(buffer,MagickPathExtent,"orientation=%s\n", 2225 CommandOptionToMnemonic(MagickOrientationOptions,image->orientation)); 2226 (void) WriteBlobString(image,buffer); 2227 } 2228 if (image->profiles != (void *) NULL) 2229 { 2230 const char 2231 *name; 2232 2233 const StringInfo 2234 *profile; 2235 2236 /* 2237 Write image profiles. 2238 */ 2239 ResetImageProfileIterator(image); 2240 name=GetNextImageProfile(image); 2241 while (name != (const char *) NULL) 2242 { 2243 profile=GetImageProfile(image,name); 2244 if (profile != (StringInfo *) NULL) 2245 { 2246 (void) FormatLocaleString(buffer,MagickPathExtent, 2247 "profile:%s=%.20g\n",name,(double) 2248 GetStringInfoLength(profile)); 2249 (void) WriteBlobString(image,buffer); 2250 } 2251 name=GetNextImageProfile(image); 2252 } 2253 } 2254 if (image->montage != (char *) NULL) 2255 { 2256 (void) FormatLocaleString(buffer,MagickPathExtent,"montage=%s\n", 2257 image->montage); 2258 (void) WriteBlobString(image,buffer); 2259 } 2260 if (quantum_info->format == FloatingPointQuantumFormat) 2261 (void) SetImageProperty(image,"quantum:format","floating-point", 2262 exception); 2263 ResetImagePropertyIterator(image); 2264 property=GetNextImageProperty(image); 2265 while (property != (const char *) NULL) 2266 { 2267 (void) FormatLocaleString(buffer,MagickPathExtent,"%s=",property); 2268 (void) WriteBlobString(image,buffer); 2269 value=GetImageProperty(image,property,exception); 2270 if (value != (const char *) NULL) 2271 { 2272 size_t 2273 length; 2274 2275 length=strlen(value); 2276 for (i=0; i < (ssize_t) length; i++) 2277 if (isspace((int) ((unsigned char) value[i])) != 0) 2278 break; 2279 if ((i == (ssize_t) length) && (i != 0)) 2280 (void) WriteBlob(image,length,(const unsigned char *) value); 2281 else 2282 { 2283 (void) WriteBlobByte(image,'{'); 2284 if (strchr(value,'}') == (char *) NULL) 2285 (void) WriteBlob(image,length,(const unsigned char *) value); 2286 else 2287 for (i=0; i < (ssize_t) length; i++) 2288 { 2289 if (value[i] == (int) '}') 2290 (void) WriteBlobByte(image,'\\'); 2291 (void) WriteBlobByte(image,value[i]); 2292 } 2293 (void) WriteBlobByte(image,'}'); 2294 } 2295 } 2296 (void) WriteBlobByte(image,'\n'); 2297 property=GetNextImageProperty(image); 2298 } 2299 (void) WriteBlobString(image,"\f\n:\032"); 2300 if (image->montage != (char *) NULL) 2301 { 2302 /* 2303 Write montage tile directory. 2304 */ 2305 if (image->directory != (char *) NULL) 2306 (void) WriteBlob(image,strlen(image->directory),(unsigned char *) 2307 image->directory); 2308 (void) WriteBlobByte(image,'\0'); 2309 } 2310 if (image->profiles != (void *) NULL) 2311 { 2312 const char 2313 *name; 2314 2315 const StringInfo 2316 *profile; 2317 2318 /* 2319 Generic profile. 2320 */ 2321 ResetImageProfileIterator(image); 2322 name=GetNextImageProfile(image); 2323 while (name != (const char *) NULL) 2324 { 2325 profile=GetImageProfile(image,name); 2326 (void) WriteBlob(image,GetStringInfoLength(profile), 2327 GetStringInfoDatum(profile)); 2328 name=GetNextImageProfile(image); 2329 } 2330 } 2331 if (image->storage_class == PseudoClass) 2332 { 2333 size_t 2334 packet_size; 2335 2336 unsigned char 2337 *colormap, 2338 *q; 2339 2340 /* 2341 Allocate colormap. 2342 */ 2343 packet_size=(size_t) (3*quantum_info->depth/8); 2344 colormap=(unsigned char *) AcquireQuantumMemory(image->colors, 2345 packet_size*sizeof(*colormap)); 2346 if (colormap == (unsigned char *) NULL) 2347 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 2348 /* 2349 Write colormap to file. 2350 */ 2351 q=colormap; 2352 for (i=0; i < (ssize_t) image->colors; i++) 2353 { 2354 switch (quantum_info->depth) 2355 { 2356 default: 2357 ThrowWriterException(CorruptImageError,"ImageDepthNotSupported"); 2358 case 32: 2359 { 2360 register unsigned int 2361 pixel; 2362 2363 pixel=ScaleQuantumToLong(image->colormap[i].red); 2364 q=PopLongPixel(MSBEndian,pixel,q); 2365 pixel=ScaleQuantumToLong(image->colormap[i].green); 2366 q=PopLongPixel(MSBEndian,pixel,q); 2367 pixel=ScaleQuantumToLong(image->colormap[i].blue); 2368 q=PopLongPixel(MSBEndian,pixel,q); 2369 break; 2370 } 2371 case 16: 2372 { 2373 register unsigned short 2374 pixel; 2375 2376 pixel=ScaleQuantumToShort(image->colormap[i].red); 2377 q=PopShortPixel(MSBEndian,pixel,q); 2378 pixel=ScaleQuantumToShort(image->colormap[i].green); 2379 q=PopShortPixel(MSBEndian,pixel,q); 2380 pixel=ScaleQuantumToShort(image->colormap[i].blue); 2381 q=PopShortPixel(MSBEndian,pixel,q); 2382 break; 2383 } 2384 case 8: 2385 { 2386 register unsigned char 2387 pixel; 2388 2389 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].red); 2390 q=PopCharPixel(pixel,q); 2391 pixel=(unsigned char) ScaleQuantumToChar( 2392 image->colormap[i].green); 2393 q=PopCharPixel(pixel,q); 2394 pixel=(unsigned char) ScaleQuantumToChar(image->colormap[i].blue); 2395 q=PopCharPixel(pixel,q); 2396 break; 2397 } 2398 } 2399 } 2400 (void) WriteBlob(image,packet_size*image->colors,colormap); 2401 colormap=(unsigned char *) RelinquishMagickMemory(colormap); 2402 } 2403 /* 2404 Write image pixels to file. 2405 */ 2406 status=MagickTrue; 2407 switch (compression) 2408 { 2409#if defined(MAGICKCORE_BZLIB_DELEGATE) 2410 case BZipCompression: 2411 { 2412 int 2413 code; 2414 2415 (void) ResetMagickMemory(&bzip_info,0,sizeof(bzip_info)); 2416 bzip_info.bzalloc=AcquireBZIPMemory; 2417 bzip_info.bzfree=RelinquishBZIPMemory; 2418 code=BZ2_bzCompressInit(&bzip_info,(int) (image->quality == 2419 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9)), 2420 (int) image_info->verbose,0); 2421 if (code != BZ_OK) 2422 status=MagickFalse; 2423 break; 2424 } 2425#endif 2426#if defined(MAGICKCORE_LZMA_DELEGATE) 2427 case LZMACompression: 2428 { 2429 int 2430 code; 2431 2432 (void) ResetMagickMemory(&allocator,0,sizeof(allocator)); 2433 allocator.alloc=AcquireLZMAMemory; 2434 allocator.free=RelinquishLZMAMemory; 2435 lzma_info=initialize_lzma; 2436 lzma_info.allocator=&allocator; 2437 code=lzma_easy_encoder(&lzma_info,image->quality/10,LZMA_CHECK_SHA256); 2438 if (code != LZMA_OK) 2439 status=MagickTrue; 2440 break; 2441 } 2442#endif 2443#if defined(MAGICKCORE_ZLIB_DELEGATE) 2444 case LZWCompression: 2445 case ZipCompression: 2446 { 2447 int 2448 code; 2449 2450 (void) ResetMagickMemory(&zip_info,0,sizeof(zip_info)); 2451 zip_info.zalloc=AcquireZIPMemory; 2452 zip_info.zfree=RelinquishZIPMemory; 2453 code=deflateInit(&zip_info,(int) (image->quality == 2454 UndefinedCompressionQuality ? 7 : MagickMin(image->quality/10,9))); 2455 if (code != Z_OK) 2456 status=MagickFalse; 2457 break; 2458 } 2459#endif 2460 default: 2461 break; 2462 } 2463 quantum_type=GetQuantumType(image,exception); 2464 pixels=(unsigned char *) GetQuantumPixels(quantum_info); 2465 for (y=0; y < (ssize_t) image->rows; y++) 2466 { 2467 register const Quantum 2468 *magick_restrict p; 2469 2470 register ssize_t 2471 x; 2472 2473 if (status == MagickFalse) 2474 break; 2475 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 2476 if (p == (const Quantum *) NULL) 2477 break; 2478 q=pixels; 2479 switch (compression) 2480 { 2481#if defined(MAGICKCORE_BZLIB_DELEGATE) 2482 case BZipCompression: 2483 { 2484 bzip_info.next_in=(char *) pixels; 2485 bzip_info.avail_in=(unsigned int) (packet_size*image->columns); 2486 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2487 quantum_type,pixels,exception); 2488 do 2489 { 2490 int 2491 code; 2492 2493 bzip_info.next_out=(char *) compress_pixels; 2494 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size* 2495 image->columns); 2496 code=BZ2_bzCompress(&bzip_info,BZ_FLUSH); 2497 if (code != BZ_OK) 2498 status=MagickFalse; 2499 length=(size_t) (bzip_info.next_out-(char *) compress_pixels); 2500 if (length != 0) 2501 { 2502 (void) WriteBlobMSBLong(image,(unsigned int) length); 2503 (void) WriteBlob(image,length,compress_pixels); 2504 } 2505 } while (bzip_info.avail_in != 0); 2506 break; 2507 } 2508#endif 2509#if defined(MAGICKCORE_LZMA_DELEGATE) 2510 case LZMACompression: 2511 { 2512 lzma_info.next_in=pixels; 2513 lzma_info.avail_in=packet_size*image->columns; 2514 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2515 quantum_type,pixels,exception); 2516 do 2517 { 2518 int 2519 code; 2520 2521 lzma_info.next_out=compress_pixels; 2522 lzma_info.avail_out=packet_size*image->columns; 2523 code=lzma_code(&lzma_info,LZMA_RUN); 2524 if (code != LZMA_OK) 2525 status=MagickFalse; 2526 length=(size_t) (lzma_info.next_out-compress_pixels); 2527 if (length != 0) 2528 { 2529 (void) WriteBlobMSBLong(image,(unsigned int) length); 2530 (void) WriteBlob(image,length,compress_pixels); 2531 } 2532 } while (lzma_info.avail_in != 0); 2533 break; 2534 } 2535#endif 2536#if defined(MAGICKCORE_ZLIB_DELEGATE) 2537 case LZWCompression: 2538 case ZipCompression: 2539 { 2540 zip_info.next_in=pixels; 2541 zip_info.avail_in=(uInt) (packet_size*image->columns); 2542 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2543 quantum_type,pixels,exception); 2544 do 2545 { 2546 int 2547 code; 2548 2549 zip_info.next_out=compress_pixels; 2550 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns); 2551 code=deflate(&zip_info,Z_SYNC_FLUSH); 2552 if (code != Z_OK) 2553 status=MagickFalse; 2554 length=(size_t) (zip_info.next_out-compress_pixels); 2555 if (length != 0) 2556 { 2557 (void) WriteBlobMSBLong(image,(unsigned int) length); 2558 (void) WriteBlob(image,length,compress_pixels); 2559 } 2560 } while (zip_info.avail_in != 0); 2561 break; 2562 } 2563#endif 2564 case RLECompression: 2565 { 2566 length=0; 2567 GetPixelInfoPixel(image,p,&pixel); 2568 p+=GetPixelChannels(image); 2569 for (x=1; x < (ssize_t) image->columns; x++) 2570 { 2571 GetPixelInfoPixel(image,p,&target); 2572 if ((length < 255) && 2573 (IsPixelInfoEquivalent(&pixel,&target) != MagickFalse)) 2574 length++; 2575 else 2576 { 2577 q=PopRunlengthPacket(image,q,length,&pixel,exception); 2578 length=0; 2579 } 2580 GetPixelInfoPixel(image,p,&pixel); 2581 p+=GetPixelChannels(image); 2582 } 2583 q=PopRunlengthPacket(image,q,length,&pixel,exception); 2584 (void) WriteBlob(image,(size_t) (q-pixels),pixels); 2585 break; 2586 } 2587 default: 2588 { 2589 (void) ExportQuantumPixels(image,(CacheView *) NULL,quantum_info, 2590 quantum_type,pixels,exception); 2591 (void) WriteBlob(image,packet_size*image->columns,pixels); 2592 break; 2593 } 2594 } 2595 if (image->previous == (Image *) NULL) 2596 { 2597 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 2598 image->rows); 2599 if (status == MagickFalse) 2600 break; 2601 } 2602 } 2603 switch (compression) 2604 { 2605#if defined(MAGICKCORE_BZLIB_DELEGATE) 2606 case BZipCompression: 2607 { 2608 int 2609 code; 2610 2611 for ( ; ; ) 2612 { 2613 if (status == MagickFalse) 2614 break; 2615 bzip_info.next_out=(char *) compress_pixels; 2616 bzip_info.avail_out=(unsigned int) BZipMaxExtent(packet_size* 2617 image->columns); 2618 code=BZ2_bzCompress(&bzip_info,BZ_FINISH); 2619 length=(size_t) (bzip_info.next_out-(char *) compress_pixels); 2620 if (length != 0) 2621 { 2622 (void) WriteBlobMSBLong(image,(unsigned int) length); 2623 (void) WriteBlob(image,length,compress_pixels); 2624 } 2625 if (code == BZ_STREAM_END) 2626 break; 2627 } 2628 code=BZ2_bzCompressEnd(&bzip_info); 2629 if (code != BZ_OK) 2630 status=MagickFalse; 2631 break; 2632 } 2633#endif 2634#if defined(MAGICKCORE_LZMA_DELEGATE) 2635 case LZMACompression: 2636 { 2637 int 2638 code; 2639 2640 for ( ; ; ) 2641 { 2642 if (status == MagickFalse) 2643 break; 2644 lzma_info.next_out=compress_pixels; 2645 lzma_info.avail_out=packet_size*image->columns; 2646 code=lzma_code(&lzma_info,LZMA_FINISH); 2647 length=(size_t) (lzma_info.next_out-compress_pixels); 2648 if (length > 6) 2649 { 2650 (void) WriteBlobMSBLong(image,(unsigned int) length); 2651 (void) WriteBlob(image,length,compress_pixels); 2652 } 2653 if (code == LZMA_STREAM_END) 2654 break; 2655 } 2656 lzma_end(&lzma_info); 2657 break; 2658 } 2659#endif 2660#if defined(MAGICKCORE_ZLIB_DELEGATE) 2661 case LZWCompression: 2662 case ZipCompression: 2663 { 2664 int 2665 code; 2666 2667 for ( ; ; ) 2668 { 2669 if (status == MagickFalse) 2670 break; 2671 zip_info.next_out=compress_pixels; 2672 zip_info.avail_out=(uInt) ZipMaxExtent(packet_size*image->columns); 2673 code=deflate(&zip_info,Z_FINISH); 2674 length=(size_t) (zip_info.next_out-compress_pixels); 2675 if (length > 6) 2676 { 2677 (void) WriteBlobMSBLong(image,(unsigned int) length); 2678 (void) WriteBlob(image,length,compress_pixels); 2679 } 2680 if (code == Z_STREAM_END) 2681 break; 2682 } 2683 code=deflateEnd(&zip_info); 2684 if (code != Z_OK) 2685 status=MagickFalse; 2686 break; 2687 } 2688#endif 2689 default: 2690 break; 2691 } 2692 quantum_info=DestroyQuantumInfo(quantum_info); 2693 compress_pixels=(unsigned char *) RelinquishMagickMemory(compress_pixels); 2694 if (GetNextImageInList(image) == (Image *) NULL) 2695 break; 2696 image=SyncNextImageInList(image); 2697 status=SetImageProgress(image,SaveImagesTag,scene++,GetImageListLength( 2698 image)); 2699 if (status == MagickFalse) 2700 break; 2701 } while (image_info->adjoin != MagickFalse); 2702 (void) CloseBlob(image); 2703 return(status); 2704} 2705