2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Write Postscript Level II Format %
20 % Copyright 1999-2014 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
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. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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"
76 #if defined(MAGICKCORE_TIFF_DELEGATE)
77 #define CCITTParam "-1"
79 #define CCITTParam "0"
85 static MagickBooleanType
86 WritePS2Image(const ImageInfo *,Image *,ExceptionInfo *);
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 % R e g i s t e r P S 2 I m a g e %
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
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.
106 % The format of the RegisterPS2Image method is:
108 % size_t RegisterPS2Image(void)
111 ModuleExport size_t RegisterPS2Image(void)
116 entry=SetMagickInfo("EPS2");
117 entry->encoder=(EncodeImageHandler *) WritePS2Image;
118 entry->adjoin=MagickFalse;
119 entry->seekable_stream=MagickTrue;
120 entry->description=ConstantString("Level II Encapsulated PostScript");
121 entry->mime_type=ConstantString("application/postscript");
122 entry->module=ConstantString("PS2");
123 (void) RegisterMagickInfo(entry);
124 entry=SetMagickInfo("PS2");
125 entry->encoder=(EncodeImageHandler *) WritePS2Image;
126 entry->seekable_stream=MagickTrue;
127 entry->description=ConstantString("Level II PostScript");
128 entry->mime_type=ConstantString("application/postscript");
129 entry->module=ConstantString("PS2");
130 (void) RegisterMagickInfo(entry);
131 return(MagickImageCoderSignature);
135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
139 % U n r e g i s t e r P S 2 I m a g e %
143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
145 % UnregisterPS2Image() removes format registrations made by the
146 % PS2 module from the list of supported formats.
148 % The format of the UnregisterPS2Image method is:
150 % UnregisterPS2Image(void)
153 ModuleExport void UnregisterPS2Image(void)
155 (void) UnregisterMagickInfo("EPS2");
156 (void) UnregisterMagickInfo("PS2");
160 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
164 % W r i t e P S 2 I m a g e %
168 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
170 % WritePS2Image translates an image to encapsulated Postscript
171 % Level II for printing. If the supplied geometry is null, the image is
172 % centered on the Postscript page. Otherwise, the image is positioned as
173 % specified by the geometry.
175 % The format of the WritePS2Image method is:
177 % MagickBooleanType WritePS2Image(const ImageInfo *image_info,
178 % Image *image,ExceptionInfo *exception)
180 % A description of each parameter follows:
182 % o image_info: the image info.
184 % o image: the image.
186 % o exception: return any errors or warnings in this structure.
190 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
191 Image *image,Image *inject_image,ExceptionInfo *exception)
209 write_info=CloneImageInfo(image_info);
210 (void) CopyMagickString(write_info->filename,"GROUP4:",MaxTextExtent);
211 (void) CopyMagickString(write_info->magick,"GROUP4",MaxTextExtent);
212 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception);
213 if (group4_image == (Image *) NULL)
215 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
217 group4_image=DestroyImage(group4_image);
218 if (group4 == (unsigned char *) NULL)
220 write_info=DestroyImageInfo(write_info);
221 if (WriteBlob(image,length,group4) != (ssize_t) length)
223 group4=(unsigned char *) RelinquishMagickMemory(group4);
227 static MagickBooleanType WritePS2Image(const ImageInfo *image_info,Image *image,
228 ExceptionInfo *exception)
235 "%% Display a color image. The image is displayed in color on",
236 "%% Postscript viewers or printers that support color, otherwise",
237 "%% it is displayed as grayscale.",
242 " %% Display a DirectClass image.",
246 " /DeviceRGB setcolorspace",
251 " /BitsPerComponent 8",
252 " /Decode [0 1 0 1 0 1]",
253 " /ImageMatrix [columns 0 0 rows neg 0 rows]",
255 " { /DataSource pixel_stream %s }",
256 " { /DataSource pixel_stream %s } ifelse",
260 " /DeviceCMYK setcolorspace",
265 " /BitsPerComponent 8",
266 " /Decode [1 0 1 0 1 0 1 0]",
267 " /ImageMatrix [columns 0 0 rows neg 0 rows]",
269 " { /DataSource pixel_stream %s }",
270 " { /DataSource pixel_stream %s } ifelse",
278 " %% Display a PseudoClass image.",
281 " %% colors: number of colors in the colormap.",
283 " currentfile buffer readline pop",
284 " token pop /colors exch def pop",
288 " %% Image is grayscale.",
290 " currentfile buffer readline pop",
291 " token pop /bits exch def pop",
292 " /DeviceGray setcolorspace",
297 " /BitsPerComponent bits",
299 " /ImageMatrix [columns 0 0 rows neg 0 rows]",
301 " { /DataSource pixel_stream %s }",
303 " /DataSource pixel_stream %s",
308 " >> /CCITTFaxDecode filter",
315 " %% colormap: red, green, blue color packets.",
317 " /colormap colors 3 mul string def",
318 " currentfile colormap readhexstring pop pop",
319 " currentfile buffer readline pop",
320 " [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace",
325 " /BitsPerComponent 8",
327 " /ImageMatrix [columns 0 0 rows neg 0 rows]",
329 " { /DataSource pixel_stream %s }",
330 " { /DataSource pixel_stream %s } ifelse",
338 " %% Display a DirectClass or PseudoClass image.",
341 " %% x & y translation.",
343 " %% label pointsize.",
345 " %% image columns & rows.",
346 " %% class: 0-DirectClass or 1-PseudoClass.",
347 " %% colorspace: 0-RGB or 1-CMYK.",
348 " %% compression: 0-RLECompression or 1-NoCompression.",
349 " %% hex color packets.",
352 " /buffer 512 string def",
353 " /pixel_stream currentfile def",
355 " currentfile buffer readline pop",
356 " token pop /x exch def",
357 " token pop /y exch def pop",
359 " currentfile buffer readline pop",
360 " token pop /x exch def",
361 " token pop /y exch def pop",
362 " currentfile buffer readline pop",
363 " token pop /pointsize exch def pop",
364 " /Helvetica findfont pointsize scalefont setfont",
370 " currentfile buffer readline pop",
371 " token pop /columns exch def",
372 " token pop /rows exch def pop",
373 " currentfile buffer readline pop",
374 " token pop /class exch def pop",
375 " currentfile buffer readline pop",
376 " token pop /colorspace exch def pop",
377 " currentfile buffer readline pop",
378 " token pop /compression exch def pop",
379 " class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
385 buffer[MaxTextExtent],
387 page_geometry[MaxTextExtent],
431 register const Quantum
459 Open output image file.
461 assert(image_info != (const ImageInfo *) NULL);
462 assert(image_info->signature == MagickSignature);
463 assert(image != (Image *) NULL);
464 assert(image->signature == MagickSignature);
465 if (image->debug != MagickFalse)
466 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
467 assert(exception != (ExceptionInfo *) NULL);
468 assert(exception->signature == MagickSignature);
469 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
470 if (status == MagickFalse)
472 compression=UndefinedCompression;
473 if (image_info->compression != UndefinedCompression)
474 compression=image_info->compression;
477 #if !defined(MAGICKCORE_JPEG_DELEGATE)
478 case JPEGCompression:
480 compression=RLECompression;
481 (void) ThrowMagickException(exception,GetMagickModule(),
482 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
490 (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
496 Scale relative to dots-per-inch.
498 delta.x=DefaultResolution;
499 delta.y=DefaultResolution;
500 resolution.x=image->resolution.x;
501 resolution.y=image->resolution.y;
502 if ((resolution.x == 0.0) || (resolution.y == 0.0))
504 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
505 resolution.x=geometry_info.rho;
506 resolution.y=geometry_info.sigma;
507 if ((flags & SigmaValue) == 0)
508 resolution.y=resolution.x;
510 if (image_info->density != (char *) NULL)
512 flags=ParseGeometry(image_info->density,&geometry_info);
513 resolution.x=geometry_info.rho;
514 resolution.y=geometry_info.sigma;
515 if ((flags & SigmaValue) == 0)
516 resolution.y=resolution.x;
518 if (image->units == PixelsPerCentimeterResolution)
520 resolution.x=(size_t) (100.0*2.54*resolution.x+0.5)/100.0;
521 resolution.y=(size_t) (100.0*2.54*resolution.y+0.5)/100.0;
523 SetGeometry(image,&geometry);
524 (void) FormatLocaleString(page_geometry,MaxTextExtent,"%.20gx%.20g",
525 (double) image->columns,(double) image->rows);
526 if (image_info->page != (char *) NULL)
527 (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent);
529 if ((image->page.width != 0) && (image->page.height != 0))
530 (void) FormatLocaleString(page_geometry,MaxTextExtent,
531 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double)
532 image->page.height,(double) image->page.x,(double) image->page.y);
534 if ((image->gravity != UndefinedGravity) &&
535 (LocaleCompare(image_info->magick,"PS") == 0))
536 (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent);
537 (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent);
538 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
539 &geometry.width,&geometry.height);
540 scale.x=(double) (geometry.width*delta.x)/resolution.x;
541 geometry.width=(size_t) floor(scale.x+0.5);
542 scale.y=(double) (geometry.height*delta.y)/resolution.y;
543 geometry.height=(size_t) floor(scale.y+0.5);
544 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
545 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception);
546 if (image->gravity != UndefinedGravity)
548 geometry.x=(-page_info.x);
549 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
552 if (image_info->pointsize != 0.0)
553 pointsize=image_info->pointsize;
555 value=GetImageProperty(image,"label",exception);
556 if (value != (const char *) NULL)
557 text_size=(size_t) (MultilineCensus(value)*pointsize+12);
561 Output Postscript header.
563 if (LocaleCompare(image_info->magick,"PS2") == 0)
564 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0\n",MaxTextExtent);
566 (void) CopyMagickString(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n",
568 (void) WriteBlobString(image,buffer);
569 (void) WriteBlobString(image,"%%Creator: (ImageMagick)\n");
570 (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Title: (%s)\n",
572 (void) WriteBlobString(image,buffer);
573 timer=time((time_t *) NULL);
574 (void) FormatMagickTime(timer,MaxTextExtent,date);
575 (void) FormatLocaleString(buffer,MaxTextExtent,
576 "%%%%CreationDate: (%s)\n",date);
577 (void) WriteBlobString(image,buffer);
578 bounds.x1=(double) geometry.x;
579 bounds.y1=(double) geometry.y;
580 bounds.x2=(double) geometry.x+geometry.width;
581 bounds.y2=(double) geometry.y+geometry.height+text_size;
582 if ((image_info->adjoin != MagickFalse) &&
583 (GetNextImageInList(image) != (Image *) NULL))
584 (void) CopyMagickString(buffer,"%%BoundingBox: (atend)\n",
588 (void) FormatLocaleString(buffer,MaxTextExtent,
589 "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5),
590 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5));
591 (void) WriteBlobString(image,buffer);
592 (void) FormatLocaleString(buffer,MaxTextExtent,
593 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,
594 bounds.y1,bounds.x2,bounds.y2);
596 (void) WriteBlobString(image,buffer);
597 value=GetImageProperty(image,"label",exception);
598 if (value != (const char *) NULL)
599 (void) WriteBlobString(image,
600 "%%DocumentNeededResources: font Helvetica\n");
601 (void) WriteBlobString(image,"%%LanguageLevel: 2\n");
602 if (LocaleCompare(image_info->magick,"PS2") != 0)
603 (void) WriteBlobString(image,"%%Pages: 1\n");
606 (void) WriteBlobString(image,"%%Orientation: Portrait\n");
607 (void) WriteBlobString(image,"%%PageOrder: Ascend\n");
608 if (image_info->adjoin == MagickFalse)
609 (void) CopyMagickString(buffer,"%%Pages: 1\n",MaxTextExtent);
611 (void) FormatLocaleString(buffer,MaxTextExtent,
612 "%%%%Pages: %.20g\n",(double) GetImageListLength(image));
613 (void) WriteBlobString(image,buffer);
615 (void) WriteBlobString(image,"%%EndComments\n");
616 (void) WriteBlobString(image,"\n%%BeginDefaults\n");
617 (void) WriteBlobString(image,"%%EndDefaults\n\n");
619 Output Postscript commands.
621 for (q=PostscriptProlog; *q; q++)
627 (void) FormatLocaleString(buffer,MaxTextExtent,*q,
628 "/ASCII85Decode filter");
631 case JPEGCompression:
633 (void) FormatLocaleString(buffer,MaxTextExtent,*q,
634 "/DCTDecode filter");
639 (void) FormatLocaleString(buffer,MaxTextExtent,*q,
640 "/LZWDecode filter");
644 case Group4Compression:
646 (void) FormatLocaleString(buffer,MaxTextExtent,*q," ");
651 (void) FormatLocaleString(buffer,MaxTextExtent,*q,
652 "/RunLengthDecode filter");
656 (void) WriteBlobString(image,buffer);
657 (void) WriteBlobByte(image,'\n');
659 value=GetImageProperty(image,"label",exception);
660 if (value != (const char *) NULL)
661 for (j=(ssize_t) MultilineCensus(value)-1; j >= 0; j--)
663 (void) WriteBlobString(image," /label 512 string def\n");
664 (void) WriteBlobString(image," currentfile label readline pop\n");
665 (void) FormatLocaleString(buffer,MaxTextExtent,
666 " 0 y %g add moveto label show pop\n",j*pointsize+12);
667 (void) WriteBlobString(image,buffer);
669 for (q=PostscriptEpilog; *q; q++)
671 (void) FormatLocaleString(buffer,MaxTextExtent,"%s\n",*q);
672 (void) WriteBlobString(image,buffer);
674 if (LocaleCompare(image_info->magick,"PS2") == 0)
675 (void) WriteBlobString(image," showpage\n");
676 (void) WriteBlobString(image,"} bind def\n");
677 (void) WriteBlobString(image,"%%EndProlog\n");
679 (void) FormatLocaleString(buffer,MaxTextExtent,"%%%%Page: 1 %.20g\n",
681 (void) WriteBlobString(image,buffer);
682 (void) FormatLocaleString(buffer,MaxTextExtent,
683 "%%%%PageBoundingBox: %.20g %.20g %.20g %.20g\n",(double) geometry.x,
684 (double) geometry.y,geometry.x+(double) geometry.width,geometry.y+(double)
685 (geometry.height+text_size));
686 (void) WriteBlobString(image,buffer);
687 if ((double) geometry.x < bounds.x1)
688 bounds.x1=(double) geometry.x;
689 if ((double) geometry.y < bounds.y1)
690 bounds.y1=(double) geometry.y;
691 if ((double) (geometry.x+geometry.width-1) > bounds.x2)
692 bounds.x2=(double) geometry.x+geometry.width-1;
693 if ((double) (geometry.y+(geometry.height+text_size)-1) > bounds.y2)
694 bounds.y2=(double) geometry.y+(geometry.height+text_size)-1;
695 value=GetImageProperty(image,"label",exception);
696 if (value != (const char *) NULL)
697 (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n");
698 if (LocaleCompare(image_info->magick,"PS2") != 0)
699 (void) WriteBlobString(image,"userdict begin\n");
700 start=TellBlob(image);
701 (void) FormatLocaleString(buffer,MaxTextExtent,
702 "%%%%BeginData:%13ld %s Bytes\n",0L,
703 compression == NoCompression ? "ASCII" : "Binary");
704 (void) WriteBlobString(image,buffer);
705 stop=TellBlob(image);
706 (void) WriteBlobString(image,"DisplayImage\n");
710 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n%g %g\n%g\n",
711 (double) geometry.x,(double) geometry.y,scale.x,scale.y,pointsize);
712 (void) WriteBlobString(image,buffer);
713 labels=(char **) NULL;
714 value=GetImageProperty(image,"label",exception);
715 if (value != (const char *) NULL)
716 labels=StringToList(value);
717 if (labels != (char **) NULL)
719 for (i=0; labels[i] != (char *) NULL; i++)
721 (void) FormatLocaleString(buffer,MaxTextExtent,"%s \n",
723 (void) WriteBlobString(image,buffer);
724 labels[i]=DestroyString(labels[i]);
726 labels=(char **) RelinquishMagickMemory(labels);
728 number_pixels=(MagickSizeType) image->columns*image->rows;
729 if (number_pixels != (MagickSizeType) ((size_t) number_pixels))
730 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
731 if ((compression == FaxCompression) || (compression == Group4Compression) ||
732 ((image_info->type != TrueColorType) &&
733 (IsImageGray(image,exception) != MagickFalse)))
735 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n",
736 (double) image->columns,(double) image->rows,(int)
737 (image->colorspace == CMYKColorspace));
738 (void) WriteBlobString(image,buffer);
739 (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
740 (int) ((compression != FaxCompression) &&
741 (compression != Group4Compression)));
742 (void) WriteBlobString(image,buffer);
743 (void) WriteBlobString(image,"0\n");
744 (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
745 (compression == FaxCompression) ||
746 (compression == Group4Compression) ? 1 : 8);
747 (void) WriteBlobString(image,buffer);
751 case Group4Compression:
753 if (LocaleCompare(CCITTParam,"0") == 0)
755 (void) HuffmanEncodeImage(image_info,image,image,exception);
758 (void) Huffman2DEncodeImage(image_info,image,image,exception);
761 case JPEGCompression:
763 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
764 if (status == MagickFalse)
766 (void) CloseBlob(image);
777 register unsigned char
781 Allocate pixel array.
783 length=(size_t) number_pixels;
784 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
785 if (pixel_info == (MemoryInfo *) NULL)
786 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
787 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
789 Dump runlength encoded pixels.
792 for (y=0; y < (ssize_t) image->rows; y++)
794 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
795 if (p == (const Quantum *) NULL)
797 for (x=0; x < (ssize_t) image->columns; x++)
799 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p)));
800 p+=GetPixelChannels(image);
802 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType) y,
804 if (progress == MagickFalse)
807 length=(size_t) (q-pixels);
808 if (compression == LZWCompression)
809 status=LZWEncodeImage(image,length,pixels,exception);
811 status=PackbitsEncodeImage(image,length,pixels,exception);
812 pixel_info=RelinquishVirtualMemory(pixel_info);
813 if (status == MagickFalse)
815 (void) CloseBlob(image);
823 Dump uncompressed PseudoColor packets.
825 Ascii85Initialize(image);
826 for (y=0; y < (ssize_t) image->rows; y++)
828 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
829 if (p == (const Quantum *) NULL)
831 for (x=0; x < (ssize_t) image->columns; x++)
833 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
834 GetPixelLuma(image,p))));
835 p+=GetPixelChannels(image);
837 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
839 if (progress == MagickFalse)
848 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
849 (compression == JPEGCompression) || (image->alpha_trait == BlendPixelTrait))
851 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n0\n%d\n",
852 (double) image->columns,(double) image->rows,(int)
853 (image->colorspace == CMYKColorspace));
854 (void) WriteBlobString(image,buffer);
855 (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
856 (int) (compression == NoCompression));
857 (void) WriteBlobString(image,buffer);
860 case JPEGCompression:
862 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
863 if (status == MagickFalse)
865 (void) CloseBlob(image);
876 register unsigned char
880 Allocate pixel array.
882 length=(size_t) number_pixels;
883 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
884 if (pixel_info == (MemoryInfo *) NULL)
885 ThrowWriterException(ResourceLimitError,
886 "MemoryAllocationFailed");
887 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
889 Dump runlength encoded pixels.
892 for (y=0; y < (ssize_t) image->rows; y++)
894 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
895 if (p == (const Quantum *) NULL)
897 for (x=0; x < (ssize_t) image->columns; x++)
899 if ((image->alpha_trait == BlendPixelTrait) &&
900 (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha))
902 *q++=ScaleQuantumToChar(QuantumRange);
903 *q++=ScaleQuantumToChar(QuantumRange);
904 *q++=ScaleQuantumToChar(QuantumRange);
907 if (image->colorspace != CMYKColorspace)
909 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
910 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
911 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
915 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
916 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
917 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
918 *q++=ScaleQuantumToChar(GetPixelBlack(image,p));
920 p+=GetPixelChannels(image);
922 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
924 if (progress == MagickFalse)
927 length=(size_t) (q-pixels);
928 if (compression == LZWCompression)
929 status=LZWEncodeImage(image,length,pixels,exception);
931 status=PackbitsEncodeImage(image,length,pixels,exception);
932 if (status == MagickFalse)
934 (void) CloseBlob(image);
937 pixel_info=RelinquishVirtualMemory(pixel_info);
943 Dump uncompressed DirectColor packets.
945 Ascii85Initialize(image);
946 for (y=0; y < (ssize_t) image->rows; y++)
948 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
949 if (p == (const Quantum *) NULL)
951 for (x=0; x < (ssize_t) image->columns; x++)
953 if ((image->alpha_trait == BlendPixelTrait) &&
954 (GetPixelAlpha(image,p) == (Quantum) TransparentAlpha))
956 Ascii85Encode(image,ScaleQuantumToChar((Quantum)
958 Ascii85Encode(image,ScaleQuantumToChar((Quantum)
960 Ascii85Encode(image,ScaleQuantumToChar((Quantum)
964 if (image->colorspace != CMYKColorspace)
966 Ascii85Encode(image,ScaleQuantumToChar(
967 GetPixelRed(image,p)));
968 Ascii85Encode(image,ScaleQuantumToChar(
969 GetPixelGreen(image,p)));
970 Ascii85Encode(image,ScaleQuantumToChar(
971 GetPixelBlue(image,p)));
975 Ascii85Encode(image,ScaleQuantumToChar(
976 GetPixelRed(image,p)));
977 Ascii85Encode(image,ScaleQuantumToChar(
978 GetPixelGreen(image,p)));
979 Ascii85Encode(image,ScaleQuantumToChar(
980 GetPixelBlue(image,p)));
981 Ascii85Encode(image,ScaleQuantumToChar(
982 GetPixelBlack(image,p)));
984 p+=GetPixelChannels(image);
986 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
988 if (progress == MagickFalse)
999 Dump number of colors and colormap.
1001 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g %.20g\n1\n%d\n",
1002 (double) image->columns,(double) image->rows,(int)
1003 (image->colorspace == CMYKColorspace));
1004 (void) WriteBlobString(image,buffer);
1005 (void) FormatLocaleString(buffer,MaxTextExtent,"%d\n",
1006 (int) (compression == NoCompression));
1007 (void) WriteBlobString(image,buffer);
1008 (void) FormatLocaleString(buffer,MaxTextExtent,"%.20g\n",(double)
1010 (void) WriteBlobString(image,buffer);
1011 for (i=0; i < (ssize_t) image->colors; i++)
1013 (void) FormatLocaleString(buffer,MaxTextExtent,"%02X%02X%02X\n",
1014 ScaleQuantumToChar(image->colormap[i].red),
1015 ScaleQuantumToChar(image->colormap[i].green),
1016 ScaleQuantumToChar(image->colormap[i].blue));
1017 (void) WriteBlobString(image,buffer);
1019 switch (compression)
1021 case RLECompression:
1027 register unsigned char
1031 Allocate pixel array.
1033 length=(size_t) number_pixels;
1034 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
1035 if (pixel_info == (MemoryInfo *) NULL)
1036 ThrowWriterException(ResourceLimitError,
1037 "MemoryAllocationFailed");
1038 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1040 Dump runlength encoded pixels.
1043 for (y=0; y < (ssize_t) image->rows; y++)
1045 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1046 if (p == (const Quantum *) NULL)
1048 for (x=0; x < (ssize_t) image->columns; x++)
1050 *q++=(unsigned char) GetPixelIndex(image,p);
1051 p+=GetPixelChannels(image);
1053 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1055 if (progress == MagickFalse)
1058 length=(size_t) (q-pixels);
1059 if (compression == LZWCompression)
1060 status=LZWEncodeImage(image,length,pixels,exception);
1062 status=PackbitsEncodeImage(image,length,pixels,exception);
1063 pixel_info=RelinquishVirtualMemory(pixel_info);
1064 if (status == MagickFalse)
1066 (void) CloseBlob(image);
1067 return(MagickFalse);
1074 Dump uncompressed PseudoColor packets.
1076 Ascii85Initialize(image);
1077 for (y=0; y < (ssize_t) image->rows; y++)
1079 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1080 if (p == (const Quantum *) NULL)
1082 for (x=0; x < (ssize_t) image->columns; x++)
1084 Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p));
1085 p+=GetPixelChannels(image);
1087 progress=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1089 if (progress == MagickFalse)
1092 Ascii85Flush(image);
1097 (void) WriteBlobByte(image,'\n');
1098 length=(size_t) (TellBlob(image)-stop);
1099 stop=TellBlob(image);
1100 offset=SeekBlob(image,start,SEEK_SET);
1102 ThrowWriterException(CorruptImageError,"ImproperImageHeader");
1103 (void) FormatLocaleString(buffer,MaxTextExtent,
1104 "%%%%BeginData:%13ld %s Bytes\n",(long) length,
1105 compression == NoCompression ? "ASCII" : "Binary");
1106 (void) WriteBlobString(image,buffer);
1107 offset=SeekBlob(image,stop,SEEK_SET);
1108 (void) WriteBlobString(image,"%%EndData\n");
1109 if (LocaleCompare(image_info->magick,"PS2") != 0)
1110 (void) WriteBlobString(image,"end\n");
1111 (void) WriteBlobString(image,"%%PageTrailer\n");
1112 if (GetNextImageInList(image) == (Image *) NULL)
1114 image=SyncNextImageInList(image);
1115 status=SetImageProgress(image,SaveImagesTag,scene++,
1116 GetImageListLength(image));
1117 if (status == MagickFalse)
1119 } while (image_info->adjoin != MagickFalse);
1120 (void) WriteBlobString(image,"%%Trailer\n");
1123 (void) FormatLocaleString(buffer,MaxTextExtent,
1124 "%%%%BoundingBox: %.20g %.20g %.20g %.20g\n",ceil(bounds.x1-0.5),
1125 ceil(bounds.y1-0.5),floor(bounds.x2+0.5),floor(bounds.y2+0.5));
1126 (void) WriteBlobString(image,buffer);
1127 (void) FormatLocaleString(buffer,MaxTextExtent,
1128 "%%%%HiResBoundingBox: %g %g %g %g\n",bounds.x1,bounds.y1,
1129 bounds.x2,bounds.y2);
1130 (void) WriteBlobString(image,buffer);
1132 (void) WriteBlobString(image,"%%EOF\n");
1133 (void) CloseBlob(image);