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