1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % PPPP SSSSS 33333 % 7 % P P SS 33 % 8 % PPPP SSS 333 % 9 % P SS 33 % 10 % P SSSSS 33333 % 11 % % 12 % % 13 % Write Postscript Level III Format % 14 % % 15 % Software Design % 16 % Cristy % 17 % Lars Ruben Skyum % 18 % July 1992 % 19 % % 20 % % 21 % Copyright 1999-2019 ImageMagick Studio LLC, a non-profit organization % 22 % dedicated to making software imaging solutions freely available. % 23 % % 24 % You may not use this file except in compliance with the License. You may % 25 % obtain a copy of the License at % 26 % % 27 % https://imagemagick.org/script/license.php % 28 % % 29 % Unless required by applicable law or agreed to in writing, software % 30 % distributed under the License is distributed on an "AS IS" BASIS, % 31 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 32 % See the License for the specific language governing permissions and % 33 % limitations under the License. % 34 % % 35 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 36 % 37 % 38 */ 39 40 /* 42 Include declarations. 43 */ 44 #include "MagickCore/studio.h" 45 #include "MagickCore/artifact.h" 46 #include "MagickCore/attribute.h" 47 #include "MagickCore/blob.h" 48 #include "MagickCore/blob-private.h" 49 #include "MagickCore/cache.h" 50 #include "MagickCore/channel.h" 51 #include "MagickCore/color.h" 52 #include "MagickCore/color-private.h" 53 #include "MagickCore/compress.h" 54 #include "MagickCore/constitute.h" 55 #include "MagickCore/draw.h" 56 #include "MagickCore/exception.h" 57 #include "MagickCore/exception-private.h" 58 #include "MagickCore/geometry.h" 59 #include "MagickCore/image.h" 60 #include "MagickCore/image-private.h" 61 #include "MagickCore/list.h" 62 #include "MagickCore/magick.h" 63 #include "MagickCore/memory_.h" 64 #include "MagickCore/monitor.h" 65 #include "MagickCore/monitor-private.h" 66 #include "MagickCore/option.h" 67 #include "MagickCore/pixel-accessor.h" 68 #include "MagickCore/property.h" 69 #include "MagickCore/quantum-private.h" 70 #include "MagickCore/resource_.h" 71 #include "MagickCore/static.h" 72 #include "MagickCore/string_.h" 73 #include "MagickCore/module.h" 74 #include "MagickCore/token.h" 75 #include "MagickCore/utility.h" 76 #include "MagickCore/module.h" 77 78 /* 80 Define declarations. 81 */ 82 #define PS3_NoCompression "0" 83 #define PS3_FaxCompression "1" 84 #define PS3_JPEGCompression "2" 85 #define PS3_LZWCompression "3" 86 #define PS3_RLECompression "4" 87 #define PS3_ZipCompression "5" 88 89 #define PS3_RGBColorspace "0" 90 #define PS3_CMYKColorspace "1" 91 92 #define PS3_DirectClass "0" 93 #define PS3_PseudoClass "1" 94 95 #if defined(MAGICKCORE_TIFF_DELEGATE) 96 #define CCITTParam "-1" 97 #else 98 #define CCITTParam "0" 99 #endif 100 101 /* 103 Forward declarations. 104 */ 105 static MagickBooleanType 106 WritePS3Image(const ImageInfo *,Image *,ExceptionInfo *); 107 108 /* 110 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 111 % % 112 % % 113 % % 114 % R e g i s t e r P S 3 I m a g e % 115 % % 116 % % 117 % % 118 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 119 % 120 % RegisterPS3Image() adds properties for the PS3 image format to the list of 121 % supported formats. The properties include the image format tag, a method to 122 % read and/or write the format, whether the format supports the saving of more 123 % than one frame to the same file or blob, whether the format supports native 124 % in-memory I/O, and a brief description of the format. 125 % 126 % The format of the RegisterPS3Image method is: 127 % 128 % size_t RegisterPS3Image(void) 129 % 130 */ 131 ModuleExport size_t RegisterPS3Image(void) 132 { 133 MagickInfo 134 *entry; 135 136 entry=AcquireMagickInfo("PS3","EPS3","Level III Encapsulated PostScript"); 137 entry->encoder=(EncodeImageHandler *) WritePS3Image; 138 entry->mime_type=ConstantString("application/postscript"); 139 entry->flags|=CoderEncoderSeekableStreamFlag; 140 entry->flags^=CoderBlobSupportFlag; 141 (void) RegisterMagickInfo(entry); 142 entry=AcquireMagickInfo("PS3","PS3","Level III PostScript"); 143 entry->encoder=(EncodeImageHandler *) WritePS3Image; 144 entry->mime_type=ConstantString("application/postscript"); 145 entry->flags|=CoderEncoderSeekableStreamFlag; 146 entry->flags^=CoderBlobSupportFlag; 147 (void) RegisterMagickInfo(entry); 148 return(MagickImageCoderSignature); 149 } 150 151 /* 153 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 154 % % 155 % % 156 % % 157 % U n r e g i s t e r P S 3 I m a g e % 158 % % 159 % % 160 % % 161 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 162 % 163 % UnregisterPS3Image() removes format registrations made by the PS3 module 164 % from the list of supported formats. 165 % 166 % The format of the UnregisterPS3Image method is: 167 % 168 % UnregisterPS3Image(void) 169 % 170 */ 171 ModuleExport void UnregisterPS3Image(void) 172 { 173 (void) UnregisterMagickInfo("EPS3"); 174 (void) UnregisterMagickInfo("PS3"); 175 } 176 177 /* 179 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 180 % % 181 % % 182 % % 183 % W r i t e P S 3 I m a g e % 184 % % 185 % % 186 % % 187 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 188 % 189 % WritePS3Image() translates an image to encapsulated Postscript Level III 190 % for printing. If the supplied geometry is null, the image is centered on 191 % the Postscript page. Otherwise, the image is positioned as specified by the 192 % geometry. 193 % 194 % The format of the WritePS3Image method is: 195 % 196 % MagickBooleanType WritePS3Image(const ImageInfo *image_info, 197 % Image *image,ExceptionInfo *exception) 198 % 199 % A description of each parameter follows: 200 % 201 % o image_info: Specifies a pointer to a ImageInfo structure. 202 % 203 % o image: the image. 204 % 205 % o exception: return any errors or warnings in this structure. 206 % 207 */ 208 209 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, 210 Image *image,Image *inject_image,ExceptionInfo *exception) 211 { 212 Image 213 *group4_image; 214 215 ImageInfo 216 *write_info; 217 218 MagickBooleanType 219 status; 220 221 size_t 222 length; 223 224 unsigned char 225 *group4; 226 227 status=MagickTrue; 228 write_info=CloneImageInfo(image_info); 229 (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent); 230 (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent); 231 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception); 232 if (group4_image == (Image *) NULL) 233 return(MagickFalse); 234 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length, 235 exception); 236 group4_image=DestroyImage(group4_image); 237 if (group4 == (unsigned char *) NULL) 238 return(MagickFalse); 239 write_info=DestroyImageInfo(write_info); 240 if (WriteBlob(image,length,group4) != (ssize_t) length) 241 status=MagickFalse; 242 group4=(unsigned char *) RelinquishMagickMemory(group4); 243 return(status); 244 } 245 246 static MagickBooleanType SerializeImage(const ImageInfo *image_info, 247 Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) 248 { 249 MagickBooleanType 250 status; 251 252 register const Quantum 253 *p; 254 255 register ssize_t 256 x; 257 258 register unsigned char 259 *q; 260 261 ssize_t 262 y; 263 264 assert(image != (Image *) NULL); 265 assert(image->signature == MagickCoreSignature); 266 if (image->debug != MagickFalse) 267 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 268 status=MagickTrue; 269 *length=(image->colorspace == CMYKColorspace ? 4 : 3)*(size_t) 270 image->columns*image->rows; 271 *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); 272 if (*pixel_info == (MemoryInfo *) NULL) 273 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 274 q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); 275 for (y=0; y < (ssize_t) image->rows; y++) 276 { 277 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 278 if (p == (const Quantum *) NULL) 279 break; 280 if (image->colorspace != CMYKColorspace) 281 for (x=0; x < (ssize_t) image->columns; x++) 282 { 283 *q++=ScaleQuantumToChar(GetPixelRed(image,p)); 284 *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); 285 *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); 286 p+=GetPixelChannels(image); 287 } 288 else 289 for (x=0; x < (ssize_t) image->columns; x++) 290 { 291 *q++=ScaleQuantumToChar(GetPixelRed(image,p)); 292 *q++=ScaleQuantumToChar(GetPixelGreen(image,p)); 293 *q++=ScaleQuantumToChar(GetPixelBlue(image,p)); 294 *q++=ScaleQuantumToChar(GetPixelBlack(image,p)); 295 p+=GetPixelChannels(image); 296 } 297 if (image->previous == (Image *) NULL) 298 { 299 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 300 image->rows); 301 if (status == MagickFalse) 302 break; 303 } 304 } 305 if (status == MagickFalse) 306 *pixel_info=RelinquishVirtualMemory(*pixel_info); 307 return(status); 308 } 309 310 static MagickBooleanType SerializeImageChannel(const ImageInfo *image_info, 311 Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) 312 { 313 MagickBooleanType 314 status; 315 316 register const Quantum 317 *p; 318 319 register ssize_t 320 x; 321 322 register unsigned char 323 *q; 324 325 size_t 326 pack, 327 padded_columns; 328 329 ssize_t 330 y; 331 332 unsigned char 333 code, 334 bit; 335 336 assert(image != (Image *) NULL); 337 assert(image->signature == MagickCoreSignature); 338 if (image->debug != MagickFalse) 339 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 340 status=MagickTrue; 341 pack=SetImageMonochrome(image,exception) == MagickFalse ? 1UL : 8UL; 342 padded_columns=((image->columns+pack-1)/pack)*pack; 343 *length=(size_t) padded_columns*image->rows/pack; 344 *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); 345 if (*pixel_info == (MemoryInfo *) NULL) 346 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 347 q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); 348 for (y=0; y < (ssize_t) image->rows; y++) 349 { 350 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 351 if (p == (const Quantum *) NULL) 352 break; 353 if (pack == 1) 354 for (x=0; x < (ssize_t) image->columns; x++) 355 { 356 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p))); 357 p+=GetPixelChannels(image); 358 } 359 else 360 { 361 code='\0'; 362 for (x=0; x < (ssize_t) padded_columns; x++) 363 { 364 bit=(unsigned char) 0x00; 365 if (x < (ssize_t) image->columns) 366 bit=(unsigned char) (GetPixelLuma(image,p) == TransparentAlpha ? 367 0x01 : 0x00); 368 code=(code << 1)+bit; 369 if (((x+1) % pack) == 0) 370 { 371 *q++=code; 372 code='\0'; 373 } 374 p+=GetPixelChannels(image); 375 } 376 } 377 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 378 image->rows); 379 if (status == MagickFalse) 380 break; 381 } 382 if (status == MagickFalse) 383 *pixel_info=RelinquishVirtualMemory(*pixel_info); 384 return(status); 385 } 386 387 static MagickBooleanType SerializeImageIndexes(const ImageInfo *image_info, 388 Image *image,MemoryInfo **pixel_info,size_t *length,ExceptionInfo *exception) 389 { 390 MagickBooleanType 391 status; 392 393 register const Quantum 394 *p; 395 396 register ssize_t 397 x; 398 399 register unsigned char 400 *q; 401 402 ssize_t 403 y; 404 405 assert(image != (Image *) NULL); 406 assert(image->signature == MagickCoreSignature); 407 if (image->debug != MagickFalse) 408 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 409 status=MagickTrue; 410 *length=(size_t) image->columns*image->rows; 411 *pixel_info=AcquireVirtualMemory(*length,sizeof(*q)); 412 if (*pixel_info == (MemoryInfo *) NULL) 413 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 414 q=(unsigned char *) GetVirtualMemoryBlob(*pixel_info); 415 for (y=0; y < (ssize_t) image->rows; y++) 416 { 417 p=GetVirtualPixels(image,0,y,image->columns,1,exception); 418 if (p == (const Quantum *) NULL) 419 break; 420 for (x=0; x < (ssize_t) image->columns; x++) 421 { 422 *q++=(unsigned char) GetPixelIndex(image,p); 423 p+=GetPixelChannels(image); 424 } 425 if (image->previous == (Image *) NULL) 426 { 427 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y, 428 image->rows); 429 if (status == MagickFalse) 430 break; 431 } 432 } 433 if (status == MagickFalse) 434 *pixel_info=RelinquishVirtualMemory(*pixel_info); 435 return(status); 436 } 437 438 static MagickBooleanType WritePS3MaskImage(const ImageInfo *image_info, 439 Image *image,const CompressionType compression,ExceptionInfo *exception) 440 { 441 char 442 buffer[MagickPathExtent]; 443 444 Image 445 *mask_image; 446 447 MagickBooleanType 448 status; 449 450 MagickOffsetType 451 offset, 452 start, 453 stop; 454 455 MemoryInfo 456 *pixel_info; 457 458 register ssize_t 459 i; 460 461 size_t 462 length; 463 464 unsigned char 465 *pixels; 466 467 assert(image_info != (ImageInfo *) NULL); 468 assert(image_info->signature == MagickCoreSignature); 469 assert(image != (Image *) NULL); 470 assert(image->signature == MagickCoreSignature); 471 if (image->debug != MagickFalse) 472 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 473 assert(image->alpha_trait != UndefinedPixelTrait); 474 status=MagickTrue; 475 /* 476 Note BeginData DSC comment for update later. 477 */ 478 start=TellBlob(image); 479 if (start < 0) 480 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 481 (void) FormatLocaleString(buffer,MagickPathExtent, 482 "%%%%BeginData:%13ld %s Bytes\n",0L,compression == NoCompression ? 483 "ASCII" : "BINARY"); 484 (void) WriteBlobString(image,buffer); 485 stop=TellBlob(image); 486 if (stop < 0) 487 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 488 /* 489 Only lossless compressions for the mask. 490 */ 491 switch (compression) 492 { 493 case NoCompression: 494 default: 495 { 496 (void) FormatLocaleString(buffer,MagickPathExtent, 497 "currentfile %.20g %.20g " PS3_NoCompression 498 " ByteStreamDecodeFilter\n",(double) image->columns,(double) 499 image->rows); 500 break; 501 } 502 case FaxCompression: 503 case Group4Compression: 504 { 505 (void) FormatLocaleString(buffer,MagickPathExtent, 506 "currentfile %.20g %.20g " PS3_FaxCompression 507 " ByteStreamDecodeFilter\n",(double) image->columns,(double) 508 image->rows); 509 break; 510 } 511 case LZWCompression: 512 { 513 (void) FormatLocaleString(buffer,MagickPathExtent, 514 "currentfile %.20g %.20g " PS3_LZWCompression 515 " ByteStreamDecodeFilter\n",(double) image->columns,(double) 516 image->rows); 517 break; 518 } 519 case RLECompression: 520 { 521 (void) FormatLocaleString(buffer,MagickPathExtent, 522 "currentfile %.20g %.20g " PS3_RLECompression 523 " ByteStreamDecodeFilter\n",(double) image->columns,(double) 524 image->rows); 525 break; 526 } 527 case ZipCompression: 528 { 529 (void) FormatLocaleString(buffer,MagickPathExtent, 530 "currentfile %.20g %.20g " PS3_ZipCompression 531 " ByteStreamDecodeFilter\n",(double) image->columns,(double) 532 image->rows); 533 break; 534 } 535 } 536 (void) WriteBlobString(image,buffer); 537 (void) WriteBlobString(image,"/ReusableStreamDecode filter\n"); 538 mask_image=SeparateImage(image,AlphaChannel,exception); 539 if (mask_image == (Image *) NULL) 540 ThrowWriterException(CoderError,exception->reason); 541 (void) SetImageType(mask_image,BilevelType,exception); 542 (void) SetImageType(mask_image,PaletteType,exception); 543 mask_image->alpha_trait=UndefinedPixelTrait; 544 pixels=(unsigned char *) NULL; 545 length=0; 546 switch (compression) 547 { 548 case NoCompression: 549 default: 550 { 551 status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, 552 exception); 553 if (status == MagickFalse) 554 break; 555 Ascii85Initialize(image); 556 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 557 for (i=0; i < (ssize_t) length; i++) 558 Ascii85Encode(image,pixels[i]); 559 Ascii85Flush(image); 560 pixel_info=RelinquishVirtualMemory(pixel_info); 561 break; 562 } 563 case FaxCompression: 564 case Group4Compression: 565 { 566 if ((compression == FaxCompression) || 567 (LocaleCompare(CCITTParam,"0") == 0)) 568 status=HuffmanEncodeImage(image_info,image,mask_image,exception); 569 else 570 status=Huffman2DEncodeImage(image_info,image,mask_image,exception); 571 break; 572 } 573 case LZWCompression: 574 { 575 status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, 576 exception); 577 if (status == MagickFalse) 578 break; 579 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 580 status=LZWEncodeImage(image,length,pixels,exception); 581 pixel_info=RelinquishVirtualMemory(pixel_info); 582 break; 583 } 584 case RLECompression: 585 { 586 status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, 587 exception); 588 if (status == MagickFalse) 589 break; 590 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 591 status=PackbitsEncodeImage(image,length,pixels,exception); 592 pixel_info=RelinquishVirtualMemory(pixel_info); 593 break; 594 } 595 case ZipCompression: 596 { 597 status=SerializeImageChannel(image_info,mask_image,&pixel_info,&length, 598 exception); 599 if (status == MagickFalse) 600 break; 601 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 602 status=ZLIBEncodeImage(image,length,pixels,exception); 603 pixel_info=RelinquishVirtualMemory(pixel_info); 604 break; 605 } 606 } 607 mask_image=DestroyImage(mask_image); 608 (void) WriteBlobByte(image,'\n'); 609 length=(size_t) (TellBlob(image)-stop); 610 stop=TellBlob(image); 611 if (stop < 0) 612 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 613 offset=SeekBlob(image,start,SEEK_SET); 614 if (offset < 0) 615 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 616 (void) FormatLocaleString(buffer,MagickPathExtent, 617 "%%%%BeginData:%13ld %s Bytes\n",(long) length, 618 compression == NoCompression ? "ASCII" : "BINARY"); 619 (void) WriteBlobString(image,buffer); 620 offset=SeekBlob(image,stop,SEEK_SET); 621 if (offset < 0) 622 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 623 (void) WriteBlobString(image,"%%EndData\n"); 624 (void) WriteBlobString(image, "/mask_stream exch def\n"); 625 return(status); 626 } 627 628 static MagickBooleanType WritePS3Image(const ImageInfo *image_info,Image *image, 629 ExceptionInfo *exception) 630 { 631 static const char 632 *const PostscriptProlog[]= 633 { 634 "/ByteStreamDecodeFilter", 635 "{", 636 " /z exch def", 637 " /r exch def", 638 " /c exch def", 639 " z " PS3_NoCompression " eq { /ASCII85Decode filter } if", 640 " z " PS3_FaxCompression " eq", 641 " {", 642 " <<", 643 " /K " CCITTParam, 644 " /Columns c", 645 " /Rows r", 646 " >>", 647 " /CCITTFaxDecode filter", 648 " } if", 649 " z " PS3_JPEGCompression " eq { /DCTDecode filter } if", 650 " z " PS3_LZWCompression " eq { /LZWDecode filter } if", 651 " z " PS3_RLECompression " eq { /RunLengthDecode filter } if", 652 " z " PS3_ZipCompression " eq { /FlateDecode filter } if", 653 "} bind def", 654 "", 655 "/DirectClassImageDict", 656 "{", 657 " colorspace " PS3_RGBColorspace " eq", 658 " {", 659 " /DeviceRGB setcolorspace", 660 " <<", 661 " /ImageType 1", 662 " /Width columns", 663 " /Height rows", 664 " /BitsPerComponent 8", 665 " /DataSource pixel_stream", 666 " /MultipleDataSources false", 667 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 668 " /Decode [0 1 0 1 0 1]", 669 " >>", 670 " }", 671 " {", 672 " /DeviceCMYK setcolorspace", 673 " <<", 674 " /ImageType 1", 675 " /Width columns", 676 " /Height rows", 677 " /BitsPerComponent 8", 678 " /DataSource pixel_stream", 679 " /MultipleDataSources false", 680 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 681 " /Decode", 682 " compression " PS3_JPEGCompression " eq", 683 " { [1 0 1 0 1 0 1 0] }", 684 " { [0 1 0 1 0 1 0 1] }", 685 " ifelse", 686 " >>", 687 " }", 688 " ifelse", 689 "} bind def", 690 "", 691 "/PseudoClassImageDict", 692 "{", 693 " % Colors in colormap image.", 694 " currentfile buffer readline pop", 695 " token pop /colors exch def pop", 696 " colors 0 eq", 697 " {", 698 " % Depth of grayscale image.", 699 " currentfile buffer readline pop", 700 " token pop /bits exch def pop", 701 " /DeviceGray setcolorspace", 702 " <<", 703 " /ImageType 1", 704 " /Width columns", 705 " /Height rows", 706 " /BitsPerComponent bits", 707 " /Decode [0 1]", 708 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 709 " /DataSource pixel_stream", 710 " >>", 711 " }", 712 " {", 713 " % RGB colormap.", 714 " /colormap colors 3 mul string def", 715 " compression " PS3_NoCompression " eq", 716 " { currentfile /ASCII85Decode filter colormap readstring pop pop }", 717 " { currentfile colormap readstring pop pop }", 718 " ifelse", 719 " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace", 720 " <<", 721 " /ImageType 1", 722 " /Width columns", 723 " /Height rows", 724 " /BitsPerComponent 8", 725 " /Decode [0 255]", 726 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 727 " /DataSource pixel_stream", 728 " >>", 729 " }", 730 " ifelse", 731 "} bind def", 732 "", 733 "/NonMaskedImageDict", 734 "{", 735 " class " PS3_PseudoClass " eq", 736 " { PseudoClassImageDict }", 737 " { DirectClassImageDict }", 738 " ifelse", 739 "} bind def", 740 "", 741 "/MaskedImageDict", 742 "{", 743 " <<", 744 " /ImageType 3", 745 " /InterleaveType 3", 746 " /DataDict NonMaskedImageDict", 747 " /MaskDict", 748 " <<", 749 " /ImageType 1", 750 " /Width columns", 751 " /Height rows", 752 " /BitsPerComponent 1", 753 " /DataSource mask_stream", 754 " /MultipleDataSources false", 755 " /ImageMatrix [ columns 0 0 rows neg 0 rows]", 756 " /Decode [ 0 1 ]", 757 " >>", 758 " >>", 759 "} bind def", 760 "", 761 "/ClipImage", 762 "{} def", 763 "", 764 "/DisplayImage", 765 "{", 766 " gsave", 767 " /buffer 512 string def", 768 " % Translation.", 769 " currentfile buffer readline pop", 770 " token pop /x exch def", 771 " token pop /y exch def pop", 772 " x y translate", 773 " % Image size and font size.", 774 " currentfile buffer readline pop", 775 " token pop /x exch def", 776 " token pop /y exch def pop", 777 " currentfile buffer readline pop", 778 " token pop /pointsize exch def pop", 779 (const char *) NULL 780 }, 781 *const PostscriptEpilog[]= 782 { 783 " x y scale", 784 " % Clipping path.", 785 " currentfile buffer readline pop", 786 " token pop /clipped exch def pop", 787 " % Showpage.", 788 " currentfile buffer readline pop", 789 " token pop /sp exch def pop", 790 " % Image pixel size.", 791 " currentfile buffer readline pop", 792 " token pop /columns exch def", 793 " token pop /rows exch def pop", 794 " % Colorspace (RGB/CMYK).", 795 " currentfile buffer readline pop", 796 " token pop /colorspace exch def pop", 797 " % Transparency.", 798 " currentfile buffer readline pop", 799 " token pop /alpha exch def pop", 800 " % Stencil mask?", 801 " currentfile buffer readline pop", 802 " token pop /stencil exch def pop", 803 " % Image class (direct/pseudo).", 804 " currentfile buffer readline pop", 805 " token pop /class exch def pop", 806 " % Compression type.", 807 " currentfile buffer readline pop", 808 " token pop /compression exch def pop", 809 " % Clip and render.", 810 " /pixel_stream currentfile columns rows compression ByteStreamDecodeFilter def", 811 " clipped { ClipImage } if", 812 " alpha stencil not and", 813 " { MaskedImageDict mask_stream resetfile }", 814 " { NonMaskedImageDict }", 815 " ifelse", 816 " stencil { 0 setgray imagemask } { image } ifelse", 817 " grestore", 818 " sp { showpage } if", 819 "} bind def", 820 (const char *) NULL 821 }; 822 823 char 824 buffer[MagickPathExtent], 825 date[MagickPathExtent], 826 **labels, 827 page_geometry[MagickPathExtent]; 828 829 CompressionType 830 compression; 831 832 const char 833 *option, 834 *const *q, 835 *value; 836 837 double 838 pointsize; 839 840 GeometryInfo 841 geometry_info; 842 843 MagickBooleanType 844 status; 845 846 MagickOffsetType 847 offset, 848 scene, 849 start, 850 stop; 851 852 MagickStatusType 853 flags; 854 855 MemoryInfo 856 *pixel_info; 857 858 PointInfo 859 delta, 860 resolution, 861 scale; 862 863 RectangleInfo 864 geometry, 865 media_info, 866 page_info; 867 868 register ssize_t 869 i; 870 871 SegmentInfo 872 bounds; 873 874 size_t 875 imageListLength, 876 length, 877 page, 878 pixel, 879 text_size; 880 881 ssize_t 882 j; 883 884 time_t 885 timer; 886 887 unsigned char 888 *pixels; 889 890 /* 891 Open output image file. 892 */ 893 assert(image_info != (const ImageInfo *) NULL); 894 assert(image_info->signature == MagickCoreSignature); 895 assert(image != (Image *) NULL); 896 assert(image->signature == MagickCoreSignature); 897 if (image->debug != MagickFalse) 898 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 899 assert(exception != (ExceptionInfo *) NULL); 900 assert(exception->signature == MagickCoreSignature); 901 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception); 902 if (status == MagickFalse) 903 return(MagickFalse); 904 compression=image->compression; 905 if (image_info->compression != UndefinedCompression) 906 compression=image_info->compression; 907 switch (compression) 908 { 909 case FaxCompression: 910 case Group4Compression: 911 { 912 if ((SetImageMonochrome(image,exception) == MagickFalse) || 913 (image->alpha_trait != UndefinedPixelTrait)) 914 compression=RLECompression; 915 break; 916 } 917 #if !defined(MAGICKCORE_JPEG_DELEGATE) 918 case JPEGCompression: 919 { 920 compression=RLECompression; 921 (void) ThrowMagickException(exception,GetMagickModule(), 922 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", 923 image->filename); 924 break; 925 } 926 #endif 927 #if !defined(MAGICKCORE_ZLIB_DELEGATE) 928 case ZipCompression: 929 { 930 compression=RLECompression; 931 (void) ThrowMagickException(exception,GetMagickModule(), 932 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)", 933 image->filename); 934 break; 935 } 936 #endif 937 default: 938 break; 939 } 940 (void) memset(&bounds,0,sizeof(bounds)); 941 page=0; 942 scene=0; 943 imageListLength=GetImageListLength(image); 944 do 945 { 946 /* 947 Scale relative to dots-per-inch. 948 */ 949 delta.x=DefaultResolution; 950 delta.y=DefaultResolution; 951 resolution.x=image->resolution.x; 952 resolution.y=image->resolution.y; 953 if ((resolution.x == 0.0) || (resolution.y == 0.0)) 954 { 955 flags=ParseGeometry(PSDensityGeometry,&geometry_info); 956 resolution.x=geometry_info.rho; 957 resolution.y=geometry_info.sigma; 958 if ((flags & SigmaValue) == 0) 959 resolution.y=resolution.x; 960 } 961 if (image_info->density != (char *) NULL) 962 { 963 flags=ParseGeometry(image_info->density,&geometry_info); 964 resolution.x=geometry_info.rho; 965 resolution.y=geometry_info.sigma; 966 if ((flags & SigmaValue) == 0) 967 resolution.y=resolution.x; 968 } 969 if (image->units == PixelsPerCentimeterResolution) 970 { 971 resolution.x=(size_t) ((100.0*2.54*resolution.x+0.5)/100.0); 972 resolution.y=(size_t) ((100.0*2.54*resolution.y+0.5)/100.0); 973 } 974 SetGeometry(image,&geometry); 975 (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g", 976 (double) image->columns,(double) image->rows); 977 if (image_info->page != (char *) NULL) 978 (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent); 979 else 980 if ((image->page.width != 0) && (image->page.height != 0)) 981 (void) FormatLocaleString(page_geometry,MagickPathExtent, 982 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) 983 image->page.height,(double) image->page.x,(double) image->page.y); 984 else 985 if ((image->gravity != UndefinedGravity) && 986 (LocaleCompare(image_info->magick,"PS") == 0)) 987 (void) CopyMagickString(page_geometry,PSPageGeometry,MagickPathExtent); 988 (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent); 989 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, 990 &geometry.width,&geometry.height); 991 scale.x=(double) (geometry.width*delta.x)/resolution.x; 992 geometry.width=(size_t) floor(scale.x+0.5); 993 scale.y=(double) (geometry.height*delta.y)/resolution.y; 994 geometry.height=(size_t) floor(scale.y+0.5); 995 (void) ParseAbsoluteGeometry(page_geometry,&media_info); 996 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception); 997 if (image->gravity != UndefinedGravity) 998 { 999 geometry.x=(-page_info.x); 1000 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows); 1001 } 1002 pointsize=12.0; 1003 if (image_info->pointsize != 0.0) 1004 pointsize=image_info->pointsize; 1005 text_size=0; 1006 value=GetImageProperty(image,"label",exception); 1007 if (value != (const char *) NULL) 1008 text_size=(size_t) (MultilineCensus(value)*pointsize+12); 1009 page++; 1010 if (page == 1) 1011 { 1012 /* 1013 Postscript header on the first page. 1014 */ 1015 if (LocaleCompare(image_info->magick,"PS3") == 0) 1016 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MagickPathExtent); 1017 else 1018 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n", 1019 MagickPathExtent); 1020 (void) WriteBlobString(image,buffer); 1021 (void) FormatLocaleString(buffer,MagickPathExtent, 1022 "%%%%Creator: ImageMagick %s\n",MagickLibVersionText); 1023 (void) WriteBlobString(image,buffer); 1024 (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Title: %s\n", 1025 image->filename); 1026 (void) WriteBlobString(image,buffer); 1027 timer=time((time_t *) NULL); 1028 (void) FormatMagickTime(timer,MagickPathExtent,date); 1029 (void) FormatLocaleString(buffer,MagickPathExtent, 1030 "%%%%CreationDate: %s\n",date); 1031 (void) WriteBlobString(image,buffer); 1032 bounds.x1=(double) geometry.x; 1033 bounds.y1=(double) geometry.y; 1034 bounds.x2=(double) geometry.x+scale.x; 1035 bounds.y2=(double) geometry.y+scale.y+text_size; 1036 if ((image_info->adjoin != MagickFalse) && 1037 (GetNextImageInList(image) != (Image *) NULL)) 1038 { 1039 (void) WriteBlobString(image,"%%BoundingBox: (atend)\n"); 1040 (void) WriteBlobString(image,"%%HiResBoundingBox: (atend)\n"); 1041 } 1042 else 1043 { 1044 (void) FormatLocaleString(buffer,MagickPathExtent, 1045 "%%%%BoundingBox: %g %g %g %g\n",ceil(bounds.x1-0.5), 1046 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); 1047 (void) WriteBlobString(image,buffer); 1048 (void) FormatLocaleString(buffer,MagickPathExtent, 1049 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1, 1050 bounds.y1,bounds.x2,bounds.y2); 1051 (void) WriteBlobString(image,buffer); 1052 if (image->colorspace == CMYKColorspace) 1053 (void) WriteBlobString(image, 1054 "%%DocumentProcessColors: Cyan Magenta Yellow Black\n"); 1055 else 1056 if (SetImageGray(image,exception) != MagickFalse) 1057 (void) WriteBlobString(image, 1058 "%%DocumentProcessColors: Black\n"); 1059 } 1060 /* 1061 Font resources 1062 */ 1063 value=GetImageProperty(image,"label",exception); 1064 if (value != (const char *) NULL) 1065 (void) WriteBlobString(image, 1066 "%%DocumentNeededResources: font Helvetica\n"); 1067 (void) WriteBlobString(image,"%%LanguageLevel: 3\n"); 1068 /* 1069 Pages, orientation and order. 1070 */ 1071 if (LocaleCompare(image_info->magick,"PS3") != 0) 1072 (void) WriteBlobString(image,"%%Pages: 1\n"); 1073 else 1074 { 1075 (void) WriteBlobString(image,"%%Orientation: Portrait\n"); 1076 (void) WriteBlobString(image,"%%PageOrder: Ascend\n"); 1077 if (image_info->adjoin == MagickFalse) 1078 (void) CopyMagickString(buffer,"%%Pages: 1\n",MagickPathExtent); 1079 else 1080 (void) FormatLocaleString(buffer,MagickPathExtent, 1081 "%%%%Pages: %.20g\n",(double) imageListLength); 1082 (void) WriteBlobString(image,buffer); 1083 } 1084 if (image->colorspace == CMYKColorspace) 1085 (void) WriteBlobString(image, 1086 "%%DocumentProcessColors: Cyan Magenta Yellow Black\n"); 1087 (void) WriteBlobString(image,"%%EndComments\n"); 1088 /* 1089 The static postscript procedures prolog. 1090 */ 1091 (void)WriteBlobString(image,"%%BeginProlog\n"); 1092 for (q=PostscriptProlog; *q; q++) 1093 { 1094 (void) WriteBlobString(image,*q); 1095 (void) WriteBlobByte(image,'\n'); 1096 } 1097 /* 1098 One label line for each line in label string. 1099 */ 1100 value=GetImageProperty(image,"label",exception); 1101 if (value != (const char *) NULL) 1102 { 1103 (void) WriteBlobString(image,"\n %% Labels.\n /Helvetica " 1104 " findfont pointsize scalefont setfont\n"); 1105 for (i=(ssize_t) MultilineCensus(value)-1; i >= 0; i--) 1106 { 1107 (void) WriteBlobString(image, 1108 " currentfile buffer readline pop token pop\n"); 1109 (void) FormatLocaleString(buffer,MagickPathExtent, 1110 " 0 y %g add moveto show pop\n",i*pointsize+12); 1111 (void) WriteBlobString(image,buffer); 1112 } 1113 } 1114 /* 1115 The static postscript procedures epilog. 1116 */ 1117 for (q=PostscriptEpilog; *q; q++) 1118 { 1119 (void) WriteBlobString(image,*q); 1120 (void) WriteBlobByte(image,'\n'); 1121 } 1122 (void)WriteBlobString(image,"%%EndProlog\n"); 1123 } 1124 (void) FormatLocaleString(buffer,MagickPathExtent,"%%%%Page: 1 %.20g\n", 1125 (double) page); 1126 (void) WriteBlobString(image,buffer); 1127 /* 1128 Page bounding box. 1129 */ 1130 (void) FormatLocaleString(buffer,MagickPathExtent, 1131 "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x, 1132 (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+ 1133 (double) (geometry.height+text_size)); 1134 (void) WriteBlobString(image,buffer); 1135 /* 1136 Page process colors if not RGB. 1137 */ 1138 if (image->colorspace == CMYKColorspace) 1139 (void) WriteBlobString(image, 1140 "%%PageProcessColors: Cyan Magenta Yellow Black\n"); 1141 else 1142 if (SetImageGray(image,exception) != MagickFalse) 1143 (void) WriteBlobString(image,"%%PageProcessColors: Black\n"); 1144 /* 1145 Adjust document bounding box to bound page bounding box. 1146 */ 1147 if ((double) geometry.x < bounds.x1) 1148 bounds.x1=(double) geometry.x; 1149 if ((double) geometry.y < bounds.y1) 1150 bounds.y1=(double) geometry.y; 1151 if ((double) (geometry.x+scale.x) > bounds.x2) 1152 bounds.x2=(double) geometry.x+scale.x; 1153 if ((double) (geometry.y+scale.y+text_size) > bounds.y2) 1154 bounds.y2=(double) geometry.y+scale.y+text_size; 1155 /* 1156 Page font resource if there's a label. 1157 */ 1158 value=GetImageProperty(image,"label",exception); 1159 if (value != (const char *) NULL) 1160 (void) WriteBlobString(image,"%%PageResources: font Helvetica\n"); 1161 /* 1162 PS clipping path from Photoshop clipping path. 1163 */ 1164 if (((image->channels & WriteMaskChannel) != 0) || 1165 (LocaleNCompare("8BIM:",image->magick_filename,5) != 0)) 1166 (void) WriteBlobString(image,"/ClipImage {} def\n"); 1167 else 1168 { 1169 const char 1170 *value; 1171 1172 value=GetImageProperty(image,image->magick_filename,exception); 1173 if (value == (const char *) NULL) 1174 return(MagickFalse); 1175 (void) WriteBlobString(image,value); 1176 (void) WriteBlobByte(image,'\n'); 1177 } 1178 /* 1179 Push a dictionary for our own def's if this an EPS. 1180 */ 1181 if (LocaleCompare(image_info->magick,"PS3") != 0) 1182 (void) WriteBlobString(image,"userdict begin\n"); 1183 /* 1184 Image mask. 1185 */ 1186 if ((image->alpha_trait != UndefinedPixelTrait) && 1187 (WritePS3MaskImage(image_info,image,compression,exception) == MagickFalse)) 1188 { 1189 (void) CloseBlob(image); 1190 return(MagickFalse); 1191 } 1192 /* 1193 Remember position of BeginData comment so we can update it. 1194 */ 1195 start=TellBlob(image); 1196 if (start < 0) 1197 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 1198 (void) FormatLocaleString(buffer,MagickPathExtent, 1199 "%%%%BeginData:%13ld %s Bytes\n",0L, 1200 compression == NoCompression ? "ASCII" : "BINARY"); 1201 (void) WriteBlobString(image,buffer); 1202 stop=TellBlob(image); 1203 if (stop < 0) 1204 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 1205 (void) WriteBlobString(image,"DisplayImage\n"); 1206 /* 1207 Translate, scale, and font point size. 1208 */ 1209 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n%g %g\n%g\n", 1210 (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize); 1211 (void) WriteBlobString(image,buffer); 1212 /* 1213 Output labels. 1214 */ 1215 labels=(char **) NULL; 1216 value=GetImageProperty(image,"label",exception); 1217 if (value != (const char *) NULL) 1218 labels=StringToList(value); 1219 if (labels != (char **) NULL) 1220 { 1221 for (i=0; labels[i] != (char *) NULL; i++) 1222 { 1223 if (compression != NoCompression) 1224 { 1225 for (j=0; labels[i][j] != '\0'; j++) 1226 (void) WriteBlobByte(image,(unsigned char) labels[i][j]); 1227 (void) WriteBlobByte(image,'\n'); 1228 } 1229 else 1230 { 1231 (void) WriteBlobString(image,"<~"); 1232 Ascii85Initialize(image); 1233 for (j=0; labels[i][j] != '\0'; j++) 1234 Ascii85Encode(image,(unsigned char) labels[i][j]); 1235 Ascii85Flush(image); 1236 } 1237 labels[i]=DestroyString(labels[i]); 1238 } 1239 labels=(char **) RelinquishMagickMemory(labels); 1240 } 1241 /* 1242 Photoshop clipping path active? 1243 */ 1244 if (((image->channels & WriteMaskChannel) != 0) && 1245 (LocaleNCompare("8BIM:",image->magick_filename,5) == 0)) 1246 (void) WriteBlobString(image,"true\n"); 1247 else 1248 (void) WriteBlobString(image,"false\n"); 1249 /* 1250 Showpage for non-EPS. 1251 */ 1252 (void) WriteBlobString(image, LocaleCompare(image_info->magick,"PS3") == 0 ? 1253 "true\n" : "false\n"); 1254 /* 1255 Image columns, rows, and color space. 1256 */ 1257 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g\n%s\n", 1258 (double) image->columns,(double) image->rows,image->colorspace == 1259 CMYKColorspace ? PS3_CMYKColorspace : PS3_RGBColorspace); 1260 (void) WriteBlobString(image,buffer); 1261 /* 1262 Masked image? 1263 */ 1264 (void) WriteBlobString(image,image->alpha_trait != UndefinedPixelTrait ? 1265 "true\n" : "false\n"); 1266 /* 1267 Render with imagemask operator? 1268 */ 1269 option=GetImageOption(image_info,"ps3:imagemask"); 1270 (void) WriteBlobString(image,((option != (const char *) NULL) && 1271 (SetImageMonochrome(image,exception) != MagickFalse)) ? 1272 "true\n" : "false\n"); 1273 /* 1274 Output pixel data. 1275 */ 1276 pixels=(unsigned char *) NULL; 1277 length=0; 1278 if ((image_info->type != TrueColorType) && 1279 (image_info->type != TrueColorAlphaType) && 1280 (image_info->type != ColorSeparationType) && 1281 (image_info->type != ColorSeparationAlphaType) && 1282 (image->colorspace != CMYKColorspace) && 1283 ((SetImageGray(image,exception) != MagickFalse) || 1284 (SetImageMonochrome(image,exception) != MagickFalse))) 1285 { 1286 /* 1287 Gray images. 1288 */ 1289 (void) WriteBlobString(image,PS3_PseudoClass"\n"); 1290 switch (compression) 1291 { 1292 case NoCompression: 1293 default: 1294 { 1295 (void) WriteBlobString(image,PS3_NoCompression"\n"); 1296 break; 1297 } 1298 case FaxCompression: 1299 case Group4Compression: 1300 { 1301 (void) WriteBlobString(image,PS3_FaxCompression"\n"); 1302 break; 1303 } 1304 case JPEGCompression: 1305 { 1306 (void) WriteBlobString(image,PS3_JPEGCompression"\n"); 1307 break; 1308 } 1309 case LZWCompression: 1310 { 1311 (void) WriteBlobString(image,PS3_LZWCompression"\n"); 1312 break; 1313 } 1314 case RLECompression: 1315 { 1316 (void) WriteBlobString(image,PS3_RLECompression"\n"); 1317 break; 1318 } 1319 case ZipCompression: 1320 { 1321 (void) WriteBlobString(image,PS3_ZipCompression"\n"); 1322 break; 1323 } 1324 } 1325 /* 1326 Number of colors -- 0 for single component non-color mapped data. 1327 */ 1328 (void) WriteBlobString(image,"0\n"); 1329 /* 1330 1 bit or 8 bit components? 1331 */ 1332 (void) FormatLocaleString(buffer,MagickPathExtent,"%d\n", 1333 SetImageMonochrome(image,exception) != MagickFalse ? 1 : 8); 1334 (void) WriteBlobString(image,buffer); 1335 /* 1336 Image data. 1337 */ 1338 if (compression == JPEGCompression) 1339 status=InjectImageBlob(image_info,image,image,"jpeg",exception); 1340 else 1341 if ((compression == FaxCompression) || 1342 (compression == Group4Compression)) 1343 { 1344 if (LocaleCompare(CCITTParam,"0") == 0) 1345 status=HuffmanEncodeImage(image_info,image,image,exception); 1346 else 1347 status=Huffman2DEncodeImage(image_info,image,image,exception); 1348 } 1349 else 1350 { 1351 status=SerializeImageChannel(image_info,image,&pixel_info,&length, 1352 exception); 1353 if (status == MagickFalse) 1354 { 1355 (void) CloseBlob(image); 1356 return(MagickFalse); 1357 } 1358 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1359 switch (compression) 1360 { 1361 case NoCompression: 1362 default: 1363 { 1364 Ascii85Initialize(image); 1365 for (i=0; i < (ssize_t) length; i++) 1366 Ascii85Encode(image,pixels[i]); 1367 Ascii85Flush(image); 1368 status=MagickTrue; 1369 break; 1370 } 1371 case LZWCompression: 1372 { 1373 status=LZWEncodeImage(image,length,pixels,exception); 1374 break; 1375 } 1376 case RLECompression: 1377 { 1378 status=PackbitsEncodeImage(image,length,pixels,exception); 1379 break; 1380 } 1381 case ZipCompression: 1382 { 1383 status=ZLIBEncodeImage(image,length,pixels,exception); 1384 break; 1385 } 1386 } 1387 pixel_info=RelinquishVirtualMemory(pixel_info); 1388 } 1389 } 1390 else 1391 if ((image->storage_class == DirectClass) || (image->colors > 256) || 1392 (compression == JPEGCompression)) 1393 { 1394 /* 1395 Truecolor image. 1396 */ 1397 (void) WriteBlobString(image,PS3_DirectClass"\n"); 1398 switch (compression) 1399 { 1400 case NoCompression: 1401 default: 1402 { 1403 (void) WriteBlobString(image,PS3_NoCompression"\n"); 1404 break; 1405 } 1406 case RLECompression: 1407 { 1408 (void) WriteBlobString(image,PS3_RLECompression"\n"); 1409 break; 1410 } 1411 case JPEGCompression: 1412 { 1413 (void) WriteBlobString(image,PS3_JPEGCompression"\n"); 1414 break; 1415 } 1416 case LZWCompression: 1417 { 1418 (void) WriteBlobString(image,PS3_LZWCompression"\n"); 1419 break; 1420 } 1421 case ZipCompression: 1422 { 1423 (void) WriteBlobString(image,PS3_ZipCompression"\n"); 1424 break; 1425 } 1426 } 1427 /* 1428 Image data. 1429 */ 1430 if (compression == JPEGCompression) 1431 status=InjectImageBlob(image_info,image,image,"jpeg",exception); 1432 else 1433 { 1434 /* 1435 Stream based compressions. 1436 */ 1437 status=SerializeImage(image_info,image,&pixel_info,&length, 1438 exception); 1439 if (status == MagickFalse) 1440 { 1441 (void) CloseBlob(image); 1442 return(MagickFalse); 1443 } 1444 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1445 switch (compression) 1446 { 1447 case NoCompression: 1448 default: 1449 { 1450 Ascii85Initialize(image); 1451 for (i=0; i < (ssize_t) length; i++) 1452 Ascii85Encode(image,pixels[i]); 1453 Ascii85Flush(image); 1454 status=MagickTrue; 1455 break; 1456 } 1457 case RLECompression: 1458 { 1459 status=PackbitsEncodeImage(image,length,pixels,exception); 1460 break; 1461 } 1462 case LZWCompression: 1463 { 1464 status=LZWEncodeImage(image,length,pixels,exception); 1465 break; 1466 } 1467 case ZipCompression: 1468 { 1469 status=ZLIBEncodeImage(image,length,pixels,exception); 1470 break; 1471 } 1472 } 1473 pixel_info=RelinquishVirtualMemory(pixel_info); 1474 } 1475 } 1476 else 1477 { 1478 /* 1479 Colormapped images. 1480 */ 1481 (void) WriteBlobString(image,PS3_PseudoClass"\n"); 1482 switch (compression) 1483 { 1484 case NoCompression: 1485 default: 1486 { 1487 (void) WriteBlobString(image,PS3_NoCompression"\n"); 1488 break; 1489 } 1490 case RLECompression: 1491 { 1492 (void) WriteBlobString(image,PS3_RLECompression"\n"); 1493 break; 1494 } 1495 case LZWCompression: 1496 { 1497 (void) WriteBlobString(image,PS3_LZWCompression"\n"); 1498 break; 1499 } 1500 case ZipCompression: 1501 { 1502 (void) WriteBlobString(image,PS3_ZipCompression"\n"); 1503 break; 1504 } 1505 } 1506 /* 1507 Number of colors in color map. 1508 */ 1509 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n", 1510 (double) image->colors); 1511 (void) WriteBlobString(image,buffer); 1512 /* 1513 Color map - uncompressed. 1514 */ 1515 if ((compression != NoCompression) && 1516 (compression != UndefinedCompression)) 1517 { 1518 for (i=0; i < (ssize_t) image->colors; i++) 1519 { 1520 pixel=ScaleQuantumToChar(image->colormap[i].red); 1521 (void) WriteBlobByte(image,(unsigned char) pixel); 1522 pixel=ScaleQuantumToChar(image->colormap[i].green); 1523 (void) WriteBlobByte(image,(unsigned char) pixel); 1524 pixel=ScaleQuantumToChar(image->colormap[i].blue); 1525 (void) WriteBlobByte(image,(unsigned char) pixel); 1526 } 1527 } 1528 else 1529 { 1530 Ascii85Initialize(image); 1531 for (i=0; i < (ssize_t) image->colors; i++) 1532 { 1533 pixel=ScaleQuantumToChar(image->colormap[i].red); 1534 Ascii85Encode(image,(unsigned char) pixel); 1535 pixel=ScaleQuantumToChar(image->colormap[i].green); 1536 Ascii85Encode(image,(unsigned char) pixel); 1537 pixel=ScaleQuantumToChar(image->colormap[i].blue); 1538 Ascii85Encode(image,(unsigned char) pixel); 1539 } 1540 Ascii85Flush(image); 1541 } 1542 status=SerializeImageIndexes(image_info,image,&pixel_info,&length, 1543 exception); 1544 if (status == MagickFalse) 1545 { 1546 (void) CloseBlob(image); 1547 return(MagickFalse); 1548 } 1549 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info); 1550 switch (compression) 1551 { 1552 case NoCompression: 1553 default: 1554 { 1555 Ascii85Initialize(image); 1556 for (i=0; i < (ssize_t) length; i++) 1557 Ascii85Encode(image,pixels[i]); 1558 Ascii85Flush(image); 1559 status=MagickTrue; 1560 break; 1561 } 1562 case RLECompression: 1563 { 1564 status=PackbitsEncodeImage(image,length,pixels,exception); 1565 break; 1566 } 1567 case LZWCompression: 1568 { 1569 status=LZWEncodeImage(image,length,pixels,exception); 1570 break; 1571 } 1572 case ZipCompression: 1573 { 1574 status=ZLIBEncodeImage(image,length,pixels,exception); 1575 break; 1576 } 1577 } 1578 pixel_info=RelinquishVirtualMemory(pixel_info); 1579 } 1580 (void) WriteBlobByte(image,'\n'); 1581 if (status == MagickFalse) 1582 { 1583 (void) CloseBlob(image); 1584 return(MagickFalse); 1585 } 1586 /* 1587 Update BeginData now that we know the data size. 1588 */ 1589 length=(size_t) (TellBlob(image)-stop); 1590 stop=TellBlob(image); 1591 if (stop < 0) 1592 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 1593 offset=SeekBlob(image,start,SEEK_SET); 1594 if (offset < 0) 1595 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 1596 (void) FormatLocaleString(buffer,MagickPathExtent, 1597 "%%%%BeginData:%13ld %s Bytes\n",(long) length, 1598 compression == NoCompression ? "ASCII" : "BINARY"); 1599 (void) WriteBlobString(image,buffer); 1600 offset=SeekBlob(image,stop,SEEK_SET); 1601 (void) WriteBlobString(image,"%%EndData\n"); 1602 /* 1603 End private dictionary if this an EPS. 1604 */ 1605 if (LocaleCompare(image_info->magick,"PS3") != 0) 1606 (void) WriteBlobString(image,"end\n"); 1607 (void) WriteBlobString(image,"%%PageTrailer\n"); 1608 if (GetNextImageInList(image) == (Image *) NULL) 1609 break; 1610 image=SyncNextImageInList(image); 1611 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength); 1612 if (status == MagickFalse) 1613 break; 1614 } while (image_info->adjoin != MagickFalse); 1615 (void) WriteBlobString(image,"%%Trailer\n"); 1616 if (page > 1) 1617 { 1618 (void) FormatLocaleString(buffer,MagickPathExtent, 1619 "%%%%BoundingBox: %g %g %g %g\n",ceil(bounds.x1-0.5), 1620 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); 1621 (void) WriteBlobString(image,buffer); 1622 (void) FormatLocaleString(buffer,MagickPathExtent, 1623 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1,bounds.x2, 1624 bounds.y2); 1625 (void) WriteBlobString(image,buffer); 1626 } 1627 (void) WriteBlobString(image,"%%EOF\n"); 1628 (void) CloseBlob(image); 1629 return(MagickTrue); 1630 } 1631