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