ps2.c revision d05ecd1dab44b782f4f1e145b0a1f36c7217b8a4
1/* 2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3% % 4% % 5% % 6% PPPP SSSSS 22222 % 7% P P SS 22 % 8% PPPP SSS 222 % 9% P SS 22 % 10% P SSSSS 22222 % 11% % 12% % 13% Write Postscript Level II Format % 14% % 15% Software Design % 16% John Cristy % 17% July 1992 % 18% % 19% % 20% Copyright 1999-2011 ImageMagick Studio LLC, a non-profit organization % 21% dedicated to making software imaging solutions freely available. % 22% % 23% You may not use this file except in compliance with the License. You may % 24% obtain a copy of the License at % 25% % 26% http://www.imagemagick.org/script/license.php % 27% % 28% Unless required by applicable law or agreed to in writing, software % 29% distributed under the License is distributed on an "AS IS" BASIS, % 30% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 31% See the License for the specific language governing permissions and % 32% limitations under the License. % 33% % 34%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 35% 36% 37*/ 38 39/* 40 Include declarations. 41*/ 42#include "magick/studio.h" 43#include "magick/blob.h" 44#include "magick/blob-private.h" 45#include "magick/cache.h" 46#include "magick/color.h" 47#include "magick/color-private.h" 48#include "magick/compress.h" 49#include "magick/constitute.h" 50#include "magick/draw.h" 51#include "magick/exception.h" 52#include "magick/exception-private.h" 53#include "magick/geometry.h" 54#include "magick/image.h" 55#include "magick/image-private.h" 56#include "magick/list.h" 57#include "magick/magick.h" 58#include "magick/memory_.h" 59#include "magick/monitor.h" 60#include "magick/monitor-private.h" 61#include "magick/monitor-private.h" 62#include "magick/option.h" 63#include "magick/resource_.h" 64#include "magick/property.h" 65#include "magick/quantum-private.h" 66#include "magick/static.h" 67#include "magick/string_.h" 68#include "magick/module.h" 69#include "magick/utility.h" 70 71/* 72 Define declarations. 73*/ 74#if defined(MAGICKCORE_TIFF_DELEGATE) 75#define CCITTParam "-1" 76#else 77#define CCITTParam "0" 78#endif 79 80/* 81 Forward declarations. 82*/ 83static MagickBooleanType 84 WritePS2Image(const ImageInfo *,Image *); 85 86/* 87%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 88% % 89% % 90% % 91% R e g i s t e r P S 2 I m a g e % 92% % 93% % 94% % 95%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 96% 97% RegisterPS2Image() adds properties for the PS2 image format to 98% the list of supported formats. The properties include the image format 99% tag, a method to read and/or write the format, whether the format 100% supports the saving of more than one frame to the same file or blob, 101% whether the format supports native in-memory I/O, and a brief 102% description of the format. 103% 104% The format of the RegisterPS2Image method is: 105% 106% size_t RegisterPS2Image(void) 107% 108*/ 109ModuleExport size_t RegisterPS2Image(void) 110{ 111 MagickInfo 112 *entry; 113 114 entry=SetMagickInfo("EPS2"); 115 entry->encoder=(EncodeImageHandler *) WritePS2Image; 116 entry->adjoin=MagickFalse; 117 entry->seekable_stream=MagickTrue; 118 entry->description=ConstantString("Level II Encapsulated PostScript"); 119 entry->module=ConstantString("PS2"); 120 (void) RegisterMagickInfo(entry); 121 entry=SetMagickInfo("PS2"); 122 entry->encoder=(EncodeImageHandler *) WritePS2Image; 123 entry->seekable_stream=MagickTrue; 124 entry->description=ConstantString("Level II PostScript"); 125 entry->module=ConstantString("PS2"); 126 (void) RegisterMagickInfo(entry); 127 return(MagickImageCoderSignature); 128} 129 130/* 131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 132% % 133% % 134% % 135% U n r e g i s t e r P S 2 I m a g e % 136% % 137% % 138% % 139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 140% 141% UnregisterPS2Image() removes format registrations made by the 142% PS2 module from the list of supported formats. 143% 144% The format of the UnregisterPS2Image method is: 145% 146% UnregisterPS2Image(void) 147% 148*/ 149ModuleExport void UnregisterPS2Image(void) 150{ 151 (void) UnregisterMagickInfo("EPS2"); 152 (void) UnregisterMagickInfo("PS2"); 153} 154 155/* 156%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 157% % 158% % 159% % 160% W r i t e P S 2 I m a g e % 161% % 162% % 163% % 164%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 165% 166% WritePS2Image translates an image to encapsulated Postscript 167% Level II for printing. If the supplied geometry is null, the image is 168% centered on the Postscript page. Otherwise, the image is positioned as 169% specified by the geometry. 170% 171% The format of the WritePS2Image method is: 172% 173% MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image) 174% 175% A description of each parameter follows: 176% 177% o image_info: the image info. 178% 179% o image: the image. 180% 181*/ 182 183static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info, 184 Image *image,Image *inject_image) 185{ 186 Image 187 *group4_image; 188 189 ImageInfo 190 *write_info; 191 192 MagickBooleanType 193 status; 194 195 size_t 196 length; 197 198 unsigned char 199 *group4; 200 201 status=MagickTrue; 202 write_info=CloneImageInfo(image_info); 203 (void) CopyMagickString(write_info->filename,"GROUP4:",MaxTextExtent); 204 (void) CopyMagickString(write_info->magick,"GROUP4",MaxTextExtent); 205 group4_image=CloneImage(inject_image,0,0,MagickTrue,&image->exception); 206 if (group4_image == (Image *) NULL) 207 return(MagickFalse); 208 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length, 209 &image->exception); 210 group4_image=DestroyImage(group4_image); 211 if (group4 == (unsigned char *) NULL) 212 return(MagickFalse); 213 write_info=DestroyImageInfo(write_info); 214 if (WriteBlob(image,length,group4) != (ssize_t) length) 215 status=MagickFalse; 216 group4=(unsigned char *) RelinquishMagickMemory(group4); 217 return(status); 218} 219 220static MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image) 221{ 222 static const char 223 *PostscriptProlog[]= 224 { 225 "%%%%BeginProlog", 226 "%%", 227 "%% Display a color image. The image is displayed in color on", 228 "%% Postscript viewers or printers that support color, otherwise", 229 "%% it is displayed as grayscale.", 230 "%%", 231 "/DirectClassImage", 232 "{", 233 " %%", 234 " %% Display a DirectClass image.", 235 " %%", 236 " colorspace 0 eq", 237 " {", 238 " /DeviceRGB setcolorspace", 239 " <<", 240 " /ImageType 1", 241 " /Width columns", 242 " /Height rows", 243 " /BitsPerComponent 8", 244 " /Decode [0 1 0 1 0 1]", 245 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 246 " compression 0 gt", 247 " { /DataSource pixel_stream %s }", 248 " { /DataSource pixel_stream %s } ifelse", 249 " >> image", 250 " }", 251 " {", 252 " /DeviceCMYK setcolorspace", 253 " <<", 254 " /ImageType 1", 255 " /Width columns", 256 " /Height rows", 257 " /BitsPerComponent 8", 258 " /Decode [1 0 1 0 1 0 1 0]", 259 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 260 " compression 0 gt", 261 " { /DataSource pixel_stream %s }", 262 " { /DataSource pixel_stream %s } ifelse", 263 " >> image", 264 " } ifelse", 265 "} bind def", 266 "", 267 "/PseudoClassImage", 268 "{", 269 " %%", 270 " %% Display a PseudoClass image.", 271 " %%", 272 " %% Parameters:", 273 " %% colors: number of colors in the colormap.", 274 " %%", 275 " currentfile buffer readline pop", 276 " token pop /colors exch def pop", 277 " colors 0 eq", 278 " {", 279 " %%", 280 " %% Image is grayscale.", 281 " %%", 282 " currentfile buffer readline pop", 283 " token pop /bits exch def pop", 284 " /DeviceGray setcolorspace", 285 " <<", 286 " /ImageType 1", 287 " /Width columns", 288 " /Height rows", 289 " /BitsPerComponent bits", 290 " /Decode [0 1]", 291 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 292 " compression 0 gt", 293 " { /DataSource pixel_stream %s }", 294 " {", 295 " /DataSource pixel_stream %s", 296 " <<", 297 " /K "CCITTParam, 298 " /Columns columns", 299 " /Rows rows", 300 " >> /CCITTFaxDecode filter", 301 " } ifelse", 302 " >> image", 303 " }", 304 " {", 305 " %%", 306 " %% Parameters:", 307 " %% colormap: red, green, blue color packets.", 308 " %%", 309 " /colormap colors 3 mul string def", 310 " currentfile colormap readhexstring pop pop", 311 " currentfile buffer readline pop", 312 " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace", 313 " <<", 314 " /ImageType 1", 315 " /Width columns", 316 " /Height rows", 317 " /BitsPerComponent 8", 318 " /Decode [0 255]", 319 " /ImageMatrix [columns 0 0 rows neg 0 rows]", 320 " compression 0 gt", 321 " { /DataSource pixel_stream %s }", 322 " { /DataSource pixel_stream %s } ifelse", 323 " >> image", 324 " } ifelse", 325 "} bind def", 326 "", 327 "/DisplayImage", 328 "{", 329 " %%", 330 " %% Display a DirectClass or PseudoClass image.", 331 " %%", 332 " %% Parameters:", 333 " %% x & y translation.", 334 " %% x & y scale.", 335 " %% label pointsize.", 336 " %% image label.", 337 " %% image columns & rows.", 338 " %% class: 0-DirectClass or 1-PseudoClass.", 339 " %% colorspace: 0-RGB or 1-CMYK.", 340 " %% compression: 0-RLECompression or 1-NoCompression.", 341 " %% hex color packets.", 342 " %%", 343 " gsave", 344 " /buffer 512 string def", 345 " /pixel_stream currentfile def", 346 "", 347 " currentfile buffer readline pop", 348 " token pop /x exch def", 349 " token pop /y exch def pop", 350 " x y translate", 351 " currentfile buffer readline pop", 352 " token pop /x exch def", 353 " token pop /y exch def pop", 354 " currentfile buffer readline pop", 355 " token pop /pointsize exch def pop", 356 " /Helvetica findfont pointsize scalefont setfont", 357 (char *) NULL 358 }, 359 *PostscriptEpilog[]= 360 { 361 " x y scale", 362 " currentfile buffer readline pop", 363 " token pop /columns exch def", 364 " token pop /rows exch def pop", 365 " currentfile buffer readline pop", 366 " token pop /class exch def pop", 367 " currentfile buffer readline pop", 368 " token pop /colorspace exch def pop", 369 " currentfile buffer readline pop", 370 " token pop /compression exch def pop", 371 " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse", 372 (char *) NULL 373 }; 374 375 char 376 buffer[MaxTextExtent], 377 date[MaxTextExtent], 378 page_geometry[MaxTextExtent], 379 **labels; 380 381 CompressionType 382 compression; 383 384 const char 385 **q, 386 *value; 387 388 double 389 pointsize; 390 391 GeometryInfo 392 geometry_info; 393 394 ssize_t 395 j, 396 y; 397 398 MagickOffsetType 399 scene, 400 start, 401 stop; 402 403 MagickBooleanType 404 progress, 405 status; 406 407 MagickOffsetType 408 offset; 409 410 MagickSizeType 411 number_pixels; 412 413 MagickStatusType 414 flags; 415 416 PointInfo 417 delta, 418 resolution, 419 scale; 420 421 RectangleInfo 422 geometry, 423 media_info, 424 page_info; 425 426 register const IndexPacket 427 *indexes; 428 429 register const PixelPacket 430 *p; 431 432 register ssize_t 433 x; 434 435 register ssize_t 436 i; 437 438 SegmentInfo 439 bounds; 440 441 size_t 442 length; 443 444 time_t 445 timer; 446 447 unsigned char 448 *pixels; 449 450 size_t 451 page, 452 text_size; 453 454 /* 455 Open output image file. 456 */ 457 assert(image_info != (const ImageInfo *) NULL); 458 assert(image_info->signature == MagickSignature); 459 assert(image != (Image *) NULL); 460 assert(image->signature == MagickSignature); 461 if (image->debug != MagickFalse) 462 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename); 463 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception); 464 if (status == MagickFalse) 465 return(status); 466 compression=image->compression; 467 if (image_info->compression != UndefinedCompression) 468 compression=image_info->compression; 469 switch (compression) 470 { 471#if !defined(MAGICKCORE_JPEG_DELEGATE) 472 case JPEGCompression: 473 { 474 compression=RLECompression; 475 (void) ThrowMagickException(&image->exception,GetMagickModule(), 476 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)", 477 image->filename); 478 break; 479 } 480#endif 481 default: 482 break; 483 } 484 (void) ResetMagickMemory(&bounds,0,sizeof(bounds)); 485 page=1; 486 scene=0; 487 do 488 { 489 /* 490 Scale relative to dots-per-inch. 491 */ 492 delta.x=DefaultResolution; 493 delta.y=DefaultResolution; 494 resolution.x=image->x_resolution; 495 resolution.y=image->y_resolution; 496 if ((resolution.x == 0.0) || (resolution.y == 0.0)) 497 { 498 flags=ParseGeometry(PSDensityGeometry,&geometry_info); 499 resolution.x=geometry_info.rho; 500 resolution.y=geometry_info.sigma; 501 if ((flags & SigmaValue) == 0) 502 resolution.y=resolution.x; 503 } 504 if (image_info->density != (char *) NULL) 505 { 506 flags=ParseGeometry(image_info->density,&geometry_info); 507 resolution.x=geometry_info.rho; 508 resolution.y=geometry_info.sigma; 509 if ((flags & SigmaValue) == 0) 510 resolution.y=resolution.x; 511 } 512 if (image->units == PixelsPerCentimeterResolution) 513 { 514 resolution.x=(size_t) (100.0*2.54*resolution.x+0.5)/100.0; 515 resolution.y=(size_t) (100.0*2.54*resolution.y+0.5)/100.0; 516 } 517 SetGeometry(image,&geometry); 518 (void) FormatMagickString(page_geometry,MaxTextExtent,"%.20gx%.20g", 519 (double) image->columns,(double) image->rows); 520 if (image_info->page != (char *) NULL) 521 (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent); 522 else 523 if ((image->page.width != 0) && (image->page.height != 0)) 524 (void) FormatMagickString(page_geometry,MaxTextExtent, 525 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double) 526 image->page.height,(double) image->page.x,(double) image->page.y); 527 else 528 if ((image->gravity != UndefinedGravity) && 529 (LocaleCompare(image_info->magick,"PS") == 0)) 530 (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent); 531 (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent); 532 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y, 533 &geometry.width,&geometry.height); 534 scale.x=(double) (geometry.width*delta.x)/resolution.x; 535 geometry.width=(size_t) floor(scale.x+0.5); 536 scale.y=(double) (geometry.height*delta.y)/resolution.y; 537 geometry.height=(size_t) floor(scale.y+0.5); 538 (void) ParseAbsoluteGeometry(page_geometry,&media_info); 539 (void) ParseGravityGeometry(image,page_geometry,&page_info, 540 &image->exception); 541 if (image->gravity != UndefinedGravity) 542 { 543 geometry.x=(-page_info.x); 544 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows); 545 } 546 pointsize=12.0; 547 if (image_info->pointsize != 0.0) 548 pointsize=image_info->pointsize; 549 text_size=0; 550 value=GetImageProperty(image,"label"); 551 if (value != (const char *) NULL) 552 text_size=(size_t) (MultilineCensus(value)*pointsize+12); 553 if (page == 1) 554 { 555 /* 556 Output Postscript header. 557 */ 558 if (LocaleCompare(image_info->magick,"PS2") == 0) 559 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MaxTextExtent); 560 else 561 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n", 562 MaxTextExtent); 563 (void) WriteBlobString(image,buffer); 564 (void) WriteBlobString(image,"%%Creator: (ImageMagick)\n"); 565 (void) FormatMagickString(buffer,MaxTextExtent,"%%%%Title: (%s)\n", 566 image->filename); 567 (void) WriteBlobString(image,buffer); 568 timer=time((time_t *) NULL); 569 (void) FormatMagickTime(timer,MaxTextExtent,date); 570 (void) FormatMagickString(buffer,MaxTextExtent, 571 "%%%%CreationDate: (%s)\n",date); 572 (void) WriteBlobString(image,buffer); 573 bounds.x1=(double) geometry.x; 574 bounds.y1=(double) geometry.y; 575 bounds.x2=(double) geometry.x+geometry.width; 576 bounds.y2=(double) geometry.y+geometry.height+text_size; 577 if ((image_info->adjoin != MagickFalse) && 578 (GetNextImageInList(image) != (Image *) NULL)) 579 (void) CopyMagickString(buffer,"%%BoundingBox: (atend)\n", 580 MaxTextExtent); 581 else 582 { 583 (void) FormatMagickString(buffer,MaxTextExtent, 584 "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), 585 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); 586 (void) WriteBlobString(image,buffer); 587 (void) FormatMagickString(buffer,MaxTextExtent, 588 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1, 589 bounds.y1,bounds.x2,bounds.y2); 590 } 591 (void) WriteBlobString(image,buffer); 592 value=GetImageProperty(image,"label"); 593 if (value != (const char *) NULL) 594 (void) WriteBlobString(image, 595 "%%DocumentNeededResources: font Helvetica\n"); 596 (void) WriteBlobString(image,"%%LanguageLevel: 2\n"); 597 if (LocaleCompare(image_info->magick,"PS2") != 0) 598 (void) WriteBlobString(image,"%%Pages: 1\n"); 599 else 600 { 601 (void) WriteBlobString(image,"%%Orientation: Portrait\n"); 602 (void) WriteBlobString(image,"%%PageOrder: Ascend\n"); 603 if (image_info->adjoin == MagickFalse) 604 (void) CopyMagickString(buffer,"%%Pages: 1\n",MaxTextExtent); 605 else 606 (void) FormatMagickString(buffer,MaxTextExtent, 607 "%%%%Pages: %.20g\n",(double) GetImageListLength(image)); 608 (void) WriteBlobString(image,buffer); 609 } 610 (void) WriteBlobString(image,"%%EndComments\n"); 611 (void) WriteBlobString(image,"\n%%BeginDefaults\n"); 612 (void) WriteBlobString(image,"%%EndDefaults\n\n"); 613 /* 614 Output Postscript commands. 615 */ 616 for (q=PostscriptProlog; *q; q++) 617 { 618 switch (compression) 619 { 620 case NoCompression: 621 { 622 (void) FormatMagickString(buffer,MaxTextExtent,*q, 623 "/ASCII85Decode filter"); 624 break; 625 } 626 case JPEGCompression: 627 { 628 (void) FormatMagickString(buffer,MaxTextExtent,*q, 629 "/DCTDecode filter"); 630 break; 631 } 632 case LZWCompression: 633 { 634 (void) FormatMagickString(buffer,MaxTextExtent,*q, 635 "/LZWDecode filter"); 636 break; 637 } 638 case FaxCompression: 639 case Group4Compression: 640 { 641 (void) FormatMagickString(buffer,MaxTextExtent,*q," "); 642 break; 643 } 644 default: 645 { 646 (void) FormatMagickString(buffer,MaxTextExtent,*q, 647 "/RunLengthDecode filter"); 648 break; 649 } 650 } 651 (void) WriteBlobString(image,buffer); 652 (void) WriteBlobByte(image,'\n'); 653 } 654 value=GetImageProperty(image,"label"); 655 if (value != (const char *) NULL) 656 for (j=(ssize_t) MultilineCensus(value)-1; j >= 0; j--) 657 { 658 (void) WriteBlobString(image," /label 512 string def\n"); 659 (void) WriteBlobString(image," currentfile label readline pop\n"); 660 (void) FormatMagickString(buffer,MaxTextExtent, 661 " 0 y %g add moveto label show pop\n",j*pointsize+12); 662 (void) WriteBlobString(image,buffer); 663 } 664 for (q=PostscriptEpilog; *q; q++) 665 { 666 (void) FormatMagickString(buffer,MaxTextExtent,"%s\n",*q); 667 (void) WriteBlobString(image,buffer); 668 } 669 if (LocaleCompare(image_info->magick,"PS2") == 0) 670 (void) WriteBlobString(image," showpage\n"); 671 (void) WriteBlobString(image,"} bind def\n"); 672 (void) WriteBlobString(image,"%%EndProlog\n"); 673 } 674 (void) FormatMagickString(buffer,MaxTextExtent,"%%%%Page: 1 %.20g\n", 675 (double) page++); 676 (void) WriteBlobString(image,buffer); 677 (void) FormatMagickString(buffer,MaxTextExtent, 678 "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x, 679 (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+(double) 680 (geometry.height+text_size)); 681 (void) WriteBlobString(image,buffer); 682 if ((double) geometry.x < bounds.x1) 683 bounds.x1=(double) geometry.x; 684 if ((double) geometry.y < bounds.y1) 685 bounds.y1=(double) geometry.y; 686 if ((double) (geometry.x+geometry.width-1) > bounds.x2) 687 bounds.x2=(double) geometry.x+geometry.width-1; 688 if ((double) (geometry.y+(geometry.height+text_size)-1) > bounds.y2) 689 bounds.y2=(double) geometry.y+(geometry.height+text_size)-1; 690 value=GetImageProperty(image,"label"); 691 if (value != (const char *) NULL) 692 (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n"); 693 if (LocaleCompare(image_info->magick,"PS2") != 0) 694 (void) WriteBlobString(image,"userdict begin\n"); 695 start=TellBlob(image); 696 (void) FormatMagickString(buffer,MaxTextExtent, 697 "%%%%BeginData:%13ld %s Bytes\n",0L, 698 compression == NoCompression ? "ASCII" : "Binary"); 699 (void) WriteBlobString(image,buffer); 700 stop=TellBlob(image); 701 (void) WriteBlobString(image,"DisplayImage\n"); 702 /* 703 Output image data. 704 */ 705 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g\n%g %g\n%g\n", 706 (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize); 707 (void) WriteBlobString(image,buffer); 708 labels=(char **) NULL; 709 value=GetImageProperty(image,"label"); 710 if (value != (const char *) NULL) 711 labels=StringToList(value); 712 if (labels != (char **) NULL) 713 { 714 for (i=0; labels[i] != (char *) NULL; i++) 715 { 716 (void) FormatMagickString(buffer,MaxTextExtent,"%s \n", 717 labels[i]); 718 (void) WriteBlobString(image,buffer); 719 labels[i]=DestroyString(labels[i]); 720 } 721 labels=(char **) RelinquishMagickMemory(labels); 722 } 723 number_pixels=(MagickSizeType) image->columns*image->rows; 724 if (number_pixels != (MagickSizeType) ((size_t) number_pixels)) 725 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 726 if ((compression == FaxCompression) || (compression == Group4Compression) || 727 ((image_info->type != TrueColorType) && 728 (IsGrayImage(image,&image->exception) != MagickFalse))) 729 { 730 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n", 731 (double) image->columns,(double) image->rows,(int) 732 (image->colorspace == CMYKColorspace)); 733 (void) WriteBlobString(image,buffer); 734 (void) FormatMagickString(buffer,MaxTextExtent,"%d\n", 735 (int) ((compression != FaxCompression) && 736 (compression != Group4Compression))); 737 (void) WriteBlobString(image,buffer); 738 (void) WriteBlobString(image,"0\n"); 739 (void) FormatMagickString(buffer,MaxTextExtent,"%d\n", 740 (compression == FaxCompression) || 741 (compression == Group4Compression) ? 1 : 8); 742 (void) WriteBlobString(image,buffer); 743 switch (compression) 744 { 745 case FaxCompression: 746 case Group4Compression: 747 { 748 if (LocaleCompare(CCITTParam,"0") == 0) 749 { 750 (void) HuffmanEncodeImage(image_info,image,image); 751 break; 752 } 753 (void) Huffman2DEncodeImage(image_info,image,image); 754 break; 755 } 756 case JPEGCompression: 757 { 758 status=InjectImageBlob(image_info,image,image,"jpeg", 759 &image->exception); 760 if (status == MagickFalse) 761 ThrowWriterException(CoderError,image->exception.reason); 762 break; 763 } 764 case RLECompression: 765 default: 766 { 767 register unsigned char 768 *q; 769 770 /* 771 Allocate pixel array. 772 */ 773 length=(size_t) number_pixels; 774 pixels=(unsigned char *) AcquireQuantumMemory(length, 775 sizeof(*pixels)); 776 if (pixels == (unsigned char *) NULL) 777 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed"); 778 /* 779 Dump Runlength encoded pixels. 780 */ 781 q=pixels; 782 for (y=0; y < (ssize_t) image->rows; y++) 783 { 784 p=GetVirtualPixels(image,0,y,image->columns,1, 785 &image->exception); 786 if (p == (const PixelPacket *) NULL) 787 break; 788 for (x=0; x < (ssize_t) image->columns; x++) 789 { 790 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p)); 791 p++; 792 } 793 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); 794 if (progress == MagickFalse) 795 break; 796 } 797 length=(size_t) (q-pixels); 798 if (compression == LZWCompression) 799 status=LZWEncodeImage(image,length,pixels); 800 else 801 status=PackbitsEncodeImage(image,length,pixels); 802 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 803 if (status == MagickFalse) 804 { 805 (void) CloseBlob(image); 806 return(MagickFalse); 807 } 808 break; 809 } 810 case NoCompression: 811 { 812 /* 813 Dump uncompressed PseudoColor packets. 814 */ 815 Ascii85Initialize(image); 816 for (y=0; y < (ssize_t) image->rows; y++) 817 { 818 p=GetVirtualPixels(image,0,y,image->columns,1, 819 &image->exception); 820 if (p == (const PixelPacket *) NULL) 821 break; 822 for (x=0; x < (ssize_t) image->columns; x++) 823 { 824 Ascii85Encode(image, 825 ScaleQuantumToChar(PixelIntensityToQuantum(p))); 826 p++; 827 } 828 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) 829 y,image->rows); 830 if (progress == MagickFalse) 831 break; 832 } 833 Ascii85Flush(image); 834 break; 835 } 836 } 837 } 838 else 839 if ((image->storage_class == DirectClass) || (image->colors > 256) || 840 (compression == JPEGCompression) || (image->matte != MagickFalse)) 841 { 842 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g\n0\n%d\n", 843 (double) image->columns,(double) image->rows,(int) 844 (image->colorspace == CMYKColorspace)); 845 (void) WriteBlobString(image,buffer); 846 (void) FormatMagickString(buffer,MaxTextExtent,"%d\n", 847 (int) (compression == NoCompression)); 848 (void) WriteBlobString(image,buffer); 849 switch (compression) 850 { 851 case JPEGCompression: 852 { 853 status=InjectImageBlob(image_info,image,image,"jpeg", 854 &image->exception); 855 if (status == MagickFalse) 856 ThrowWriterException(CoderError,image->exception.reason); 857 break; 858 } 859 case RLECompression: 860 default: 861 { 862 register unsigned char 863 *q; 864 865 /* 866 Allocate pixel array. 867 */ 868 length=(size_t) number_pixels; 869 pixels=(unsigned char *) AcquireQuantumMemory(length, 870 4*sizeof(*pixels)); 871 if (pixels == (unsigned char *) NULL) 872 ThrowWriterException(ResourceLimitError, 873 "MemoryAllocationFailed"); 874 /* 875 Dump Packbit encoded pixels. 876 */ 877 q=pixels; 878 for (y=0; y < (ssize_t) image->rows; y++) 879 { 880 p=GetVirtualPixels(image,0,y,image->columns,1, 881 &image->exception); 882 if (p == (const PixelPacket *) NULL) 883 break; 884 indexes=GetVirtualIndexQueue(image); 885 for (x=0; x < (ssize_t) image->columns; x++) 886 { 887 if ((image->matte != MagickFalse) && 888 (GetOpacityPixelComponent(p) == (Quantum) TransparentOpacity)) 889 { 890 *q++=ScaleQuantumToChar((Quantum) QuantumRange); 891 *q++=ScaleQuantumToChar((Quantum) QuantumRange); 892 *q++=ScaleQuantumToChar((Quantum) QuantumRange); 893 } 894 else 895 if (image->colorspace != CMYKColorspace) 896 { 897 *q++=ScaleQuantumToChar(GetRedPixelComponent(p)); 898 *q++=ScaleQuantumToChar(GetGreenPixelComponent(p)); 899 *q++=ScaleQuantumToChar(GetBluePixelComponent(p)); 900 } 901 else 902 { 903 *q++=ScaleQuantumToChar(GetRedPixelComponent(p)); 904 *q++=ScaleQuantumToChar(GetGreenPixelComponent(p)); 905 *q++=ScaleQuantumToChar(GetBluePixelComponent(p)); 906 *q++=ScaleQuantumToChar(indexes[x]); 907 } 908 p++; 909 } 910 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); 911 if (progress == MagickFalse) 912 break; 913 } 914 length=(size_t) (q-pixels); 915 if (compression == LZWCompression) 916 status=LZWEncodeImage(image,length,pixels); 917 else 918 status=PackbitsEncodeImage(image,length,pixels); 919 if (status == MagickFalse) 920 { 921 (void) CloseBlob(image); 922 return(MagickFalse); 923 } 924 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 925 break; 926 } 927 case NoCompression: 928 { 929 /* 930 Dump uncompressed DirectColor packets. 931 */ 932 Ascii85Initialize(image); 933 for (y=0; y < (ssize_t) image->rows; y++) 934 { 935 p=GetVirtualPixels(image,0,y,image->columns,1, 936 &image->exception); 937 if (p == (const PixelPacket *) NULL) 938 break; 939 indexes=GetVirtualIndexQueue(image); 940 for (x=0; x < (ssize_t) image->columns; x++) 941 { 942 if ((image->matte != MagickFalse) && 943 (GetOpacityPixelComponent(p) == (Quantum) TransparentOpacity)) 944 { 945 Ascii85Encode(image,ScaleQuantumToChar((Quantum) 946 QuantumRange)); 947 Ascii85Encode(image,ScaleQuantumToChar((Quantum) 948 QuantumRange)); 949 Ascii85Encode(image,ScaleQuantumToChar((Quantum) 950 QuantumRange)); 951 } 952 else 953 if (image->colorspace != CMYKColorspace) 954 { 955 Ascii85Encode(image,ScaleQuantumToChar(GetRedPixelComponent(p))); 956 Ascii85Encode(image,ScaleQuantumToChar(GetGreenPixelComponent(p))); 957 Ascii85Encode(image,ScaleQuantumToChar(GetBluePixelComponent(p))); 958 } 959 else 960 { 961 Ascii85Encode(image,ScaleQuantumToChar(GetRedPixelComponent(p))); 962 Ascii85Encode(image,ScaleQuantumToChar(GetGreenPixelComponent(p))); 963 Ascii85Encode(image,ScaleQuantumToChar(GetBluePixelComponent(p))); 964 Ascii85Encode(image,ScaleQuantumToChar(indexes[x])); 965 } 966 p++; 967 } 968 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); 969 if (progress == MagickFalse) 970 break; 971 } 972 Ascii85Flush(image); 973 break; 974 } 975 } 976 } 977 else 978 { 979 /* 980 Dump number of colors and colormap. 981 */ 982 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n", 983 (double) image->columns,(double) image->rows,(int) 984 (image->colorspace == CMYKColorspace)); 985 (void) WriteBlobString(image,buffer); 986 (void) FormatMagickString(buffer,MaxTextExtent,"%d\n", 987 (int) (compression == NoCompression)); 988 (void) WriteBlobString(image,buffer); 989 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double) 990 image->colors); 991 (void) WriteBlobString(image,buffer); 992 for (i=0; i < (ssize_t) image->colors; i++) 993 { 994 (void) FormatMagickString(buffer,MaxTextExtent,"%02X%02X%02X\n", 995 ScaleQuantumToChar(image->colormap[i].red), 996 ScaleQuantumToChar(image->colormap[i].green), 997 ScaleQuantumToChar(image->colormap[i].blue)); 998 (void) WriteBlobString(image,buffer); 999 } 1000 switch (compression) 1001 { 1002 case RLECompression: 1003 default: 1004 { 1005 register unsigned char 1006 *q; 1007 1008 /* 1009 Allocate pixel array. 1010 */ 1011 length=(size_t) number_pixels; 1012 pixels=(unsigned char *) AcquireQuantumMemory(length, 1013 sizeof(*pixels)); 1014 if (pixels == (unsigned char *) NULL) 1015 ThrowWriterException(ResourceLimitError, 1016 "MemoryAllocationFailed"); 1017 /* 1018 Dump Runlength encoded pixels. 1019 */ 1020 q=pixels; 1021 for (y=0; y < (ssize_t) image->rows; y++) 1022 { 1023 p=GetVirtualPixels(image,0,y,image->columns,1, 1024 &image->exception); 1025 if (p == (const PixelPacket *) NULL) 1026 break; 1027 indexes=GetVirtualIndexQueue(image); 1028 for (x=0; x < (ssize_t) image->columns; x++) 1029 *q++=(unsigned char) indexes[x]; 1030 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); 1031 if (progress == MagickFalse) 1032 break; 1033 } 1034 length=(size_t) (q-pixels); 1035 if (compression == LZWCompression) 1036 status=LZWEncodeImage(image,length,pixels); 1037 else 1038 status=PackbitsEncodeImage(image,length,pixels); 1039 pixels=(unsigned char *) RelinquishMagickMemory(pixels); 1040 if (status == MagickFalse) 1041 { 1042 (void) CloseBlob(image); 1043 return(MagickFalse); 1044 } 1045 break; 1046 } 1047 case NoCompression: 1048 { 1049 /* 1050 Dump uncompressed PseudoColor packets. 1051 */ 1052 Ascii85Initialize(image); 1053 for (y=0; y < (ssize_t) image->rows; y++) 1054 { 1055 p=GetVirtualPixels(image,0,y,image->columns,1, 1056 &image->exception); 1057 if (p == (const PixelPacket *) NULL) 1058 break; 1059 indexes=GetVirtualIndexQueue(image); 1060 for (x=0; x < (ssize_t) image->columns; x++) 1061 Ascii85Encode(image,(unsigned char) indexes[x]); 1062 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,image->rows); 1063 if (progress == MagickFalse) 1064 break; 1065 } 1066 Ascii85Flush(image); 1067 break; 1068 } 1069 } 1070 } 1071 (void) WriteBlobByte(image,'\n'); 1072 length=(size_t) (TellBlob(image)-stop); 1073 stop=TellBlob(image); 1074 offset=SeekBlob(image,start,SEEK_SET); 1075 if (offset < 0) 1076 ThrowWriterException(CorruptImageError,"ImproperImageHeader"); 1077 (void) FormatMagickString(buffer,MaxTextExtent, 1078 "%%%%BeginData:%13ld %s Bytes\n",(long) length, 1079 compression == NoCompression ? "ASCII" : "Binary"); 1080 (void) WriteBlobString(image,buffer); 1081 offset=SeekBlob(image,stop,SEEK_SET); 1082 (void) WriteBlobString(image,"%%EndData\n"); 1083 if (LocaleCompare(image_info->magick,"PS2") != 0) 1084 (void) WriteBlobString(image,"end\n"); 1085 (void) WriteBlobString(image,"%%PageTrailer\n"); 1086 if (GetNextImageInList(image) == (Image *) NULL) 1087 break; 1088 image=SyncNextImageInList(image); 1089 status=SetImageProgress(image,SaveImagesTag,scene++, 1090 GetImageListLength(image)); 1091 if (status == MagickFalse) 1092 break; 1093 } while (image_info->adjoin != MagickFalse); 1094 (void) WriteBlobString(image,"%%Trailer\n"); 1095 if (page > 1) 1096 { 1097 (void) FormatMagickString(buffer,MaxTextExtent, 1098 "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5), 1099 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5)); 1100 (void) WriteBlobString(image,buffer); 1101 (void) FormatMagickString(buffer,MaxTextExtent, 1102 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1, 1103 bounds.x2,bounds.y2); 1104 (void) WriteBlobString(image,buffer); 1105 } 1106 (void) WriteBlobString(image,"%%EOF\n"); 1107 (void) CloseBlob(image); 1108 return(MagickTrue); 1109} 1110