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