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