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