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