2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Portable Document Format %
20 % Copyright 1999-2018 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 % https://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 if (*messages == (char *) NULL)
150 (void) memcpy(*messages+offset,message,length);
151 (*messages)[length+offset] ='\0';
156 static MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
157 const char *command,char *message,ExceptionInfo *exception)
162 #define ExecuteGhostscriptCommand(command,status) \
164 status=ExternalDelegateCommand(MagickFalse,verbose,command,message, \
167 return(MagickTrue); \
169 return(MagickFalse); \
170 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError, \
171 "FailedToExecuteCommand","`%s' (%d)",command,status); \
172 return(MagickFalse); \
175 #if defined(MAGICKCORE_GS_DELEGATE) || defined(MAGICKCORE_WINDOWS_SUPPORT)
176 #define SetArgsStart(command,args_start) \
177 if (args_start == (const char *) NULL) \
179 if (*command != '"') \
180 args_start=strchr(command,' '); \
183 args_start=strchr(command+1,'"'); \
184 if (args_start != (const char *) NULL) \
194 *args_start = (const char *) NULL;
212 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
213 ghost_info=NTGhostscriptDLLVectors();
218 ghost_info=(&ghost_info_struct);
219 (void) memset(&ghost_info_struct,0,sizeof(ghost_info_struct));
220 ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
221 gsapi_delete_instance;
222 ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
223 ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
225 ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
226 gsapi_init_with_args;
227 ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
228 int *)) gsapi_run_string;
229 ghost_info_struct.set_stdio=(int (*)(gs_main_instance *,int (*)(void *,char *,
230 int),int (*)(void *,const char *,int),int (*)(void *, const char *, int)))
232 ghost_info_struct.revision=(int (*)(gsapi_revision_t *,int)) gsapi_revision;
234 if (ghost_info == (GhostInfo *) NULL)
235 ExecuteGhostscriptCommand(command,status);
236 if ((ghost_info->revision)(&revision,sizeof(revision)) != 0)
238 if (verbose != MagickFalse)
240 (void) fprintf(stdout,"[ghostscript library %.2f]",(double)
241 revision.revision/100.0);
242 SetArgsStart(command,args_start);
243 (void) fputs(args_start,stdout);
245 errors=(char *) NULL;
246 status=(ghost_info->new_instance)(&interpreter,(void *) &errors);
248 ExecuteGhostscriptCommand(command,status);
250 argv=StringToArgv(command,&argc);
251 if (argv == (char **) NULL)
253 (ghost_info->delete_instance)(interpreter);
256 (void) (ghost_info->set_stdio)(interpreter,(int (MagickDLLCall *)(void *,
257 char *,int)) NULL,PDFDelegateMessage,PDFDelegateMessage);
258 status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
260 status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
262 (ghost_info->exit)(interpreter);
263 (ghost_info->delete_instance)(interpreter);
264 for (i=0; i < (ssize_t) argc; i++)
265 argv[i]=DestroyString(argv[i]);
266 argv=(char **) RelinquishMagickMemory(argv);
269 SetArgsStart(command,args_start);
270 if (status == -101) /* quit */
271 (void) FormatLocaleString(message,MagickPathExtent,
272 "[ghostscript library %.2f]%s: %s",(double) revision.revision/100.0,
276 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
277 "PDFDelegateFailed","`[ghostscript library %.2f]%s': %s",(double)
278 revision.revision/100.0,args_start,errors);
279 if (errors != (char *) NULL)
280 errors=DestroyString(errors);
281 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
282 "Ghostscript returns status %d, exit code %d",status,code);
286 if (errors != (char *) NULL)
287 errors=DestroyString(errors);
290 ExecuteGhostscriptCommand(command,status);
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 BeginXMPPacket "<?xpacket begin="
375 #define CMYKProcessColor "CMYKProcessColor"
376 #define CropBox "CropBox"
377 #define DefaultCMYK "DefaultCMYK"
378 #define DeviceCMYK "DeviceCMYK"
379 #define EndXMPPacket "<?xpacket end="
380 #define MediaBox "MediaBox"
381 #define RenderPostscriptText "Rendering Postscript... "
382 #define PDFRotate "Rotate"
383 #define SpotColor "Separation"
384 #define TrimBox "TrimBox"
385 #define PDFVersion "PDF-"
388 command[MagickPathExtent],
390 filename[MagickPathExtent],
391 geometry[MagickPathExtent],
392 input_filename[MagickPathExtent],
393 message[MagickPathExtent],
395 postscript_filename[MagickPathExtent];
456 assert(image_info != (const ImageInfo *) NULL);
457 assert(image_info->signature == MagickCoreSignature);
458 if (image_info->debug != MagickFalse)
459 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
460 image_info->filename);
461 assert(exception != (ExceptionInfo *) NULL);
462 assert(exception->signature == MagickCoreSignature);
466 image=AcquireImage(image_info,exception);
467 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
468 if (status == MagickFalse)
470 image=DestroyImageList(image);
471 return((Image *) NULL);
473 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
474 if (status == MagickFalse)
476 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
477 image_info->filename);
478 image=DestroyImageList(image);
479 return((Image *) NULL);
482 Set the page density.
484 delta.x=DefaultResolution;
485 delta.y=DefaultResolution;
486 if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0))
488 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
489 image->resolution.x=geometry_info.rho;
490 image->resolution.y=geometry_info.sigma;
491 if ((flags & SigmaValue) == 0)
492 image->resolution.y=image->resolution.x;
494 if (image_info->density != (char *) NULL)
496 flags=ParseGeometry(image_info->density,&geometry_info);
497 image->resolution.x=geometry_info.rho;
498 image->resolution.y=geometry_info.sigma;
499 if ((flags & SigmaValue) == 0)
500 image->resolution.y=image->resolution.x;
502 (void) memset(&page,0,sizeof(page));
503 (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
504 if (image_info->page != (char *) NULL)
505 (void) ParseAbsoluteGeometry(image_info->page,&page);
506 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)-
508 page.height=(size_t) ceil((double) (page.height*image->resolution.y/delta.y)-
511 Determine page geometry from the PDF media box.
513 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
514 cropbox=IsStringTrue(GetImageOption(image_info,"pdf:use-cropbox"));
515 stop_on_error=IsStringTrue(GetImageOption(image_info,"pdf:stop-on-error"));
516 trimbox=IsStringTrue(GetImageOption(image_info,"pdf:use-trimbox"));
519 (void) memset(&bounding_box,0,sizeof(bounding_box));
520 (void) memset(&bounds,0,sizeof(bounds));
521 (void) memset(&hires_bounds,0,sizeof(hires_bounds));
522 (void) memset(command,0,sizeof(command));
525 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
533 if ((c != (int) '/') && (c != (int) '%') &&
534 ((size_t) (p-command) < (MagickPathExtent-1)))
538 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
539 count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
541 Is this a CMYK document?
543 if (LocaleNCompare(DefaultCMYK,command,strlen(DefaultCMYK)) == 0)
545 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
547 if (LocaleNCompare(CMYKProcessColor,command,strlen(CMYKProcessColor)) == 0)
549 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
552 name[MagickPathExtent],
553 property[MagickPathExtent],
559 (void) FormatLocaleString(property,MagickPathExtent,
560 "pdf:SpotColor-%.20g",(double) spotcolor++);
562 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
564 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MagickPathExtent))
569 value=ConstantString(name);
570 (void) SubstituteString(&value,"#20"," ");
572 (void) SetImageProperty(image,property,value,exception);
573 value=DestroyString(value);
576 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
577 (void) SetImageProperty(image,"pdf:Version",command,exception);
578 if (image_info->page != (char *) NULL)
581 if (cropbox != MagickFalse)
583 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
586 Note region defined by crop box.
588 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
589 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
591 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
592 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
596 if (trimbox != MagickFalse)
598 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
601 Note region defined by trim box.
603 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
604 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
606 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
607 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
611 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
614 Note region defined by media box.
616 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
617 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
619 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
620 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
624 if ((fabs(bounds.x2-bounds.x1) <= fabs(hires_bounds.x2-hires_bounds.x1)) ||
625 (fabs(bounds.y2-bounds.y1) <= fabs(hires_bounds.y2-hires_bounds.y1)))
629 if ((fabs(hires_bounds.x2-hires_bounds.x1) >= MagickEpsilon) &&
630 (fabs(hires_bounds.y2-hires_bounds.y1) >= MagickEpsilon))
633 Set PDF render geometry.
635 (void) FormatLocaleString(geometry,MagickPathExtent,"%gx%g%+.15g%+.15g",
636 hires_bounds.x2-bounds.x1,hires_bounds.y2-hires_bounds.y1,
637 hires_bounds.x1,hires_bounds.y1);
638 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry,exception);
639 page.width=(size_t) ceil((double) ((hires_bounds.x2-hires_bounds.x1)*
640 image->resolution.x/delta.x)-0.5);
641 page.height=(size_t) ceil((double) ((hires_bounds.y2-hires_bounds.y1)*
642 image->resolution.y/delta.y)-0.5);
645 option=GetImageOption(image_info,"pdf:fit-page");
646 if (option != (char *) NULL)
651 page_geometry=GetPageGeometry(option);
652 flags=ParseMetaGeometry(page_geometry,&page.x,&page.y,&page.width,
654 page_geometry=DestroyString(page_geometry);
655 if (flags == NoValue)
657 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
658 "InvalidGeometry","`%s'",option);
659 image=DestroyImage(image);
660 return((Image *) NULL);
662 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)
664 page.height=(size_t) ceil((double) (page.height*image->resolution.y/
668 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
674 page.width=page.height;
677 if (IssRGBCompatibleColorspace(image_info->colorspace) != MagickFalse)
680 Create Ghostscript control file.
682 file=AcquireUniqueFileResource(postscript_filename);
685 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
686 image_info->filename);
687 image=DestroyImage(image);
688 return((Image *) NULL);
690 count=write(file," ",1);
693 Render Postscript with the Ghostscript delegate.
695 if (image_info->monochrome != MagickFalse)
696 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
698 if (cmyk != MagickFalse)
699 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
701 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
702 if (delegate_info == (const DelegateInfo *) NULL)
704 (void) RelinquishUniqueFileResource(postscript_filename);
705 image=DestroyImage(image);
706 return((Image *) NULL);
708 density=AcquireString("");
709 options=AcquireString("");
710 (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",
711 image->resolution.x,image->resolution.y);
712 if ((image_info->page != (char *) NULL) || (fitPage != MagickFalse))
713 (void) FormatLocaleString(options,MagickPathExtent,"-g%.20gx%.20g ",(double)
714 page.width,(double) page.height);
715 if (fitPage != MagickFalse)
716 (void) ConcatenateMagickString(options,"-dPSFitPage ",MagickPathExtent);
717 if (cmyk != MagickFalse)
718 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MagickPathExtent);
719 if (cropbox != MagickFalse)
720 (void) ConcatenateMagickString(options,"-dUseCropBox ",MagickPathExtent);
721 if (stop_on_error != MagickFalse)
722 (void) ConcatenateMagickString(options,"-dPDFSTOPONERROR ",
724 if (trimbox != MagickFalse)
725 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MagickPathExtent);
726 option=GetImageOption(image_info,"authenticate");
727 if (option != (char *) NULL)
730 passphrase[MagickPathExtent];
732 (void) FormatLocaleString(passphrase,MagickPathExtent,
733 "\"-sPDFPassword=%s\" ",option);
734 (void) ConcatenateMagickString(options,passphrase,MagickPathExtent);
736 read_info=CloneImageInfo(image_info);
737 *read_info->magick='\0';
738 if (read_info->number_scenes != 0)
741 pages[MagickPathExtent];
743 (void) FormatLocaleString(pages,MagickPathExtent,"-dFirstPage=%.20g "
744 "-dLastPage=%.20g",(double) read_info->scene+1,(double)
745 (read_info->scene+read_info->number_scenes));
746 (void) ConcatenateMagickString(options,pages,MagickPathExtent);
747 read_info->number_scenes=0;
748 if (read_info->scenes != (char *) NULL)
749 *read_info->scenes='\0';
751 (void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
752 (void) AcquireUniqueFilename(filename);
753 (void) RelinquishUniqueFileResource(filename);
754 (void) ConcatenateMagickString(filename,"%d",MagickPathExtent);
755 (void) FormatLocaleString(command,MagickPathExtent,
756 GetDelegateCommands(delegate_info),
757 read_info->antialias != MagickFalse ? 4 : 1,
758 read_info->antialias != MagickFalse ? 4 : 1,density,options,filename,
759 postscript_filename,input_filename);
760 options=DestroyString(options);
761 density=DestroyString(density);
763 status=InvokePDFDelegate(read_info->verbose,command,message,exception);
764 (void) RelinquishUniqueFileResource(postscript_filename);
765 (void) RelinquishUniqueFileResource(input_filename);
766 pdf_image=(Image *) NULL;
767 if (status == MagickFalse)
770 (void) InterpretImageFilename(image_info,image,filename,(int) i,
771 read_info->filename,exception);
772 if (IsPDFRendered(read_info->filename) == MagickFalse)
774 (void) RelinquishUniqueFileResource(read_info->filename);
779 (void) InterpretImageFilename(image_info,image,filename,(int) i,
780 read_info->filename,exception);
781 if (IsPDFRendered(read_info->filename) == MagickFalse)
783 read_info->blob=NULL;
785 next=ReadImage(read_info,exception);
786 (void) RelinquishUniqueFileResource(read_info->filename);
787 if (next == (Image *) NULL)
789 AppendImageToList(&pdf_image,next);
791 read_info=DestroyImageInfo(read_info);
792 if (pdf_image == (Image *) NULL)
794 if (*message != '\0')
795 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
796 "PDFDelegateFailed","`%s'",message);
797 image=DestroyImage(image);
798 return((Image *) NULL);
800 if (LocaleCompare(pdf_image->magick,"BMP") == 0)
805 cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
806 if (cmyk_image != (Image *) NULL)
808 pdf_image=DestroyImageList(pdf_image);
809 pdf_image=cmyk_image;
812 (void) SeekBlob(image,0,SEEK_SET);
813 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
816 Note document structuring comments.
819 if ((strchr("\n\r%",c) == (char *) NULL) &&
820 ((size_t) (p-command) < (MagickPathExtent-1)))
824 if (LocaleNCompare(BeginXMPPacket,command,strlen(BeginXMPPacket)) == 0)
833 profile=StringToStringInfo(command);
834 for (i=(ssize_t) GetStringInfoLength(profile)-1; c != EOF; i++)
836 SetStringInfoLength(profile,(size_t) (i+1));
837 c=ReadBlobByte(image);
838 GetStringInfoDatum(profile)[i]=(unsigned char) c;
840 if ((strchr("\n\r%",c) == (char *) NULL) &&
841 ((size_t) (p-command) < (MagickPathExtent-1)))
845 if (LocaleNCompare(EndXMPPacket,command,strlen(EndXMPPacket)) == 0)
848 SetStringInfoLength(profile,(size_t) i);
849 (void) SetImageProfile(image,"xmp",profile,exception);
850 profile=DestroyStringInfo(profile);
854 (void) CloseBlob(image);
855 if (image_info->number_scenes != 0)
861 Add place holder images to meet the subimage specification requirement.
863 for (i=0; i < (ssize_t) image_info->scene; i++)
865 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
866 if (clone_image != (Image *) NULL)
867 PrependImageToList(&pdf_image,clone_image);
872 (void) CopyMagickString(pdf_image->filename,filename,MagickPathExtent);
873 (void) CopyMagickString(pdf_image->magick,image->magick,MagickPathExtent);
874 pdf_image->page=page;
875 (void) CloneImageProfiles(pdf_image,image);
876 (void) CloneImageProperties(pdf_image,image);
877 next=SyncNextImageInList(pdf_image);
878 if (next != (Image *) NULL)
880 } while (next != (Image *) NULL);
881 image=DestroyImage(image);
883 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
886 next=GetNextImageInList(next);
888 return(GetFirstImageInList(pdf_image));
892 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
896 % R e g i s t e r P D F I m a g e %
900 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
902 % RegisterPDFImage() adds properties for the PDF image format to
903 % the list of supported formats. The properties include the image format
904 % tag, a method to read and/or write the format, whether the format
905 % supports the saving of more than one frame to the same file or blob,
906 % whether the format supports native in-memory I/O, and a brief
907 % description of the format.
909 % The format of the RegisterPDFImage method is:
911 % size_t RegisterPDFImage(void)
914 ModuleExport size_t RegisterPDFImage(void)
919 entry=AcquireMagickInfo("PDF","AI","Adobe Illustrator CS2");
920 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
921 entry->encoder=(EncodeImageHandler *) WritePDFImage;
922 entry->flags^=CoderAdjoinFlag;
923 entry->flags^=CoderBlobSupportFlag;
924 entry->mime_type=ConstantString("application/pdf");
925 (void) RegisterMagickInfo(entry);
926 entry=AcquireMagickInfo("PDF","EPDF",
927 "Encapsulated Portable Document Format");
928 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
929 entry->encoder=(EncodeImageHandler *) WritePDFImage;
930 entry->flags^=CoderAdjoinFlag;
931 entry->flags^=CoderBlobSupportFlag;
932 entry->mime_type=ConstantString("application/pdf");
933 (void) RegisterMagickInfo(entry);
934 entry=AcquireMagickInfo("PDF","PDF","Portable Document Format");
935 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
936 entry->encoder=(EncodeImageHandler *) WritePDFImage;
937 entry->magick=(IsImageFormatHandler *) IsPDF;
938 entry->flags^=CoderBlobSupportFlag;
939 entry->mime_type=ConstantString("application/pdf");
940 (void) RegisterMagickInfo(entry);
941 entry=AcquireMagickInfo("PDF","PDFA","Portable Document Archive Format");
942 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
943 entry->encoder=(EncodeImageHandler *) WritePDFImage;
944 entry->magick=(IsImageFormatHandler *) IsPDF;
945 entry->flags^=CoderBlobSupportFlag;
946 entry->mime_type=ConstantString("application/pdf");
947 (void) RegisterMagickInfo(entry);
948 return(MagickImageCoderSignature);
952 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956 % U n r e g i s t e r P D F I m a g e %
960 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
962 % UnregisterPDFImage() removes format registrations made by the
963 % PDF module from the list of supported formats.
965 % The format of the UnregisterPDFImage method is:
967 % UnregisterPDFImage(void)
970 ModuleExport void UnregisterPDFImage(void)
972 (void) UnregisterMagickInfo("AI");
973 (void) UnregisterMagickInfo("EPDF");
974 (void) UnregisterMagickInfo("PDF");
975 (void) UnregisterMagickInfo("PDFA");
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
983 % W r i t e P D F I m a g e %
987 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
989 % WritePDFImage() writes an image in the Portable Document image
992 % The format of the WritePDFImage method is:
994 % MagickBooleanType WritePDFImage(const ImageInfo *image_info,
995 % Image *image,ExceptionInfo *exception)
997 % A description of each parameter follows.
999 % o image_info: the image info.
1001 % o image: The image.
1003 % o exception: return any errors or warnings in this structure.
1007 static char *EscapeParenthesis(const char *source)
1021 assert(source != (const char *) NULL);
1023 for (p=source; *p != '\0'; p++)
1025 if ((*p == '\\') || (*p == '(') || (*p == ')'))
1028 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
1033 destination=(char *) NULL;
1034 if (~length >= (MagickPathExtent-1))
1035 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent,
1036 sizeof(*destination));
1037 if (destination == (char *) NULL)
1038 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
1041 for (p=source; *p != '\0'; p++)
1043 if ((*p == '\\') || (*p == '(') || (*p == ')'))
1048 return(destination);
1051 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
1053 register const unsigned char
1056 if (utf16 != (wchar_t *) NULL)
1065 Convert UTF-8 to UTF-16.
1068 for (p=utf8; *p != '\0'; p++)
1070 if ((*p & 0x80) == 0)
1073 if ((*p & 0xE0) == 0xC0)
1078 if ((*p & 0xC0) != 0x80)
1083 if ((*p & 0xF0) == 0xE0)
1088 if ((*p & 0xC0) != 0x80)
1091 *q|=(c & 0x3F) << 6;
1093 if ((*p & 0xC0) != 0x80)
1101 *q++=(wchar_t) '\0';
1102 return((size_t) (q-utf16));
1105 Compute UTF-16 string length.
1107 for (p=utf8; *p != '\0'; p++)
1109 if ((*p & 0x80) == 0)
1112 if ((*p & 0xE0) == 0xC0)
1115 if ((*p & 0xC0) != 0x80)
1119 if ((*p & 0xF0) == 0xE0)
1122 if ((*p & 0xC0) != 0x80)
1125 if ((*p & 0xC0) != 0x80)
1131 return((size_t) (p-utf8));
1134 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source,size_t *length)
1139 *length=UTF8ToUTF16(source,(wchar_t *) NULL);
1146 Not UTF-8, just copy.
1148 *length=strlen((const char *) source);
1149 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1150 if (utf16 == (wchar_t *) NULL)
1151 return((wchar_t *) NULL);
1152 for (i=0; i <= (ssize_t) *length; i++)
1156 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1157 if (utf16 == (wchar_t *) NULL)
1158 return((wchar_t *) NULL);
1159 *length=UTF8ToUTF16(source,utf16);
1163 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
1164 Image *image,Image *inject_image,ExceptionInfo *exception)
1182 write_info=CloneImageInfo(image_info);
1183 (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent);
1184 (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent);
1185 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception);
1186 if (group4_image == (Image *) NULL)
1187 return(MagickFalse);
1188 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
1190 group4_image=DestroyImage(group4_image);
1191 if (group4 == (unsigned char *) NULL)
1192 return(MagickFalse);
1193 write_info=DestroyImageInfo(write_info);
1194 if (WriteBlob(image,length,group4) != (ssize_t) length)
1196 group4=(unsigned char *) RelinquishMagickMemory(group4);
1200 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image,
1201 ExceptionInfo *exception)
1203 #define CFormat "/Filter [ /%s ]\n"
1204 #define ObjectsPerImage 14
1205 #define ThrowPDFException(exception,message) \
1207 if (xref != (MagickOffsetType *) NULL) \
1208 xref=(MagickOffsetType *) RelinquishMagickMemory(xref); \
1209 ThrowWriterException((exception),(message)); \
1212 DisableMSCWarning(4310)
1216 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
1217 "<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"
1218 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
1219 " <rdf:Description rdf:about=\"\"\n"
1220 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
1221 " <xap:ModifyDate>%s</xap:ModifyDate>\n"
1222 " <xap:CreateDate>%s</xap:CreateDate>\n"
1223 " <xap:MetadataDate>%s</xap:MetadataDate>\n"
1224 " <xap:CreatorTool>%s</xap:CreatorTool>\n"
1225 " </rdf:Description>\n"
1226 " <rdf:Description rdf:about=\"\"\n"
1227 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
1228 " <dc:format>application/pdf</dc:format>\n"
1231 " <rdf:li xml:lang=\"x-default\">%s</rdf:li>\n"
1234 " </rdf:Description>\n"
1235 " <rdf:Description rdf:about=\"\"\n"
1236 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
1237 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
1238 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
1239 " </rdf:Description>\n"
1240 " <rdf:Description rdf:about=\"\"\n"
1241 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
1242 " <pdf:Producer>%s</pdf:Producer>\n"
1243 " </rdf:Description>\n"
1244 " <rdf:Description rdf:about=\"\"\n"
1245 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
1246 " <pdfaid:part>3</pdfaid:part>\n"
1247 " <pdfaid:conformance>B</pdfaid:conformance>\n"
1248 " </rdf:Description>\n"
1251 "<?xpacket end=\"w\"?>\n"
1253 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
1257 basename[MagickPathExtent],
1258 buffer[MagickPathExtent],
1260 date[MagickPathExtent],
1262 page_geometry[MagickPathExtent],
1310 register const Quantum
1313 register unsigned char
1349 Open output image file.
1351 assert(image_info != (const ImageInfo *) NULL);
1352 assert(image_info->signature == MagickCoreSignature);
1353 assert(image != (Image *) NULL);
1354 assert(image->signature == MagickCoreSignature);
1355 if (image->debug != MagickFalse)
1356 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1357 assert(exception != (ExceptionInfo *) NULL);
1358 assert(exception->signature == MagickCoreSignature);
1359 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1360 if (status == MagickFalse)
1363 Allocate X ref memory.
1365 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
1366 if (xref == (MagickOffsetType *) NULL)
1367 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1368 (void) memset(xref,0,2048UL*sizeof(*xref));
1374 if (image_info->compression == JPEG2000Compression)
1375 version=(size_t) MagickMax(version,5);
1376 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1377 if (next->alpha_trait != UndefinedPixelTrait)
1378 version=(size_t) MagickMax(version,4);
1379 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1380 version=(size_t) MagickMax(version,6);
1381 profile=GetImageProfile(image,"icc");
1382 if (profile != (StringInfo *) NULL)
1383 version=(size_t) MagickMax(version,7);
1384 (void) FormatLocaleString(buffer,MagickPathExtent,"%%PDF-1.%.20g \n",(double)
1386 (void) WriteBlobString(image,buffer);
1387 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1389 (void) WriteBlobByte(image,'%');
1390 (void) WriteBlobByte(image,0xe2);
1391 (void) WriteBlobByte(image,0xe3);
1392 (void) WriteBlobByte(image,0xcf);
1393 (void) WriteBlobByte(image,0xd3);
1394 (void) WriteBlobByte(image,'\n');
1397 Write Catalog object.
1399 xref[object++]=TellBlob(image);
1401 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1403 (void) WriteBlobString(image,buffer);
1404 (void) WriteBlobString(image,"<<\n");
1405 if (LocaleCompare(image_info->magick,"PDFA") != 0)
1406 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1410 (void) FormatLocaleString(buffer,MagickPathExtent,"/Metadata %.20g 0 R\n",
1412 (void) WriteBlobString(image,buffer);
1413 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1416 (void) WriteBlobString(image,buffer);
1417 (void) WriteBlobString(image,"/Type /Catalog");
1418 option=GetImageOption(image_info,"pdf:page-direction");
1419 if ((option != (const char *) NULL) &&
1420 (LocaleCompare(option,"right-to-left") == 0))
1421 (void) WriteBlobString(image,"/ViewerPreferences<</PageDirection/R2L>>\n");
1422 (void) WriteBlobString(image,"\n");
1423 (void) WriteBlobString(image,">>\n");
1424 (void) WriteBlobString(image,"endobj\n");
1425 GetPathComponent(image->filename,BasePath,basename);
1426 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1429 create_date[MagickPathExtent],
1430 modify_date[MagickPathExtent],
1431 timestamp[MagickPathExtent],
1433 xmp_profile[MagickPathExtent];
1438 xref[object++]=TellBlob(image);
1439 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1441 (void) WriteBlobString(image,buffer);
1442 (void) WriteBlobString(image,"<<\n");
1443 (void) WriteBlobString(image,"/Subtype /XML\n");
1445 value=GetImageProperty(image,"date:modify",exception);
1446 if (value != (const char *) NULL)
1447 (void) CopyMagickString(modify_date,value,MagickPathExtent);
1449 value=GetImageProperty(image,"date:create",exception);
1450 if (value != (const char *) NULL)
1451 (void) CopyMagickString(create_date,value,MagickPathExtent);
1452 (void) FormatMagickTime(time((time_t *) NULL),MagickPathExtent,timestamp);
1453 url=(char *) MagickAuthoritativeURL;
1454 escape=EscapeParenthesis(basename);
1455 i=FormatLocaleString(xmp_profile,MagickPathExtent,XMPProfile,
1456 XMPProfileMagick,modify_date,create_date,timestamp,url,escape,url);
1457 escape=DestroyString(escape);
1458 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g\n",
1460 (void) WriteBlobString(image,buffer);
1461 (void) WriteBlobString(image,"/Type /Metadata\n");
1462 (void) WriteBlobString(image,">>\nstream\n");
1463 (void) WriteBlobString(image,xmp_profile);
1464 (void) WriteBlobString(image,"\nendstream\n");
1465 (void) WriteBlobString(image,"endobj\n");
1470 xref[object++]=TellBlob(image);
1472 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1474 (void) WriteBlobString(image,buffer);
1475 (void) WriteBlobString(image,"<<\n");
1476 (void) WriteBlobString(image,"/Type /Pages\n");
1477 (void) FormatLocaleString(buffer,MagickPathExtent,"/Kids [ %.20g 0 R ",
1479 (void) WriteBlobString(image,buffer);
1480 count=(ssize_t) (pages_id+ObjectsPerImage+1);
1482 if (image_info->adjoin != MagickFalse)
1488 Predict page object id's.
1491 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1494 profile=GetImageProfile(kid_image,"icc");
1495 if (profile != (StringInfo *) NULL)
1497 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 R ",(double)
1499 (void) WriteBlobString(image,buffer);
1500 kid_image=GetNextImageInList(kid_image);
1502 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1504 if (xref == (MagickOffsetType *) NULL)
1505 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1507 (void) WriteBlobString(image,"]\n");
1508 (void) FormatLocaleString(buffer,MagickPathExtent,"/Count %.20g\n",(double)
1510 (void) WriteBlobString(image,buffer);
1511 (void) WriteBlobString(image,">>\n");
1512 (void) WriteBlobString(image,"endobj\n");
1514 imageListLength=GetImageListLength(image);
1520 profile=GetImageProfile(image,"icc");
1521 has_icc_profile=(profile != (StringInfo *) NULL) ? MagickTrue : MagickFalse;
1522 compression=image->compression;
1523 if (image_info->compression != UndefinedCompression)
1524 compression=image_info->compression;
1525 switch (compression)
1527 case FaxCompression:
1528 case Group4Compression:
1530 if ((SetImageMonochrome(image,exception) == MagickFalse) ||
1531 (image->alpha_trait != UndefinedPixelTrait))
1532 compression=RLECompression;
1535 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1536 case JPEGCompression:
1538 compression=RLECompression;
1539 (void) ThrowMagickException(exception,GetMagickModule(),
1540 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1545 #if !defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
1546 case JPEG2000Compression:
1548 compression=RLECompression;
1549 (void) ThrowMagickException(exception,GetMagickModule(),
1550 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1555 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1556 case ZipCompression:
1558 compression=RLECompression;
1559 (void) ThrowMagickException(exception,GetMagickModule(),
1560 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1565 case LZWCompression:
1567 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1568 compression=RLECompression; /* LZW compression is forbidden */
1573 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1574 compression=RLECompression; /* ASCII 85 compression is forbidden */
1580 if (compression == JPEG2000Compression)
1581 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1583 Scale relative to dots-per-inch.
1585 delta.x=DefaultResolution;
1586 delta.y=DefaultResolution;
1587 resolution.x=image->resolution.x;
1588 resolution.y=image->resolution.y;
1589 if ((resolution.x == 0.0) || (resolution.y == 0.0))
1591 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1592 resolution.x=geometry_info.rho;
1593 resolution.y=geometry_info.sigma;
1594 if ((flags & SigmaValue) == 0)
1595 resolution.y=resolution.x;
1597 if (image_info->density != (char *) NULL)
1599 flags=ParseGeometry(image_info->density,&geometry_info);
1600 resolution.x=geometry_info.rho;
1601 resolution.y=geometry_info.sigma;
1602 if ((flags & SigmaValue) == 0)
1603 resolution.y=resolution.x;
1605 if (image->units == PixelsPerCentimeterResolution)
1607 resolution.x=(double) ((size_t) (100.0*2.54*resolution.x+0.5)/100.0);
1608 resolution.y=(double) ((size_t) (100.0*2.54*resolution.y+0.5)/100.0);
1610 SetGeometry(image,&geometry);
1611 (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g",
1612 (double) image->columns,(double) image->rows);
1613 if (image_info->page != (char *) NULL)
1614 (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent);
1616 if ((image->page.width != 0) && (image->page.height != 0))
1617 (void) FormatLocaleString(page_geometry,MagickPathExtent,
1618 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double)
1619 image->page.height,(double) image->page.x,(double) image->page.y);
1621 if ((image->gravity != UndefinedGravity) &&
1622 (LocaleCompare(image_info->magick,"PDF") == 0))
1623 (void) CopyMagickString(page_geometry,PSPageGeometry,
1625 (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent);
1626 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1627 &geometry.width,&geometry.height);
1628 scale.x=(double) (geometry.width*delta.x)/resolution.x;
1629 geometry.width=(size_t) floor(scale.x+0.5);
1630 scale.y=(double) (geometry.height*delta.y)/resolution.y;
1631 geometry.height=(size_t) floor(scale.y+0.5);
1632 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1633 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception);
1634 if (image->gravity != UndefinedGravity)
1636 geometry.x=(-page_info.x);
1637 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
1640 if (image_info->pointsize != 0.0)
1641 pointsize=image_info->pointsize;
1643 value=GetImageProperty(image,"label",exception);
1644 if (value != (const char *) NULL)
1645 text_size=(size_t) (MultilineCensus(value)*pointsize+12);
1650 xref[object++]=TellBlob(image);
1651 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1653 (void) WriteBlobString(image,buffer);
1654 (void) WriteBlobString(image,"<<\n");
1655 (void) WriteBlobString(image,"/Type /Page\n");
1656 (void) FormatLocaleString(buffer,MagickPathExtent,"/Parent %.20g 0 R\n",
1658 (void) WriteBlobString(image,buffer);
1659 (void) WriteBlobString(image,"/Resources <<\n");
1660 labels=(char **) NULL;
1661 value=GetImageProperty(image,"label",exception);
1662 if (value != (const char *) NULL)
1663 labels=StringToList(value);
1664 if (labels != (char **) NULL)
1666 (void) FormatLocaleString(buffer,MagickPathExtent,
1667 "/Font << /F%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1669 (void) WriteBlobString(image,buffer);
1671 (void) FormatLocaleString(buffer,MagickPathExtent,
1672 "/XObject << /Im%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1674 (void) WriteBlobString(image,buffer);
1675 (void) FormatLocaleString(buffer,MagickPathExtent,"/ProcSet %.20g 0 R >>\n",
1677 (void) WriteBlobString(image,buffer);
1678 (void) FormatLocaleString(buffer,MagickPathExtent,
1679 "/MediaBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1680 72.0*media_info.height/resolution.y);
1681 (void) WriteBlobString(image,buffer);
1682 (void) FormatLocaleString(buffer,MagickPathExtent,
1683 "/CropBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1684 72.0*media_info.height/resolution.y);
1685 (void) WriteBlobString(image,buffer);
1686 (void) FormatLocaleString(buffer,MagickPathExtent,"/Contents %.20g 0 R\n",
1688 (void) WriteBlobString(image,buffer);
1689 (void) FormatLocaleString(buffer,MagickPathExtent,"/Thumb %.20g 0 R\n",
1690 (double) object+(has_icc_profile != MagickFalse ? 10 : 8));
1691 (void) WriteBlobString(image,buffer);
1692 (void) WriteBlobString(image,">>\n");
1693 (void) WriteBlobString(image,"endobj\n");
1695 Write Contents object.
1697 xref[object++]=TellBlob(image);
1698 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1700 (void) WriteBlobString(image,buffer);
1701 (void) WriteBlobString(image,"<<\n");
1702 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1704 (void) WriteBlobString(image,buffer);
1705 (void) WriteBlobString(image,">>\n");
1706 (void) WriteBlobString(image,"stream\n");
1707 offset=TellBlob(image);
1708 (void) WriteBlobString(image,"q\n");
1709 if (labels != (char **) NULL)
1710 for (i=0; labels[i] != (char *) NULL; i++)
1712 (void) WriteBlobString(image,"BT\n");
1713 (void) FormatLocaleString(buffer,MagickPathExtent,"/F%.20g %g Tf\n",
1714 (double) image->scene,pointsize);
1715 (void) WriteBlobString(image,buffer);
1716 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g Td\n",
1717 (double) geometry.x,(double) (geometry.y+geometry.height+i*pointsize+
1719 (void) WriteBlobString(image,buffer);
1720 (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n",
1722 (void) WriteBlobString(image,buffer);
1723 (void) WriteBlobString(image,"ET\n");
1724 labels[i]=DestroyString(labels[i]);
1726 (void) FormatLocaleString(buffer,MagickPathExtent,
1727 "%g 0 0 %g %.20g %.20g cm\n",scale.x,scale.y,(double) geometry.x,
1728 (double) geometry.y);
1729 (void) WriteBlobString(image,buffer);
1730 (void) FormatLocaleString(buffer,MagickPathExtent,"/Im%.20g Do\n",(double)
1732 (void) WriteBlobString(image,buffer);
1733 (void) WriteBlobString(image,"Q\n");
1734 offset=TellBlob(image)-offset;
1735 (void) WriteBlobString(image,"\nendstream\n");
1736 (void) WriteBlobString(image,"endobj\n");
1738 Write Length object.
1740 xref[object++]=TellBlob(image);
1741 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1743 (void) WriteBlobString(image,buffer);
1744 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
1746 (void) WriteBlobString(image,buffer);
1747 (void) WriteBlobString(image,"endobj\n");
1749 Write Procset object.
1751 xref[object++]=TellBlob(image);
1752 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1754 (void) WriteBlobString(image,buffer);
1755 if ((image->storage_class == DirectClass) || (image->colors > 256))
1756 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MagickPathExtent);
1758 if ((compression == FaxCompression) || (compression == Group4Compression))
1759 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MagickPathExtent);
1761 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MagickPathExtent);
1762 (void) WriteBlobString(image,buffer);
1763 (void) WriteBlobString(image," ]\n");
1764 (void) WriteBlobString(image,"endobj\n");
1768 xref[object++]=TellBlob(image);
1769 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1771 (void) WriteBlobString(image,buffer);
1772 (void) WriteBlobString(image,"<<\n");
1773 if (labels != (char **) NULL)
1775 (void) WriteBlobString(image,"/Type /Font\n");
1776 (void) WriteBlobString(image,"/Subtype /Type1\n");
1777 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /F%.20g\n",
1778 (double) image->scene);
1779 (void) WriteBlobString(image,buffer);
1780 (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1781 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1782 labels=(char **) RelinquishMagickMemory(labels);
1784 (void) WriteBlobString(image,">>\n");
1785 (void) WriteBlobString(image,"endobj\n");
1787 Write XObject object.
1789 xref[object++]=TellBlob(image);
1790 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1792 (void) WriteBlobString(image,buffer);
1793 (void) WriteBlobString(image,"<<\n");
1794 (void) WriteBlobString(image,"/Type /XObject\n");
1795 (void) WriteBlobString(image,"/Subtype /Image\n");
1796 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Im%.20g\n",
1797 (double) image->scene);
1798 (void) WriteBlobString(image,buffer);
1799 switch (compression)
1803 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1807 case JPEGCompression:
1809 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
1810 if (image->colorspace != CMYKColorspace)
1812 (void) WriteBlobString(image,buffer);
1813 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1817 case JPEG2000Compression:
1819 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
1820 if (image->colorspace != CMYKColorspace)
1822 (void) WriteBlobString(image,buffer);
1823 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1827 case LZWCompression:
1829 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
1832 case ZipCompression:
1834 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1838 case FaxCompression:
1839 case Group4Compression:
1841 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1843 (void) WriteBlobString(image,buffer);
1844 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
1845 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
1846 (double) image->columns,(double) image->rows);
1851 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1856 (void) WriteBlobString(image,buffer);
1857 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
1859 (void) WriteBlobString(image,buffer);
1860 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
1862 (void) WriteBlobString(image,buffer);
1863 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
1865 (void) WriteBlobString(image,buffer);
1866 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
1867 (compression == FaxCompression) || (compression == Group4Compression) ?
1869 (void) WriteBlobString(image,buffer);
1870 if (image->alpha_trait != UndefinedPixelTrait)
1872 (void) FormatLocaleString(buffer,MagickPathExtent,"/SMask %.20g 0 R\n",
1873 (double) object+(has_icc_profile != MagickFalse ? 9 : 7));
1874 (void) WriteBlobString(image,buffer);
1876 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1878 (void) WriteBlobString(image,buffer);
1879 (void) WriteBlobString(image,">>\n");
1880 (void) WriteBlobString(image,"stream\n");
1881 offset=TellBlob(image);
1882 number_pixels=(MagickSizeType) image->columns*image->rows;
1883 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1884 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
1885 if ((compression == FaxCompression) || (compression == Group4Compression) ||
1886 ((image_info->type != TrueColorType) &&
1887 (SetImageGray(image,exception) != MagickFalse)))
1889 switch (compression)
1891 case FaxCompression:
1892 case Group4Compression:
1894 if (LocaleCompare(CCITTParam,"0") == 0)
1896 (void) HuffmanEncodeImage(image_info,image,image,exception);
1899 (void) Huffman2DEncodeImage(image_info,image,image,exception);
1902 case JPEGCompression:
1904 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
1905 if (status == MagickFalse)
1907 (void) CloseBlob(image);
1908 return(MagickFalse);
1912 case JPEG2000Compression:
1914 status=InjectImageBlob(image_info,image,image,"jp2",exception);
1915 if (status == MagickFalse)
1917 (void) CloseBlob(image);
1918 return(MagickFalse);
1922 case RLECompression:
1929 Allocate pixel array.
1931 length=(size_t) number_pixels;
1932 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
1933 if (pixel_info == (MemoryInfo *) NULL)
1934 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
1935 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1937 Dump Runlength encoded pixels.
1940 for (y=0; y < (ssize_t) image->rows; y++)
1942 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1943 if (p == (const Quantum *) NULL)
1945 for (x=0; x < (ssize_t) image->columns; x++)
1947 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p)));
1948 p+=GetPixelChannels(image);
1950 if (image->previous == (Image *) NULL)
1952 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1954 if (status == MagickFalse)
1958 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1959 if (compression == ZipCompression)
1960 status=ZLIBEncodeImage(image,length,pixels,exception);
1963 if (compression == LZWCompression)
1964 status=LZWEncodeImage(image,length,pixels,exception);
1966 status=PackbitsEncodeImage(image,length,pixels,exception);
1967 pixel_info=RelinquishVirtualMemory(pixel_info);
1968 if (status == MagickFalse)
1970 (void) CloseBlob(image);
1971 return(MagickFalse);
1978 Dump uncompressed PseudoColor packets.
1980 Ascii85Initialize(image);
1981 for (y=0; y < (ssize_t) image->rows; y++)
1983 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1984 if (p == (const Quantum *) NULL)
1986 for (x=0; x < (ssize_t) image->columns; x++)
1988 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
1989 GetPixelLuma(image,p))));
1990 p+=GetPixelChannels(image);
1992 if (image->previous == (Image *) NULL)
1994 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1996 if (status == MagickFalse)
2000 Ascii85Flush(image);
2006 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2007 (compression == JPEGCompression) ||
2008 (compression == JPEG2000Compression))
2009 switch (compression)
2011 case JPEGCompression:
2013 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
2014 if (status == MagickFalse)
2016 (void) CloseBlob(image);
2017 return(MagickFalse);
2021 case JPEG2000Compression:
2023 status=InjectImageBlob(image_info,image,image,"jp2",exception);
2024 if (status == MagickFalse)
2026 (void) CloseBlob(image);
2027 return(MagickFalse);
2031 case RLECompression:
2038 Allocate pixel array.
2040 length=(size_t) number_pixels;
2041 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
2042 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2043 if (pixel_info == (MemoryInfo *) NULL)
2045 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2046 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2048 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2050 Dump runoffset encoded pixels.
2053 for (y=0; y < (ssize_t) image->rows; y++)
2055 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2056 if (p == (const Quantum *) NULL)
2058 for (x=0; x < (ssize_t) image->columns; x++)
2060 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2061 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2062 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2063 if (image->colorspace == CMYKColorspace)
2064 *q++=ScaleQuantumToChar(GetPixelBlack(image,p));
2065 p+=GetPixelChannels(image);
2067 if (image->previous == (Image *) NULL)
2069 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
2071 if (status == MagickFalse)
2075 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2076 if (compression == ZipCompression)
2077 status=ZLIBEncodeImage(image,length,pixels,exception);
2080 if (compression == LZWCompression)
2081 status=LZWEncodeImage(image,length,pixels,exception);
2083 status=PackbitsEncodeImage(image,length,pixels,exception);
2084 pixel_info=RelinquishVirtualMemory(pixel_info);
2085 if (status == MagickFalse)
2087 (void) CloseBlob(image);
2088 return(MagickFalse);
2095 Dump uncompressed DirectColor packets.
2097 Ascii85Initialize(image);
2098 for (y=0; y < (ssize_t) image->rows; y++)
2100 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2101 if (p == (const Quantum *) NULL)
2103 for (x=0; x < (ssize_t) image->columns; x++)
2105 Ascii85Encode(image,ScaleQuantumToChar(GetPixelRed(image,p)));
2106 Ascii85Encode(image,ScaleQuantumToChar(GetPixelGreen(image,p)));
2107 Ascii85Encode(image,ScaleQuantumToChar(GetPixelBlue(image,p)));
2108 if (image->colorspace == CMYKColorspace)
2109 Ascii85Encode(image,ScaleQuantumToChar(
2110 GetPixelBlack(image,p)));
2111 p+=GetPixelChannels(image);
2113 if (image->previous == (Image *) NULL)
2115 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
2117 if (status == MagickFalse)
2121 Ascii85Flush(image);
2128 Dump number of colors and colormap.
2130 switch (compression)
2132 case RLECompression:
2139 Allocate pixel array.
2141 length=(size_t) number_pixels;
2142 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2143 if (pixel_info == (MemoryInfo *) NULL)
2145 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2146 ThrowPDFException(ResourceLimitError,
2147 "MemoryAllocationFailed");
2149 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2151 Dump Runlength encoded pixels.
2154 for (y=0; y < (ssize_t) image->rows; y++)
2156 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2157 if (p == (const Quantum *) NULL)
2159 for (x=0; x < (ssize_t) image->columns; x++)
2161 *q++=(unsigned char) GetPixelIndex(image,p);
2162 p+=GetPixelChannels(image);
2164 if (image->previous == (Image *) NULL)
2166 status=SetImageProgress(image,SaveImageTag,
2167 (MagickOffsetType) y,image->rows);
2168 if (status == MagickFalse)
2172 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2173 if (compression == ZipCompression)
2174 status=ZLIBEncodeImage(image,length,pixels,exception);
2177 if (compression == LZWCompression)
2178 status=LZWEncodeImage(image,length,pixels,exception);
2180 status=PackbitsEncodeImage(image,length,pixels,exception);
2181 pixel_info=RelinquishVirtualMemory(pixel_info);
2182 if (status == MagickFalse)
2184 (void) CloseBlob(image);
2185 return(MagickFalse);
2192 Dump uncompressed PseudoColor packets.
2194 Ascii85Initialize(image);
2195 for (y=0; y < (ssize_t) image->rows; y++)
2197 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2198 if (p == (const Quantum *) NULL)
2200 for (x=0; x < (ssize_t) image->columns; x++)
2202 Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p));
2203 p+=GetPixelChannels(image);
2205 if (image->previous == (Image *) NULL)
2207 status=SetImageProgress(image,SaveImageTag,
2208 (MagickOffsetType) y,image->rows);
2209 if (status == MagickFalse)
2213 Ascii85Flush(image);
2218 offset=TellBlob(image)-offset;
2219 (void) WriteBlobString(image,"\nendstream\n");
2220 (void) WriteBlobString(image,"endobj\n");
2222 Write Length object.
2224 xref[object++]=TellBlob(image);
2225 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2227 (void) WriteBlobString(image,buffer);
2228 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2230 (void) WriteBlobString(image,buffer);
2231 (void) WriteBlobString(image,"endobj\n");
2233 Write Colorspace object.
2235 xref[object++]=TellBlob(image);
2236 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2238 (void) WriteBlobString(image,buffer);
2241 if (image->colorspace == CMYKColorspace)
2243 device="DeviceCMYK";
2247 if ((compression == FaxCompression) ||
2248 (compression == Group4Compression) ||
2249 ((image_info->type != TrueColorType) &&
2250 (SetImageGray(image,exception) != MagickFalse)))
2252 device="DeviceGray";
2256 if ((image->storage_class == DirectClass) ||
2257 (image->colors > 256) || (compression == JPEGCompression) ||
2258 (compression == JPEG2000Compression))
2263 profile=GetImageProfile(image,"icc");
2264 if ((profile == (StringInfo *) NULL) || (channels == 0))
2267 (void) FormatLocaleString(buffer,MagickPathExtent,"/%s\n",device);
2269 (void) FormatLocaleString(buffer,MagickPathExtent,
2270 "[ /Indexed /%s %.20g %.20g 0 R ]\n",device,(double) image->colors-
2271 1,(double) object+3);
2272 (void) WriteBlobString(image,buffer);
2282 (void) FormatLocaleString(buffer,MagickPathExtent,
2283 "[/ICCBased %.20g 0 R]\n",(double) object+1);
2284 (void) WriteBlobString(image,buffer);
2285 (void) WriteBlobString(image,"endobj\n");
2286 xref[object++]=TellBlob(image);
2287 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",
2289 (void) WriteBlobString(image,buffer);
2290 (void) FormatLocaleString(buffer,MagickPathExtent,"<<\n/N %.20g\n"
2291 "/Filter /ASCII85Decode\n/Length %.20g 0 R\n/Alternate /%s\n>>\n"
2292 "stream\n",(double) channels,(double) object+1,device);
2293 (void) WriteBlobString(image,buffer);
2294 offset=TellBlob(image);
2295 Ascii85Initialize(image);
2296 p=GetStringInfoDatum(profile);
2297 for (i=0; i < (ssize_t) GetStringInfoLength(profile); i++)
2298 Ascii85Encode(image,(unsigned char) *p++);
2299 Ascii85Flush(image);
2300 offset=TellBlob(image)-offset;
2301 (void) WriteBlobString(image,"endstream\n");
2302 (void) WriteBlobString(image,"endobj\n");
2304 Write Length object.
2306 xref[object++]=TellBlob(image);
2307 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",
2309 (void) WriteBlobString(image,buffer);
2310 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2312 (void) WriteBlobString(image,buffer);
2314 (void) WriteBlobString(image,"endobj\n");
2318 SetGeometry(image,&geometry);
2319 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
2320 &geometry.width,&geometry.height);
2321 tile_image=ThumbnailImage(image,geometry.width,geometry.height,exception);
2322 if (tile_image == (Image *) NULL)
2323 return(MagickFalse);
2324 xref[object++]=TellBlob(image);
2325 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2327 (void) WriteBlobString(image,buffer);
2328 (void) WriteBlobString(image,"<<\n");
2329 switch (compression)
2333 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2337 case JPEGCompression:
2339 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
2340 if (image->colorspace != CMYKColorspace)
2342 (void) WriteBlobString(image,buffer);
2343 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2347 case JPEG2000Compression:
2349 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
2350 if (image->colorspace != CMYKColorspace)
2352 (void) WriteBlobString(image,buffer);
2353 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2357 case LZWCompression:
2359 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
2362 case ZipCompression:
2364 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2368 case FaxCompression:
2369 case Group4Compression:
2371 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
2373 (void) WriteBlobString(image,buffer);
2374 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
2375 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
2376 (double) tile_image->columns,(double) tile_image->rows);
2381 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2386 (void) WriteBlobString(image,buffer);
2387 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
2388 tile_image->columns);
2389 (void) WriteBlobString(image,buffer);
2390 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
2392 (void) WriteBlobString(image,buffer);
2393 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
2394 (double) object-(has_icc_profile != MagickFalse ? 3 : 1));
2395 (void) WriteBlobString(image,buffer);
2396 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
2397 (compression == FaxCompression) || (compression == Group4Compression) ?
2399 (void) WriteBlobString(image,buffer);
2400 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2402 (void) WriteBlobString(image,buffer);
2403 (void) WriteBlobString(image,">>\n");
2404 (void) WriteBlobString(image,"stream\n");
2405 offset=TellBlob(image);
2406 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
2407 if ((compression == FaxCompression) ||
2408 (compression == Group4Compression) ||
2409 ((image_info->type != TrueColorType) &&
2410 (SetImageGray(tile_image,exception) != MagickFalse)))
2412 switch (compression)
2414 case FaxCompression:
2415 case Group4Compression:
2417 if (LocaleCompare(CCITTParam,"0") == 0)
2419 (void) HuffmanEncodeImage(image_info,image,tile_image,
2423 (void) Huffman2DEncodeImage(image_info,image,tile_image,exception);
2426 case JPEGCompression:
2428 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2430 if (status == MagickFalse)
2432 (void) CloseBlob(image);
2433 return(MagickFalse);
2437 case JPEG2000Compression:
2439 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2440 if (status == MagickFalse)
2442 (void) CloseBlob(image);
2443 return(MagickFalse);
2447 case RLECompression:
2454 Allocate pixel array.
2456 length=(size_t) number_pixels;
2457 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2458 if (pixel_info == (MemoryInfo *) NULL)
2460 tile_image=DestroyImage(tile_image);
2461 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2463 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2465 Dump runlength encoded pixels.
2468 for (y=0; y < (ssize_t) tile_image->rows; y++)
2470 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2472 if (p == (const Quantum *) NULL)
2474 for (x=0; x < (ssize_t) tile_image->columns; x++)
2476 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(
2478 p+=GetPixelChannels(tile_image);
2481 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2482 if (compression == ZipCompression)
2483 status=ZLIBEncodeImage(image,length,pixels,exception);
2486 if (compression == LZWCompression)
2487 status=LZWEncodeImage(image,length,pixels,exception);
2489 status=PackbitsEncodeImage(image,length,pixels,exception);
2490 pixel_info=RelinquishVirtualMemory(pixel_info);
2491 if (status == MagickFalse)
2493 (void) CloseBlob(image);
2494 return(MagickFalse);
2501 Dump uncompressed PseudoColor packets.
2503 Ascii85Initialize(image);
2504 for (y=0; y < (ssize_t) tile_image->rows; y++)
2506 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2508 if (p == (const Quantum *) NULL)
2510 for (x=0; x < (ssize_t) tile_image->columns; x++)
2512 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2513 GetPixelLuma(tile_image,p))));
2514 p+=GetPixelChannels(tile_image);
2517 Ascii85Flush(image);
2523 if ((tile_image->storage_class == DirectClass) ||
2524 (tile_image->colors > 256) || (compression == JPEGCompression) ||
2525 (compression == JPEG2000Compression))
2526 switch (compression)
2528 case JPEGCompression:
2530 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2532 if (status == MagickFalse)
2534 (void) CloseBlob(image);
2535 return(MagickFalse);
2539 case JPEG2000Compression:
2541 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2542 if (status == MagickFalse)
2544 (void) CloseBlob(image);
2545 return(MagickFalse);
2549 case RLECompression:
2556 Allocate pixel array.
2558 length=(size_t) number_pixels;
2559 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2560 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2561 if (pixel_info == (MemoryInfo *) NULL)
2563 tile_image=DestroyImage(tile_image);
2564 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2566 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2568 Dump runlength encoded pixels.
2571 for (y=0; y < (ssize_t) tile_image->rows; y++)
2573 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2575 if (p == (const Quantum *) NULL)
2577 for (x=0; x < (ssize_t) tile_image->columns; x++)
2579 *q++=ScaleQuantumToChar(GetPixelRed(tile_image,p));
2580 *q++=ScaleQuantumToChar(GetPixelGreen(tile_image,p));
2581 *q++=ScaleQuantumToChar(GetPixelBlue(tile_image,p));
2582 if (tile_image->colorspace == CMYKColorspace)
2583 *q++=ScaleQuantumToChar(GetPixelBlack(tile_image,p));
2584 p+=GetPixelChannels(tile_image);
2587 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2588 if (compression == ZipCompression)
2589 status=ZLIBEncodeImage(image,length,pixels,exception);
2592 if (compression == LZWCompression)
2593 status=LZWEncodeImage(image,length,pixels,exception);
2595 status=PackbitsEncodeImage(image,length,pixels,exception);
2596 pixel_info=RelinquishVirtualMemory(pixel_info);
2597 if (status == MagickFalse)
2599 (void) CloseBlob(image);
2600 return(MagickFalse);
2607 Dump uncompressed DirectColor packets.
2609 Ascii85Initialize(image);
2610 for (y=0; y < (ssize_t) tile_image->rows; y++)
2612 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2614 if (p == (const Quantum *) NULL)
2616 for (x=0; x < (ssize_t) tile_image->columns; x++)
2618 Ascii85Encode(image,ScaleQuantumToChar(
2619 GetPixelRed(tile_image,p)));
2620 Ascii85Encode(image,ScaleQuantumToChar(
2621 GetPixelGreen(tile_image,p)));
2622 Ascii85Encode(image,ScaleQuantumToChar(
2623 GetPixelBlue(tile_image,p)));
2624 if (image->colorspace == CMYKColorspace)
2625 Ascii85Encode(image,ScaleQuantumToChar(
2626 GetPixelBlack(tile_image,p)));
2627 p+=GetPixelChannels(tile_image);
2630 Ascii85Flush(image);
2637 Dump number of colors and colormap.
2639 switch (compression)
2641 case RLECompression:
2648 Allocate pixel array.
2650 length=(size_t) number_pixels;
2651 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2652 if (pixel_info == (MemoryInfo *) NULL)
2654 tile_image=DestroyImage(tile_image);
2655 ThrowPDFException(ResourceLimitError,
2656 "MemoryAllocationFailed");
2658 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2660 Dump runlength encoded pixels.
2663 for (y=0; y < (ssize_t) tile_image->rows; y++)
2665 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2667 if (p == (const Quantum *) NULL)
2669 for (x=0; x < (ssize_t) tile_image->columns; x++)
2671 *q++=(unsigned char) GetPixelIndex(tile_image,p);
2672 p+=GetPixelChannels(tile_image);
2675 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2676 if (compression == ZipCompression)
2677 status=ZLIBEncodeImage(image,length,pixels,exception);
2680 if (compression == LZWCompression)
2681 status=LZWEncodeImage(image,length,pixels,exception);
2683 status=PackbitsEncodeImage(image,length,pixels,exception);
2684 pixel_info=RelinquishVirtualMemory(pixel_info);
2685 if (status == MagickFalse)
2687 (void) CloseBlob(image);
2688 return(MagickFalse);
2695 Dump uncompressed PseudoColor packets.
2697 Ascii85Initialize(image);
2698 for (y=0; y < (ssize_t) tile_image->rows; y++)
2700 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2702 if (p == (const Quantum *) NULL)
2704 for (x=0; x < (ssize_t) tile_image->columns; x++)
2706 Ascii85Encode(image,(unsigned char)
2707 GetPixelIndex(tile_image,p));
2708 p+=GetPixelChannels(image);
2711 Ascii85Flush(image);
2716 tile_image=DestroyImage(tile_image);
2717 offset=TellBlob(image)-offset;
2718 (void) WriteBlobString(image,"\nendstream\n");
2719 (void) WriteBlobString(image,"endobj\n");
2721 Write Length object.
2723 xref[object++]=TellBlob(image);
2724 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2726 (void) WriteBlobString(image,buffer);
2727 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2729 (void) WriteBlobString(image,buffer);
2730 (void) WriteBlobString(image,"endobj\n");
2731 xref[object++]=TellBlob(image);
2732 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2734 (void) WriteBlobString(image,buffer);
2735 (void) WriteBlobString(image,"<<\n");
2736 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2737 (compression == FaxCompression) || (compression == Group4Compression))
2738 (void) WriteBlobString(image,">>\n");
2742 Write Colormap object.
2744 if (compression == NoCompression)
2745 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2746 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2748 (void) WriteBlobString(image,buffer);
2749 (void) WriteBlobString(image,">>\n");
2750 (void) WriteBlobString(image,"stream\n");
2751 offset=TellBlob(image);
2752 if (compression == NoCompression)
2753 Ascii85Initialize(image);
2754 for (i=0; i < (ssize_t) image->colors; i++)
2756 if (compression == NoCompression)
2758 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2759 image->colormap[i].red)));
2760 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2761 image->colormap[i].green)));
2762 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2763 image->colormap[i].blue)));
2766 (void) WriteBlobByte(image,ScaleQuantumToChar(
2767 ClampToQuantum(image->colormap[i].red)));
2768 (void) WriteBlobByte(image,ScaleQuantumToChar(
2769 ClampToQuantum(image->colormap[i].green)));
2770 (void) WriteBlobByte(image,ScaleQuantumToChar(
2771 ClampToQuantum(image->colormap[i].blue)));
2773 if (compression == NoCompression)
2774 Ascii85Flush(image);
2775 offset=TellBlob(image)-offset;
2776 (void) WriteBlobString(image,"\nendstream\n");
2778 (void) WriteBlobString(image,"endobj\n");
2780 Write Length object.
2782 xref[object++]=TellBlob(image);
2783 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2785 (void) WriteBlobString(image,buffer);
2786 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2788 (void) WriteBlobString(image,buffer);
2789 (void) WriteBlobString(image,"endobj\n");
2791 Write softmask object.
2793 xref[object++]=TellBlob(image);
2794 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2796 (void) WriteBlobString(image,buffer);
2797 (void) WriteBlobString(image,"<<\n");
2798 if (image->alpha_trait == UndefinedPixelTrait)
2799 (void) WriteBlobString(image,">>\n");
2802 (void) WriteBlobString(image,"/Type /XObject\n");
2803 (void) WriteBlobString(image,"/Subtype /Image\n");
2804 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Ma%.20g\n",
2805 (double) image->scene);
2806 (void) WriteBlobString(image,buffer);
2807 switch (compression)
2811 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2815 case LZWCompression:
2817 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2821 case ZipCompression:
2823 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2829 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2834 (void) WriteBlobString(image,buffer);
2835 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",
2836 (double) image->columns);
2837 (void) WriteBlobString(image,buffer);
2838 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",
2839 (double) image->rows);
2840 (void) WriteBlobString(image,buffer);
2841 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2842 (void) FormatLocaleString(buffer,MagickPathExtent,
2843 "/BitsPerComponent %d\n",(compression == FaxCompression) ||
2844 (compression == Group4Compression) ? 1 : 8);
2845 (void) WriteBlobString(image,buffer);
2846 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2848 (void) WriteBlobString(image,buffer);
2849 (void) WriteBlobString(image,">>\n");
2850 (void) WriteBlobString(image,"stream\n");
2851 offset=TellBlob(image);
2852 number_pixels=(MagickSizeType) image->columns*image->rows;
2853 switch (compression)
2855 case RLECompression:
2862 Allocate pixel array.
2864 length=(size_t) number_pixels;
2865 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2866 if (pixel_info == (MemoryInfo *) NULL)
2868 image=DestroyImage(image);
2869 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2871 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2873 Dump Runlength encoded pixels.
2876 for (y=0; y < (ssize_t) image->rows; y++)
2878 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2879 if (p == (const Quantum *) NULL)
2881 for (x=0; x < (ssize_t) image->columns; x++)
2883 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
2884 p+=GetPixelChannels(image);
2887 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2888 if (compression == ZipCompression)
2889 status=ZLIBEncodeImage(image,length,pixels,exception);
2892 if (compression == LZWCompression)
2893 status=LZWEncodeImage(image,length,pixels,exception);
2895 status=PackbitsEncodeImage(image,length,pixels,exception);
2896 pixel_info=RelinquishVirtualMemory(pixel_info);
2897 if (status == MagickFalse)
2899 (void) CloseBlob(image);
2900 return(MagickFalse);
2907 Dump uncompressed PseudoColor packets.
2909 Ascii85Initialize(image);
2910 for (y=0; y < (ssize_t) image->rows; y++)
2912 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2913 if (p == (const Quantum *) NULL)
2915 for (x=0; x < (ssize_t) image->columns; x++)
2917 Ascii85Encode(image,ScaleQuantumToChar(GetPixelAlpha(image,p)));
2918 p+=GetPixelChannels(image);
2921 Ascii85Flush(image);
2925 offset=TellBlob(image)-offset;
2926 (void) WriteBlobString(image,"\nendstream\n");
2928 (void) WriteBlobString(image,"endobj\n");
2930 Write Length object.
2932 xref[object++]=TellBlob(image);
2933 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2935 (void) WriteBlobString(image,buffer);
2936 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2938 (void) WriteBlobString(image,buffer);
2939 (void) WriteBlobString(image,"endobj\n");
2940 if (GetNextImageInList(image) == (Image *) NULL)
2942 image=SyncNextImageInList(image);
2943 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2944 if (status == MagickFalse)
2946 } while (image_info->adjoin != MagickFalse);
2948 Write Metadata object.
2950 xref[object++]=TellBlob(image);
2952 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2954 (void) WriteBlobString(image,buffer);
2955 (void) WriteBlobString(image,"<<\n");
2956 utf16=ConvertUTF8ToUTF16((unsigned char *) basename,&length);
2957 if (utf16 != (wchar_t *) NULL)
2959 (void) FormatLocaleString(buffer,MagickPathExtent,"/Title (\xfe\xff");
2960 (void) WriteBlobString(image,buffer);
2961 for (i=0; i < (ssize_t) length; i++)
2962 (void) WriteBlobMSBShort(image,(unsigned short) utf16[i]);
2963 (void) FormatLocaleString(buffer,MagickPathExtent,")\n");
2964 (void) WriteBlobString(image,buffer);
2965 utf16=(wchar_t *) RelinquishMagickMemory(utf16);
2967 seconds=time((time_t *) NULL);
2968 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2969 (void) localtime_r(&seconds,&local_time);
2971 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2973 (void) FormatLocaleString(date,MagickPathExtent,"D:%04d%02d%02d%02d%02d%02d",
2974 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2975 local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2976 (void) FormatLocaleString(buffer,MagickPathExtent,"/CreationDate (%s)\n",
2978 (void) WriteBlobString(image,buffer);
2979 (void) FormatLocaleString(buffer,MagickPathExtent,"/ModDate (%s)\n",date);
2980 (void) WriteBlobString(image,buffer);
2981 url=(char *) MagickAuthoritativeURL;
2982 escape=EscapeParenthesis(url);
2983 (void) FormatLocaleString(buffer,MagickPathExtent,"/Producer (%s)\n",escape);
2984 escape=DestroyString(escape);
2985 (void) WriteBlobString(image,buffer);
2986 (void) WriteBlobString(image,">>\n");
2987 (void) WriteBlobString(image,"endobj\n");
2991 offset=TellBlob(image)-xref[0]+
2992 (LocaleCompare(image_info->magick,"PDFA") == 0 ? 6 : 0)+10;
2993 (void) WriteBlobString(image,"xref\n");
2994 (void) FormatLocaleString(buffer,MagickPathExtent,"0 %.20g\n",(double)
2996 (void) WriteBlobString(image,buffer);
2997 (void) WriteBlobString(image,"0000000000 65535 f \n");
2998 for (i=0; i < (ssize_t) object; i++)
3000 (void) FormatLocaleString(buffer,MagickPathExtent,"%010lu 00000 n \n",
3001 (unsigned long) xref[i]);
3002 (void) WriteBlobString(image,buffer);
3004 (void) WriteBlobString(image,"trailer\n");
3005 (void) WriteBlobString(image,"<<\n");
3006 (void) FormatLocaleString(buffer,MagickPathExtent,"/Size %.20g\n",(double)
3008 (void) WriteBlobString(image,buffer);
3009 (void) FormatLocaleString(buffer,MagickPathExtent,"/Info %.20g 0 R\n",(double)
3011 (void) WriteBlobString(image,buffer);
3012 (void) FormatLocaleString(buffer,MagickPathExtent,"/Root %.20g 0 R\n",(double)
3014 (void) WriteBlobString(image,buffer);
3015 (void) SignatureImage(image,exception);
3016 (void) FormatLocaleString(buffer,MagickPathExtent,"/ID [<%s> <%s>]\n",
3017 GetImageProperty(image,"signature",exception),
3018 GetImageProperty(image,"signature",exception));
3019 (void) WriteBlobString(image,buffer);
3020 (void) WriteBlobString(image,">>\n");
3021 (void) WriteBlobString(image,"startxref\n");
3022 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) offset);
3023 (void) WriteBlobString(image,buffer);
3024 (void) WriteBlobString(image,"%%EOF\n");
3025 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
3026 (void) CloseBlob(image);