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