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