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