2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Portable Document Format %
20 % Copyright 1999-2017 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/artifact.h"
45 #include "MagickCore/blob.h"
46 #include "MagickCore/blob-private.h"
47 #include "MagickCore/cache.h"
48 #include "MagickCore/color.h"
49 #include "MagickCore/color-private.h"
50 #include "MagickCore/colorspace.h"
51 #include "MagickCore/colorspace-private.h"
52 #include "MagickCore/compress.h"
53 #include "MagickCore/constitute.h"
54 #include "MagickCore/delegate.h"
55 #include "MagickCore/delegate-private.h"
56 #include "MagickCore/draw.h"
57 #include "MagickCore/exception.h"
58 #include "MagickCore/exception-private.h"
59 #include "MagickCore/geometry.h"
60 #include "MagickCore/image.h"
61 #include "MagickCore/image-private.h"
62 #include "MagickCore/list.h"
63 #include "MagickCore/magick.h"
64 #include "MagickCore/memory_.h"
65 #include "MagickCore/monitor.h"
66 #include "MagickCore/monitor-private.h"
67 #include "MagickCore/nt-base-private.h"
68 #include "MagickCore/option.h"
69 #include "MagickCore/pixel-accessor.h"
70 #include "MagickCore/profile.h"
71 #include "MagickCore/property.h"
72 #include "MagickCore/quantum-private.h"
73 #include "MagickCore/resource_.h"
74 #include "MagickCore/resize.h"
75 #include "MagickCore/signature.h"
76 #include "MagickCore/static.h"
77 #include "MagickCore/string_.h"
78 #include "MagickCore/module.h"
79 #include "MagickCore/token.h"
80 #include "MagickCore/transform.h"
81 #include "MagickCore/utility.h"
82 #include "MagickCore/module.h"
87 #if defined(MAGICKCORE_TIFF_DELEGATE)
88 #define CCITTParam "-1"
90 #define CCITTParam "0"
96 static MagickBooleanType
97 WritePDFImage(const ImageInfo *,Image *,ExceptionInfo *);
100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
104 % I n v o k e P D F D e l e g a t e %
108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
110 % InvokePDFDelegate() executes the PDF interpreter with the specified command.
112 % The format of the InvokePDFDelegate method is:
114 % MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
115 % const char *command,ExceptionInfo *exception)
117 % A description of each parameter follows:
119 % o verbose: A value other than zero displays the command prior to
122 % o command: the address of a character string containing the command to
125 % o exception: return any errors or warnings in this structure.
128 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
129 static int MagickDLLCall PDFDelegateMessage(void *handle,const char *message,
139 messages=(char **) handle;
140 if (*messages == (char *) NULL)
141 *messages=(char *) AcquireQuantumMemory(length+1,sizeof(char *));
144 offset=strlen(*messages);
145 *messages=(char *) ResizeQuantumMemory(*messages,offset+length+1,
148 (void) memcpy(*messages+offset,message,length);
149 (*messages)[length+offset] ='\0';
154 static MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
155 const char *command,char *message,ExceptionInfo *exception)
160 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
161 #define SetArgsStart(command,args_start) \
162 if (args_start == (const char *) NULL) \
164 if (*command != '"') \
165 args_start=strchr(command,' '); \
168 args_start=strchr(command+1,'"'); \
169 if (args_start != (const char *) NULL) \
174 #define ExecuteGhostscriptCommand(command,status) \
176 status=ExternalDelegateCommand(MagickFalse,verbose,command,message, \
179 return(MagickTrue); \
181 return(MagickFalse); \
182 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, \
183 "FailedToExecuteCommand","`%s' (%d)",command,status); \
184 return(MagickFalse); \
192 *args_start = (const char *) NULL;
210 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
211 ghost_info=NTGhostscriptDLLVectors();
216 ghost_info=(&ghost_info_struct);
217 (void) ResetMagickMemory(&ghost_info_struct,0,sizeof(ghost_info_struct));
218 ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
219 gsapi_delete_instance;
220 ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
221 ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
223 ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
224 gsapi_init_with_args;
225 ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
226 int *)) gsapi_run_string;
227 ghost_info_struct.set_stdio=(int (*)(gs_main_instance *,int(*)(void *,char *,
228 int),int(*)(void *,const char *,int),int(*)(void *, const char *, int)))
230 ghost_info_struct.revision=(int (*)(gsapi_revision_t *,int)) gsapi_revision;
232 if (ghost_info == (GhostInfo *) NULL)
233 ExecuteGhostscriptCommand(command,status);
234 if ((ghost_info->revision)(&revision,sizeof(revision)) != 0)
236 if (verbose != MagickFalse)
238 (void) fprintf(stdout,"[ghostscript library %.2f]",(double)
239 revision.revision/100.0);
240 SetArgsStart(command,args_start);
241 (void) fputs(args_start,stdout);
243 errors=(char *) NULL;
244 status=(ghost_info->new_instance)(&interpreter,(void *) &errors);
246 ExecuteGhostscriptCommand(command,status);
248 argv=StringToArgv(command,&argc);
249 if (argv == (char **) NULL)
251 (ghost_info->delete_instance)(interpreter);
254 (void) (ghost_info->set_stdio)(interpreter,(int(MagickDLLCall *)(void *,
255 char *,int)) NULL,PDFDelegateMessage,PDFDelegateMessage);
256 status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
258 status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
260 (ghost_info->exit)(interpreter);
261 (ghost_info->delete_instance)(interpreter);
262 for (i=0; i < (ssize_t) argc; i++)
263 argv[i]=DestroyString(argv[i]);
264 argv=(char **) RelinquishMagickMemory(argv);
267 SetArgsStart(command,args_start);
268 if (status == -101) /* quit */
269 (void) FormatLocaleString(message,MagickPathExtent,
270 "[ghostscript library %.2f]%s: %s",(double)revision.revision / 100,
274 (void) ThrowMagickException(exception,GetMagickModule(),
275 DelegateError,"PDFDelegateFailed",
276 "`[ghostscript library %.2f]%s': %s",
277 (double)revision.revision / 100,args_start,errors);
278 if (errors != (char *) NULL)
279 errors=DestroyString(errors);
280 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
281 "Ghostscript returns status %d, exit code %d",status,code);
285 if (errors != (char *) NULL)
286 errors=DestroyString(errors);
289 status=ExternalDelegateCommand(MagickFalse,verbose,command,message,exception);
290 return(status == 0 ? MagickTrue : MagickFalse);
295 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
303 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
305 % IsPDF() returns MagickTrue if the image format type, identified by the
306 % magick string, is PDF.
308 % The format of the IsPDF method is:
310 % MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
312 % A description of each parameter follows:
314 % o magick: compare image format pattern against these bytes.
316 % o offset: Specifies the offset of the magick string.
319 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
323 if (LocaleNCompare((const char *) magick,"%PDF-",5) == 0)
329 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333 % R e a d P D F I m a g e %
337 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
339 % ReadPDFImage() reads a Portable Document Format image file and
340 % returns it. It allocates the memory necessary for the new Image structure
341 % and returns a pointer to the new image.
343 % The format of the ReadPDFImage method is:
345 % Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
347 % A description of each parameter follows:
349 % o image_info: the image info.
351 % o exception: return any errors or warnings in this structure.
355 static MagickBooleanType IsPDFRendered(const char *path)
363 if ((path == (const char *) NULL) || (*path == '\0'))
365 status=GetPathAttributes(path,&attributes);
366 if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
367 (attributes.st_size > 0))
372 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
374 #define CMYKProcessColor "CMYKProcessColor"
375 #define CropBox "CropBox"
376 #define DefaultCMYK "DefaultCMYK"
377 #define DeviceCMYK "DeviceCMYK"
378 #define MediaBox "MediaBox"
379 #define RenderPostscriptText "Rendering Postscript... "
380 #define PDFRotate "Rotate"
381 #define SpotColor "Separation"
382 #define TrimBox "TrimBox"
383 #define PDFVersion "PDF-"
386 command[MagickPathExtent],
388 filename[MagickPathExtent],
389 geometry[MagickPathExtent],
390 input_filename[MagickPathExtent],
391 message[MagickPathExtent],
393 postscript_filename[MagickPathExtent];
454 assert(image_info != (const ImageInfo *) NULL);
455 assert(image_info->signature == MagickCoreSignature);
456 if (image_info->debug != MagickFalse)
457 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
458 image_info->filename);
459 assert(exception != (ExceptionInfo *) NULL);
460 assert(exception->signature == MagickCoreSignature);
464 image=AcquireImage(image_info,exception);
465 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
466 if (status == MagickFalse)
468 image=DestroyImageList(image);
469 return((Image *) NULL);
471 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
472 if (status == MagickFalse)
474 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
475 image_info->filename);
476 image=DestroyImageList(image);
477 return((Image *) NULL);
480 Set the page density.
482 delta.x=DefaultResolution;
483 delta.y=DefaultResolution;
484 if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0))
486 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
487 image->resolution.x=geometry_info.rho;
488 image->resolution.y=geometry_info.sigma;
489 if ((flags & SigmaValue) == 0)
490 image->resolution.y=image->resolution.x;
492 if (image_info->density != (char *) NULL)
494 flags=ParseGeometry(image_info->density,&geometry_info);
495 image->resolution.x=geometry_info.rho;
496 image->resolution.y=geometry_info.sigma;
497 if ((flags & SigmaValue) == 0)
498 image->resolution.y=image->resolution.x;
500 (void) ResetMagickMemory(&page,0,sizeof(page));
501 (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
502 if (image_info->page != (char *) NULL)
503 (void) ParseAbsoluteGeometry(image_info->page,&page);
504 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)-
506 page.height=(size_t) ceil((double) (page.height*image->resolution.y/delta.y)-
509 Determine page geometry from the PDF media box.
511 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
512 cropbox=IsStringTrue(GetImageOption(image_info,"pdf:use-cropbox"));
513 stop_on_error=IsStringTrue(GetImageOption(image_info,"pdf:stop-on-error"));
514 trimbox=IsStringTrue(GetImageOption(image_info,"pdf:use-trimbox"));
517 (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box));
518 (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
519 (void) ResetMagickMemory(&hires_bounds,0,sizeof(hires_bounds));
520 (void) ResetMagickMemory(command,0,sizeof(command));
523 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
531 if ((c != (int) '/') && (c != (int) '%') &&
532 ((size_t) (p-command) < (MagickPathExtent-1)))
536 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
537 count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
539 Is this a CMYK document?
541 if (LocaleNCompare(DefaultCMYK,command,strlen(DefaultCMYK)) == 0)
543 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
545 if (LocaleNCompare(CMYKProcessColor,command,strlen(CMYKProcessColor)) == 0)
547 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
550 name[MagickPathExtent],
551 property[MagickPathExtent],
557 (void) FormatLocaleString(property,MagickPathExtent,
558 "pdf:SpotColor-%.20g",(double) spotcolor++);
560 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
562 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MagickPathExtent))
567 value=AcquireString(name);
568 (void) SubstituteString(&value,"#20"," ");
569 (void) SetImageProperty(image,property,value,exception);
570 value=DestroyString(value);
573 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
574 (void) SetImageProperty(image,"pdf:Version",command,exception);
575 if (image_info->page != (char *) NULL)
578 if (cropbox != MagickFalse)
580 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
583 Note region defined by crop box.
585 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
586 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
588 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
589 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
593 if (trimbox != MagickFalse)
595 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
598 Note region defined by trim box.
600 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
601 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
603 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
604 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
608 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
611 Note region defined by media box.
613 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
614 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
616 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
617 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
621 if ((fabs(bounds.x2-bounds.x1) <= fabs(hires_bounds.x2-hires_bounds.x1)) ||
622 (fabs(bounds.y2-bounds.y1) <= fabs(hires_bounds.y2-hires_bounds.y1)))
626 if ((fabs(hires_bounds.x2-hires_bounds.x1) >= MagickEpsilon) &&
627 (fabs(hires_bounds.y2-hires_bounds.y1) >= MagickEpsilon))
630 Set PDF render geometry.
632 (void) FormatLocaleString(geometry,MagickPathExtent,"%gx%g%+.15g%+.15g",
633 hires_bounds.x2-bounds.x1,hires_bounds.y2-hires_bounds.y1,
634 hires_bounds.x1,hires_bounds.y1);
635 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry,exception);
636 page.width=(size_t) ceil((double) ((hires_bounds.x2-hires_bounds.x1)*
637 image->resolution.x/delta.x)-0.5);
638 page.height=(size_t) ceil((double) ((hires_bounds.y2-hires_bounds.y1)*
639 image->resolution.y/delta.y)-0.5);
642 option=GetImageOption(image_info,"pdf:fit-page");
643 if (option != (char *) NULL)
648 page_geometry=GetPageGeometry(option);
649 flags=ParseMetaGeometry(page_geometry,&page.x,&page.y,&page.width,
651 page_geometry=DestroyString(page_geometry);
652 if (flags == NoValue)
654 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
655 "InvalidGeometry","`%s'",option);
656 image=DestroyImage(image);
657 return((Image *) NULL);
659 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)
661 page.height=(size_t) ceil((double) (page.height*image->resolution.y/
665 (void) CloseBlob(image);
666 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
672 page.width=page.height;
675 if (IssRGBCompatibleColorspace(image_info->colorspace) != MagickFalse)
678 Create Ghostscript control file.
680 file=AcquireUniqueFileResource(postscript_filename);
683 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
684 image_info->filename);
685 image=DestroyImage(image);
686 return((Image *) NULL);
688 count=write(file," ",1);
691 Render Postscript with the Ghostscript delegate.
693 if (image_info->monochrome != MagickFalse)
694 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
696 if (cmyk != MagickFalse)
697 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
699 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
700 if (delegate_info == (const DelegateInfo *) NULL)
702 (void) RelinquishUniqueFileResource(postscript_filename);
703 image=DestroyImage(image);
704 return((Image *) NULL);
706 density=AcquireString("");
707 options=AcquireString("");
708 (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",
709 image->resolution.x,image->resolution.y);
710 if ((image_info->page != (char *) NULL) || (fitPage != MagickFalse))
711 (void) FormatLocaleString(options,MagickPathExtent,"-g%.20gx%.20g ",(double)
712 page.width,(double) page.height);
713 if (fitPage != MagickFalse)
714 (void) ConcatenateMagickString(options,"-dPSFitPage ",MagickPathExtent);
715 if (cmyk != MagickFalse)
716 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MagickPathExtent);
717 if (cropbox != MagickFalse)
718 (void) ConcatenateMagickString(options,"-dUseCropBox ",MagickPathExtent);
719 if (stop_on_error != MagickFalse)
720 (void) ConcatenateMagickString(options,"-dPDFSTOPONERROR ",
722 if (trimbox != MagickFalse)
723 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MagickPathExtent);
724 read_info=CloneImageInfo(image_info);
725 *read_info->magick='\0';
726 if (read_info->number_scenes != 0)
729 pages[MagickPathExtent];
731 (void) FormatLocaleString(pages,MagickPathExtent,"-dFirstPage=%.20g "
732 "-dLastPage=%.20g",(double) read_info->scene+1,(double)
733 (read_info->scene+read_info->number_scenes));
734 (void) ConcatenateMagickString(options,pages,MagickPathExtent);
735 read_info->number_scenes=0;
736 if (read_info->scenes != (char *) NULL)
737 *read_info->scenes='\0';
739 (void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
740 (void) AcquireUniqueFilename(filename);
741 (void) RelinquishUniqueFileResource(filename);
742 (void) ConcatenateMagickString(filename,"%d",MagickPathExtent);
743 (void) FormatLocaleString(command,MagickPathExtent,
744 GetDelegateCommands(delegate_info),
745 read_info->antialias != MagickFalse ? 4 : 1,
746 read_info->antialias != MagickFalse ? 4 : 1,density,options,filename,
747 postscript_filename,input_filename);
748 options=DestroyString(options);
749 density=DestroyString(density);
751 status=InvokePDFDelegate(read_info->verbose,command,message,exception);
752 (void) RelinquishUniqueFileResource(postscript_filename);
753 (void) RelinquishUniqueFileResource(input_filename);
754 pdf_image=(Image *) NULL;
755 if (status == MagickFalse)
758 (void) InterpretImageFilename(image_info,image,filename,(int) i,
759 read_info->filename,exception);
760 if (IsPDFRendered(read_info->filename) == MagickFalse)
762 (void) RelinquishUniqueFileResource(read_info->filename);
767 (void) InterpretImageFilename(image_info,image,filename,(int) i,
768 read_info->filename,exception);
769 if (IsPDFRendered(read_info->filename) == MagickFalse)
771 read_info->blob=NULL;
773 next=ReadImage(read_info,exception);
774 (void) RelinquishUniqueFileResource(read_info->filename);
775 if (next == (Image *) NULL)
777 AppendImageToList(&pdf_image,next);
779 read_info=DestroyImageInfo(read_info);
780 if (pdf_image == (Image *) NULL)
782 if (*message != '\0')
783 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
784 "PDFDelegateFailed","`%s'",message);
785 image=DestroyImage(image);
786 return((Image *) NULL);
788 if (LocaleCompare(pdf_image->magick,"BMP") == 0)
793 cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
794 if (cmyk_image != (Image *) NULL)
796 pdf_image=DestroyImageList(pdf_image);
797 pdf_image=cmyk_image;
800 if (image_info->number_scenes != 0)
806 Add place holder images to meet the subimage specification requirement.
808 for (i=0; i < (ssize_t) image_info->scene; i++)
810 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
811 if (clone_image != (Image *) NULL)
812 PrependImageToList(&pdf_image,clone_image);
817 (void) CopyMagickString(pdf_image->filename,filename,MagickPathExtent);
818 (void) CopyMagickString(pdf_image->magick,image->magick,MagickPathExtent);
819 pdf_image->page=page;
820 (void) CloneImageProfiles(pdf_image,image);
821 (void) CloneImageProperties(pdf_image,image);
822 next=SyncNextImageInList(pdf_image);
823 if (next != (Image *) NULL)
825 } while (next != (Image *) NULL);
826 image=DestroyImage(image);
828 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
831 next=GetNextImageInList(next);
833 return(GetFirstImageInList(pdf_image));
837 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 % R e g i s t e r P D F I m a g e %
845 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
847 % RegisterPDFImage() adds properties for the PDF image format to
848 % the list of supported formats. The properties include the image format
849 % tag, a method to read and/or write the format, whether the format
850 % supports the saving of more than one frame to the same file or blob,
851 % whether the format supports native in-memory I/O, and a brief
852 % description of the format.
854 % The format of the RegisterPDFImage method is:
856 % size_t RegisterPDFImage(void)
859 ModuleExport size_t RegisterPDFImage(void)
864 entry=AcquireMagickInfo("PDF","AI","Adobe Illustrator CS2");
865 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
866 entry->encoder=(EncodeImageHandler *) WritePDFImage;
867 entry->flags^=CoderAdjoinFlag;
868 entry->flags^=CoderBlobSupportFlag;
869 entry->flags|=CoderSeekableStreamFlag;
870 entry->mime_type=ConstantString("application/pdf");
871 (void) RegisterMagickInfo(entry);
872 entry=AcquireMagickInfo("PDF","EPDF",
873 "Encapsulated Portable Document Format");
874 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
875 entry->encoder=(EncodeImageHandler *) WritePDFImage;
876 entry->flags^=CoderAdjoinFlag;
877 entry->flags^=CoderBlobSupportFlag;
878 entry->flags|=CoderSeekableStreamFlag;
879 entry->mime_type=ConstantString("application/pdf");
880 (void) RegisterMagickInfo(entry);
881 entry=AcquireMagickInfo("PDF","PDF","Portable Document Format");
882 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
883 entry->encoder=(EncodeImageHandler *) WritePDFImage;
884 entry->magick=(IsImageFormatHandler *) IsPDF;
885 entry->flags^=CoderBlobSupportFlag;
886 entry->flags|=CoderSeekableStreamFlag;
887 entry->mime_type=ConstantString("application/pdf");
888 (void) RegisterMagickInfo(entry);
889 entry=AcquireMagickInfo("PDF","PDFA","Portable Document Archive Format");
890 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
891 entry->encoder=(EncodeImageHandler *) WritePDFImage;
892 entry->magick=(IsImageFormatHandler *) IsPDF;
893 entry->flags^=CoderBlobSupportFlag;
894 entry->flags|=CoderSeekableStreamFlag;
895 entry->mime_type=ConstantString("application/pdf");
896 (void) RegisterMagickInfo(entry);
897 return(MagickImageCoderSignature);
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 % U n r e g i s t e r P D F I m a g e %
909 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
911 % UnregisterPDFImage() removes format registrations made by the
912 % PDF module from the list of supported formats.
914 % The format of the UnregisterPDFImage method is:
916 % UnregisterPDFImage(void)
919 ModuleExport void UnregisterPDFImage(void)
921 (void) UnregisterMagickInfo("AI");
922 (void) UnregisterMagickInfo("EPDF");
923 (void) UnregisterMagickInfo("PDF");
924 (void) UnregisterMagickInfo("PDFA");
928 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
932 % W r i t e P D F I m a g e %
936 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
938 % WritePDFImage() writes an image in the Portable Document image
941 % The format of the WritePDFImage method is:
943 % MagickBooleanType WritePDFImage(const ImageInfo *image_info,
944 % Image *image,ExceptionInfo *exception)
946 % A description of each parameter follows.
948 % o image_info: the image info.
950 % o image: The image.
952 % o exception: return any errors or warnings in this structure.
956 static char *EscapeParenthesis(const char *source)
970 assert(source != (const char *) NULL);
972 for (p=source; *p != '\0'; p++)
974 if ((*p == '\\') || (*p == '(') || (*p == ')'))
977 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
982 destination=(char *) NULL;
983 if (~length >= (MagickPathExtent-1))
984 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent,
985 sizeof(*destination));
986 if (destination == (char *) NULL)
987 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
990 for (p=source; *p != '\0'; p++)
992 if ((*p == '\\') || (*p == '(') || (*p == ')'))
1000 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
1002 register const unsigned char
1005 if (utf16 != (wchar_t *) NULL)
1014 Convert UTF-8 to UTF-16.
1017 for (p=utf8; *p != '\0'; p++)
1019 if ((*p & 0x80) == 0)
1022 if ((*p & 0xE0) == 0xC0)
1027 if ((*p & 0xC0) != 0x80)
1032 if ((*p & 0xF0) == 0xE0)
1037 if ((*p & 0xC0) != 0x80)
1040 *q|=(c & 0x3F) << 6;
1042 if ((*p & 0xC0) != 0x80)
1054 Compute UTF-16 string length.
1056 for (p=utf8; *p != '\0'; p++)
1058 if ((*p & 0x80) == 0)
1061 if ((*p & 0xE0) == 0xC0)
1064 if ((*p & 0xC0) != 0x80)
1068 if ((*p & 0xF0) == 0xE0)
1071 if ((*p & 0xC0) != 0x80)
1074 if ((*p & 0xC0) != 0x80)
1083 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source,size_t *length)
1088 *length=UTF8ToUTF16(source,(wchar_t *) NULL);
1095 Not UTF-8, just copy.
1097 *length=strlen((const char *) source);
1098 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1099 if (utf16 == (wchar_t *) NULL)
1100 return((wchar_t *) NULL);
1101 for (i=0; i <= (ssize_t) *length; i++)
1105 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1106 if (utf16 == (wchar_t *) NULL)
1107 return((wchar_t *) NULL);
1108 *length=UTF8ToUTF16(source,utf16);
1112 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
1113 Image *image,Image *inject_image,ExceptionInfo *exception)
1131 write_info=CloneImageInfo(image_info);
1132 (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent);
1133 (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent);
1134 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception);
1135 if (group4_image == (Image *) NULL)
1136 return(MagickFalse);
1137 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
1139 group4_image=DestroyImage(group4_image);
1140 if (group4 == (unsigned char *) NULL)
1141 return(MagickFalse);
1142 write_info=DestroyImageInfo(write_info);
1143 if (WriteBlob(image,length,group4) != (ssize_t) length)
1145 group4=(unsigned char *) RelinquishMagickMemory(group4);
1149 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image,
1150 ExceptionInfo *exception)
1152 #define CFormat "/Filter [ /%s ]\n"
1153 #define ObjectsPerImage 14
1155 DisableMSCWarning(4310)
1159 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
1160 "<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"
1161 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
1162 " <rdf:Description rdf:about=\"\"\n"
1163 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
1164 " <xap:ModifyDate>%s</xap:ModifyDate>\n"
1165 " <xap:CreateDate>%s</xap:CreateDate>\n"
1166 " <xap:MetadataDate>%s</xap:MetadataDate>\n"
1167 " <xap:CreatorTool>%s</xap:CreatorTool>\n"
1168 " </rdf:Description>\n"
1169 " <rdf:Description rdf:about=\"\"\n"
1170 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
1171 " <dc:format>application/pdf</dc:format>\n"
1174 " <rdf:li xml:lang=\"x-default\">%s</rdf:li>\n"
1177 " </rdf:Description>\n"
1178 " <rdf:Description rdf:about=\"\"\n"
1179 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
1180 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
1181 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
1182 " </rdf:Description>\n"
1183 " <rdf:Description rdf:about=\"\"\n"
1184 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
1185 " <pdf:Producer>%s</pdf:Producer>\n"
1186 " </rdf:Description>\n"
1187 " <rdf:Description rdf:about=\"\"\n"
1188 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
1189 " <pdfaid:part>3</pdfaid:part>\n"
1190 " <pdfaid:conformance>B</pdfaid:conformance>\n"
1191 " </rdf:Description>\n"
1194 "<?xpacket end=\"w\"?>\n"
1196 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
1200 basename[MagickPathExtent],
1201 buffer[MagickPathExtent],
1202 date[MagickPathExtent],
1204 page_geometry[MagickPathExtent],
1248 register const Quantum
1251 register unsigned char
1284 Open output image file.
1286 assert(image_info != (const ImageInfo *) NULL);
1287 assert(image_info->signature == MagickCoreSignature);
1288 assert(image != (Image *) NULL);
1289 assert(image->signature == MagickCoreSignature);
1290 if (image->debug != MagickFalse)
1291 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1292 assert(exception != (ExceptionInfo *) NULL);
1293 assert(exception->signature == MagickCoreSignature);
1294 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1295 if (status == MagickFalse)
1298 Allocate X ref memory.
1300 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
1301 if (xref == (MagickOffsetType *) NULL)
1302 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1303 (void) ResetMagickMemory(xref,0,2048UL*sizeof(*xref));
1309 if (image_info->compression == JPEG2000Compression)
1310 version=(size_t) MagickMax(version,5);
1311 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1312 if (next->alpha_trait != UndefinedPixelTrait)
1313 version=(size_t) MagickMax(version,4);
1314 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1315 version=(size_t) MagickMax(version,6);
1316 (void) FormatLocaleString(buffer,MagickPathExtent,"%%PDF-1.%.20g \n",(double)
1318 (void) WriteBlobString(image,buffer);
1319 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1321 (void) WriteBlobByte(image,'%');
1322 (void) WriteBlobByte(image,0xe2);
1323 (void) WriteBlobByte(image,0xe3);
1324 (void) WriteBlobByte(image,0xcf);
1325 (void) WriteBlobByte(image,0xd3);
1326 (void) WriteBlobByte(image,'\n');
1329 Write Catalog object.
1331 xref[object++]=TellBlob(image);
1333 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1335 (void) WriteBlobString(image,buffer);
1336 (void) WriteBlobString(image,"<<\n");
1337 if (LocaleCompare(image_info->magick,"PDFA") != 0)
1338 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1342 (void) FormatLocaleString(buffer,MagickPathExtent,"/Metadata %.20g 0 R\n",
1344 (void) WriteBlobString(image,buffer);
1345 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1348 (void) WriteBlobString(image,buffer);
1349 (void) WriteBlobString(image,"/Type /Catalog");
1350 option=GetImageOption(image_info,"pdf:page-direction");
1351 if ((option != (const char *) NULL) &&
1352 (LocaleCompare(option,"right-to-left") != MagickFalse))
1353 (void) WriteBlobString(image,"/ViewerPreferences<</PageDirection/R2L>>\n");
1354 (void) WriteBlobString(image,"\n");
1355 (void) WriteBlobString(image,">>\n");
1356 (void) WriteBlobString(image,"endobj\n");
1357 GetPathComponent(image->filename,BasePath,basename);
1358 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1361 create_date[MagickPathExtent],
1362 modify_date[MagickPathExtent],
1363 timestamp[MagickPathExtent],
1365 xmp_profile[MagickPathExtent];
1370 xref[object++]=TellBlob(image);
1371 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1373 (void) WriteBlobString(image,buffer);
1374 (void) WriteBlobString(image,"<<\n");
1375 (void) WriteBlobString(image,"/Subtype /XML\n");
1377 value=GetImageProperty(image,"date:modify",exception);
1378 if (value != (const char *) NULL)
1379 (void) CopyMagickString(modify_date,value,MagickPathExtent);
1381 value=GetImageProperty(image,"date:create",exception);
1382 if (value != (const char *) NULL)
1383 (void) CopyMagickString(create_date,value,MagickPathExtent);
1384 (void) FormatMagickTime(time((time_t *) NULL),MagickPathExtent,timestamp);
1385 url=GetMagickHomeURL();
1386 i=FormatLocaleString(xmp_profile,MagickPathExtent,XMPProfile,
1387 XMPProfileMagick,modify_date,create_date,timestamp,url,
1388 EscapeParenthesis(basename),url);
1389 url=DestroyString(url);
1390 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g\n",
1392 (void) WriteBlobString(image,buffer);
1393 (void) WriteBlobString(image,"/Type /Metadata\n");
1394 (void) WriteBlobString(image,">>\nstream\n");
1395 (void) WriteBlobString(image,xmp_profile);
1396 (void) WriteBlobString(image,"\nendstream\n");
1397 (void) WriteBlobString(image,"endobj\n");
1402 xref[object++]=TellBlob(image);
1404 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1406 (void) WriteBlobString(image,buffer);
1407 (void) WriteBlobString(image,"<<\n");
1408 (void) WriteBlobString(image,"/Type /Pages\n");
1409 (void) FormatLocaleString(buffer,MagickPathExtent,"/Kids [ %.20g 0 R ",
1411 (void) WriteBlobString(image,buffer);
1412 count=(ssize_t) (pages_id+ObjectsPerImage+1);
1413 if (image_info->adjoin != MagickFalse)
1419 Predict page object id's.
1422 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1424 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 R ",(double)
1426 (void) WriteBlobString(image,buffer);
1427 kid_image=GetNextImageInList(kid_image);
1429 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1431 if (xref == (MagickOffsetType *) NULL)
1432 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1434 (void) WriteBlobString(image,"]\n");
1435 (void) FormatLocaleString(buffer,MagickPathExtent,"/Count %.20g\n",(double)
1436 ((count-pages_id)/ObjectsPerImage));
1437 (void) WriteBlobString(image,buffer);
1438 (void) WriteBlobString(image,">>\n");
1439 (void) WriteBlobString(image,"endobj\n");
1443 compression=image->compression;
1444 if (image_info->compression != UndefinedCompression)
1445 compression=image_info->compression;
1446 switch (compression)
1448 case FaxCompression:
1449 case Group4Compression:
1451 if ((SetImageMonochrome(image,exception) == MagickFalse) ||
1452 (image->alpha_trait != UndefinedPixelTrait))
1453 compression=RLECompression;
1456 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1457 case JPEGCompression:
1459 compression=RLECompression;
1460 (void) ThrowMagickException(exception,GetMagickModule(),
1461 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1466 #if !defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
1467 case JPEG2000Compression:
1469 compression=RLECompression;
1470 (void) ThrowMagickException(exception,GetMagickModule(),
1471 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1476 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1477 case ZipCompression:
1479 compression=RLECompression;
1480 (void) ThrowMagickException(exception,GetMagickModule(),
1481 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1486 case LZWCompression:
1488 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1489 compression=RLECompression; /* LZW compression is forbidden */
1494 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1495 compression=RLECompression; /* ASCII 85 compression is forbidden */
1501 if (compression == JPEG2000Compression)
1502 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1504 Scale relative to dots-per-inch.
1506 delta.x=DefaultResolution;
1507 delta.y=DefaultResolution;
1508 resolution.x=image->resolution.x;
1509 resolution.y=image->resolution.y;
1510 if ((resolution.x == 0.0) || (resolution.y == 0.0))
1512 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1513 resolution.x=geometry_info.rho;
1514 resolution.y=geometry_info.sigma;
1515 if ((flags & SigmaValue) == 0)
1516 resolution.y=resolution.x;
1518 if (image_info->density != (char *) NULL)
1520 flags=ParseGeometry(image_info->density,&geometry_info);
1521 resolution.x=geometry_info.rho;
1522 resolution.y=geometry_info.sigma;
1523 if ((flags & SigmaValue) == 0)
1524 resolution.y=resolution.x;
1526 if (image->units == PixelsPerCentimeterResolution)
1528 resolution.x=(double) ((size_t) (100.0*2.54*resolution.x+0.5)/100.0);
1529 resolution.y=(double) ((size_t) (100.0*2.54*resolution.y+0.5)/100.0);
1531 SetGeometry(image,&geometry);
1532 (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g",
1533 (double) image->columns,(double) image->rows);
1534 if (image_info->page != (char *) NULL)
1535 (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent);
1537 if ((image->page.width != 0) && (image->page.height != 0))
1538 (void) FormatLocaleString(page_geometry,MagickPathExtent,
1539 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double)
1540 image->page.height,(double) image->page.x,(double) image->page.y);
1542 if ((image->gravity != UndefinedGravity) &&
1543 (LocaleCompare(image_info->magick,"PDF") == 0))
1544 (void) CopyMagickString(page_geometry,PSPageGeometry,
1546 (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent);
1547 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1548 &geometry.width,&geometry.height);
1549 scale.x=(double) (geometry.width*delta.x)/resolution.x;
1550 geometry.width=(size_t) floor(scale.x+0.5);
1551 scale.y=(double) (geometry.height*delta.y)/resolution.y;
1552 geometry.height=(size_t) floor(scale.y+0.5);
1553 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1554 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception);
1555 if (image->gravity != UndefinedGravity)
1557 geometry.x=(-page_info.x);
1558 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
1561 if (image_info->pointsize != 0.0)
1562 pointsize=image_info->pointsize;
1564 value=GetImageProperty(image,"label",exception);
1565 if (value != (const char *) NULL)
1566 text_size=(size_t) (MultilineCensus(value)*pointsize+12);
1571 xref[object++]=TellBlob(image);
1572 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1574 (void) WriteBlobString(image,buffer);
1575 (void) WriteBlobString(image,"<<\n");
1576 (void) WriteBlobString(image,"/Type /Page\n");
1577 (void) FormatLocaleString(buffer,MagickPathExtent,"/Parent %.20g 0 R\n",
1579 (void) WriteBlobString(image,buffer);
1580 (void) WriteBlobString(image,"/Resources <<\n");
1581 labels=(char **) NULL;
1582 value=GetImageProperty(image,"label",exception);
1583 if (value != (const char *) NULL)
1584 labels=StringToList(value);
1585 if (labels != (char **) NULL)
1587 (void) FormatLocaleString(buffer,MagickPathExtent,
1588 "/Font << /F%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1590 (void) WriteBlobString(image,buffer);
1592 (void) FormatLocaleString(buffer,MagickPathExtent,
1593 "/XObject << /Im%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1595 (void) WriteBlobString(image,buffer);
1596 (void) FormatLocaleString(buffer,MagickPathExtent,"/ProcSet %.20g 0 R >>\n",
1598 (void) WriteBlobString(image,buffer);
1599 (void) FormatLocaleString(buffer,MagickPathExtent,
1600 "/MediaBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1601 72.0*media_info.height/resolution.y);
1602 (void) WriteBlobString(image,buffer);
1603 (void) FormatLocaleString(buffer,MagickPathExtent,
1604 "/CropBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1605 72.0*media_info.height/resolution.y);
1606 (void) WriteBlobString(image,buffer);
1607 (void) FormatLocaleString(buffer,MagickPathExtent,"/Contents %.20g 0 R\n",
1609 (void) WriteBlobString(image,buffer);
1610 (void) FormatLocaleString(buffer,MagickPathExtent,"/Thumb %.20g 0 R\n",(double)
1612 (void) WriteBlobString(image,buffer);
1613 (void) WriteBlobString(image,">>\n");
1614 (void) WriteBlobString(image,"endobj\n");
1616 Write Contents object.
1618 xref[object++]=TellBlob(image);
1619 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1621 (void) WriteBlobString(image,buffer);
1622 (void) WriteBlobString(image,"<<\n");
1623 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1625 (void) WriteBlobString(image,buffer);
1626 (void) WriteBlobString(image,">>\n");
1627 (void) WriteBlobString(image,"stream\n");
1628 offset=TellBlob(image);
1629 (void) WriteBlobString(image,"q\n");
1630 if (labels != (char **) NULL)
1631 for (i=0; labels[i] != (char *) NULL; i++)
1633 (void) WriteBlobString(image,"BT\n");
1634 (void) FormatLocaleString(buffer,MagickPathExtent,"/F%.20g %g Tf\n",
1635 (double) image->scene,pointsize);
1636 (void) WriteBlobString(image,buffer);
1637 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g Td\n",
1638 (double) geometry.x,(double) (geometry.y+geometry.height+i*pointsize+
1640 (void) WriteBlobString(image,buffer);
1641 (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n",
1643 (void) WriteBlobString(image,buffer);
1644 (void) WriteBlobString(image,"ET\n");
1645 labels[i]=DestroyString(labels[i]);
1647 (void) FormatLocaleString(buffer,MagickPathExtent,
1648 "%g 0 0 %g %.20g %.20g cm\n",scale.x,scale.y,(double) geometry.x,
1649 (double) geometry.y);
1650 (void) WriteBlobString(image,buffer);
1651 (void) FormatLocaleString(buffer,MagickPathExtent,"/Im%.20g Do\n",(double)
1653 (void) WriteBlobString(image,buffer);
1654 (void) WriteBlobString(image,"Q\n");
1655 offset=TellBlob(image)-offset;
1656 (void) WriteBlobString(image,"\nendstream\n");
1657 (void) WriteBlobString(image,"endobj\n");
1659 Write Length object.
1661 xref[object++]=TellBlob(image);
1662 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1664 (void) WriteBlobString(image,buffer);
1665 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",
1667 (void) WriteBlobString(image,buffer);
1668 (void) WriteBlobString(image,"endobj\n");
1670 Write Procset object.
1672 xref[object++]=TellBlob(image);
1673 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1675 (void) WriteBlobString(image,buffer);
1676 if ((image->storage_class == DirectClass) || (image->colors > 256))
1677 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MagickPathExtent);
1679 if ((compression == FaxCompression) || (compression == Group4Compression))
1680 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MagickPathExtent);
1682 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MagickPathExtent);
1683 (void) WriteBlobString(image,buffer);
1684 (void) WriteBlobString(image," ]\n");
1685 (void) WriteBlobString(image,"endobj\n");
1689 xref[object++]=TellBlob(image);
1690 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1692 (void) WriteBlobString(image,buffer);
1693 (void) WriteBlobString(image,"<<\n");
1694 if (labels != (char **) NULL)
1696 (void) WriteBlobString(image,"/Type /Font\n");
1697 (void) WriteBlobString(image,"/Subtype /Type1\n");
1698 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /F%.20g\n",
1699 (double) image->scene);
1700 (void) WriteBlobString(image,buffer);
1701 (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1702 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1703 labels=(char **) RelinquishMagickMemory(labels);
1705 (void) WriteBlobString(image,">>\n");
1706 (void) WriteBlobString(image,"endobj\n");
1708 Write XObject object.
1710 xref[object++]=TellBlob(image);
1711 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1713 (void) WriteBlobString(image,buffer);
1714 (void) WriteBlobString(image,"<<\n");
1715 (void) WriteBlobString(image,"/Type /XObject\n");
1716 (void) WriteBlobString(image,"/Subtype /Image\n");
1717 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Im%.20g\n",(double)
1719 (void) WriteBlobString(image,buffer);
1720 switch (compression)
1724 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"ASCII85Decode");
1727 case JPEGCompression:
1729 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
1730 if (image->colorspace != CMYKColorspace)
1732 (void) WriteBlobString(image,buffer);
1733 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1737 case JPEG2000Compression:
1739 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
1740 if (image->colorspace != CMYKColorspace)
1742 (void) WriteBlobString(image,buffer);
1743 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1747 case LZWCompression:
1749 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
1752 case ZipCompression:
1754 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1758 case FaxCompression:
1759 case Group4Compression:
1761 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1763 (void) WriteBlobString(image,buffer);
1764 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
1765 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
1766 (double) image->columns,(double) image->rows);
1771 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1776 (void) WriteBlobString(image,buffer);
1777 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
1779 (void) WriteBlobString(image,buffer);
1780 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
1782 (void) WriteBlobString(image,buffer);
1783 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
1785 (void) WriteBlobString(image,buffer);
1786 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
1787 (compression == FaxCompression) || (compression == Group4Compression) ?
1789 (void) WriteBlobString(image,buffer);
1790 if (image->alpha_trait != UndefinedPixelTrait)
1792 (void) FormatLocaleString(buffer,MagickPathExtent,"/SMask %.20g 0 R\n",
1794 (void) WriteBlobString(image,buffer);
1796 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1798 (void) WriteBlobString(image,buffer);
1799 (void) WriteBlobString(image,">>\n");
1800 (void) WriteBlobString(image,"stream\n");
1801 offset=TellBlob(image);
1802 number_pixels=(MagickSizeType) image->columns*image->rows;
1803 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1804 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1805 if ((compression == FaxCompression) || (compression == Group4Compression) ||
1806 ((image_info->type != TrueColorType) &&
1807 (SetImageGray(image,exception) != MagickFalse)))
1809 switch (compression)
1811 case FaxCompression:
1812 case Group4Compression:
1814 if (LocaleCompare(CCITTParam,"0") == 0)
1816 (void) HuffmanEncodeImage(image_info,image,image,exception);
1819 (void) Huffman2DEncodeImage(image_info,image,image,exception);
1822 case JPEGCompression:
1824 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
1825 if (status == MagickFalse)
1827 (void) CloseBlob(image);
1828 return(MagickFalse);
1832 case JPEG2000Compression:
1834 status=InjectImageBlob(image_info,image,image,"jp2",exception);
1835 if (status == MagickFalse)
1837 (void) CloseBlob(image);
1838 return(MagickFalse);
1842 case RLECompression:
1849 Allocate pixel array.
1851 length=(size_t) number_pixels;
1852 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
1853 if (pixel_info == (MemoryInfo *) NULL)
1854 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1855 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1857 Dump Runlength encoded pixels.
1860 for (y=0; y < (ssize_t) image->rows; y++)
1862 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1863 if (p == (const Quantum *) NULL)
1865 for (x=0; x < (ssize_t) image->columns; x++)
1867 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p)));
1868 p+=GetPixelChannels(image);
1870 if (image->previous == (Image *) NULL)
1872 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1874 if (status == MagickFalse)
1878 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1879 if (compression == ZipCompression)
1880 status=ZLIBEncodeImage(image,length,pixels,exception);
1883 if (compression == LZWCompression)
1884 status=LZWEncodeImage(image,length,pixels,exception);
1886 status=PackbitsEncodeImage(image,length,pixels,exception);
1887 pixel_info=RelinquishVirtualMemory(pixel_info);
1888 if (status == MagickFalse)
1890 (void) CloseBlob(image);
1891 return(MagickFalse);
1898 Dump uncompressed PseudoColor packets.
1900 Ascii85Initialize(image);
1901 for (y=0; y < (ssize_t) image->rows; y++)
1903 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1904 if (p == (const Quantum *) NULL)
1906 for (x=0; x < (ssize_t) image->columns; x++)
1908 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
1909 GetPixelLuma(image,p))));
1910 p+=GetPixelChannels(image);
1912 if (image->previous == (Image *) NULL)
1914 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1916 if (status == MagickFalse)
1920 Ascii85Flush(image);
1926 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1927 (compression == JPEGCompression) ||
1928 (compression == JPEG2000Compression))
1929 switch (compression)
1931 case JPEGCompression:
1933 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
1934 if (status == MagickFalse)
1936 (void) CloseBlob(image);
1937 return(MagickFalse);
1941 case JPEG2000Compression:
1943 status=InjectImageBlob(image_info,image,image,"jp2",exception);
1944 if (status == MagickFalse)
1946 (void) CloseBlob(image);
1947 return(MagickFalse);
1951 case RLECompression:
1958 Allocate pixel array.
1960 length=(size_t) number_pixels;
1961 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
1962 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
1963 if (pixel_info == (MemoryInfo *) NULL)
1964 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1965 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1967 Dump runoffset encoded pixels.
1970 for (y=0; y < (ssize_t) image->rows; y++)
1972 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1973 if (p == (const Quantum *) NULL)
1975 for (x=0; x < (ssize_t) image->columns; x++)
1977 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
1978 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
1979 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
1980 if (image->colorspace == CMYKColorspace)
1981 *q++=ScaleQuantumToChar(GetPixelBlack(image,p));
1982 p+=GetPixelChannels(image);
1984 if (image->previous == (Image *) NULL)
1986 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1988 if (status == MagickFalse)
1992 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1993 if (compression == ZipCompression)
1994 status=ZLIBEncodeImage(image,length,pixels,exception);
1997 if (compression == LZWCompression)
1998 status=LZWEncodeImage(image,length,pixels,exception);
2000 status=PackbitsEncodeImage(image,length,pixels,exception);
2001 pixel_info=RelinquishVirtualMemory(pixel_info);
2002 if (status == MagickFalse)
2004 (void) CloseBlob(image);
2005 return(MagickFalse);
2012 Dump uncompressed DirectColor packets.
2014 Ascii85Initialize(image);
2015 for (y=0; y < (ssize_t) image->rows; y++)
2017 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2018 if (p == (const Quantum *) NULL)
2020 for (x=0; x < (ssize_t) image->columns; x++)
2022 Ascii85Encode(image,ScaleQuantumToChar(GetPixelRed(image,p)));
2023 Ascii85Encode(image,ScaleQuantumToChar(GetPixelGreen(image,p)));
2024 Ascii85Encode(image,ScaleQuantumToChar(GetPixelBlue(image,p)));
2025 if (image->colorspace == CMYKColorspace)
2026 Ascii85Encode(image,ScaleQuantumToChar(
2027 GetPixelBlack(image,p)));
2028 p+=GetPixelChannels(image);
2030 if (image->previous == (Image *) NULL)
2032 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
2034 if (status == MagickFalse)
2038 Ascii85Flush(image);
2045 Dump number of colors and colormap.
2047 switch (compression)
2049 case RLECompression:
2056 Allocate pixel array.
2058 length=(size_t) number_pixels;
2059 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2060 if (pixel_info == (MemoryInfo *) NULL)
2061 ThrowWriterException(ResourceLimitError,
2062 "MemoryAllocationFailed");
2063 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2065 Dump Runlength encoded pixels.
2068 for (y=0; y < (ssize_t) image->rows; y++)
2070 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2071 if (p == (const Quantum *) NULL)
2073 for (x=0; x < (ssize_t) image->columns; x++)
2075 *q++=(unsigned char) GetPixelIndex(image,p);
2076 p+=GetPixelChannels(image);
2078 if (image->previous == (Image *) NULL)
2080 status=SetImageProgress(image,SaveImageTag,
2081 (MagickOffsetType) y,image->rows);
2082 if (status == MagickFalse)
2086 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2087 if (compression == ZipCompression)
2088 status=ZLIBEncodeImage(image,length,pixels,exception);
2091 if (compression == LZWCompression)
2092 status=LZWEncodeImage(image,length,pixels,exception);
2094 status=PackbitsEncodeImage(image,length,pixels,exception);
2095 pixel_info=RelinquishVirtualMemory(pixel_info);
2096 if (status == MagickFalse)
2098 (void) CloseBlob(image);
2099 return(MagickFalse);
2106 Dump uncompressed PseudoColor packets.
2108 Ascii85Initialize(image);
2109 for (y=0; y < (ssize_t) image->rows; y++)
2111 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2112 if (p == (const Quantum *) NULL)
2114 for (x=0; x < (ssize_t) image->columns; x++)
2116 Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p));
2117 p+=GetPixelChannels(image);
2119 if (image->previous == (Image *) NULL)
2121 status=SetImageProgress(image,SaveImageTag,
2122 (MagickOffsetType) y,image->rows);
2123 if (status == MagickFalse)
2127 Ascii85Flush(image);
2132 offset=TellBlob(image)-offset;
2133 (void) WriteBlobString(image,"\nendstream\n");
2134 (void) WriteBlobString(image,"endobj\n");
2136 Write Length object.
2138 xref[object++]=TellBlob(image);
2139 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2141 (void) WriteBlobString(image,buffer);
2142 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2144 (void) WriteBlobString(image,buffer);
2145 (void) WriteBlobString(image,"endobj\n");
2147 Write Colorspace object.
2149 xref[object++]=TellBlob(image);
2150 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2152 (void) WriteBlobString(image,buffer);
2153 if (image->colorspace == CMYKColorspace)
2154 (void) CopyMagickString(buffer,"/DeviceCMYK\n",MagickPathExtent);
2156 if ((compression == FaxCompression) ||
2157 (compression == Group4Compression) ||
2158 ((image_info->type != TrueColorType) &&
2159 (SetImageGray(image,exception) != MagickFalse)))
2160 (void) CopyMagickString(buffer,"/DeviceGray\n",MagickPathExtent);
2162 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2163 (compression == JPEGCompression) ||
2164 (compression == JPEG2000Compression))
2165 (void) CopyMagickString(buffer,"/DeviceRGB\n",MagickPathExtent);
2167 (void) FormatLocaleString(buffer,MagickPathExtent,
2168 "[ /Indexed /DeviceRGB %.20g %.20g 0 R ]\n",(double) image->colors-
2169 1,(double) object+3);
2170 (void) WriteBlobString(image,buffer);
2171 (void) WriteBlobString(image,"endobj\n");
2175 SetGeometry(image,&geometry);
2176 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
2177 &geometry.width,&geometry.height);
2178 tile_image=ThumbnailImage(image,geometry.width,geometry.height,exception);
2179 if (tile_image == (Image *) NULL)
2180 return(MagickFalse);
2181 xref[object++]=TellBlob(image);
2182 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2184 (void) WriteBlobString(image,buffer);
2185 (void) WriteBlobString(image,"<<\n");
2186 switch (compression)
2190 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2194 case JPEGCompression:
2196 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
2197 if (image->colorspace != CMYKColorspace)
2199 (void) WriteBlobString(image,buffer);
2200 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2204 case JPEG2000Compression:
2206 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
2207 if (image->colorspace != CMYKColorspace)
2209 (void) WriteBlobString(image,buffer);
2210 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2214 case LZWCompression:
2216 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
2219 case ZipCompression:
2221 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2225 case FaxCompression:
2226 case Group4Compression:
2228 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
2230 (void) WriteBlobString(image,buffer);
2231 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
2232 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
2233 (double) tile_image->columns,(double) tile_image->rows);
2238 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2243 (void) WriteBlobString(image,buffer);
2244 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
2245 tile_image->columns);
2246 (void) WriteBlobString(image,buffer);
2247 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
2249 (void) WriteBlobString(image,buffer);
2250 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
2252 (void) WriteBlobString(image,buffer);
2253 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
2254 (compression == FaxCompression) || (compression == Group4Compression) ?
2256 (void) WriteBlobString(image,buffer);
2257 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2259 (void) WriteBlobString(image,buffer);
2260 (void) WriteBlobString(image,">>\n");
2261 (void) WriteBlobString(image,"stream\n");
2262 offset=TellBlob(image);
2263 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
2264 if ((compression == FaxCompression) ||
2265 (compression == Group4Compression) ||
2266 ((image_info->type != TrueColorType) &&
2267 (SetImageGray(tile_image,exception) != MagickFalse)))
2269 switch (compression)
2271 case FaxCompression:
2272 case Group4Compression:
2274 if (LocaleCompare(CCITTParam,"0") == 0)
2276 (void) HuffmanEncodeImage(image_info,image,tile_image,
2280 (void) Huffman2DEncodeImage(image_info,image,tile_image,exception);
2283 case JPEGCompression:
2285 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2287 if (status == MagickFalse)
2289 (void) CloseBlob(image);
2290 return(MagickFalse);
2294 case JPEG2000Compression:
2296 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2297 if (status == MagickFalse)
2299 (void) CloseBlob(image);
2300 return(MagickFalse);
2304 case RLECompression:
2311 Allocate pixel array.
2313 length=(size_t) number_pixels;
2314 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2315 if (pixel_info == (MemoryInfo *) NULL)
2317 tile_image=DestroyImage(tile_image);
2318 ThrowWriterException(ResourceLimitError,
2319 "MemoryAllocationFailed");
2321 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2323 Dump runlength encoded pixels.
2326 for (y=0; y < (ssize_t) tile_image->rows; y++)
2328 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2330 if (p == (const Quantum *) NULL)
2332 for (x=0; x < (ssize_t) tile_image->columns; x++)
2334 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(
2336 p+=GetPixelChannels(tile_image);
2339 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2340 if (compression == ZipCompression)
2341 status=ZLIBEncodeImage(image,length,pixels,exception);
2344 if (compression == LZWCompression)
2345 status=LZWEncodeImage(image,length,pixels,exception);
2347 status=PackbitsEncodeImage(image,length,pixels,exception);
2348 pixel_info=RelinquishVirtualMemory(pixel_info);
2349 if (status == MagickFalse)
2351 (void) CloseBlob(image);
2352 return(MagickFalse);
2359 Dump uncompressed PseudoColor packets.
2361 Ascii85Initialize(image);
2362 for (y=0; y < (ssize_t) tile_image->rows; y++)
2364 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2366 if (p == (const Quantum *) NULL)
2368 for (x=0; x < (ssize_t) tile_image->columns; x++)
2370 Ascii85Encode(tile_image,ScaleQuantumToChar(ClampToQuantum(
2371 GetPixelLuma(tile_image,p))));
2372 p+=GetPixelChannels(tile_image);
2375 Ascii85Flush(image);
2381 if ((tile_image->storage_class == DirectClass) ||
2382 (tile_image->colors > 256) || (compression == JPEGCompression) ||
2383 (compression == JPEG2000Compression))
2384 switch (compression)
2386 case JPEGCompression:
2388 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2390 if (status == MagickFalse)
2392 (void) CloseBlob(image);
2393 return(MagickFalse);
2397 case JPEG2000Compression:
2399 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2400 if (status == MagickFalse)
2402 (void) CloseBlob(image);
2403 return(MagickFalse);
2407 case RLECompression:
2414 Allocate pixel array.
2416 length=(size_t) number_pixels;
2417 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2418 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2419 if (pixel_info == (MemoryInfo *) NULL)
2421 tile_image=DestroyImage(tile_image);
2422 ThrowWriterException(ResourceLimitError,
2423 "MemoryAllocationFailed");
2425 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2427 Dump runlength encoded pixels.
2430 for (y=0; y < (ssize_t) tile_image->rows; y++)
2432 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2434 if (p == (const Quantum *) NULL)
2436 for (x=0; x < (ssize_t) tile_image->columns; x++)
2438 *q++=ScaleQuantumToChar(GetPixelRed(tile_image,p));
2439 *q++=ScaleQuantumToChar(GetPixelGreen(tile_image,p));
2440 *q++=ScaleQuantumToChar(GetPixelBlue(tile_image,p));
2441 if (tile_image->colorspace == CMYKColorspace)
2442 *q++=ScaleQuantumToChar(GetPixelBlack(tile_image,p));
2443 p+=GetPixelChannels(tile_image);
2446 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2447 if (compression == ZipCompression)
2448 status=ZLIBEncodeImage(image,length,pixels,exception);
2451 if (compression == LZWCompression)
2452 status=LZWEncodeImage(image,length,pixels,exception);
2454 status=PackbitsEncodeImage(image,length,pixels,exception);
2455 pixel_info=RelinquishVirtualMemory(pixel_info);
2456 if (status == MagickFalse)
2458 (void) CloseBlob(image);
2459 return(MagickFalse);
2466 Dump uncompressed DirectColor packets.
2468 Ascii85Initialize(image);
2469 for (y=0; y < (ssize_t) tile_image->rows; y++)
2471 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2473 if (p == (const Quantum *) NULL)
2475 for (x=0; x < (ssize_t) tile_image->columns; x++)
2477 Ascii85Encode(image,ScaleQuantumToChar(
2478 GetPixelRed(tile_image,p)));
2479 Ascii85Encode(image,ScaleQuantumToChar(
2480 GetPixelGreen(tile_image,p)));
2481 Ascii85Encode(image,ScaleQuantumToChar(
2482 GetPixelBlue(tile_image,p)));
2483 if (image->colorspace == CMYKColorspace)
2484 Ascii85Encode(image,ScaleQuantumToChar(
2485 GetPixelBlack(tile_image,p)));
2486 p+=GetPixelChannels(tile_image);
2489 Ascii85Flush(image);
2496 Dump number of colors and colormap.
2498 switch (compression)
2500 case RLECompression:
2507 Allocate pixel array.
2509 length=(size_t) number_pixels;
2510 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2511 if (pixel_info == (MemoryInfo *) NULL)
2513 tile_image=DestroyImage(tile_image);
2514 ThrowWriterException(ResourceLimitError,
2515 "MemoryAllocationFailed");
2517 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2519 Dump runlength encoded pixels.
2522 for (y=0; y < (ssize_t) tile_image->rows; y++)
2524 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2526 if (p == (const Quantum *) NULL)
2528 for (x=0; x < (ssize_t) tile_image->columns; x++)
2530 *q++=(unsigned char) GetPixelIndex(tile_image,p);
2531 p+=GetPixelChannels(tile_image);
2534 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2535 if (compression == ZipCompression)
2536 status=ZLIBEncodeImage(image,length,pixels,exception);
2539 if (compression == LZWCompression)
2540 status=LZWEncodeImage(image,length,pixels,exception);
2542 status=PackbitsEncodeImage(image,length,pixels,exception);
2543 pixel_info=RelinquishVirtualMemory(pixel_info);
2544 if (status == MagickFalse)
2546 (void) CloseBlob(image);
2547 return(MagickFalse);
2554 Dump uncompressed PseudoColor packets.
2556 Ascii85Initialize(image);
2557 for (y=0; y < (ssize_t) tile_image->rows; y++)
2559 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2561 if (p == (const Quantum *) NULL)
2563 for (x=0; x < (ssize_t) tile_image->columns; x++)
2565 Ascii85Encode(image,(unsigned char)
2566 GetPixelIndex(tile_image,p));
2567 p+=GetPixelChannels(image);
2570 Ascii85Flush(image);
2575 tile_image=DestroyImage(tile_image);
2576 offset=TellBlob(image)-offset;
2577 (void) WriteBlobString(image,"\nendstream\n");
2578 (void) WriteBlobString(image,"endobj\n");
2580 Write Length object.
2582 xref[object++]=TellBlob(image);
2583 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2585 (void) WriteBlobString(image,buffer);
2586 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2588 (void) WriteBlobString(image,buffer);
2589 (void) WriteBlobString(image,"endobj\n");
2590 xref[object++]=TellBlob(image);
2591 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2593 (void) WriteBlobString(image,buffer);
2594 (void) WriteBlobString(image,"<<\n");
2595 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2596 (compression == FaxCompression) || (compression == Group4Compression))
2597 (void) WriteBlobString(image,">>\n");
2601 Write Colormap object.
2603 if (compression == NoCompression)
2604 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2605 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2607 (void) WriteBlobString(image,buffer);
2608 (void) WriteBlobString(image,">>\n");
2609 (void) WriteBlobString(image,"stream\n");
2610 offset=TellBlob(image);
2611 if (compression == NoCompression)
2612 Ascii85Initialize(image);
2613 for (i=0; i < (ssize_t) image->colors; i++)
2615 if (compression == NoCompression)
2617 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2618 image->colormap[i].red)));
2619 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2620 image->colormap[i].green)));
2621 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2622 image->colormap[i].blue)));
2625 (void) WriteBlobByte(image,ScaleQuantumToChar(
2626 ClampToQuantum(image->colormap[i].red)));
2627 (void) WriteBlobByte(image,ScaleQuantumToChar(
2628 ClampToQuantum(image->colormap[i].green)));
2629 (void) WriteBlobByte(image,ScaleQuantumToChar(
2630 ClampToQuantum(image->colormap[i].blue)));
2632 if (compression == NoCompression)
2633 Ascii85Flush(image);
2634 offset=TellBlob(image)-offset;
2635 (void) WriteBlobString(image,"\nendstream\n");
2637 (void) WriteBlobString(image,"endobj\n");
2639 Write Length object.
2641 xref[object++]=TellBlob(image);
2642 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2644 (void) WriteBlobString(image,buffer);
2645 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2647 (void) WriteBlobString(image,buffer);
2648 (void) WriteBlobString(image,"endobj\n");
2650 Write softmask object.
2652 xref[object++]=TellBlob(image);
2653 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2655 (void) WriteBlobString(image,buffer);
2656 (void) WriteBlobString(image,"<<\n");
2657 if (image->alpha_trait == UndefinedPixelTrait)
2658 (void) WriteBlobString(image,">>\n");
2661 (void) WriteBlobString(image,"/Type /XObject\n");
2662 (void) WriteBlobString(image,"/Subtype /Image\n");
2663 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Ma%.20g\n",
2664 (double) image->scene);
2665 (void) WriteBlobString(image,buffer);
2666 switch (compression)
2670 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2674 case LZWCompression:
2676 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2680 case ZipCompression:
2682 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2688 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2693 (void) WriteBlobString(image,buffer);
2694 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",
2695 (double) image->columns);
2696 (void) WriteBlobString(image,buffer);
2697 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",
2698 (double) image->rows);
2699 (void) WriteBlobString(image,buffer);
2700 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2701 (void) FormatLocaleString(buffer,MagickPathExtent,
2702 "/BitsPerComponent %d\n",(compression == FaxCompression) ||
2703 (compression == Group4Compression) ? 1 : 8);
2704 (void) WriteBlobString(image,buffer);
2705 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2707 (void) WriteBlobString(image,buffer);
2708 (void) WriteBlobString(image,">>\n");
2709 (void) WriteBlobString(image,"stream\n");
2710 offset=TellBlob(image);
2711 number_pixels=(MagickSizeType) image->columns*image->rows;
2712 switch (compression)
2714 case RLECompression:
2721 Allocate pixel array.
2723 length=(size_t) number_pixels;
2724 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2725 if (pixel_info == (MemoryInfo *) NULL)
2727 image=DestroyImage(image);
2728 ThrowWriterException(ResourceLimitError,
2729 "MemoryAllocationFailed");
2731 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2733 Dump Runlength encoded pixels.
2736 for (y=0; y < (ssize_t) image->rows; y++)
2738 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2739 if (p == (const Quantum *) NULL)
2741 for (x=0; x < (ssize_t) image->columns; x++)
2743 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
2744 p+=GetPixelChannels(image);
2747 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2748 if (compression == ZipCompression)
2749 status=ZLIBEncodeImage(image,length,pixels,exception);
2752 if (compression == LZWCompression)
2753 status=LZWEncodeImage(image,length,pixels,exception);
2755 status=PackbitsEncodeImage(image,length,pixels,exception);
2756 pixel_info=RelinquishVirtualMemory(pixel_info);
2757 if (status == MagickFalse)
2759 (void) CloseBlob(image);
2760 return(MagickFalse);
2767 Dump uncompressed PseudoColor packets.
2769 Ascii85Initialize(image);
2770 for (y=0; y < (ssize_t) image->rows; y++)
2772 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2773 if (p == (const Quantum *) NULL)
2775 for (x=0; x < (ssize_t) image->columns; x++)
2777 Ascii85Encode(image,ScaleQuantumToChar(GetPixelAlpha(image,p)));
2778 p+=GetPixelChannels(image);
2781 Ascii85Flush(image);
2785 offset=TellBlob(image)-offset;
2786 (void) WriteBlobString(image,"\nendstream\n");
2788 (void) WriteBlobString(image,"endobj\n");
2790 Write Length object.
2792 xref[object++]=TellBlob(image);
2793 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2795 (void) WriteBlobString(image,buffer);
2796 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2798 (void) WriteBlobString(image,buffer);
2799 (void) WriteBlobString(image,"endobj\n");
2800 if (GetNextImageInList(image) == (Image *) NULL)
2802 image=SyncNextImageInList(image);
2803 status=SetImageProgress(image,SaveImagesTag,scene++,
2804 GetImageListLength(image));
2805 if (status == MagickFalse)
2807 } while (image_info->adjoin != MagickFalse);
2809 Write Metadata object.
2811 xref[object++]=TellBlob(image);
2813 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2815 (void) WriteBlobString(image,buffer);
2816 (void) WriteBlobString(image,"<<\n");
2817 utf16=ConvertUTF8ToUTF16((unsigned char *) basename,&length);
2818 if (utf16 != (wchar_t *) NULL)
2820 (void) FormatLocaleString(buffer,MagickPathExtent,"/Title (\xfe\xff");
2821 (void) WriteBlobString(image,buffer);
2822 for (i=0; i < (ssize_t) length; i++)
2823 WriteBlobMSBShort(image,(unsigned short) utf16[i]);
2824 (void) FormatLocaleString(buffer,MagickPathExtent,")\n");
2825 (void) WriteBlobString(image,buffer);
2826 utf16=(wchar_t *) RelinquishMagickMemory(utf16);
2828 seconds=time((time_t *) NULL);
2829 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2830 (void) localtime_r(&seconds,&local_time);
2832 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2834 (void) FormatLocaleString(date,MagickPathExtent,"D:%04d%02d%02d%02d%02d%02d",
2835 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2836 local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2837 (void) FormatLocaleString(buffer,MagickPathExtent,"/CreationDate (%s)\n",
2839 (void) WriteBlobString(image,buffer);
2840 (void) FormatLocaleString(buffer,MagickPathExtent,"/ModDate (%s)\n",date);
2841 (void) WriteBlobString(image,buffer);
2842 url=GetMagickHomeURL();
2843 (void) FormatLocaleString(buffer,MagickPathExtent,"/Producer (%s)\n",
2844 EscapeParenthesis(url));
2845 url=DestroyString(url);
2846 (void) WriteBlobString(image,buffer);
2847 (void) WriteBlobString(image,">>\n");
2848 (void) WriteBlobString(image,"endobj\n");
2852 offset=TellBlob(image)-xref[0]+
2853 (LocaleCompare(image_info->magick,"PDFA") == 0 ? 6 : 0)+10;
2854 (void) WriteBlobString(image,"xref\n");
2855 (void) FormatLocaleString(buffer,MagickPathExtent,"0 %.20g\n",(double)
2857 (void) WriteBlobString(image,buffer);
2858 (void) WriteBlobString(image,"0000000000 65535 f \n");
2859 for (i=0; i < (ssize_t) object; i++)
2861 (void) FormatLocaleString(buffer,MagickPathExtent,"%010lu 00000 n \n",
2862 (unsigned long) xref[i]);
2863 (void) WriteBlobString(image,buffer);
2865 (void) WriteBlobString(image,"trailer\n");
2866 (void) WriteBlobString(image,"<<\n");
2867 (void) FormatLocaleString(buffer,MagickPathExtent,"/Size %.20g\n",(double)
2869 (void) WriteBlobString(image,buffer);
2870 (void) FormatLocaleString(buffer,MagickPathExtent,"/Info %.20g 0 R\n",(double)
2872 (void) WriteBlobString(image,buffer);
2873 (void) FormatLocaleString(buffer,MagickPathExtent,"/Root %.20g 0 R\n",(double)
2875 (void) WriteBlobString(image,buffer);
2876 (void) SignatureImage(image,exception);
2877 (void) FormatLocaleString(buffer,MagickPathExtent,"/ID [<%s> <%s>]\n",
2878 GetImageProperty(image,"signature",exception),
2879 GetImageProperty(image,"signature",exception));
2880 (void) WriteBlobString(image,buffer);
2881 (void) WriteBlobString(image,">>\n");
2882 (void) WriteBlobString(image,"startxref\n");
2883 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) offset);
2884 (void) WriteBlobString(image,buffer);
2885 (void) WriteBlobString(image,"%%EOF\n");
2886 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2887 (void) CloseBlob(image);