2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Portable Document Format %
20 % Copyright 1999-2011 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 "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/colorspace.h"
49 #include "magick/compress.h"
50 #include "magick/constitute.h"
51 #include "magick/delegate.h"
52 #include "magick/delegate-private.h"
53 #include "magick/draw.h"
54 #include "magick/exception.h"
55 #include "magick/exception-private.h"
56 #include "magick/geometry.h"
57 #include "magick/image.h"
58 #include "magick/image-private.h"
59 #include "magick/list.h"
60 #include "magick/magick.h"
61 #include "magick/memory_.h"
62 #include "magick/monitor.h"
63 #include "magick/monitor-private.h"
64 #include "magick/option.h"
65 #include "magick/profile.h"
66 #include "magick/property.h"
67 #include "magick/quantum-private.h"
68 #include "magick/resource_.h"
69 #include "magick/resize.h"
70 #include "magick/static.h"
71 #include "magick/string_.h"
72 #include "magick/module.h"
73 #include "magick/transform.h"
74 #include "magick/utility.h"
75 #include "magick/module.h"
80 #if defined(MAGICKCORE_TIFF_DELEGATE)
81 #define CCITTParam "-1"
83 #define CCITTParam "0"
89 static MagickBooleanType
90 WritePDFImage(const ImageInfo *,Image *);
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
97 % I n v o k e P D F D e l e g a t e %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103 % InvokePDFDelegate() executes the PDF interpreter with the specified command.
105 % The format of the InvokePDFDelegate method is:
107 % MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
108 % const char *command,ExceptionInfo *exception)
110 % A description of each parameter follows:
112 % o verbose: A value other than zero displays the command prior to
115 % o command: the address of a character string containing the command to
118 % o exception: return any errors or warnings in this structure.
121 static MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
122 const char *command,ExceptionInfo *exception)
127 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
144 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
145 ghost_info=NTGhostscriptDLLVectors();
150 ghost_info=(&ghost_info_struct);
151 (void) ResetMagickMemory(&ghost_info,0,sizeof(ghost_info));
152 ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
154 ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
155 gsapi_init_with_args;
156 ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
157 int *)) gsapi_run_string;
158 ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
159 gsapi_delete_instance;
160 ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
162 if (ghost_info == (GhostInfo *) NULL)
164 status=SystemCommand(MagickFalse,verbose,command,exception);
165 return(status == 0 ? MagickTrue : MagickFalse);
167 if (verbose != MagickFalse)
169 (void) fputs("[ghostscript library]",stdout);
170 (void) fputs(strchr(command,' '),stdout);
172 status=(ghost_info->new_instance)(&interpreter,(void *) NULL);
175 status=SystemCommand(MagickFalse,verbose,command,exception);
176 return(status == 0 ? MagickTrue : MagickFalse);
179 argv=StringToArgv(command,&argc);
180 status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
182 status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
184 (ghost_info->exit)(interpreter);
185 (ghost_info->delete_instance)(interpreter);
186 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
187 NTGhostscriptUnLoadDLL();
189 for (i=0; i < (ssize_t) argc; i++)
190 argv[i]=DestroyString(argv[i]);
191 argv=(char **) RelinquishMagickMemory(argv);
192 if ((status != 0) && (status != -101))
197 message=GetExceptionMessage(errno);
198 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
199 "`%s': %s",command,message);
200 message=DestroyString(message);
201 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
202 "Ghostscript returns status %d, exit code %d",status,code);
207 status=SystemCommand(MagickFalse,verbose,command,exception);
208 return(status == 0 ? MagickTrue : MagickFalse);
213 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
223 % IsPDF() returns MagickTrue if the image format type, identified by the
224 % magick string, is PDF.
226 % The format of the IsPDF method is:
228 % MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
230 % A description of each parameter follows:
232 % o magick: compare image format pattern against these bytes.
234 % o offset: Specifies the offset of the magick string.
237 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
241 if (LocaleNCompare((const char *) magick,"%PDF-",5) == 0)
247 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
251 % R e a d P D F I m a g e %
255 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
257 % ReadPDFImage() reads a Portable Document Format image file and
258 % returns it. It allocates the memory necessary for the new Image structure
259 % and returns a pointer to the new image.
261 % The format of the ReadPDFImage method is:
263 % Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
265 % A description of each parameter follows:
267 % o image_info: the image info.
269 % o exception: return any errors or warnings in this structure.
273 static MagickBooleanType IsPDFRendered(const char *path)
281 if ((path == (const char *) NULL) || (*path == '\0'))
283 status=GetPathAttributes(path,&attributes);
284 if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
285 (attributes.st_size > 0))
290 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
292 #define CropBox "CropBox"
293 #define DeviceCMYK "DeviceCMYK"
294 #define MediaBox "MediaBox"
295 #define RenderPostscriptText "Rendering Postscript... "
296 #define PDFRotate "Rotate"
297 #define SpotColor "Separation"
298 #define TrimBox "TrimBox"
299 #define PDFVersion "PDF-"
302 command[MaxTextExtent],
303 density[MaxTextExtent],
304 filename[MaxTextExtent],
305 geometry[MaxTextExtent],
306 options[MaxTextExtent],
307 input_filename[MaxTextExtent],
308 postscript_filename[MaxTextExtent];
367 assert(image_info != (const ImageInfo *) NULL);
368 assert(image_info->signature == MagickSignature);
369 if (image_info->debug != MagickFalse)
370 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
371 image_info->filename);
372 assert(exception != (ExceptionInfo *) NULL);
373 assert(exception->signature == MagickSignature);
377 image=AcquireImage(image_info);
378 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
379 if (status == MagickFalse)
381 image=DestroyImageList(image);
382 return((Image *) NULL);
384 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
385 if (status == MagickFalse)
387 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
388 image_info->filename);
389 image=DestroyImageList(image);
390 return((Image *) NULL);
393 Set the page density.
395 delta.x=DefaultResolution;
396 delta.y=DefaultResolution;
397 if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
399 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
400 image->x_resolution=geometry_info.rho;
401 image->y_resolution=geometry_info.sigma;
402 if ((flags & SigmaValue) == 0)
403 image->y_resolution=image->x_resolution;
406 Determine page geometry from the PDF media box.
408 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
410 option=GetImageOption(image_info,"pdf:use-cropbox");
411 if (option != (const char *) NULL)
412 cropbox=IsMagickTrue(option);
414 option=GetImageOption(image_info,"pdf:use-trimbox");
415 if (option != (const char *) NULL)
416 trimbox=IsMagickTrue(option);
419 (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box));
420 (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
421 (void) ResetMagickMemory(&hires_bounds,0,sizeof(hires_bounds));
422 (void) ResetMagickMemory(&page,0,sizeof(page));
423 (void) ResetMagickMemory(command,0,sizeof(command));
428 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
436 if ((c != (int) '/') && (c != (int) '%') &&
437 ((size_t) (p-command) < (MaxTextExtent-1)))
441 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
442 count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
444 Is this a CMYK document?
446 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
448 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
452 property[MaxTextExtent],
461 (void) FormatMagickString(property,MaxTextExtent,"pdf:SpotColor-%.20g",
462 (double) spotcolor++);
464 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
466 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MaxTextExtent))
471 value=AcquireString(name);
472 (void) SubstituteString(&value,"#20"," ");
473 (void) SetImageProperty(image,property,value);
474 value=DestroyString(value);
477 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
478 (void) SetImageProperty(image,"pdf:Version",command);
480 if (cropbox != MagickFalse)
482 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
485 Note region defined by crop box.
487 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
488 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
490 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
491 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
495 if (trimbox != MagickFalse)
497 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
500 Note region defined by trim box.
502 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
503 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
505 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
506 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
510 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
513 Note region defined by media box.
515 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
516 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
518 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
519 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
523 if (((bounds.x2 > hires_bounds.x2) && (bounds.y2 > hires_bounds.y2)) ||
524 ((hires_bounds.x2 == 0.0) && (hires_bounds.y2 == 0.0)))
527 Set PDF render geometry.
529 (void) FormatMagickString(geometry,MaxTextExtent,
530 "%gx%g%+.15g%+.15g",bounds.x2-bounds.x1,bounds.y2-bounds.y1,
531 bounds.x1,bounds.y1);
532 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry);
533 page.width=(size_t) floor(bounds.x2-bounds.x1+0.5);
534 page.height=(size_t) floor(bounds.y2-bounds.y1+0.5);
538 (void) CloseBlob(image);
539 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
545 page.width=page.height;
548 if (image_info->colorspace == RGBColorspace)
551 Create Ghostscript control file.
553 file=AcquireUniqueFileResource(postscript_filename);
556 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
557 image_info->filename);
558 image=DestroyImage(image);
559 return((Image *) NULL);
561 count=write(file," ",1);
564 Render Postscript with the Ghostscript delegate.
566 if ((image_info->ping != MagickFalse) ||
567 (image_info->monochrome != MagickFalse))
568 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
570 if (cmyk != MagickFalse)
571 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
573 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
574 if (delegate_info == (const DelegateInfo *) NULL)
576 (void) RelinquishUniqueFileResource(postscript_filename);
577 image=DestroyImage(image);
578 return((Image *) NULL);
581 if (image_info->density != (char *) NULL)
583 flags=ParseGeometry(image_info->density,&geometry_info);
584 image->x_resolution=geometry_info.rho;
585 image->y_resolution=geometry_info.sigma;
586 if ((flags & SigmaValue) == 0)
587 image->y_resolution=image->x_resolution;
589 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",image->x_resolution,
590 image->y_resolution);
591 if (image_info->page != (char *) NULL)
593 (void) ParseAbsoluteGeometry(image_info->page,&page);
594 page.width=(size_t) floor((double) (page.width*image->x_resolution/
596 page.height=(size_t) floor((double) (page.height*image->y_resolution/
598 (void) FormatMagickString(options,MaxTextExtent,"-g%.20gx%.20g ",(double)
599 page.width,(double) page.height);
601 if (cmyk != MagickFalse)
602 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MaxTextExtent);
603 if (cropbox != MagickFalse)
604 (void) ConcatenateMagickString(options,"-dUseCropBox ",MaxTextExtent);
605 if (trimbox != MagickFalse)
606 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MaxTextExtent);
607 read_info=CloneImageInfo(image_info);
608 *read_info->magick='\0';
609 if (read_info->number_scenes != 0)
612 pages[MaxTextExtent];
614 (void) FormatMagickString(pages,MaxTextExtent,"-dFirstPage=%.20g "
615 "-dLastPage=%.20g",(double) read_info->scene+1,(double)
616 (read_info->scene+read_info->number_scenes));
617 (void) ConcatenateMagickString(options,pages,MaxTextExtent);
618 read_info->number_scenes=0;
619 if (read_info->scenes != (char *) NULL)
620 *read_info->scenes='\0';
622 if (read_info->authenticate != (char *) NULL)
623 (void) FormatMagickString(options+strlen(options),MaxTextExtent,
624 " -sPDFPassword=%s",read_info->authenticate);
625 (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
626 (void) AcquireUniqueFilename(filename);
627 (void) ConcatenateMagickString(filename,"-%08d",MaxTextExtent);
628 (void) FormatMagickString(command,MaxTextExtent,
629 GetDelegateCommands(delegate_info),
630 read_info->antialias != MagickFalse ? 4 : 1,
631 read_info->antialias != MagickFalse ? 4 : 1,density,options,filename,
632 postscript_filename,input_filename);
633 status=InvokePDFDelegate(read_info->verbose,command,exception);
634 (void) RelinquishUniqueFileResource(postscript_filename);
635 (void) RelinquishUniqueFileResource(input_filename);
636 pdf_image=(Image *) NULL;
637 if (status == MagickFalse)
640 (void) InterpretImageFilename(image_info,image,filename,(int) i,
641 read_info->filename);
642 if (IsPDFRendered(read_info->filename) == MagickFalse)
644 (void) RelinquishUniqueFileResource(read_info->filename);
649 (void) InterpretImageFilename(image_info,image,filename,(int) i,
650 read_info->filename);
651 if (IsPDFRendered(read_info->filename) == MagickFalse)
653 next=ReadImage(read_info,exception);
654 (void) RelinquishUniqueFileResource(read_info->filename);
655 if (next == (Image *) NULL)
657 AppendImageToList(&pdf_image,next);
659 read_info=DestroyImageInfo(read_info);
660 if (pdf_image == (Image *) NULL)
662 ThrowFileException(exception,DelegateError,"PostscriptDelegateFailed",
663 image_info->filename);
664 return((Image *) NULL);
666 if (LocaleCompare(pdf_image->magick,"BMP") == 0)
671 cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
672 if (cmyk_image != (Image *) NULL)
674 pdf_image=DestroyImageList(pdf_image);
675 pdf_image=cmyk_image;
678 if (image_info->number_scenes != 0)
687 Add place holder images to meet the subimage specification requirement.
689 for (i=0; i < (ssize_t) image_info->scene; i++)
691 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
692 if (clone_image != (Image *) NULL)
693 PrependImageToList(&pdf_image,clone_image);
698 (void) CopyMagickString(pdf_image->filename,filename,MaxTextExtent);
699 pdf_image->page=page;
700 (void) CloneImageProfiles(pdf_image,image);
701 (void) CloneImageProperties(pdf_image,image);
702 next=SyncNextImageInList(pdf_image);
703 if (next != (Image *) NULL)
705 } while (next != (Image *) NULL);
706 image=DestroyImage(image);
708 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
711 next=GetNextImageInList(next);
713 return(GetFirstImageInList(pdf_image));
717 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 % R e g i s t e r P D F I m a g e %
725 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
727 % RegisterPDFImage() adds properties for the PDF image format to
728 % the list of supported formats. The properties include the image format
729 % tag, a method to read and/or write the format, whether the format
730 % supports the saving of more than one frame to the same file or blob,
731 % whether the format supports native in-memory I/O, and a brief
732 % description of the format.
734 % The format of the RegisterPDFImage method is:
736 % size_t RegisterPDFImage(void)
739 ModuleExport size_t RegisterPDFImage(void)
744 entry=SetMagickInfo("AI");
745 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
746 entry->encoder=(EncodeImageHandler *) WritePDFImage;
747 entry->adjoin=MagickFalse;
748 entry->blob_support=MagickFalse;
749 entry->seekable_stream=MagickTrue;
750 entry->thread_support=EncoderThreadSupport;
751 entry->description=ConstantString("Adobe Illustrator CS2");
752 entry->module=ConstantString("PDF");
753 (void) RegisterMagickInfo(entry);
754 entry=SetMagickInfo("EPDF");
755 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
756 entry->encoder=(EncodeImageHandler *) WritePDFImage;
757 entry->adjoin=MagickFalse;
758 entry->blob_support=MagickFalse;
759 entry->seekable_stream=MagickTrue;
760 entry->thread_support=EncoderThreadSupport;
761 entry->description=ConstantString("Encapsulated Portable Document Format");
762 entry->module=ConstantString("PDF");
763 (void) RegisterMagickInfo(entry);
764 entry=SetMagickInfo("PDF");
765 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
766 entry->encoder=(EncodeImageHandler *) WritePDFImage;
767 entry->magick=(IsImageFormatHandler *) IsPDF;
768 entry->blob_support=MagickFalse;
769 entry->seekable_stream=MagickTrue;
770 entry->thread_support=EncoderThreadSupport;
771 entry->description=ConstantString("Portable Document Format");
772 entry->module=ConstantString("PDF");
773 (void) RegisterMagickInfo(entry);
774 entry=SetMagickInfo("PDFA");
775 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
776 entry->encoder=(EncodeImageHandler *) WritePDFImage;
777 entry->magick=(IsImageFormatHandler *) IsPDF;
778 entry->blob_support=MagickFalse;
779 entry->seekable_stream=MagickTrue;
780 entry->thread_support=EncoderThreadSupport;
781 entry->description=ConstantString("Portable Document Archive Format");
782 entry->module=ConstantString("PDF");
783 (void) RegisterMagickInfo(entry);
784 return(MagickImageCoderSignature);
788 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
792 % U n r e g i s t e r P D F I m a g e %
796 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798 % UnregisterPDFImage() removes format registrations made by the
799 % PDF module from the list of supported formats.
801 % The format of the UnregisterPDFImage method is:
803 % UnregisterPDFImage(void)
806 ModuleExport void UnregisterPDFImage(void)
808 (void) UnregisterMagickInfo("AI");
809 (void) UnregisterMagickInfo("EPDF");
810 (void) UnregisterMagickInfo("PDF");
811 (void) UnregisterMagickInfo("PDFA");
815 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819 % W r i t e P D F I m a g e %
823 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 % WritePDFImage() writes an image in the Portable Document image
828 % The format of the WritePDFImage method is:
830 % MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
832 % A description of each parameter follows.
834 % o image_info: the image info.
836 % o image: The image.
840 static inline size_t MagickMax(const size_t x,const size_t y)
847 static inline size_t MagickMin(const size_t x,const size_t y)
854 static char *EscapeParenthesis(const char *text)
863 buffer[MaxTextExtent];
870 for (i=0; i < (ssize_t) MagickMin(strlen(text),(MaxTextExtent-escapes-1)); i++)
872 if ((text[i] == '(') || (text[i] == ')'))
883 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
884 Image *image,Image *inject_image)
902 write_info=CloneImageInfo(image_info);
903 (void) CopyMagickString(write_info->filename,"GROUP4:",MaxTextExtent);
904 (void) CopyMagickString(write_info->magick,"GROUP4",MaxTextExtent);
905 group4_image=CloneImage(inject_image,0,0,MagickTrue,&image->exception);
906 if (group4_image == (Image *) NULL)
908 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
910 group4_image=DestroyImage(group4_image);
911 if (group4 == (unsigned char *) NULL)
913 write_info=DestroyImageInfo(write_info);
914 if (WriteBlob(image,length,group4) != (ssize_t) length)
916 group4=(unsigned char *) RelinquishMagickMemory(group4);
920 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
922 #define CFormat "/Filter [ /%s ]\n"
923 #define ObjectsPerImage 14
928 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
929 "<x:xmpmeta xmlns:x=\"adobe:ns:meta/\" x:xmptk=\"Adobe XMP Core 4.0-c316 44.253921, Sun Oct 01 2006 17:08:23\">\n"
930 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
931 " <rdf:Description rdf:about=\"\"\n"
932 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
933 " <xap:ModifyDate>%s</xap:ModifyDate>\n"
934 " <xap:CreateDate>%s</xap:CreateDate>\n"
935 " <xap:MetadataDate>%s</xap:MetadataDate>\n"
936 " <xap:CreatorTool>%s</xap:CreatorTool>\n"
937 " </rdf:Description>\n"
938 " <rdf:Description rdf:about=\"\"\n"
939 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
940 " <dc:format>application/pdf</dc:format>\n"
941 " </rdf:Description>\n"
942 " <rdf:Description rdf:about=\"\"\n"
943 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
944 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
945 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
946 " </rdf:Description>\n"
947 " <rdf:Description rdf:about=\"\"\n"
948 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
949 " <pdf:Producer>%s</pdf:Producer>\n"
950 " </rdf:Description>\n"
951 " <rdf:Description rdf:about=\"\"\n"
952 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
953 " <pdfaid:part>1</pdfaid:part>\n"
954 " <pdfaid:conformance>B</pdfaid:conformance>\n"
955 " </rdf:Description>\n"
958 "<?xpacket end=\"w\"?>\n"
960 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
963 basename[MaxTextExtent],
964 buffer[MaxTextExtent],
967 page_geometry[MaxTextExtent];
1013 register const IndexPacket
1016 register const PixelPacket
1019 register unsigned char
1047 Open output image file.
1049 assert(image_info != (const ImageInfo *) NULL);
1050 assert(image_info->signature == MagickSignature);
1051 assert(image != (Image *) NULL);
1052 assert(image->signature == MagickSignature);
1053 if (image->debug != MagickFalse)
1054 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1055 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1056 if (status == MagickFalse)
1059 Allocate X ref memory.
1061 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
1062 if (xref == (MagickOffsetType *) NULL)
1063 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1064 (void) ResetMagickMemory(xref,0,2048UL*sizeof(*xref));
1070 if (image_info->compression == JPEG2000Compression)
1071 version=(size_t) MagickMax(version,5);
1072 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1073 if (next->matte != MagickFalse)
1074 version=(size_t) MagickMax(version,4);
1075 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1076 version=(size_t) MagickMax(version,6);
1077 (void) FormatMagickString(buffer,MaxTextExtent,"%%PDF-1.%.20g \n",
1079 (void) WriteBlobString(image,buffer);
1080 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1081 (void) WriteBlobString(image,"%âãÏÓ\n");
1083 Write Catalog object.
1085 xref[object++]=TellBlob(image);
1087 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1089 (void) WriteBlobString(image,buffer);
1090 (void) WriteBlobString(image,"<<\n");
1091 if (LocaleCompare(image_info->magick,"PDFA") != 0)
1092 (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %.20g 0 R\n",
1096 (void) FormatMagickString(buffer,MaxTextExtent,"/Metadata %.20g 0 R\n",
1098 (void) WriteBlobString(image,buffer);
1099 (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %.20g 0 R\n",
1102 (void) WriteBlobString(image,buffer);
1103 (void) WriteBlobString(image,"/Type /Catalog\n");
1104 (void) WriteBlobString(image,">>\n");
1105 (void) WriteBlobString(image,"endobj\n");
1106 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1109 create_date[MaxTextExtent],
1110 modify_date[MaxTextExtent],
1111 timestamp[MaxTextExtent],
1112 xmp_profile[MaxTextExtent];
1120 xref[object++]=TellBlob(image);
1121 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",
1123 (void) WriteBlobString(image,buffer);
1124 (void) WriteBlobString(image,"<<\n");
1125 (void) WriteBlobString(image,"/Subtype /XML\n");
1127 value=GetImageProperty(image,"date:modify");
1128 if (value != (const char *) NULL)
1129 (void) CopyMagickString(modify_date,value,MaxTextExtent);
1131 value=GetImageProperty(image,"date:create");
1132 if (value != (const char *) NULL)
1133 (void) CopyMagickString(create_date,value,MaxTextExtent);
1134 (void) FormatMagickTime(time((time_t *) NULL),MaxTextExtent,timestamp);
1135 i=FormatMagickString(xmp_profile,MaxTextExtent,XMPProfile,
1136 XMPProfileMagick,modify_date,create_date,timestamp,
1137 GetMagickVersion(&version),GetMagickVersion(&version));
1138 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g\n",
1140 (void) WriteBlobString(image,buffer);
1141 (void) WriteBlobString(image,"/Type /Metadata\n");
1142 (void) WriteBlobString(image,">>\nstream\n");
1143 (void) WriteBlobString(image,xmp_profile);
1144 (void) WriteBlobString(image,"endstream\n");
1145 (void) WriteBlobString(image,"endobj\n");
1150 xref[object++]=TellBlob(image);
1152 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1154 (void) WriteBlobString(image,buffer);
1155 (void) WriteBlobString(image,"<<\n");
1156 (void) WriteBlobString(image,"/Type /Pages\n");
1157 (void) FormatMagickString(buffer,MaxTextExtent,"/Kids [ %.20g 0 R ",
1159 (void) WriteBlobString(image,buffer);
1160 count=(ssize_t) (pages_id+ObjectsPerImage+1);
1161 if (image_info->adjoin != MagickFalse)
1167 Predict page object id's.
1170 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1172 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 R ",(double)
1174 (void) WriteBlobString(image,buffer);
1175 kid_image=GetNextImageInList(kid_image);
1177 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1179 if (xref == (MagickOffsetType *) NULL)
1180 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1182 (void) WriteBlobString(image,"]\n");
1183 (void) FormatMagickString(buffer,MaxTextExtent,"/Count %.20g\n",
1184 (double) ((count-pages_id)/ObjectsPerImage));
1185 (void) WriteBlobString(image,buffer);
1186 (void) WriteBlobString(image,">>\n");
1187 (void) WriteBlobString(image,"endobj\n");
1191 compression=image->compression;
1192 if (image_info->compression != UndefinedCompression)
1193 compression=image_info->compression;
1194 switch (compression)
1196 case FaxCompression:
1197 case Group4Compression:
1199 if ((IsMonochromeImage(image,&image->exception) == MagickFalse) ||
1200 (image->matte != MagickFalse))
1201 compression=RLECompression;
1204 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1205 case JPEGCompression:
1207 compression=RLECompression;
1208 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1209 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1214 #if !defined(MAGICKCORE_JP2_DELEGATE)
1215 case JPEG2000Compression:
1217 compression=RLECompression;
1218 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1219 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1224 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1225 case ZipCompression:
1227 compression=RLECompression;
1228 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1229 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1234 case LZWCompression:
1236 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1237 compression=RLECompression; /* LZW compression is forbidden */
1242 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1243 compression=RLECompression; /* ASCII 85 compression is forbidden */
1249 if (compression == JPEG2000Compression)
1251 if (image->colorspace != RGBColorspace)
1252 (void) TransformImageColorspace(image,RGBColorspace);
1255 Scale relative to dots-per-inch.
1257 delta.x=DefaultResolution;
1258 delta.y=DefaultResolution;
1259 resolution.x=image->x_resolution;
1260 resolution.y=image->y_resolution;
1261 if ((resolution.x == 0.0) || (resolution.y == 0.0))
1263 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1264 resolution.x=geometry_info.rho;
1265 resolution.y=geometry_info.sigma;
1266 if ((flags & SigmaValue) == 0)
1267 resolution.y=resolution.x;
1269 if (image_info->density != (char *) NULL)
1271 flags=ParseGeometry(image_info->density,&geometry_info);
1272 resolution.x=geometry_info.rho;
1273 resolution.y=geometry_info.sigma;
1274 if ((flags & SigmaValue) == 0)
1275 resolution.y=resolution.x;
1277 if (image->units == PixelsPerCentimeterResolution)
1279 resolution.x=(double) ((size_t) (100.0*2.54*resolution.x+0.5)/100.0);
1280 resolution.y=(double) ((size_t) (100.0*2.54*resolution.y+0.5)/100.0);
1282 SetGeometry(image,&geometry);
1283 (void) FormatMagickString(page_geometry,MaxTextExtent,"%.20gx%.20g",
1284 (double) image->columns,(double) image->rows);
1285 if (image_info->page != (char *) NULL)
1286 (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent);
1288 if ((image->page.width != 0) && (image->page.height != 0))
1289 (void) FormatMagickString(page_geometry,MaxTextExtent,
1290 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,
1291 (double) image->page.height,(double) image->page.x,(double)
1294 if ((image->gravity != UndefinedGravity) &&
1295 (LocaleCompare(image_info->magick,"PDF") == 0))
1296 (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent);
1297 (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent);
1298 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1299 &geometry.width,&geometry.height);
1300 scale.x=(double) (geometry.width*delta.x)/resolution.x;
1301 geometry.width=(size_t) floor(scale.x+0.5);
1302 scale.y=(double) (geometry.height*delta.y)/resolution.y;
1303 geometry.height=(size_t) floor(scale.y+0.5);
1304 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1305 (void) ParseGravityGeometry(image,page_geometry,&page_info,
1307 if (image->gravity != UndefinedGravity)
1309 geometry.x=(-page_info.x);
1310 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
1313 if (image_info->pointsize != 0.0)
1314 pointsize=image_info->pointsize;
1316 value=GetImageProperty(image,"Label");
1317 if (value != (const char *) NULL)
1318 text_size=(size_t) (MultilineCensus(value)*pointsize+12);
1323 xref[object++]=TellBlob(image);
1324 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1326 (void) WriteBlobString(image,buffer);
1327 (void) WriteBlobString(image,"<<\n");
1328 (void) WriteBlobString(image,"/Type /Page\n");
1329 (void) FormatMagickString(buffer,MaxTextExtent,"/Parent %.20g 0 R\n",
1331 (void) WriteBlobString(image,buffer);
1332 (void) WriteBlobString(image,"/Resources <<\n");
1333 labels=(char **) NULL;
1334 value=GetImageProperty(image,"Label");
1335 if (value != (const char *) NULL)
1336 labels=StringToList(value);
1337 if (labels != (char **) NULL)
1339 (void) FormatMagickString(buffer,MaxTextExtent,
1340 "/Font << /F%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1342 (void) WriteBlobString(image,buffer);
1344 (void) FormatMagickString(buffer,MaxTextExtent,
1345 "/XObject << /Im%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1347 (void) WriteBlobString(image,buffer);
1348 (void) FormatMagickString(buffer,MaxTextExtent,"/ProcSet %.20g 0 R >>\n",
1350 (void) WriteBlobString(image,buffer);
1351 (void) FormatMagickString(buffer,MaxTextExtent,
1352 "/MediaBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1353 72.0*media_info.height/resolution.y);
1354 (void) WriteBlobString(image,buffer);
1355 (void) FormatMagickString(buffer,MaxTextExtent,
1356 "/CropBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1357 72.0*media_info.height/resolution.y);
1358 (void) WriteBlobString(image,buffer);
1359 (void) FormatMagickString(buffer,MaxTextExtent,"/Contents %.20g 0 R\n",
1361 (void) WriteBlobString(image,buffer);
1362 (void) FormatMagickString(buffer,MaxTextExtent,"/Thumb %.20g 0 R\n",
1364 (void) WriteBlobString(image,buffer);
1365 (void) WriteBlobString(image,">>\n");
1366 (void) WriteBlobString(image,"endobj\n");
1368 Write Contents object.
1370 xref[object++]=TellBlob(image);
1371 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1373 (void) WriteBlobString(image,buffer);
1374 (void) WriteBlobString(image,"<<\n");
1375 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g 0 R\n",
1377 (void) WriteBlobString(image,buffer);
1378 (void) WriteBlobString(image,">>\n");
1379 (void) WriteBlobString(image,"stream\n");
1380 offset=TellBlob(image);
1381 (void) WriteBlobString(image,"q\n");
1382 if (labels != (char **) NULL)
1383 for (i=0; labels[i] != (char *) NULL; i++)
1385 (void) WriteBlobString(image,"BT\n");
1386 (void) FormatMagickString(buffer,MaxTextExtent,"/F%.20g %g Tf\n",
1387 (double) image->scene,pointsize);
1388 (void) WriteBlobString(image,buffer);
1389 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g %.20g Td\n",
1390 (double) geometry.x,(double) (geometry.y+geometry.height+i*pointsize+
1392 (void) WriteBlobString(image,buffer);
1393 (void) FormatMagickString(buffer,MaxTextExtent,"(%s) Tj\n",labels[i]);
1394 (void) WriteBlobString(image,buffer);
1395 (void) WriteBlobString(image,"ET\n");
1396 labels[i]=DestroyString(labels[i]);
1398 (void) FormatMagickString(buffer,MaxTextExtent,"%g 0 0 %g %.20g %.20g cm\n",
1399 scale.x,scale.y,(double) geometry.x,(double) geometry.y);
1400 (void) WriteBlobString(image,buffer);
1401 (void) FormatMagickString(buffer,MaxTextExtent,"/Im%.20g Do\n",
1402 (double) image->scene);
1403 (void) WriteBlobString(image,buffer);
1404 (void) WriteBlobString(image,"Q\n");
1405 offset=TellBlob(image)-offset;
1406 (void) WriteBlobString(image,"endstream\n");
1407 (void) WriteBlobString(image,"endobj\n");
1409 Write Length object.
1411 xref[object++]=TellBlob(image);
1412 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1414 (void) WriteBlobString(image,buffer);
1415 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double) offset);
1416 (void) WriteBlobString(image,buffer);
1417 (void) WriteBlobString(image,"endobj\n");
1419 Write Procset object.
1421 xref[object++]=TellBlob(image);
1422 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",
1424 (void) WriteBlobString(image,buffer);
1425 if ((image->storage_class == DirectClass) || (image->colors > 256))
1426 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MaxTextExtent);
1428 if ((compression == FaxCompression) || (compression == Group4Compression))
1429 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MaxTextExtent);
1431 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MaxTextExtent);
1432 (void) WriteBlobString(image,buffer);
1433 (void) WriteBlobString(image," ]\n");
1434 (void) WriteBlobString(image,"endobj\n");
1438 xref[object++]=TellBlob(image);
1439 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",
1441 (void) WriteBlobString(image,buffer);
1442 (void) WriteBlobString(image,"<<\n");
1443 if (labels != (char **) NULL)
1445 (void) WriteBlobString(image,"/Type /Font\n");
1446 (void) WriteBlobString(image,"/Subtype /Type1\n");
1447 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /F%.20g\n",
1448 (double) image->scene);
1449 (void) WriteBlobString(image,buffer);
1450 (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1451 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1452 labels=(char **) RelinquishMagickMemory(labels);
1454 (void) WriteBlobString(image,">>\n");
1455 (void) WriteBlobString(image,"endobj\n");
1457 Write XObject object.
1459 xref[object++]=TellBlob(image);
1460 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1462 (void) WriteBlobString(image,buffer);
1463 (void) WriteBlobString(image,"<<\n");
1464 (void) WriteBlobString(image,"/Type /XObject\n");
1465 (void) WriteBlobString(image,"/Subtype /Image\n");
1466 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Im%.20g\n",
1467 (double) image->scene);
1468 (void) WriteBlobString(image,buffer);
1469 switch (compression)
1473 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1476 case JPEGCompression:
1478 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1479 if (image->colorspace != CMYKColorspace)
1481 (void) WriteBlobString(image,buffer);
1482 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1486 case JPEG2000Compression:
1488 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1489 if (image->colorspace != CMYKColorspace)
1491 (void) WriteBlobString(image,buffer);
1492 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1496 case LZWCompression:
1498 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1501 case ZipCompression:
1503 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
1506 case FaxCompression:
1507 case Group4Compression:
1509 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1511 (void) WriteBlobString(image,buffer);
1512 (void) FormatMagickString(buffer,MaxTextExtent,"/DecodeParms [ << "
1513 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
1514 (double) image->columns,(double) image->rows);
1519 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
1524 (void) WriteBlobString(image,buffer);
1525 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %.20g\n",(double)
1527 (void) WriteBlobString(image,buffer);
1528 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %.20g\n",(double)
1530 (void) WriteBlobString(image,buffer);
1531 (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %.20g 0 R\n",
1533 (void) WriteBlobString(image,buffer);
1534 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
1535 (compression == FaxCompression) || (compression == Group4Compression) ?
1537 (void) WriteBlobString(image,buffer);
1538 if (image->matte != MagickFalse)
1540 (void) FormatMagickString(buffer,MaxTextExtent,"/SMask %.20g 0 R\n",
1542 (void) WriteBlobString(image,buffer);
1544 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g 0 R\n",
1546 (void) WriteBlobString(image,buffer);
1547 (void) WriteBlobString(image,">>\n");
1548 (void) WriteBlobString(image,"stream\n");
1549 offset=TellBlob(image);
1550 number_pixels=(MagickSizeType) image->columns*image->rows;
1551 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1552 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1553 if ((compression == FaxCompression) || (compression == Group4Compression) ||
1554 ((image_info->type != TrueColorType) &&
1555 (IsGrayImage(image,&image->exception) != MagickFalse)))
1557 switch (compression)
1559 case FaxCompression:
1560 case Group4Compression:
1562 if (LocaleCompare(CCITTParam,"0") == 0)
1564 (void) HuffmanEncodeImage(image_info,image,image);
1567 (void) Huffman2DEncodeImage(image_info,image,image);
1570 case JPEGCompression:
1572 status=InjectImageBlob(image_info,image,image,"jpeg",
1574 if (status == MagickFalse)
1575 ThrowWriterException(CoderError,image->exception.reason);
1578 case JPEG2000Compression:
1580 status=InjectImageBlob(image_info,image,image,"jp2",
1582 if (status == MagickFalse)
1583 ThrowWriterException(CoderError,image->exception.reason);
1586 case RLECompression:
1590 Allocate pixel array.
1592 length=(size_t) number_pixels;
1593 pixels=(unsigned char *) AcquireQuantumMemory(length,
1595 if (pixels == (unsigned char *) NULL)
1596 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1598 Dump Runlength encoded pixels.
1601 for (y=0; y < (ssize_t) image->rows; y++)
1603 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1604 if (p == (const PixelPacket *) NULL)
1606 for (x=0; x < (ssize_t) image->columns; x++)
1608 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
1611 if (image->previous == (Image *) NULL)
1613 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1615 if (status == MagickFalse)
1619 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1620 if (compression == ZipCompression)
1621 status=ZLIBEncodeImage(image,length,pixels);
1624 if (compression == LZWCompression)
1625 status=LZWEncodeImage(image,length,pixels);
1627 status=PackbitsEncodeImage(image,length,pixels);
1628 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1629 if (status == MagickFalse)
1631 (void) CloseBlob(image);
1632 return(MagickFalse);
1639 Dump uncompressed PseudoColor packets.
1641 Ascii85Initialize(image);
1642 for (y=0; y < (ssize_t) image->rows; y++)
1644 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1645 if (p == (const PixelPacket *) NULL)
1647 for (x=0; x < (ssize_t) image->columns; x++)
1649 Ascii85Encode(image,
1650 ScaleQuantumToChar(PixelIntensityToQuantum(p)));
1653 if (image->previous == (Image *) NULL)
1655 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1657 if (status == MagickFalse)
1661 Ascii85Flush(image);
1667 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1668 (compression == JPEGCompression) ||
1669 (compression == JPEG2000Compression))
1670 switch (compression)
1672 case JPEGCompression:
1674 status=InjectImageBlob(image_info,image,image,"jpeg",
1676 if (status == MagickFalse)
1677 ThrowWriterException(CoderError,image->exception.reason);
1680 case JPEG2000Compression:
1682 status=InjectImageBlob(image_info,image,image,"jp2",
1684 if (status == MagickFalse)
1685 ThrowWriterException(CoderError,image->exception.reason);
1688 case RLECompression:
1692 Allocate pixel array.
1694 length=(size_t) number_pixels;
1695 pixels=(unsigned char *) AcquireQuantumMemory(length,
1697 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
1698 if (pixels == (unsigned char *) NULL)
1699 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1701 Dump runoffset encoded pixels.
1704 for (y=0; y < (ssize_t) image->rows; y++)
1706 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1707 if (p == (const PixelPacket *) NULL)
1709 indexes=GetVirtualIndexQueue(image);
1710 for (x=0; x < (ssize_t) image->columns; x++)
1712 *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
1713 *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
1714 *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
1715 if (image->colorspace == CMYKColorspace)
1716 *q++=ScaleQuantumToChar(indexes[x]);
1719 if (image->previous == (Image *) NULL)
1721 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1723 if (status == MagickFalse)
1727 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1728 if (compression == ZipCompression)
1729 status=ZLIBEncodeImage(image,length,pixels);
1732 if (compression == LZWCompression)
1733 status=LZWEncodeImage(image,length,pixels);
1735 status=PackbitsEncodeImage(image,length,pixels);
1736 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1737 if (status == MagickFalse)
1739 (void) CloseBlob(image);
1740 return(MagickFalse);
1747 Dump uncompressed DirectColor packets.
1749 Ascii85Initialize(image);
1750 for (y=0; y < (ssize_t) image->rows; y++)
1752 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
1753 if (p == (const PixelPacket *) NULL)
1755 indexes=GetVirtualIndexQueue(image);
1756 for (x=0; x < (ssize_t) image->columns; x++)
1758 Ascii85Encode(image,ScaleQuantumToChar(
1759 GetRedPixelComponent(p)));
1760 Ascii85Encode(image,ScaleQuantumToChar(
1761 GetGreenPixelComponent(p)));
1762 Ascii85Encode(image,ScaleQuantumToChar(
1763 GetBluePixelComponent(p)));
1764 if (image->colorspace == CMYKColorspace)
1765 Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
1768 if (image->previous == (Image *) NULL)
1770 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1772 if (status == MagickFalse)
1776 Ascii85Flush(image);
1783 Dump number of colors and colormap.
1785 switch (compression)
1787 case RLECompression:
1791 Allocate pixel array.
1793 length=(size_t) number_pixels;
1794 pixels=(unsigned char *) AcquireQuantumMemory(length,
1796 if (pixels == (unsigned char *) NULL)
1797 ThrowWriterException(ResourceLimitError,
1798 "MemoryAllocationFailed");
1800 Dump Runlength encoded pixels.
1803 for (y=0; y < (ssize_t) image->rows; y++)
1805 p=GetVirtualPixels(image,0,y,image->columns,1,
1807 if (p == (const PixelPacket *) NULL)
1809 indexes=GetVirtualIndexQueue(image);
1810 for (x=0; x < (ssize_t) image->columns; x++)
1811 *q++=(unsigned char) indexes[x];
1812 if (image->previous == (Image *) NULL)
1814 status=SetImageProgress(image,SaveImageTag,
1815 (MagickOffsetType) y,image->rows);
1816 if (status == MagickFalse)
1820 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1821 if (compression == ZipCompression)
1822 status=ZLIBEncodeImage(image,length,pixels);
1825 if (compression == LZWCompression)
1826 status=LZWEncodeImage(image,length,pixels);
1828 status=PackbitsEncodeImage(image,length,pixels);
1829 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1830 if (status == MagickFalse)
1832 (void) CloseBlob(image);
1833 return(MagickFalse);
1840 Dump uncompressed PseudoColor packets.
1842 Ascii85Initialize(image);
1843 for (y=0; y < (ssize_t) image->rows; y++)
1845 p=GetVirtualPixels(image,0,y,image->columns,1,
1847 if (p == (const PixelPacket *) NULL)
1849 indexes=GetVirtualIndexQueue(image);
1850 for (x=0; x < (ssize_t) image->columns; x++)
1851 Ascii85Encode(image,(unsigned char) indexes[x]);
1852 if (image->previous == (Image *) NULL)
1854 status=SetImageProgress(image,SaveImageTag,
1855 (MagickOffsetType) y,image->rows);
1856 if (status == MagickFalse)
1860 Ascii85Flush(image);
1865 offset=TellBlob(image)-offset;
1866 (void) WriteBlobString(image,"\nendstream\n");
1867 (void) WriteBlobString(image,"endobj\n");
1869 Write Length object.
1871 xref[object++]=TellBlob(image);
1872 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1874 (void) WriteBlobString(image,buffer);
1875 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",
1877 (void) WriteBlobString(image,buffer);
1878 (void) WriteBlobString(image,"endobj\n");
1880 Write Colorspace object.
1882 xref[object++]=TellBlob(image);
1883 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1885 (void) WriteBlobString(image,buffer);
1886 if (image->colorspace == CMYKColorspace)
1887 (void) CopyMagickString(buffer,"/DeviceCMYK\n",MaxTextExtent);
1889 if ((compression == FaxCompression) ||
1890 (compression == Group4Compression) ||
1891 ((image_info->type != TrueColorType) &&
1892 (IsGrayImage(image,&image->exception) != MagickFalse)))
1893 (void) CopyMagickString(buffer,"/DeviceGray\n",MaxTextExtent);
1895 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1896 (compression == JPEGCompression) ||
1897 (compression == JPEG2000Compression))
1898 (void) CopyMagickString(buffer,"/DeviceRGB\n",MaxTextExtent);
1900 (void) FormatMagickString(buffer,MaxTextExtent,
1901 "[ /Indexed /DeviceRGB %.20g %.20g 0 R ]\n",(double) image->colors-
1902 1,(double) object+3);
1903 (void) WriteBlobString(image,buffer);
1904 (void) WriteBlobString(image,"endobj\n");
1908 SetGeometry(image,&geometry);
1909 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
1910 &geometry.width,&geometry.height);
1911 tile_image=ThumbnailImage(image,geometry.width,geometry.height,
1913 if (tile_image == (Image *) NULL)
1914 ThrowWriterException(ResourceLimitError,image->exception.reason);
1915 xref[object++]=TellBlob(image);
1916 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
1918 (void) WriteBlobString(image,buffer);
1919 (void) WriteBlobString(image,"<<\n");
1920 switch (compression)
1924 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1927 case JPEGCompression:
1929 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1930 if (image->colorspace != CMYKColorspace)
1932 (void) WriteBlobString(image,buffer);
1933 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1937 case JPEG2000Compression:
1939 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1940 if (image->colorspace != CMYKColorspace)
1942 (void) WriteBlobString(image,buffer);
1943 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1947 case LZWCompression:
1949 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1952 case ZipCompression:
1954 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
1957 case FaxCompression:
1958 case Group4Compression:
1960 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1962 (void) WriteBlobString(image,buffer);
1963 (void) FormatMagickString(buffer,MaxTextExtent,"/DecodeParms [ << "
1964 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
1965 (double) tile_image->columns,(double) tile_image->rows);
1970 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
1975 (void) WriteBlobString(image,buffer);
1976 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %.20g\n",(double)
1977 tile_image->columns);
1978 (void) WriteBlobString(image,buffer);
1979 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %.20g\n",(double)
1981 (void) WriteBlobString(image,buffer);
1982 (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %.20g 0 R\n",
1984 (void) WriteBlobString(image,buffer);
1985 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
1986 (compression == FaxCompression) || (compression == Group4Compression) ?
1988 (void) WriteBlobString(image,buffer);
1989 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g 0 R\n",
1991 (void) WriteBlobString(image,buffer);
1992 (void) WriteBlobString(image,">>\n");
1993 (void) WriteBlobString(image,"stream\n");
1994 offset=TellBlob(image);
1995 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
1996 if ((compression == FaxCompression) ||
1997 (compression == Group4Compression) ||
1998 ((image_info->type != TrueColorType) &&
1999 (IsGrayImage(tile_image,&image->exception) != MagickFalse)))
2001 switch (compression)
2003 case FaxCompression:
2004 case Group4Compression:
2006 if (LocaleCompare(CCITTParam,"0") == 0)
2008 (void) HuffmanEncodeImage(image_info,image,tile_image);
2011 (void) Huffman2DEncodeImage(image_info,image,tile_image);
2014 case JPEGCompression:
2016 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2018 if (status == MagickFalse)
2019 ThrowWriterException(CoderError,tile_image->exception.reason);
2022 case JPEG2000Compression:
2024 status=InjectImageBlob(image_info,image,tile_image,"jp2",
2026 if (status == MagickFalse)
2027 ThrowWriterException(CoderError,tile_image->exception.reason);
2030 case RLECompression:
2034 Allocate pixel array.
2036 length=(size_t) number_pixels;
2037 pixels=(unsigned char *) AcquireQuantumMemory(length,
2039 if (pixels == (unsigned char *) NULL)
2041 tile_image=DestroyImage(tile_image);
2042 ThrowWriterException(ResourceLimitError,
2043 "MemoryAllocationFailed");
2046 Dump Runlength encoded pixels.
2049 for (y=0; y < (ssize_t) tile_image->rows; y++)
2051 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2052 &tile_image->exception);
2053 if (p == (const PixelPacket *) NULL)
2055 for (x=0; x < (ssize_t) tile_image->columns; x++)
2057 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
2061 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2062 if (compression == ZipCompression)
2063 status=ZLIBEncodeImage(image,length,pixels);
2066 if (compression == LZWCompression)
2067 status=LZWEncodeImage(image,length,pixels);
2069 status=PackbitsEncodeImage(image,length,pixels);
2070 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2071 if (status == MagickFalse)
2073 (void) CloseBlob(image);
2074 return(MagickFalse);
2081 Dump uncompressed PseudoColor packets.
2083 Ascii85Initialize(image);
2084 for (y=0; y < (ssize_t) tile_image->rows; y++)
2086 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2087 &tile_image->exception);
2088 if (p == (const PixelPacket *) NULL)
2090 for (x=0; x < (ssize_t) tile_image->columns; x++)
2092 Ascii85Encode(image,
2093 ScaleQuantumToChar(PixelIntensityToQuantum(p)));
2097 Ascii85Flush(image);
2103 if ((tile_image->storage_class == DirectClass) ||
2104 (tile_image->colors > 256) || (compression == JPEGCompression) ||
2105 (compression == JPEG2000Compression))
2106 switch (compression)
2108 case JPEGCompression:
2110 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2112 if (status == MagickFalse)
2113 ThrowWriterException(CoderError,tile_image->exception.reason);
2116 case JPEG2000Compression:
2118 status=InjectImageBlob(image_info,image,tile_image,"jp2",
2120 if (status == MagickFalse)
2121 ThrowWriterException(CoderError,tile_image->exception.reason);
2124 case RLECompression:
2128 Allocate pixel array.
2130 length=(size_t) number_pixels;
2131 pixels=(unsigned char *) AcquireQuantumMemory(length,4*
2133 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2134 if (pixels == (unsigned char *) NULL)
2136 tile_image=DestroyImage(tile_image);
2137 ThrowWriterException(ResourceLimitError,
2138 "MemoryAllocationFailed");
2141 Dump runoffset encoded pixels.
2144 for (y=0; y < (ssize_t) tile_image->rows; y++)
2146 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2147 &tile_image->exception);
2148 if (p == (const PixelPacket *) NULL)
2150 indexes=GetVirtualIndexQueue(tile_image);
2151 for (x=0; x < (ssize_t) tile_image->columns; x++)
2153 *q++=ScaleQuantumToChar(GetRedPixelComponent(p));
2154 *q++=ScaleQuantumToChar(GetGreenPixelComponent(p));
2155 *q++=ScaleQuantumToChar(GetBluePixelComponent(p));
2156 if (image->colorspace == CMYKColorspace)
2157 *q++=ScaleQuantumToChar(indexes[x]);
2161 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2162 if (compression == ZipCompression)
2163 status=ZLIBEncodeImage(image,length,pixels);
2166 if (compression == LZWCompression)
2167 status=LZWEncodeImage(image,length,pixels);
2169 status=PackbitsEncodeImage(image,length,pixels);
2170 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2171 if (status == MagickFalse)
2173 (void) CloseBlob(image);
2174 return(MagickFalse);
2181 Dump uncompressed DirectColor packets.
2183 Ascii85Initialize(image);
2184 for (y=0; y < (ssize_t) tile_image->rows; y++)
2186 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2187 &tile_image->exception);
2188 if (p == (const PixelPacket *) NULL)
2190 indexes=GetVirtualIndexQueue(tile_image);
2191 for (x=0; x < (ssize_t) tile_image->columns; x++)
2193 Ascii85Encode(image,ScaleQuantumToChar(
2194 GetRedPixelComponent(p)));
2195 Ascii85Encode(image,ScaleQuantumToChar(
2196 GetGreenPixelComponent(p)));
2197 Ascii85Encode(image,ScaleQuantumToChar(
2198 GetBluePixelComponent(p)));
2199 if (image->colorspace == CMYKColorspace)
2200 Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
2204 Ascii85Flush(image);
2211 Dump number of colors and colormap.
2213 switch (compression)
2215 case RLECompression:
2219 Allocate pixel array.
2221 length=(size_t) number_pixels;
2222 pixels=(unsigned char *) AcquireQuantumMemory(length,
2224 if (pixels == (unsigned char *) NULL)
2226 tile_image=DestroyImage(tile_image);
2227 ThrowWriterException(ResourceLimitError,
2228 "MemoryAllocationFailed");
2231 Dump Runlength encoded pixels.
2234 for (y=0; y < (ssize_t) tile_image->rows; y++)
2236 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2237 &tile_image->exception);
2238 if (p == (const PixelPacket *) NULL)
2240 indexes=GetVirtualIndexQueue(tile_image);
2241 for (x=0; x < (ssize_t) tile_image->columns; x++)
2242 *q++=(unsigned char) indexes[x];
2244 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2245 if (compression == ZipCompression)
2246 status=ZLIBEncodeImage(image,length,pixels);
2249 if (compression == LZWCompression)
2250 status=LZWEncodeImage(image,length,pixels);
2252 status=PackbitsEncodeImage(image,length,pixels);
2253 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2254 if (status == MagickFalse)
2256 (void) CloseBlob(image);
2257 return(MagickFalse);
2264 Dump uncompressed PseudoColor packets.
2266 Ascii85Initialize(image);
2267 for (y=0; y < (ssize_t) tile_image->rows; y++)
2269 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2270 &tile_image->exception);
2271 if (p == (const PixelPacket *) NULL)
2273 indexes=GetVirtualIndexQueue(tile_image);
2274 for (x=0; x < (ssize_t) tile_image->columns; x++)
2275 Ascii85Encode(image,(unsigned char) indexes[x]);
2277 Ascii85Flush(image);
2282 tile_image=DestroyImage(tile_image);
2283 offset=TellBlob(image)-offset;
2284 (void) WriteBlobString(image,"\nendstream\n");
2285 (void) WriteBlobString(image,"endobj\n");
2287 Write Length object.
2289 xref[object++]=TellBlob(image);
2290 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2292 (void) WriteBlobString(image,buffer);
2293 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double) offset);
2294 (void) WriteBlobString(image,buffer);
2295 (void) WriteBlobString(image,"endobj\n");
2296 xref[object++]=TellBlob(image);
2297 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2299 (void) WriteBlobString(image,buffer);
2300 if ((image->storage_class != DirectClass) && (image->colors <= 256) &&
2301 (compression != FaxCompression) && (compression != Group4Compression))
2304 Write Colormap object.
2306 (void) WriteBlobString(image,"<<\n");
2307 if (compression == NoCompression)
2308 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2309 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g 0 R\n",
2311 (void) WriteBlobString(image,buffer);
2312 (void) WriteBlobString(image,">>\n");
2313 (void) WriteBlobString(image,"stream\n");
2314 offset=TellBlob(image);
2315 if (compression == NoCompression)
2316 Ascii85Initialize(image);
2317 for (i=0; i < (ssize_t) image->colors; i++)
2319 if (compression == NoCompression)
2321 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].red));
2322 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].green));
2323 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].blue));
2326 (void) WriteBlobByte(image,
2327 ScaleQuantumToChar(image->colormap[i].red));
2328 (void) WriteBlobByte(image,
2329 ScaleQuantumToChar(image->colormap[i].green));
2330 (void) WriteBlobByte(image,
2331 ScaleQuantumToChar(image->colormap[i].blue));
2333 if (compression == NoCompression)
2334 Ascii85Flush(image);
2335 offset=TellBlob(image)-offset;
2336 (void) WriteBlobString(image,"\nendstream\n");
2338 (void) WriteBlobString(image,"endobj\n");
2340 Write Length object.
2342 xref[object++]=TellBlob(image);
2343 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2345 (void) WriteBlobString(image,buffer);
2346 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double)
2348 (void) WriteBlobString(image,buffer);
2349 (void) WriteBlobString(image,"endobj\n");
2351 Write softmask object.
2353 xref[object++]=TellBlob(image);
2354 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2356 (void) WriteBlobString(image,buffer);
2357 (void) WriteBlobString(image,"<<\n");
2358 if (image->matte == MagickFalse)
2359 (void) WriteBlobString(image,">>\n");
2362 (void) WriteBlobString(image,"/Type /XObject\n");
2363 (void) WriteBlobString(image,"/Subtype /Image\n");
2364 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Ma%.20g\n",
2365 (double) image->scene);
2366 (void) WriteBlobString(image,buffer);
2367 switch (compression)
2371 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2375 case LZWCompression:
2377 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
2380 case ZipCompression:
2382 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2388 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2393 (void) WriteBlobString(image,buffer);
2394 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %.20g\n",
2395 (double) image->columns);
2396 (void) WriteBlobString(image,buffer);
2397 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %.20g\n",
2398 (double) image->rows);
2399 (void) WriteBlobString(image,buffer);
2400 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2401 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
2402 (compression == FaxCompression) || (compression == Group4Compression)
2404 (void) WriteBlobString(image,buffer);
2405 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %.20g 0 R\n",
2407 (void) WriteBlobString(image,buffer);
2408 (void) WriteBlobString(image,">>\n");
2409 (void) WriteBlobString(image,"stream\n");
2410 offset=TellBlob(image);
2411 number_pixels=(MagickSizeType) image->columns*image->rows;
2412 switch (compression)
2414 case RLECompression:
2418 Allocate pixel array.
2420 length=(size_t) number_pixels;
2421 pixels=(unsigned char *) AcquireQuantumMemory(length,
2423 if (pixels == (unsigned char *) NULL)
2425 image=DestroyImage(image);
2426 ThrowWriterException(ResourceLimitError,
2427 "MemoryAllocationFailed");
2430 Dump Runlength encoded pixels.
2433 for (y=0; y < (ssize_t) image->rows; y++)
2435 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2436 if (p == (const PixelPacket *) NULL)
2438 for (x=0; x < (ssize_t) image->columns; x++)
2440 *q++=ScaleQuantumToChar((Quantum) (GetAlphaPixelComponent(p)));
2444 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2445 if (compression == ZipCompression)
2446 status=ZLIBEncodeImage(image,length,pixels);
2449 if (compression == LZWCompression)
2450 status=LZWEncodeImage(image,length,pixels);
2452 status=PackbitsEncodeImage(image,length,pixels);
2453 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2454 if (status == MagickFalse)
2456 (void) CloseBlob(image);
2457 return(MagickFalse);
2464 Dump uncompressed PseudoColor packets.
2466 Ascii85Initialize(image);
2467 for (y=0; y < (ssize_t) image->rows; y++)
2469 p=GetVirtualPixels(image,0,y,image->columns,1,&image->exception);
2470 if (p == (const PixelPacket *) NULL)
2472 for (x=0; x < (ssize_t) image->columns; x++)
2474 Ascii85Encode(image,ScaleQuantumToChar((Quantum) (QuantumRange-
2475 GetOpacityPixelComponent(p))));
2479 Ascii85Flush(image);
2483 offset=TellBlob(image)-offset;
2484 (void) WriteBlobString(image,"\nendstream\n");
2486 (void) WriteBlobString(image,"endobj\n");
2488 Write Length object.
2490 xref[object++]=TellBlob(image);
2491 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2493 (void) WriteBlobString(image,buffer);
2494 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double) offset);
2495 (void) WriteBlobString(image,buffer);
2496 (void) WriteBlobString(image,"endobj\n");
2497 if (GetNextImageInList(image) == (Image *) NULL)
2499 image=SyncNextImageInList(image);
2500 status=SetImageProgress(image,SaveImagesTag,scene++,
2501 GetImageListLength(image));
2502 if (status == MagickFalse)
2504 } while (image_info->adjoin != MagickFalse);
2506 Write Metadata object.
2508 xref[object++]=TellBlob(image);
2510 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g 0 obj\n",(double)
2512 (void) WriteBlobString(image,buffer);
2513 (void) WriteBlobString(image,"<<\n");
2514 GetPathComponent(image->filename,BasePath,basename);
2515 (void) FormatMagickString(buffer,MaxTextExtent,"/Title (%s)\n",
2516 EscapeParenthesis(basename));
2517 (void) WriteBlobString(image,buffer);
2518 seconds=time((time_t *) NULL);
2519 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2520 (void) localtime_r(&seconds,&local_time);
2522 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2524 (void) FormatMagickString(date,MaxTextExtent,"D:%04d%02d%02d%02d%02d%02d",
2525 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2526 local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2527 (void) FormatMagickString(buffer,MaxTextExtent,"/CreationDate (%s)\n",date);
2528 (void) WriteBlobString(image,buffer);
2529 (void) FormatMagickString(buffer,MaxTextExtent,"/ModDate (%s)\n",date);
2530 (void) WriteBlobString(image,buffer);
2531 (void) FormatMagickString(buffer,MaxTextExtent,"/Producer (%s)\n",
2532 EscapeParenthesis(GetMagickVersion((size_t *) NULL)));
2533 (void) WriteBlobString(image,buffer);
2534 (void) WriteBlobString(image,">>\n");
2535 (void) WriteBlobString(image,"endobj\n");
2539 offset=TellBlob(image)-xref[0]+10;
2540 (void) WriteBlobString(image,"xref\n");
2541 (void) FormatMagickString(buffer,MaxTextExtent,"0 %.20g\n",(double)
2543 (void) WriteBlobString(image,buffer);
2544 (void) WriteBlobString(image,"0000000000 65535 f \n");
2545 for (i=0; i < (ssize_t) object; i++)
2547 (void) FormatMagickString(buffer,MaxTextExtent,"%010lu 00000 n \n",
2548 (unsigned long) xref[i]);
2549 (void) WriteBlobString(image,buffer);
2551 (void) WriteBlobString(image,"trailer\n");
2552 (void) WriteBlobString(image,"<<\n");
2553 (void) FormatMagickString(buffer,MaxTextExtent,"/Size %.20g\n",(double)
2555 (void) WriteBlobString(image,buffer);
2556 (void) FormatMagickString(buffer,MaxTextExtent,"/Info %.20g 0 R\n",(double)
2558 (void) WriteBlobString(image,buffer);
2559 (void) FormatMagickString(buffer,MaxTextExtent,"/Root %.20g 0 R\n",(double)
2561 (void) WriteBlobString(image,buffer);
2562 (void) WriteBlobString(image,">>\n");
2563 (void) WriteBlobString(image,"startxref\n");
2564 (void) FormatMagickString(buffer,MaxTextExtent,"%.20g\n",(double) offset);
2565 (void) WriteBlobString(image,buffer);
2566 (void) WriteBlobString(image,"%%EOF\n");
2567 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2568 (void) CloseBlob(image);