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://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 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(),
277 DelegateError,"PDFDelegateFailed",
278 "`[ghostscript library %.2f]%s': %s",
279 (double)revision.revision/100.0,args_start,errors);
280 if (errors != (char *) NULL)
281 errors=DestroyString(errors);
282 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
283 "Ghostscript returns status %d, exit code %d",status,code);
287 if (errors != (char *) NULL)
288 errors=DestroyString(errors);
291 ExecuteGhostscriptCommand(command,status);
296 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
304 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
306 % IsPDF() returns MagickTrue if the image format type, identified by the
307 % magick string, is PDF.
309 % The format of the IsPDF method is:
311 % MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
313 % A description of each parameter follows:
315 % o magick: compare image format pattern against these bytes.
317 % o offset: Specifies the offset of the magick string.
320 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
324 if (LocaleNCompare((const char *) magick,"%PDF-",5) == 0)
330 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
334 % R e a d P D F I m a g e %
338 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 % ReadPDFImage() reads a Portable Document Format image file and
341 % returns it. It allocates the memory necessary for the new Image structure
342 % and returns a pointer to the new image.
344 % The format of the ReadPDFImage method is:
346 % Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
348 % A description of each parameter follows:
350 % o image_info: the image info.
352 % o exception: return any errors or warnings in this structure.
356 static MagickBooleanType IsPDFRendered(const char *path)
364 if ((path == (const char *) NULL) || (*path == '\0'))
366 status=GetPathAttributes(path,&attributes);
367 if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
368 (attributes.st_size > 0))
373 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
375 #define BeginXMPPacket "<?xpacket begin="
376 #define CMYKProcessColor "CMYKProcessColor"
377 #define CropBox "CropBox"
378 #define DefaultCMYK "DefaultCMYK"
379 #define DeviceCMYK "DeviceCMYK"
380 #define EndXMPPacket "<?xpacket end="
381 #define MediaBox "MediaBox"
382 #define RenderPostscriptText "Rendering Postscript... "
383 #define PDFRotate "Rotate"
384 #define SpotColor "Separation"
385 #define TrimBox "TrimBox"
386 #define PDFVersion "PDF-"
389 command[MagickPathExtent],
391 filename[MagickPathExtent],
392 geometry[MagickPathExtent],
393 input_filename[MagickPathExtent],
394 message[MagickPathExtent],
396 postscript_filename[MagickPathExtent];
457 assert(image_info != (const ImageInfo *) NULL);
458 assert(image_info->signature == MagickCoreSignature);
459 if (image_info->debug != MagickFalse)
460 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
461 image_info->filename);
462 assert(exception != (ExceptionInfo *) NULL);
463 assert(exception->signature == MagickCoreSignature);
467 image=AcquireImage(image_info,exception);
468 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
469 if (status == MagickFalse)
471 image=DestroyImageList(image);
472 return((Image *) NULL);
474 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
475 if (status == MagickFalse)
477 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
478 image_info->filename);
479 image=DestroyImageList(image);
480 return((Image *) NULL);
483 Set the page density.
485 delta.x=DefaultResolution;
486 delta.y=DefaultResolution;
487 if ((image->resolution.x == 0.0) || (image->resolution.y == 0.0))
489 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
490 image->resolution.x=geometry_info.rho;
491 image->resolution.y=geometry_info.sigma;
492 if ((flags & SigmaValue) == 0)
493 image->resolution.y=image->resolution.x;
495 if (image_info->density != (char *) NULL)
497 flags=ParseGeometry(image_info->density,&geometry_info);
498 image->resolution.x=geometry_info.rho;
499 image->resolution.y=geometry_info.sigma;
500 if ((flags & SigmaValue) == 0)
501 image->resolution.y=image->resolution.x;
503 (void) memset(&page,0,sizeof(page));
504 (void) ParseAbsoluteGeometry(PSPageGeometry,&page);
505 if (image_info->page != (char *) NULL)
506 (void) ParseAbsoluteGeometry(image_info->page,&page);
507 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)-
509 page.height=(size_t) ceil((double) (page.height*image->resolution.y/delta.y)-
512 Determine page geometry from the PDF media box.
514 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
515 cropbox=IsStringTrue(GetImageOption(image_info,"pdf:use-cropbox"));
516 stop_on_error=IsStringTrue(GetImageOption(image_info,"pdf:stop-on-error"));
517 trimbox=IsStringTrue(GetImageOption(image_info,"pdf:use-trimbox"));
520 (void) memset(&bounding_box,0,sizeof(bounding_box));
521 (void) memset(&bounds,0,sizeof(bounds));
522 (void) memset(&hires_bounds,0,sizeof(hires_bounds));
523 (void) memset(command,0,sizeof(command));
526 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
534 if ((c != (int) '/') && (c != (int) '%') &&
535 ((size_t) (p-command) < (MagickPathExtent-1)))
539 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
540 count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
542 Is this a CMYK document?
544 if (LocaleNCompare(DefaultCMYK,command,strlen(DefaultCMYK)) == 0)
546 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
548 if (LocaleNCompare(CMYKProcessColor,command,strlen(CMYKProcessColor)) == 0)
550 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
553 name[MagickPathExtent],
554 property[MagickPathExtent],
560 (void) FormatLocaleString(property,MagickPathExtent,
561 "pdf:SpotColor-%.20g",(double) spotcolor++);
563 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
565 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MagickPathExtent))
570 value=ConstantString(name);
571 (void) SubstituteString(&value,"#20"," ");
573 (void) SetImageProperty(image,property,value,exception);
574 value=DestroyString(value);
577 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
578 (void) SetImageProperty(image,"pdf:Version",command,exception);
579 if (image_info->page != (char *) NULL)
582 if (cropbox != MagickFalse)
584 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
587 Note region defined by crop box.
589 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
590 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
592 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
593 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
597 if (trimbox != MagickFalse)
599 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
602 Note region defined by trim box.
604 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
605 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
607 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
608 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
612 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
615 Note region defined by media box.
617 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
618 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
620 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
621 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
625 if ((fabs(bounds.x2-bounds.x1) <= fabs(hires_bounds.x2-hires_bounds.x1)) ||
626 (fabs(bounds.y2-bounds.y1) <= fabs(hires_bounds.y2-hires_bounds.y1)))
630 if ((fabs(hires_bounds.x2-hires_bounds.x1) >= MagickEpsilon) &&
631 (fabs(hires_bounds.y2-hires_bounds.y1) >= MagickEpsilon))
634 Set PDF render geometry.
636 (void) FormatLocaleString(geometry,MagickPathExtent,"%gx%g%+.15g%+.15g",
637 hires_bounds.x2-bounds.x1,hires_bounds.y2-hires_bounds.y1,
638 hires_bounds.x1,hires_bounds.y1);
639 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry,exception);
640 page.width=(size_t) ceil((double) ((hires_bounds.x2-hires_bounds.x1)*
641 image->resolution.x/delta.x)-0.5);
642 page.height=(size_t) ceil((double) ((hires_bounds.y2-hires_bounds.y1)*
643 image->resolution.y/delta.y)-0.5);
646 option=GetImageOption(image_info,"pdf:fit-page");
647 if (option != (char *) NULL)
652 page_geometry=GetPageGeometry(option);
653 flags=ParseMetaGeometry(page_geometry,&page.x,&page.y,&page.width,
655 page_geometry=DestroyString(page_geometry);
656 if (flags == NoValue)
658 (void) ThrowMagickException(exception,GetMagickModule(),OptionError,
659 "InvalidGeometry","`%s'",option);
660 image=DestroyImage(image);
661 return((Image *) NULL);
663 page.width=(size_t) ceil((double) (page.width*image->resolution.x/delta.x)
665 page.height=(size_t) ceil((double) (page.height*image->resolution.y/
669 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
675 page.width=page.height;
678 if (IssRGBCompatibleColorspace(image_info->colorspace) != MagickFalse)
681 Create Ghostscript control file.
683 file=AcquireUniqueFileResource(postscript_filename);
686 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
687 image_info->filename);
688 image=DestroyImage(image);
689 return((Image *) NULL);
691 count=write(file," ",1);
694 Render Postscript with the Ghostscript delegate.
696 if (image_info->monochrome != MagickFalse)
697 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
699 if (cmyk != MagickFalse)
700 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
702 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
703 if (delegate_info == (const DelegateInfo *) NULL)
705 (void) RelinquishUniqueFileResource(postscript_filename);
706 image=DestroyImage(image);
707 return((Image *) NULL);
709 density=AcquireString("");
710 options=AcquireString("");
711 (void) FormatLocaleString(density,MagickPathExtent,"%gx%g",
712 image->resolution.x,image->resolution.y);
713 if ((image_info->page != (char *) NULL) || (fitPage != MagickFalse))
714 (void) FormatLocaleString(options,MagickPathExtent,"-g%.20gx%.20g ",(double)
715 page.width,(double) page.height);
716 if (fitPage != MagickFalse)
717 (void) ConcatenateMagickString(options,"-dPSFitPage ",MagickPathExtent);
718 if (cmyk != MagickFalse)
719 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MagickPathExtent);
720 if (cropbox != MagickFalse)
721 (void) ConcatenateMagickString(options,"-dUseCropBox ",MagickPathExtent);
722 if (stop_on_error != MagickFalse)
723 (void) ConcatenateMagickString(options,"-dPDFSTOPONERROR ",
725 if (trimbox != MagickFalse)
726 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MagickPathExtent);
727 option=GetImageOption(image_info,"authenticate");
728 if (option != (char *) NULL)
731 passphrase[MagickPathExtent];
733 (void) FormatLocaleString(passphrase,MagickPathExtent,
734 "\"-sPDFPassword=%s\" ",option);
735 (void) ConcatenateMagickString(options,passphrase,MagickPathExtent);
737 read_info=CloneImageInfo(image_info);
738 *read_info->magick='\0';
739 if (read_info->number_scenes != 0)
742 pages[MagickPathExtent];
744 (void) FormatLocaleString(pages,MagickPathExtent,"-dFirstPage=%.20g "
745 "-dLastPage=%.20g",(double) read_info->scene+1,(double)
746 (read_info->scene+read_info->number_scenes));
747 (void) ConcatenateMagickString(options,pages,MagickPathExtent);
748 read_info->number_scenes=0;
749 if (read_info->scenes != (char *) NULL)
750 *read_info->scenes='\0';
752 (void) CopyMagickString(filename,read_info->filename,MagickPathExtent);
753 (void) AcquireUniqueFilename(filename);
754 (void) RelinquishUniqueFileResource(filename);
755 (void) ConcatenateMagickString(filename,"%d",MagickPathExtent);
756 (void) FormatLocaleString(command,MagickPathExtent,
757 GetDelegateCommands(delegate_info),
758 read_info->antialias != MagickFalse ? 4 : 1,
759 read_info->antialias != MagickFalse ? 4 : 1,density,options,filename,
760 postscript_filename,input_filename);
761 options=DestroyString(options);
762 density=DestroyString(density);
764 status=InvokePDFDelegate(read_info->verbose,command,message,exception);
765 (void) RelinquishUniqueFileResource(postscript_filename);
766 (void) RelinquishUniqueFileResource(input_filename);
767 pdf_image=(Image *) NULL;
768 if (status == MagickFalse)
771 (void) InterpretImageFilename(image_info,image,filename,(int) i,
772 read_info->filename,exception);
773 if (IsPDFRendered(read_info->filename) == MagickFalse)
775 (void) RelinquishUniqueFileResource(read_info->filename);
780 (void) InterpretImageFilename(image_info,image,filename,(int) i,
781 read_info->filename,exception);
782 if (IsPDFRendered(read_info->filename) == MagickFalse)
784 read_info->blob=NULL;
786 next=ReadImage(read_info,exception);
787 (void) RelinquishUniqueFileResource(read_info->filename);
788 if (next == (Image *) NULL)
790 AppendImageToList(&pdf_image,next);
792 read_info=DestroyImageInfo(read_info);
793 if (pdf_image == (Image *) NULL)
795 if (*message != '\0')
796 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
797 "PDFDelegateFailed","`%s'",message);
798 image=DestroyImage(image);
799 return((Image *) NULL);
801 if (LocaleCompare(pdf_image->magick,"BMP") == 0)
806 cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
807 if (cmyk_image != (Image *) NULL)
809 pdf_image=DestroyImageList(pdf_image);
810 pdf_image=cmyk_image;
813 (void) SeekBlob(image,0,SEEK_SET);
814 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
817 Note document structuring comments.
820 if ((strchr("\n\r%",c) == (char *) NULL) &&
821 ((size_t) (p-command) < (MagickPathExtent-1)))
825 if (LocaleNCompare(BeginXMPPacket,command,strlen(BeginXMPPacket)) == 0)
834 profile=StringToStringInfo(command);
835 for (i=(ssize_t) GetStringInfoLength(profile)-1; c != EOF; i++)
837 SetStringInfoLength(profile,(size_t) (i+1));
838 c=ReadBlobByte(image);
839 GetStringInfoDatum(profile)[i]=(unsigned char) c;
841 if ((strchr("\n\r%",c) == (char *) NULL) &&
842 ((size_t) (p-command) < (MagickPathExtent-1)))
846 if (LocaleNCompare(EndXMPPacket,command,strlen(EndXMPPacket)) == 0)
849 SetStringInfoLength(profile,(size_t) i);
850 (void) SetImageProfile(image,"xmp",profile,exception);
851 profile=DestroyStringInfo(profile);
855 (void) CloseBlob(image);
856 if (image_info->number_scenes != 0)
862 Add place holder images to meet the subimage specification requirement.
864 for (i=0; i < (ssize_t) image_info->scene; i++)
866 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
867 if (clone_image != (Image *) NULL)
868 PrependImageToList(&pdf_image,clone_image);
873 (void) CopyMagickString(pdf_image->filename,filename,MagickPathExtent);
874 (void) CopyMagickString(pdf_image->magick,image->magick,MagickPathExtent);
875 pdf_image->page=page;
876 (void) CloneImageProfiles(pdf_image,image);
877 (void) CloneImageProperties(pdf_image,image);
878 next=SyncNextImageInList(pdf_image);
879 if (next != (Image *) NULL)
881 } while (next != (Image *) NULL);
882 image=DestroyImage(image);
884 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
887 next=GetNextImageInList(next);
889 return(GetFirstImageInList(pdf_image));
893 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
897 % R e g i s t e r P D F I m a g e %
901 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
903 % RegisterPDFImage() adds properties for the PDF image format to
904 % the list of supported formats. The properties include the image format
905 % tag, a method to read and/or write the format, whether the format
906 % supports the saving of more than one frame to the same file or blob,
907 % whether the format supports native in-memory I/O, and a brief
908 % description of the format.
910 % The format of the RegisterPDFImage method is:
912 % size_t RegisterPDFImage(void)
915 ModuleExport size_t RegisterPDFImage(void)
920 entry=AcquireMagickInfo("PDF","AI","Adobe Illustrator CS2");
921 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
922 entry->encoder=(EncodeImageHandler *) WritePDFImage;
923 entry->flags^=CoderAdjoinFlag;
924 entry->flags^=CoderBlobSupportFlag;
925 entry->mime_type=ConstantString("application/pdf");
926 (void) RegisterMagickInfo(entry);
927 entry=AcquireMagickInfo("PDF","EPDF",
928 "Encapsulated Portable Document Format");
929 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
930 entry->encoder=(EncodeImageHandler *) WritePDFImage;
931 entry->flags^=CoderAdjoinFlag;
932 entry->flags^=CoderBlobSupportFlag;
933 entry->mime_type=ConstantString("application/pdf");
934 (void) RegisterMagickInfo(entry);
935 entry=AcquireMagickInfo("PDF","PDF","Portable Document Format");
936 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
937 entry->encoder=(EncodeImageHandler *) WritePDFImage;
938 entry->magick=(IsImageFormatHandler *) IsPDF;
939 entry->flags^=CoderBlobSupportFlag;
940 entry->mime_type=ConstantString("application/pdf");
941 (void) RegisterMagickInfo(entry);
942 entry=AcquireMagickInfo("PDF","PDFA","Portable Document Archive Format");
943 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
944 entry->encoder=(EncodeImageHandler *) WritePDFImage;
945 entry->magick=(IsImageFormatHandler *) IsPDF;
946 entry->flags^=CoderBlobSupportFlag;
947 entry->mime_type=ConstantString("application/pdf");
948 (void) RegisterMagickInfo(entry);
949 return(MagickImageCoderSignature);
953 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
957 % U n r e g i s t e r P D F I m a g e %
961 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
963 % UnregisterPDFImage() removes format registrations made by the
964 % PDF module from the list of supported formats.
966 % The format of the UnregisterPDFImage method is:
968 % UnregisterPDFImage(void)
971 ModuleExport void UnregisterPDFImage(void)
973 (void) UnregisterMagickInfo("AI");
974 (void) UnregisterMagickInfo("EPDF");
975 (void) UnregisterMagickInfo("PDF");
976 (void) UnregisterMagickInfo("PDFA");
980 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
984 % W r i t e P D F I m a g e %
988 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
990 % WritePDFImage() writes an image in the Portable Document image
993 % The format of the WritePDFImage method is:
995 % MagickBooleanType WritePDFImage(const ImageInfo *image_info,
996 % Image *image,ExceptionInfo *exception)
998 % A description of each parameter follows.
1000 % o image_info: the image info.
1002 % o image: The image.
1004 % o exception: return any errors or warnings in this structure.
1008 static char *EscapeParenthesis(const char *source)
1022 assert(source != (const char *) NULL);
1024 for (p=source; *p != '\0'; p++)
1026 if ((*p == '\\') || (*p == '(') || (*p == ')'))
1029 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
1034 destination=(char *) NULL;
1035 if (~length >= (MagickPathExtent-1))
1036 destination=(char *) AcquireQuantumMemory(length+MagickPathExtent,
1037 sizeof(*destination));
1038 if (destination == (char *) NULL)
1039 ThrowFatalException(ResourceLimitFatalError,"UnableToEscapeString");
1042 for (p=source; *p != '\0'; p++)
1044 if ((*p == '\\') || (*p == '(') || (*p == ')'))
1049 return(destination);
1052 static size_t UTF8ToUTF16(const unsigned char *utf8,wchar_t *utf16)
1054 register const unsigned char
1057 if (utf16 != (wchar_t *) NULL)
1066 Convert UTF-8 to UTF-16.
1069 for (p=utf8; *p != '\0'; p++)
1071 if ((*p & 0x80) == 0)
1074 if ((*p & 0xE0) == 0xC0)
1079 if ((*p & 0xC0) != 0x80)
1084 if ((*p & 0xF0) == 0xE0)
1089 if ((*p & 0xC0) != 0x80)
1092 *q|=(c & 0x3F) << 6;
1094 if ((*p & 0xC0) != 0x80)
1102 *q++=(wchar_t) '\0';
1103 return((size_t) (q-utf16));
1106 Compute UTF-16 string length.
1108 for (p=utf8; *p != '\0'; p++)
1110 if ((*p & 0x80) == 0)
1113 if ((*p & 0xE0) == 0xC0)
1116 if ((*p & 0xC0) != 0x80)
1120 if ((*p & 0xF0) == 0xE0)
1123 if ((*p & 0xC0) != 0x80)
1126 if ((*p & 0xC0) != 0x80)
1132 return((size_t) (p-utf8));
1135 static wchar_t *ConvertUTF8ToUTF16(const unsigned char *source,size_t *length)
1140 *length=UTF8ToUTF16(source,(wchar_t *) NULL);
1147 Not UTF-8, just copy.
1149 *length=strlen((const char *) source);
1150 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1151 if (utf16 == (wchar_t *) NULL)
1152 return((wchar_t *) NULL);
1153 for (i=0; i <= (ssize_t) *length; i++)
1157 utf16=(wchar_t *) AcquireQuantumMemory(*length+1,sizeof(*utf16));
1158 if (utf16 == (wchar_t *) NULL)
1159 return((wchar_t *) NULL);
1160 *length=UTF8ToUTF16(source,utf16);
1164 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
1165 Image *image,Image *inject_image,ExceptionInfo *exception)
1183 write_info=CloneImageInfo(image_info);
1184 (void) CopyMagickString(write_info->filename,"GROUP4:",MagickPathExtent);
1185 (void) CopyMagickString(write_info->magick,"GROUP4",MagickPathExtent);
1186 group4_image=CloneImage(inject_image,0,0,MagickTrue,exception);
1187 if (group4_image == (Image *) NULL)
1188 return(MagickFalse);
1189 group4=(unsigned char *) ImageToBlob(write_info,group4_image,&length,
1191 group4_image=DestroyImage(group4_image);
1192 if (group4 == (unsigned char *) NULL)
1193 return(MagickFalse);
1194 write_info=DestroyImageInfo(write_info);
1195 if (WriteBlob(image,length,group4) != (ssize_t) length)
1197 group4=(unsigned char *) RelinquishMagickMemory(group4);
1201 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image,
1202 ExceptionInfo *exception)
1204 #define CFormat "/Filter [ /%s ]\n"
1205 #define ObjectsPerImage 14
1206 #define ThrowPDFException(exception,message) \
1208 if (xref != (MagickOffsetType *) NULL) \
1209 xref=(MagickOffsetType *) RelinquishMagickMemory(xref); \
1210 ThrowWriterException((exception),(message)); \
1213 DisableMSCWarning(4310)
1217 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
1218 "<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"
1219 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
1220 " <rdf:Description rdf:about=\"\"\n"
1221 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
1222 " <xap:ModifyDate>%s</xap:ModifyDate>\n"
1223 " <xap:CreateDate>%s</xap:CreateDate>\n"
1224 " <xap:MetadataDate>%s</xap:MetadataDate>\n"
1225 " <xap:CreatorTool>%s</xap:CreatorTool>\n"
1226 " </rdf:Description>\n"
1227 " <rdf:Description rdf:about=\"\"\n"
1228 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
1229 " <dc:format>application/pdf</dc:format>\n"
1232 " <rdf:li xml:lang=\"x-default\">%s</rdf:li>\n"
1235 " </rdf:Description>\n"
1236 " <rdf:Description rdf:about=\"\"\n"
1237 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
1238 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
1239 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
1240 " </rdf:Description>\n"
1241 " <rdf:Description rdf:about=\"\"\n"
1242 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
1243 " <pdf:Producer>%s</pdf:Producer>\n"
1244 " </rdf:Description>\n"
1245 " <rdf:Description rdf:about=\"\"\n"
1246 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
1247 " <pdfaid:part>3</pdfaid:part>\n"
1248 " <pdfaid:conformance>B</pdfaid:conformance>\n"
1249 " </rdf:Description>\n"
1252 "<?xpacket end=\"w\"?>\n"
1254 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
1258 basename[MagickPathExtent],
1259 buffer[MagickPathExtent],
1261 date[MagickPathExtent],
1263 page_geometry[MagickPathExtent],
1311 register const Quantum
1314 register unsigned char
1350 Open output image file.
1352 assert(image_info != (const ImageInfo *) NULL);
1353 assert(image_info->signature == MagickCoreSignature);
1354 assert(image != (Image *) NULL);
1355 assert(image->signature == MagickCoreSignature);
1356 if (image->debug != MagickFalse)
1357 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1358 assert(exception != (ExceptionInfo *) NULL);
1359 assert(exception->signature == MagickCoreSignature);
1360 status=OpenBlob(image_info,image,WriteBinaryBlobMode,exception);
1361 if (status == MagickFalse)
1364 Allocate X ref memory.
1366 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
1367 if (xref == (MagickOffsetType *) NULL)
1368 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1369 (void) memset(xref,0,2048UL*sizeof(*xref));
1375 if (image_info->compression == JPEG2000Compression)
1376 version=(size_t) MagickMax(version,5);
1377 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1378 if (next->alpha_trait != UndefinedPixelTrait)
1379 version=(size_t) MagickMax(version,4);
1380 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1381 version=(size_t) MagickMax(version,6);
1382 profile=GetImageProfile(image,"icc");
1383 if (profile != (StringInfo *) NULL)
1384 version=(size_t) MagickMax(version,7);
1385 (void) FormatLocaleString(buffer,MagickPathExtent,"%%PDF-1.%.20g \n",(double)
1387 (void) WriteBlobString(image,buffer);
1388 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1390 (void) WriteBlobByte(image,'%');
1391 (void) WriteBlobByte(image,0xe2);
1392 (void) WriteBlobByte(image,0xe3);
1393 (void) WriteBlobByte(image,0xcf);
1394 (void) WriteBlobByte(image,0xd3);
1395 (void) WriteBlobByte(image,'\n');
1398 Write Catalog object.
1400 xref[object++]=TellBlob(image);
1402 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1404 (void) WriteBlobString(image,buffer);
1405 (void) WriteBlobString(image,"<<\n");
1406 if (LocaleCompare(image_info->magick,"PDFA") != 0)
1407 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1411 (void) FormatLocaleString(buffer,MagickPathExtent,"/Metadata %.20g 0 R\n",
1413 (void) WriteBlobString(image,buffer);
1414 (void) FormatLocaleString(buffer,MagickPathExtent,"/Pages %.20g 0 R\n",
1417 (void) WriteBlobString(image,buffer);
1418 (void) WriteBlobString(image,"/Type /Catalog");
1419 option=GetImageOption(image_info,"pdf:page-direction");
1420 if ((option != (const char *) NULL) &&
1421 (LocaleCompare(option,"right-to-left") == 0))
1422 (void) WriteBlobString(image,"/ViewerPreferences<</PageDirection/R2L>>\n");
1423 (void) WriteBlobString(image,"\n");
1424 (void) WriteBlobString(image,">>\n");
1425 (void) WriteBlobString(image,"endobj\n");
1426 GetPathComponent(image->filename,BasePath,basename);
1427 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1430 create_date[MagickPathExtent],
1431 modify_date[MagickPathExtent],
1432 timestamp[MagickPathExtent],
1434 xmp_profile[MagickPathExtent];
1439 xref[object++]=TellBlob(image);
1440 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1442 (void) WriteBlobString(image,buffer);
1443 (void) WriteBlobString(image,"<<\n");
1444 (void) WriteBlobString(image,"/Subtype /XML\n");
1446 value=GetImageProperty(image,"date:modify",exception);
1447 if (value != (const char *) NULL)
1448 (void) CopyMagickString(modify_date,value,MagickPathExtent);
1450 value=GetImageProperty(image,"date:create",exception);
1451 if (value != (const char *) NULL)
1452 (void) CopyMagickString(create_date,value,MagickPathExtent);
1453 (void) FormatMagickTime(time((time_t *) NULL),MagickPathExtent,timestamp);
1454 url=MagickAuthoritativeURL;
1455 escape=EscapeParenthesis(basename);
1456 i=FormatLocaleString(xmp_profile,MagickPathExtent,XMPProfile,
1457 XMPProfileMagick,modify_date,create_date,timestamp,url,escape,url);
1458 escape=DestroyString(escape);
1459 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g\n",
1461 (void) WriteBlobString(image,buffer);
1462 (void) WriteBlobString(image,"/Type /Metadata\n");
1463 (void) WriteBlobString(image,">>\nstream\n");
1464 (void) WriteBlobString(image,xmp_profile);
1465 (void) WriteBlobString(image,"\nendstream\n");
1466 (void) WriteBlobString(image,"endobj\n");
1471 xref[object++]=TellBlob(image);
1473 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1475 (void) WriteBlobString(image,buffer);
1476 (void) WriteBlobString(image,"<<\n");
1477 (void) WriteBlobString(image,"/Type /Pages\n");
1478 (void) FormatLocaleString(buffer,MagickPathExtent,"/Kids [ %.20g 0 R ",
1480 (void) WriteBlobString(image,buffer);
1481 count=(ssize_t) (pages_id+ObjectsPerImage+1);
1483 if (image_info->adjoin != MagickFalse)
1489 Predict page object id's.
1492 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1495 profile=GetImageProfile(kid_image,"icc");
1496 if (profile != (StringInfo *) NULL)
1498 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 R ",(double)
1500 (void) WriteBlobString(image,buffer);
1501 kid_image=GetNextImageInList(kid_image);
1503 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1505 if (xref == (MagickOffsetType *) NULL)
1506 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1508 (void) WriteBlobString(image,"]\n");
1509 (void) FormatLocaleString(buffer,MagickPathExtent,"/Count %.20g\n",(double)
1511 (void) WriteBlobString(image,buffer);
1512 (void) WriteBlobString(image,">>\n");
1513 (void) WriteBlobString(image,"endobj\n");
1515 imageListLength=GetImageListLength(image);
1521 profile=GetImageProfile(image,"icc");
1522 has_icc_profile=(profile != (StringInfo *) NULL) ? MagickTrue : MagickFalse;
1523 compression=image->compression;
1524 if (image_info->compression != UndefinedCompression)
1525 compression=image_info->compression;
1526 switch (compression)
1528 case FaxCompression:
1529 case Group4Compression:
1531 if ((SetImageMonochrome(image,exception) == MagickFalse) ||
1532 (image->alpha_trait != UndefinedPixelTrait))
1533 compression=RLECompression;
1536 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1537 case JPEGCompression:
1539 compression=RLECompression;
1540 (void) ThrowMagickException(exception,GetMagickModule(),
1541 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1546 #if !defined(MAGICKCORE_LIBOPENJP2_DELEGATE)
1547 case JPEG2000Compression:
1549 compression=RLECompression;
1550 (void) ThrowMagickException(exception,GetMagickModule(),
1551 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1556 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1557 case ZipCompression:
1559 compression=RLECompression;
1560 (void) ThrowMagickException(exception,GetMagickModule(),
1561 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1566 case LZWCompression:
1568 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1569 compression=RLECompression; /* LZW compression is forbidden */
1574 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1575 compression=RLECompression; /* ASCII 85 compression is forbidden */
1581 if (compression == JPEG2000Compression)
1582 (void) TransformImageColorspace(image,sRGBColorspace,exception);
1584 Scale relative to dots-per-inch.
1586 delta.x=DefaultResolution;
1587 delta.y=DefaultResolution;
1588 resolution.x=image->resolution.x;
1589 resolution.y=image->resolution.y;
1590 if ((resolution.x == 0.0) || (resolution.y == 0.0))
1592 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1593 resolution.x=geometry_info.rho;
1594 resolution.y=geometry_info.sigma;
1595 if ((flags & SigmaValue) == 0)
1596 resolution.y=resolution.x;
1598 if (image_info->density != (char *) NULL)
1600 flags=ParseGeometry(image_info->density,&geometry_info);
1601 resolution.x=geometry_info.rho;
1602 resolution.y=geometry_info.sigma;
1603 if ((flags & SigmaValue) == 0)
1604 resolution.y=resolution.x;
1606 if (image->units == PixelsPerCentimeterResolution)
1608 resolution.x=(double) ((size_t) (100.0*2.54*resolution.x+0.5)/100.0);
1609 resolution.y=(double) ((size_t) (100.0*2.54*resolution.y+0.5)/100.0);
1611 SetGeometry(image,&geometry);
1612 (void) FormatLocaleString(page_geometry,MagickPathExtent,"%.20gx%.20g",
1613 (double) image->columns,(double) image->rows);
1614 if (image_info->page != (char *) NULL)
1615 (void) CopyMagickString(page_geometry,image_info->page,MagickPathExtent);
1617 if ((image->page.width != 0) && (image->page.height != 0))
1618 (void) FormatLocaleString(page_geometry,MagickPathExtent,
1619 "%.20gx%.20g%+.20g%+.20g",(double) image->page.width,(double)
1620 image->page.height,(double) image->page.x,(double) image->page.y);
1622 if ((image->gravity != UndefinedGravity) &&
1623 (LocaleCompare(image_info->magick,"PDF") == 0))
1624 (void) CopyMagickString(page_geometry,PSPageGeometry,
1626 (void) ConcatenateMagickString(page_geometry,">",MagickPathExtent);
1627 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1628 &geometry.width,&geometry.height);
1629 scale.x=(double) (geometry.width*delta.x)/resolution.x;
1630 geometry.width=(size_t) floor(scale.x+0.5);
1631 scale.y=(double) (geometry.height*delta.y)/resolution.y;
1632 geometry.height=(size_t) floor(scale.y+0.5);
1633 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1634 (void) ParseGravityGeometry(image,page_geometry,&page_info,exception);
1635 if (image->gravity != UndefinedGravity)
1637 geometry.x=(-page_info.x);
1638 geometry.y=(ssize_t) (media_info.height+page_info.y-image->rows);
1641 if (image_info->pointsize != 0.0)
1642 pointsize=image_info->pointsize;
1644 value=GetImageProperty(image,"label",exception);
1645 if (value != (const char *) NULL)
1646 text_size=(size_t) (MultilineCensus(value)*pointsize+12);
1651 xref[object++]=TellBlob(image);
1652 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1654 (void) WriteBlobString(image,buffer);
1655 (void) WriteBlobString(image,"<<\n");
1656 (void) WriteBlobString(image,"/Type /Page\n");
1657 (void) FormatLocaleString(buffer,MagickPathExtent,"/Parent %.20g 0 R\n",
1659 (void) WriteBlobString(image,buffer);
1660 (void) WriteBlobString(image,"/Resources <<\n");
1661 labels=(char **) NULL;
1662 value=GetImageProperty(image,"label",exception);
1663 if (value != (const char *) NULL)
1664 labels=StringToList(value);
1665 if (labels != (char **) NULL)
1667 (void) FormatLocaleString(buffer,MagickPathExtent,
1668 "/Font << /F%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1670 (void) WriteBlobString(image,buffer);
1672 (void) FormatLocaleString(buffer,MagickPathExtent,
1673 "/XObject << /Im%.20g %.20g 0 R >>\n",(double) image->scene,(double)
1675 (void) WriteBlobString(image,buffer);
1676 (void) FormatLocaleString(buffer,MagickPathExtent,"/ProcSet %.20g 0 R >>\n",
1678 (void) WriteBlobString(image,buffer);
1679 (void) FormatLocaleString(buffer,MagickPathExtent,
1680 "/MediaBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1681 72.0*media_info.height/resolution.y);
1682 (void) WriteBlobString(image,buffer);
1683 (void) FormatLocaleString(buffer,MagickPathExtent,
1684 "/CropBox [0 0 %g %g]\n",72.0*media_info.width/resolution.x,
1685 72.0*media_info.height/resolution.y);
1686 (void) WriteBlobString(image,buffer);
1687 (void) FormatLocaleString(buffer,MagickPathExtent,"/Contents %.20g 0 R\n",
1689 (void) WriteBlobString(image,buffer);
1690 (void) FormatLocaleString(buffer,MagickPathExtent,"/Thumb %.20g 0 R\n",
1691 (double) object+(has_icc_profile != MagickFalse ? 10 : 8));
1692 (void) WriteBlobString(image,buffer);
1693 (void) WriteBlobString(image,">>\n");
1694 (void) WriteBlobString(image,"endobj\n");
1696 Write Contents object.
1698 xref[object++]=TellBlob(image);
1699 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1701 (void) WriteBlobString(image,buffer);
1702 (void) WriteBlobString(image,"<<\n");
1703 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1705 (void) WriteBlobString(image,buffer);
1706 (void) WriteBlobString(image,">>\n");
1707 (void) WriteBlobString(image,"stream\n");
1708 offset=TellBlob(image);
1709 (void) WriteBlobString(image,"q\n");
1710 if (labels != (char **) NULL)
1711 for (i=0; labels[i] != (char *) NULL; i++)
1713 (void) WriteBlobString(image,"BT\n");
1714 (void) FormatLocaleString(buffer,MagickPathExtent,"/F%.20g %g Tf\n",
1715 (double) image->scene,pointsize);
1716 (void) WriteBlobString(image,buffer);
1717 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g %.20g Td\n",
1718 (double) geometry.x,(double) (geometry.y+geometry.height+i*pointsize+
1720 (void) WriteBlobString(image,buffer);
1721 (void) FormatLocaleString(buffer,MagickPathExtent,"(%s) Tj\n",
1723 (void) WriteBlobString(image,buffer);
1724 (void) WriteBlobString(image,"ET\n");
1725 labels[i]=DestroyString(labels[i]);
1727 (void) FormatLocaleString(buffer,MagickPathExtent,
1728 "%g 0 0 %g %.20g %.20g cm\n",scale.x,scale.y,(double) geometry.x,
1729 (double) geometry.y);
1730 (void) WriteBlobString(image,buffer);
1731 (void) FormatLocaleString(buffer,MagickPathExtent,"/Im%.20g Do\n",(double)
1733 (void) WriteBlobString(image,buffer);
1734 (void) WriteBlobString(image,"Q\n");
1735 offset=TellBlob(image)-offset;
1736 (void) WriteBlobString(image,"\nendstream\n");
1737 (void) WriteBlobString(image,"endobj\n");
1739 Write Length object.
1741 xref[object++]=TellBlob(image);
1742 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1744 (void) WriteBlobString(image,buffer);
1745 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
1747 (void) WriteBlobString(image,buffer);
1748 (void) WriteBlobString(image,"endobj\n");
1750 Write Procset object.
1752 xref[object++]=TellBlob(image);
1753 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1755 (void) WriteBlobString(image,buffer);
1756 if ((image->storage_class == DirectClass) || (image->colors > 256))
1757 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MagickPathExtent);
1759 if ((compression == FaxCompression) || (compression == Group4Compression))
1760 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MagickPathExtent);
1762 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MagickPathExtent);
1763 (void) WriteBlobString(image,buffer);
1764 (void) WriteBlobString(image," ]\n");
1765 (void) WriteBlobString(image,"endobj\n");
1769 xref[object++]=TellBlob(image);
1770 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1772 (void) WriteBlobString(image,buffer);
1773 (void) WriteBlobString(image,"<<\n");
1774 if (labels != (char **) NULL)
1776 (void) WriteBlobString(image,"/Type /Font\n");
1777 (void) WriteBlobString(image,"/Subtype /Type1\n");
1778 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /F%.20g\n",
1779 (double) image->scene);
1780 (void) WriteBlobString(image,buffer);
1781 (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1782 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1783 labels=(char **) RelinquishMagickMemory(labels);
1785 (void) WriteBlobString(image,">>\n");
1786 (void) WriteBlobString(image,"endobj\n");
1788 Write XObject object.
1790 xref[object++]=TellBlob(image);
1791 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
1793 (void) WriteBlobString(image,buffer);
1794 (void) WriteBlobString(image,"<<\n");
1795 (void) WriteBlobString(image,"/Type /XObject\n");
1796 (void) WriteBlobString(image,"/Subtype /Image\n");
1797 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Im%.20g\n",
1798 (double) image->scene);
1799 (void) WriteBlobString(image,buffer);
1800 switch (compression)
1804 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1808 case JPEGCompression:
1810 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
1811 if (image->colorspace != CMYKColorspace)
1813 (void) WriteBlobString(image,buffer);
1814 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1818 case JPEG2000Compression:
1820 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
1821 if (image->colorspace != CMYKColorspace)
1823 (void) WriteBlobString(image,buffer);
1824 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1828 case LZWCompression:
1830 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
1833 case ZipCompression:
1835 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1839 case FaxCompression:
1840 case Group4Compression:
1842 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1844 (void) WriteBlobString(image,buffer);
1845 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
1846 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
1847 (double) image->columns,(double) image->rows);
1852 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
1857 (void) WriteBlobString(image,buffer);
1858 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
1860 (void) WriteBlobString(image,buffer);
1861 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
1863 (void) WriteBlobString(image,buffer);
1864 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
1866 (void) WriteBlobString(image,buffer);
1867 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
1868 (compression == FaxCompression) || (compression == Group4Compression) ?
1870 (void) WriteBlobString(image,buffer);
1871 if (image->alpha_trait != UndefinedPixelTrait)
1873 (void) FormatLocaleString(buffer,MagickPathExtent,"/SMask %.20g 0 R\n",
1874 (double) object+(has_icc_profile != MagickFalse ? 9 : 7));
1875 (void) WriteBlobString(image,buffer);
1877 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
1879 (void) WriteBlobString(image,buffer);
1880 (void) WriteBlobString(image,">>\n");
1881 (void) WriteBlobString(image,"stream\n");
1882 offset=TellBlob(image);
1883 number_pixels=(MagickSizeType) image->columns*image->rows;
1884 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1885 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
1886 if ((compression == FaxCompression) || (compression == Group4Compression) ||
1887 ((image_info->type != TrueColorType) &&
1888 (SetImageGray(image,exception) != MagickFalse)))
1890 switch (compression)
1892 case FaxCompression:
1893 case Group4Compression:
1895 if (LocaleCompare(CCITTParam,"0") == 0)
1897 (void) HuffmanEncodeImage(image_info,image,image,exception);
1900 (void) Huffman2DEncodeImage(image_info,image,image,exception);
1903 case JPEGCompression:
1905 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
1906 if (status == MagickFalse)
1908 (void) CloseBlob(image);
1909 return(MagickFalse);
1913 case JPEG2000Compression:
1915 status=InjectImageBlob(image_info,image,image,"jp2",exception);
1916 if (status == MagickFalse)
1918 (void) CloseBlob(image);
1919 return(MagickFalse);
1923 case RLECompression:
1930 Allocate pixel array.
1932 length=(size_t) number_pixels;
1933 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
1934 if (pixel_info == (MemoryInfo *) NULL)
1935 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
1936 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
1938 Dump Runlength encoded pixels.
1941 for (y=0; y < (ssize_t) image->rows; y++)
1943 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1944 if (p == (const Quantum *) NULL)
1946 for (x=0; x < (ssize_t) image->columns; x++)
1948 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(image,p)));
1949 p+=GetPixelChannels(image);
1951 if (image->previous == (Image *) NULL)
1953 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1955 if (status == MagickFalse)
1959 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1960 if (compression == ZipCompression)
1961 status=ZLIBEncodeImage(image,length,pixels,exception);
1964 if (compression == LZWCompression)
1965 status=LZWEncodeImage(image,length,pixels,exception);
1967 status=PackbitsEncodeImage(image,length,pixels,exception);
1968 pixel_info=RelinquishVirtualMemory(pixel_info);
1969 if (status == MagickFalse)
1971 (void) CloseBlob(image);
1972 return(MagickFalse);
1979 Dump uncompressed PseudoColor packets.
1981 Ascii85Initialize(image);
1982 for (y=0; y < (ssize_t) image->rows; y++)
1984 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
1985 if (p == (const Quantum *) NULL)
1987 for (x=0; x < (ssize_t) image->columns; x++)
1989 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
1990 GetPixelLuma(image,p))));
1991 p+=GetPixelChannels(image);
1993 if (image->previous == (Image *) NULL)
1995 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
1997 if (status == MagickFalse)
2001 Ascii85Flush(image);
2007 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2008 (compression == JPEGCompression) ||
2009 (compression == JPEG2000Compression))
2010 switch (compression)
2012 case JPEGCompression:
2014 status=InjectImageBlob(image_info,image,image,"jpeg",exception);
2015 if (status == MagickFalse)
2017 (void) CloseBlob(image);
2018 return(MagickFalse);
2022 case JPEG2000Compression:
2024 status=InjectImageBlob(image_info,image,image,"jp2",exception);
2025 if (status == MagickFalse)
2027 (void) CloseBlob(image);
2028 return(MagickFalse);
2032 case RLECompression:
2039 Allocate pixel array.
2041 length=(size_t) number_pixels;
2042 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
2043 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2044 if (pixel_info == (MemoryInfo *) NULL)
2046 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2047 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2049 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2051 Dump runoffset encoded pixels.
2054 for (y=0; y < (ssize_t) image->rows; y++)
2056 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2057 if (p == (const Quantum *) NULL)
2059 for (x=0; x < (ssize_t) image->columns; x++)
2061 *q++=ScaleQuantumToChar(GetPixelRed(image,p));
2062 *q++=ScaleQuantumToChar(GetPixelGreen(image,p));
2063 *q++=ScaleQuantumToChar(GetPixelBlue(image,p));
2064 if (image->colorspace == CMYKColorspace)
2065 *q++=ScaleQuantumToChar(GetPixelBlack(image,p));
2066 p+=GetPixelChannels(image);
2068 if (image->previous == (Image *) NULL)
2070 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
2072 if (status == MagickFalse)
2076 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2077 if (compression == ZipCompression)
2078 status=ZLIBEncodeImage(image,length,pixels,exception);
2081 if (compression == LZWCompression)
2082 status=LZWEncodeImage(image,length,pixels,exception);
2084 status=PackbitsEncodeImage(image,length,pixels,exception);
2085 pixel_info=RelinquishVirtualMemory(pixel_info);
2086 if (status == MagickFalse)
2088 (void) CloseBlob(image);
2089 return(MagickFalse);
2096 Dump uncompressed DirectColor packets.
2098 Ascii85Initialize(image);
2099 for (y=0; y < (ssize_t) image->rows; y++)
2101 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2102 if (p == (const Quantum *) NULL)
2104 for (x=0; x < (ssize_t) image->columns; x++)
2106 Ascii85Encode(image,ScaleQuantumToChar(GetPixelRed(image,p)));
2107 Ascii85Encode(image,ScaleQuantumToChar(GetPixelGreen(image,p)));
2108 Ascii85Encode(image,ScaleQuantumToChar(GetPixelBlue(image,p)));
2109 if (image->colorspace == CMYKColorspace)
2110 Ascii85Encode(image,ScaleQuantumToChar(
2111 GetPixelBlack(image,p)));
2112 p+=GetPixelChannels(image);
2114 if (image->previous == (Image *) NULL)
2116 status=SetImageProgress(image,SaveImageTag,(MagickOffsetType)
2118 if (status == MagickFalse)
2122 Ascii85Flush(image);
2129 Dump number of colors and colormap.
2131 switch (compression)
2133 case RLECompression:
2140 Allocate pixel array.
2142 length=(size_t) number_pixels;
2143 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2144 if (pixel_info == (MemoryInfo *) NULL)
2146 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2147 ThrowPDFException(ResourceLimitError,
2148 "MemoryAllocationFailed");
2150 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2152 Dump Runlength encoded pixels.
2155 for (y=0; y < (ssize_t) image->rows; y++)
2157 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2158 if (p == (const Quantum *) NULL)
2160 for (x=0; x < (ssize_t) image->columns; x++)
2162 *q++=(unsigned char) GetPixelIndex(image,p);
2163 p+=GetPixelChannels(image);
2165 if (image->previous == (Image *) NULL)
2167 status=SetImageProgress(image,SaveImageTag,
2168 (MagickOffsetType) y,image->rows);
2169 if (status == MagickFalse)
2173 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2174 if (compression == ZipCompression)
2175 status=ZLIBEncodeImage(image,length,pixels,exception);
2178 if (compression == LZWCompression)
2179 status=LZWEncodeImage(image,length,pixels,exception);
2181 status=PackbitsEncodeImage(image,length,pixels,exception);
2182 pixel_info=RelinquishVirtualMemory(pixel_info);
2183 if (status == MagickFalse)
2185 (void) CloseBlob(image);
2186 return(MagickFalse);
2193 Dump uncompressed PseudoColor packets.
2195 Ascii85Initialize(image);
2196 for (y=0; y < (ssize_t) image->rows; y++)
2198 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2199 if (p == (const Quantum *) NULL)
2201 for (x=0; x < (ssize_t) image->columns; x++)
2203 Ascii85Encode(image,(unsigned char) GetPixelIndex(image,p));
2204 p+=GetPixelChannels(image);
2206 if (image->previous == (Image *) NULL)
2208 status=SetImageProgress(image,SaveImageTag,
2209 (MagickOffsetType) y,image->rows);
2210 if (status == MagickFalse)
2214 Ascii85Flush(image);
2219 offset=TellBlob(image)-offset;
2220 (void) WriteBlobString(image,"\nendstream\n");
2221 (void) WriteBlobString(image,"endobj\n");
2223 Write Length object.
2225 xref[object++]=TellBlob(image);
2226 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2228 (void) WriteBlobString(image,buffer);
2229 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2231 (void) WriteBlobString(image,buffer);
2232 (void) WriteBlobString(image,"endobj\n");
2234 Write Colorspace object.
2236 xref[object++]=TellBlob(image);
2237 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2239 (void) WriteBlobString(image,buffer);
2242 if (image->colorspace == CMYKColorspace)
2244 device="DeviceCMYK";
2248 if ((compression == FaxCompression) ||
2249 (compression == Group4Compression) ||
2250 ((image_info->type != TrueColorType) &&
2251 (SetImageGray(image,exception) != MagickFalse)))
2253 device="DeviceGray";
2257 if ((image->storage_class == DirectClass) ||
2258 (image->colors > 256) || (compression == JPEGCompression) ||
2259 (compression == JPEG2000Compression))
2264 profile=GetImageProfile(image,"icc");
2265 if ((profile == (StringInfo *) NULL) || (channels == 0))
2268 (void) FormatLocaleString(buffer,MagickPathExtent,"/%s\n",device);
2270 (void) FormatLocaleString(buffer,MagickPathExtent,
2271 "[ /Indexed /%s %.20g %.20g 0 R ]\n",device,(double) image->colors-
2272 1,(double) object+3);
2273 (void) WriteBlobString(image,buffer);
2283 (void) FormatLocaleString(buffer,MagickPathExtent,
2284 "[/ICCBased %.20g 0 R]\n",(double) object+1);
2285 (void) WriteBlobString(image,buffer);
2286 (void) WriteBlobString(image,"endobj\n");
2287 xref[object++]=TellBlob(image);
2288 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",
2290 (void) WriteBlobString(image,buffer);
2291 (void) FormatLocaleString(buffer,MagickPathExtent,"<<\n/N %.20g\n"
2292 "/Filter /ASCII85Decode\n/Length %.20g 0 R\n/Alternate /%s\n>>\n"
2293 "stream\n",(double) channels,(double) object+1,device);
2294 (void) WriteBlobString(image,buffer);
2295 offset=TellBlob(image);
2296 Ascii85Initialize(image);
2297 p=GetStringInfoDatum(profile);
2298 for (i=0; i < (ssize_t) GetStringInfoLength(profile); i++)
2299 Ascii85Encode(image,(unsigned char) *p++);
2300 Ascii85Flush(image);
2301 offset=TellBlob(image)-offset;
2302 (void) WriteBlobString(image,"endstream\n");
2303 (void) WriteBlobString(image,"endobj\n");
2305 Write Length object.
2307 xref[object++]=TellBlob(image);
2308 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",
2310 (void) WriteBlobString(image,buffer);
2311 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2313 (void) WriteBlobString(image,buffer);
2315 (void) WriteBlobString(image,"endobj\n");
2319 SetGeometry(image,&geometry);
2320 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
2321 &geometry.width,&geometry.height);
2322 tile_image=ThumbnailImage(image,geometry.width,geometry.height,exception);
2323 if (tile_image == (Image *) NULL)
2324 return(MagickFalse);
2325 xref[object++]=TellBlob(image);
2326 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2328 (void) WriteBlobString(image,buffer);
2329 (void) WriteBlobString(image,"<<\n");
2330 switch (compression)
2334 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2338 case JPEGCompression:
2340 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"DCTDecode");
2341 if (image->colorspace != CMYKColorspace)
2343 (void) WriteBlobString(image,buffer);
2344 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2348 case JPEG2000Compression:
2350 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"JPXDecode");
2351 if (image->colorspace != CMYKColorspace)
2353 (void) WriteBlobString(image,buffer);
2354 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
2358 case LZWCompression:
2360 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,"LZWDecode");
2363 case ZipCompression:
2365 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2369 case FaxCompression:
2370 case Group4Compression:
2372 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
2374 (void) WriteBlobString(image,buffer);
2375 (void) FormatLocaleString(buffer,MagickPathExtent,"/DecodeParms [ << "
2376 "/K %s /BlackIs1 false /Columns %.20g /Rows %.20g >> ]\n",CCITTParam,
2377 (double) tile_image->columns,(double) tile_image->rows);
2382 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2387 (void) WriteBlobString(image,buffer);
2388 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",(double)
2389 tile_image->columns);
2390 (void) WriteBlobString(image,buffer);
2391 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",(double)
2393 (void) WriteBlobString(image,buffer);
2394 (void) FormatLocaleString(buffer,MagickPathExtent,"/ColorSpace %.20g 0 R\n",
2395 (double) object-(has_icc_profile != MagickFalse ? 3 : 1));
2396 (void) WriteBlobString(image,buffer);
2397 (void) FormatLocaleString(buffer,MagickPathExtent,"/BitsPerComponent %d\n",
2398 (compression == FaxCompression) || (compression == Group4Compression) ?
2400 (void) WriteBlobString(image,buffer);
2401 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2403 (void) WriteBlobString(image,buffer);
2404 (void) WriteBlobString(image,">>\n");
2405 (void) WriteBlobString(image,"stream\n");
2406 offset=TellBlob(image);
2407 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
2408 if ((compression == FaxCompression) ||
2409 (compression == Group4Compression) ||
2410 ((image_info->type != TrueColorType) &&
2411 (SetImageGray(tile_image,exception) != MagickFalse)))
2413 switch (compression)
2415 case FaxCompression:
2416 case Group4Compression:
2418 if (LocaleCompare(CCITTParam,"0") == 0)
2420 (void) HuffmanEncodeImage(image_info,image,tile_image,
2424 (void) Huffman2DEncodeImage(image_info,image,tile_image,exception);
2427 case JPEGCompression:
2429 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2431 if (status == MagickFalse)
2433 (void) CloseBlob(image);
2434 return(MagickFalse);
2438 case JPEG2000Compression:
2440 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2441 if (status == MagickFalse)
2443 (void) CloseBlob(image);
2444 return(MagickFalse);
2448 case RLECompression:
2455 Allocate pixel array.
2457 length=(size_t) number_pixels;
2458 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2459 if (pixel_info == (MemoryInfo *) NULL)
2461 tile_image=DestroyImage(tile_image);
2462 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2464 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2466 Dump runlength encoded pixels.
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 *q++=ScaleQuantumToChar(ClampToQuantum(GetPixelLuma(
2479 p+=GetPixelChannels(tile_image);
2482 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2483 if (compression == ZipCompression)
2484 status=ZLIBEncodeImage(image,length,pixels,exception);
2487 if (compression == LZWCompression)
2488 status=LZWEncodeImage(image,length,pixels,exception);
2490 status=PackbitsEncodeImage(image,length,pixels,exception);
2491 pixel_info=RelinquishVirtualMemory(pixel_info);
2492 if (status == MagickFalse)
2494 (void) CloseBlob(image);
2495 return(MagickFalse);
2502 Dump uncompressed PseudoColor packets.
2504 Ascii85Initialize(image);
2505 for (y=0; y < (ssize_t) tile_image->rows; y++)
2507 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2509 if (p == (const Quantum *) NULL)
2511 for (x=0; x < (ssize_t) tile_image->columns; x++)
2513 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2514 GetPixelLuma(tile_image,p))));
2515 p+=GetPixelChannels(tile_image);
2518 Ascii85Flush(image);
2524 if ((tile_image->storage_class == DirectClass) ||
2525 (tile_image->colors > 256) || (compression == JPEGCompression) ||
2526 (compression == JPEG2000Compression))
2527 switch (compression)
2529 case JPEGCompression:
2531 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2533 if (status == MagickFalse)
2535 (void) CloseBlob(image);
2536 return(MagickFalse);
2540 case JPEG2000Compression:
2542 status=InjectImageBlob(image_info,image,tile_image,"jp2",exception);
2543 if (status == MagickFalse)
2545 (void) CloseBlob(image);
2546 return(MagickFalse);
2550 case RLECompression:
2557 Allocate pixel array.
2559 length=(size_t) number_pixels;
2560 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2561 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2562 if (pixel_info == (MemoryInfo *) NULL)
2564 tile_image=DestroyImage(tile_image);
2565 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2567 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2569 Dump runlength encoded pixels.
2572 for (y=0; y < (ssize_t) tile_image->rows; y++)
2574 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2576 if (p == (const Quantum *) NULL)
2578 for (x=0; x < (ssize_t) tile_image->columns; x++)
2580 *q++=ScaleQuantumToChar(GetPixelRed(tile_image,p));
2581 *q++=ScaleQuantumToChar(GetPixelGreen(tile_image,p));
2582 *q++=ScaleQuantumToChar(GetPixelBlue(tile_image,p));
2583 if (tile_image->colorspace == CMYKColorspace)
2584 *q++=ScaleQuantumToChar(GetPixelBlack(tile_image,p));
2585 p+=GetPixelChannels(tile_image);
2588 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2589 if (compression == ZipCompression)
2590 status=ZLIBEncodeImage(image,length,pixels,exception);
2593 if (compression == LZWCompression)
2594 status=LZWEncodeImage(image,length,pixels,exception);
2596 status=PackbitsEncodeImage(image,length,pixels,exception);
2597 pixel_info=RelinquishVirtualMemory(pixel_info);
2598 if (status == MagickFalse)
2600 (void) CloseBlob(image);
2601 return(MagickFalse);
2608 Dump uncompressed DirectColor packets.
2610 Ascii85Initialize(image);
2611 for (y=0; y < (ssize_t) tile_image->rows; y++)
2613 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2615 if (p == (const Quantum *) NULL)
2617 for (x=0; x < (ssize_t) tile_image->columns; x++)
2619 Ascii85Encode(image,ScaleQuantumToChar(
2620 GetPixelRed(tile_image,p)));
2621 Ascii85Encode(image,ScaleQuantumToChar(
2622 GetPixelGreen(tile_image,p)));
2623 Ascii85Encode(image,ScaleQuantumToChar(
2624 GetPixelBlue(tile_image,p)));
2625 if (image->colorspace == CMYKColorspace)
2626 Ascii85Encode(image,ScaleQuantumToChar(
2627 GetPixelBlack(tile_image,p)));
2628 p+=GetPixelChannels(tile_image);
2631 Ascii85Flush(image);
2638 Dump number of colors and colormap.
2640 switch (compression)
2642 case RLECompression:
2649 Allocate pixel array.
2651 length=(size_t) number_pixels;
2652 pixel_info=AcquireVirtualMemory(length,sizeof(*pixels));
2653 if (pixel_info == (MemoryInfo *) NULL)
2655 tile_image=DestroyImage(tile_image);
2656 ThrowPDFException(ResourceLimitError,
2657 "MemoryAllocationFailed");
2659 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2661 Dump runlength encoded pixels.
2664 for (y=0; y < (ssize_t) tile_image->rows; y++)
2666 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2668 if (p == (const Quantum *) NULL)
2670 for (x=0; x < (ssize_t) tile_image->columns; x++)
2672 *q++=(unsigned char) GetPixelIndex(tile_image,p);
2673 p+=GetPixelChannels(tile_image);
2676 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2677 if (compression == ZipCompression)
2678 status=ZLIBEncodeImage(image,length,pixels,exception);
2681 if (compression == LZWCompression)
2682 status=LZWEncodeImage(image,length,pixels,exception);
2684 status=PackbitsEncodeImage(image,length,pixels,exception);
2685 pixel_info=RelinquishVirtualMemory(pixel_info);
2686 if (status == MagickFalse)
2688 (void) CloseBlob(image);
2689 return(MagickFalse);
2696 Dump uncompressed PseudoColor packets.
2698 Ascii85Initialize(image);
2699 for (y=0; y < (ssize_t) tile_image->rows; y++)
2701 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2703 if (p == (const Quantum *) NULL)
2705 for (x=0; x < (ssize_t) tile_image->columns; x++)
2707 Ascii85Encode(image,(unsigned char)
2708 GetPixelIndex(tile_image,p));
2709 p+=GetPixelChannels(image);
2712 Ascii85Flush(image);
2717 tile_image=DestroyImage(tile_image);
2718 offset=TellBlob(image)-offset;
2719 (void) WriteBlobString(image,"\nendstream\n");
2720 (void) WriteBlobString(image,"endobj\n");
2722 Write Length object.
2724 xref[object++]=TellBlob(image);
2725 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2727 (void) WriteBlobString(image,buffer);
2728 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2730 (void) WriteBlobString(image,buffer);
2731 (void) WriteBlobString(image,"endobj\n");
2732 xref[object++]=TellBlob(image);
2733 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2735 (void) WriteBlobString(image,buffer);
2736 (void) WriteBlobString(image,"<<\n");
2737 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
2738 (compression == FaxCompression) || (compression == Group4Compression))
2739 (void) WriteBlobString(image,">>\n");
2743 Write Colormap object.
2745 if (compression == NoCompression)
2746 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2747 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2749 (void) WriteBlobString(image,buffer);
2750 (void) WriteBlobString(image,">>\n");
2751 (void) WriteBlobString(image,"stream\n");
2752 offset=TellBlob(image);
2753 if (compression == NoCompression)
2754 Ascii85Initialize(image);
2755 for (i=0; i < (ssize_t) image->colors; i++)
2757 if (compression == NoCompression)
2759 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2760 image->colormap[i].red)));
2761 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2762 image->colormap[i].green)));
2763 Ascii85Encode(image,ScaleQuantumToChar(ClampToQuantum(
2764 image->colormap[i].blue)));
2767 (void) WriteBlobByte(image,ScaleQuantumToChar(
2768 ClampToQuantum(image->colormap[i].red)));
2769 (void) WriteBlobByte(image,ScaleQuantumToChar(
2770 ClampToQuantum(image->colormap[i].green)));
2771 (void) WriteBlobByte(image,ScaleQuantumToChar(
2772 ClampToQuantum(image->colormap[i].blue)));
2774 if (compression == NoCompression)
2775 Ascii85Flush(image);
2776 offset=TellBlob(image)-offset;
2777 (void) WriteBlobString(image,"\nendstream\n");
2779 (void) WriteBlobString(image,"endobj\n");
2781 Write Length object.
2783 xref[object++]=TellBlob(image);
2784 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2786 (void) WriteBlobString(image,buffer);
2787 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2789 (void) WriteBlobString(image,buffer);
2790 (void) WriteBlobString(image,"endobj\n");
2792 Write softmask object.
2794 xref[object++]=TellBlob(image);
2795 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2797 (void) WriteBlobString(image,buffer);
2798 (void) WriteBlobString(image,"<<\n");
2799 if (image->alpha_trait == UndefinedPixelTrait)
2800 (void) WriteBlobString(image,">>\n");
2803 (void) WriteBlobString(image,"/Type /XObject\n");
2804 (void) WriteBlobString(image,"/Subtype /Image\n");
2805 (void) FormatLocaleString(buffer,MagickPathExtent,"/Name /Ma%.20g\n",
2806 (double) image->scene);
2807 (void) WriteBlobString(image,buffer);
2808 switch (compression)
2812 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2816 case LZWCompression:
2818 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2822 case ZipCompression:
2824 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2830 (void) FormatLocaleString(buffer,MagickPathExtent,CFormat,
2835 (void) WriteBlobString(image,buffer);
2836 (void) FormatLocaleString(buffer,MagickPathExtent,"/Width %.20g\n",
2837 (double) image->columns);
2838 (void) WriteBlobString(image,buffer);
2839 (void) FormatLocaleString(buffer,MagickPathExtent,"/Height %.20g\n",
2840 (double) image->rows);
2841 (void) WriteBlobString(image,buffer);
2842 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2843 (void) FormatLocaleString(buffer,MagickPathExtent,
2844 "/BitsPerComponent %d\n",(compression == FaxCompression) ||
2845 (compression == Group4Compression) ? 1 : 8);
2846 (void) WriteBlobString(image,buffer);
2847 (void) FormatLocaleString(buffer,MagickPathExtent,"/Length %.20g 0 R\n",
2849 (void) WriteBlobString(image,buffer);
2850 (void) WriteBlobString(image,">>\n");
2851 (void) WriteBlobString(image,"stream\n");
2852 offset=TellBlob(image);
2853 number_pixels=(MagickSizeType) image->columns*image->rows;
2854 switch (compression)
2856 case RLECompression:
2863 Allocate pixel array.
2865 length=(size_t) number_pixels;
2866 pixel_info=AcquireVirtualMemory(length,4*sizeof(*pixels));
2867 if (pixel_info == (MemoryInfo *) NULL)
2869 image=DestroyImage(image);
2870 ThrowPDFException(ResourceLimitError,"MemoryAllocationFailed");
2872 pixels=(unsigned char *) GetVirtualMemoryBlob(pixel_info);
2874 Dump Runlength encoded pixels.
2877 for (y=0; y < (ssize_t) image->rows; y++)
2879 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2880 if (p == (const Quantum *) NULL)
2882 for (x=0; x < (ssize_t) image->columns; x++)
2884 *q++=ScaleQuantumToChar(GetPixelAlpha(image,p));
2885 p+=GetPixelChannels(image);
2888 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2889 if (compression == ZipCompression)
2890 status=ZLIBEncodeImage(image,length,pixels,exception);
2893 if (compression == LZWCompression)
2894 status=LZWEncodeImage(image,length,pixels,exception);
2896 status=PackbitsEncodeImage(image,length,pixels,exception);
2897 pixel_info=RelinquishVirtualMemory(pixel_info);
2898 if (status == MagickFalse)
2900 (void) CloseBlob(image);
2901 return(MagickFalse);
2908 Dump uncompressed PseudoColor packets.
2910 Ascii85Initialize(image);
2911 for (y=0; y < (ssize_t) image->rows; y++)
2913 p=GetVirtualPixels(image,0,y,image->columns,1,exception);
2914 if (p == (const Quantum *) NULL)
2916 for (x=0; x < (ssize_t) image->columns; x++)
2918 Ascii85Encode(image,ScaleQuantumToChar(GetPixelAlpha(image,p)));
2919 p+=GetPixelChannels(image);
2922 Ascii85Flush(image);
2926 offset=TellBlob(image)-offset;
2927 (void) WriteBlobString(image,"\nendstream\n");
2929 (void) WriteBlobString(image,"endobj\n");
2931 Write Length object.
2933 xref[object++]=TellBlob(image);
2934 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2936 (void) WriteBlobString(image,buffer);
2937 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double)
2939 (void) WriteBlobString(image,buffer);
2940 (void) WriteBlobString(image,"endobj\n");
2941 if (GetNextImageInList(image) == (Image *) NULL)
2943 image=SyncNextImageInList(image);
2944 status=SetImageProgress(image,SaveImagesTag,scene++,imageListLength);
2945 if (status == MagickFalse)
2947 } while (image_info->adjoin != MagickFalse);
2949 Write Metadata object.
2951 xref[object++]=TellBlob(image);
2953 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g 0 obj\n",(double)
2955 (void) WriteBlobString(image,buffer);
2956 (void) WriteBlobString(image,"<<\n");
2957 utf16=ConvertUTF8ToUTF16((unsigned char *) basename,&length);
2958 if (utf16 != (wchar_t *) NULL)
2960 (void) FormatLocaleString(buffer,MagickPathExtent,"/Title (\xfe\xff");
2961 (void) WriteBlobString(image,buffer);
2962 for (i=0; i < (ssize_t) length; i++)
2963 (void) WriteBlobMSBShort(image,(unsigned short) utf16[i]);
2964 (void) FormatLocaleString(buffer,MagickPathExtent,")\n");
2965 (void) WriteBlobString(image,buffer);
2966 utf16=(wchar_t *) RelinquishMagickMemory(utf16);
2968 seconds=time((time_t *) NULL);
2969 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2970 (void) localtime_r(&seconds,&local_time);
2972 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2974 (void) FormatLocaleString(date,MagickPathExtent,"D:%04d%02d%02d%02d%02d%02d",
2975 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2976 local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2977 (void) FormatLocaleString(buffer,MagickPathExtent,"/CreationDate (%s)\n",
2979 (void) WriteBlobString(image,buffer);
2980 (void) FormatLocaleString(buffer,MagickPathExtent,"/ModDate (%s)\n",date);
2981 (void) WriteBlobString(image,buffer);
2982 url=MagickAuthoritativeURL;
2983 escape=EscapeParenthesis(url);
2984 (void) FormatLocaleString(buffer,MagickPathExtent,"/Producer (%s)\n",escape);
2985 escape=DestroyString(escape);
2986 (void) WriteBlobString(image,buffer);
2987 (void) WriteBlobString(image,">>\n");
2988 (void) WriteBlobString(image,"endobj\n");
2992 offset=TellBlob(image)-xref[0]+
2993 (LocaleCompare(image_info->magick,"PDFA") == 0 ? 6 : 0)+10;
2994 (void) WriteBlobString(image,"xref\n");
2995 (void) FormatLocaleString(buffer,MagickPathExtent,"0 %.20g\n",(double)
2997 (void) WriteBlobString(image,buffer);
2998 (void) WriteBlobString(image,"0000000000 65535 f \n");
2999 for (i=0; i < (ssize_t) object; i++)
3001 (void) FormatLocaleString(buffer,MagickPathExtent,"%010lu 00000 n \n",
3002 (unsigned long) xref[i]);
3003 (void) WriteBlobString(image,buffer);
3005 (void) WriteBlobString(image,"trailer\n");
3006 (void) WriteBlobString(image,"<<\n");
3007 (void) FormatLocaleString(buffer,MagickPathExtent,"/Size %.20g\n",(double)
3009 (void) WriteBlobString(image,buffer);
3010 (void) FormatLocaleString(buffer,MagickPathExtent,"/Info %.20g 0 R\n",(double)
3012 (void) WriteBlobString(image,buffer);
3013 (void) FormatLocaleString(buffer,MagickPathExtent,"/Root %.20g 0 R\n",(double)
3015 (void) WriteBlobString(image,buffer);
3016 (void) SignatureImage(image,exception);
3017 (void) FormatLocaleString(buffer,MagickPathExtent,"/ID [<%s> <%s>]\n",
3018 GetImageProperty(image,"signature",exception),
3019 GetImageProperty(image,"signature",exception));
3020 (void) WriteBlobString(image,buffer);
3021 (void) WriteBlobString(image,">>\n");
3022 (void) WriteBlobString(image,"startxref\n");
3023 (void) FormatLocaleString(buffer,MagickPathExtent,"%.20g\n",(double) offset);
3024 (void) WriteBlobString(image,buffer);
3025 (void) WriteBlobString(image,"%%EOF\n");
3026 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
3027 (void) CloseBlob(image);