2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
13 % Read/Write Portable Document Format %
20 % Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization %
21 % dedicated to making software imaging solutions freely available. %
23 % You may not use this file except in compliance with the License. You may %
24 % obtain a copy of the License at %
26 % http://www.imagemagick.org/script/license.php %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/blob-private.h"
45 #include "magick/cache.h"
46 #include "magick/color.h"
47 #include "magick/color-private.h"
48 #include "magick/colorspace.h"
49 #include "magick/compress.h"
50 #include "magick/constitute.h"
51 #include "magick/delegate.h"
52 #include "magick/delegate-private.h"
53 #include "magick/draw.h"
54 #include "magick/exception.h"
55 #include "magick/exception-private.h"
56 #include "magick/geometry.h"
57 #include "magick/image.h"
58 #include "magick/image-private.h"
59 #include "magick/list.h"
60 #include "magick/magick.h"
61 #include "magick/memory_.h"
62 #include "magick/monitor.h"
63 #include "magick/monitor-private.h"
64 #include "magick/option.h"
65 #include "magick/profile.h"
66 #include "magick/property.h"
67 #include "magick/quantum-private.h"
68 #include "magick/resource_.h"
69 #include "magick/resize.h"
70 #include "magick/static.h"
71 #include "magick/string_.h"
72 #include "magick/module.h"
73 #include "magick/transform.h"
74 #include "magick/utility.h"
75 #include "magick/module.h"
76 #if defined(MAGICKCORE_TIFF_DELEGATE)
77 #define CCITTParam "-1"
79 #define CCITTParam "0"
85 static MagickBooleanType
86 WritePDFImage(const ImageInfo *,Image *);
89 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
93 % I n v o k e P o s t s r i p t D e l e g a t e %
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
99 % InvokePostscriptDelegate() executes the postscript interpreter with the
102 % The format of the InvokePostscriptDelegate method is:
104 % MagickBooleanType InvokePostscriptDelegate(
105 % const MagickBooleanType verbose,const char *command,
106 % ExceptionInfo *exception)
108 % A description of each parameter follows:
110 % o verbose: A value other than zero displays the command prior to
113 % o command: the address of a character string containing the command to
116 % o exception: return any errors or warnings in this structure.
119 static MagickBooleanType InvokePostscriptDelegate(
120 const MagickBooleanType verbose,const char *command,ExceptionInfo *exception)
125 #if defined(MAGICKCORE_GS_DELEGATE) || defined(__WINDOWS__)
129 const GhostscriptVectors
142 #if defined(__WINDOWS__)
143 gs_func=NTGhostscriptDLLVectors();
148 gs_func=(&gs_func_struct);
149 (void) ResetMagickMemory(&gs_func,0,sizeof(gs_func));
150 gs_func_struct.new_instance=(int (*)(gs_main_instance **,void *))
152 gs_func_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
153 gsapi_init_with_args;
154 gs_func_struct.run_string=(int (*)(gs_main_instance *,const char *,int,int *))
156 gs_func_struct.delete_instance=(void (*)(gs_main_instance *))
157 gsapi_delete_instance;
158 gs_func_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
160 if (gs_func == (GhostscriptVectors *) NULL)
162 status=SystemCommand(verbose,command,exception);
163 return(status != 0 ? MagickTrue : MagickFalse);
165 if (verbose != MagickFalse)
167 (void) fputs("[ghostscript library]",stdout);
168 (void) fputs(strchr(command,' '),stdout);
170 status=(gs_func->new_instance)(&interpreter,(void *) NULL);
173 status=SystemCommand(verbose,command,exception);
174 return(status != 0 ? MagickTrue : MagickFalse);
176 argv=StringToArgv(command,&argc);
177 status=(gs_func->init_with_args)(interpreter,argc-1,argv+1);
179 status=(gs_func->run_string)(interpreter,"systemdict /start get exec\n",0,
181 (gs_func->exit)(interpreter);
182 (gs_func->delete_instance)(interpreter);
183 #if defined(__WINDOWS__)
184 NTGhostscriptUnLoadDLL();
186 for (i=0; i < (long) argc; i++)
187 argv[i]=DestroyString(argv[i]);
188 argv=(char **) RelinquishMagickMemory(argv);
189 if ((status <= -1) && (status >= -100))
194 message=GetExceptionMessage(errno);
195 (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
196 "`%s': %s",command,message);
197 message=DestroyString(message);
200 (void) LogMagickEvent(CoderEvent,GetMagickModule(),
201 "Ghostscript returns status %d, exit code %d",status,code);
204 status=SystemCommand(verbose,command,exception);
205 return(status != 0 ? MagickTrue : MagickFalse);
210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
218 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220 % IsPDF() returns MagickTrue if the image format type, identified by the
221 % magick string, is PDF.
223 % The format of the IsPDF method is:
225 % MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
227 % A description of each parameter follows:
229 % o magick: compare image format pattern against these bytes.
231 % o offset: Specifies the offset of the magick string.
234 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
238 if (LocaleNCompare((char *) magick,"%PDF-",5) == 0)
244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
248 % R e a d P D F I m a g e %
252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 % ReadPDFImage() reads a Portable Document Format image file and
255 % returns it. It allocates the memory necessary for the new Image structure
256 % and returns a pointer to the new image.
258 % The format of the ReadPDFImage method is:
260 % Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
262 % A description of each parameter follows:
264 % o image_info: the image info.
266 % o exception: return any errors or warnings in this structure.
270 static MagickBooleanType IsPDFRendered(const char *path)
278 if ((path == (const char *) NULL) || (*path == '\0'))
280 status=GetPathAttributes(path,&attributes);
281 if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
282 (attributes.st_size > 0))
287 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
289 #define CropBox "CropBox"
290 #define DeviceCMYK "DeviceCMYK"
291 #define MediaBox "MediaBox"
292 #define RenderPostscriptText "Rendering Postscript... "
293 #define PDFRotate "Rotate"
294 #define SpotColor "Separation"
295 #define TrimBox "TrimBox"
296 #define PDFVersion "PDF-"
299 command[MaxTextExtent],
300 density[MaxTextExtent],
301 filename[MaxTextExtent],
302 geometry[MaxTextExtent],
303 options[MaxTextExtent],
304 input_filename[MaxTextExtent],
305 postscript_filename[MaxTextExtent];
357 assert(image_info != (const ImageInfo *) NULL);
358 assert(image_info->signature == MagickSignature);
359 if (image_info->debug != MagickFalse)
360 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
361 image_info->filename);
362 assert(exception != (ExceptionInfo *) NULL);
363 assert(exception->signature == MagickSignature);
367 image=AcquireImage(image_info);
368 status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
369 if (status == MagickFalse)
371 image=DestroyImageList(image);
372 return((Image *) NULL);
374 status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
375 if (status == MagickFalse)
377 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
378 image_info->filename);
379 image=DestroyImageList(image);
380 return((Image *) NULL);
383 Set the page density.
385 delta.x=DefaultResolution;
386 delta.y=DefaultResolution;
387 if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
395 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
396 image->x_resolution=geometry_info.rho;
397 image->y_resolution=geometry_info.sigma;
398 if ((flags & SigmaValue) == 0)
399 image->y_resolution=image->x_resolution;
402 Determine page geometry from the PDF media box.
404 cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
406 option=GetImageOption(image_info,"pdf:use-cropbox");
407 if (option != (const char *) NULL)
408 cropbox=IsMagickTrue(option);
410 option=GetImageOption(image_info,"pdf:use-trimbox");
411 if (option != (const char *) NULL)
412 trimbox=IsMagickTrue(option);
415 (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box));
416 (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
417 (void) ResetMagickMemory(&hires_bounds,0,sizeof(hires_bounds));
418 (void) ResetMagickMemory(&page,0,sizeof(page));
419 (void) ResetMagickMemory(command,0,sizeof(command));
424 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
432 if ((c != (int) '/') && (c != (int) '%') &&
433 ((size_t) (p-command) < (MaxTextExtent-1)))
437 if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
438 count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
440 Is this a CMYK document?
442 if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
444 if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
448 property[MaxTextExtent],
457 (void) FormatMagickString(property,MaxTextExtent,"pdf:SpotColor-%lu",
460 for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
462 if ((isspace(c) != 0) || (c == '/') || ((i+1) == MaxTextExtent))
467 value=AcquireString(name);
468 (void) SubstituteString(&value,"#20"," ");
469 (void) SetImageProperty(image,property,value);
470 value=DestroyString(value);
473 if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
474 (void) SetImageProperty(image,"pdf:Version",command);
476 if (cropbox != MagickFalse)
478 if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
481 Note region defined by crop box.
483 count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
484 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
486 count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
487 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
491 if (trimbox != MagickFalse)
493 if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
496 Note region defined by trim box.
498 count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
499 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
501 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
502 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
506 if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
509 Note region defined by media box.
511 count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
512 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
514 count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
515 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
519 if (((bounds.x2 > hires_bounds.x2) && (bounds.y2 > hires_bounds.y2)) ||
520 ((hires_bounds.x2 == 0.0) && (hires_bounds.y2 == 0.0)))
523 Set PDF render geometry.
525 (void) FormatMagickString(geometry,MaxTextExtent,"%gx%g%+g%+g",
526 bounds.x2-bounds.x1,bounds.y2-bounds.y1,bounds.x1,bounds.y1);
527 (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry);
528 page.width=(unsigned long) (bounds.x2-bounds.x1+0.5);
529 page.height=(unsigned long) (bounds.y2-bounds.y1+0.5);
533 (void) CloseBlob(image);
534 if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
540 page.width=page.height;
543 if (image_info->colorspace == RGBColorspace)
546 Create Ghostscript control file.
548 file=AcquireUniqueFileResource(postscript_filename);
551 ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
552 image_info->filename);
553 image=DestroyImage(image);
554 return((Image *) NULL);
556 count=write(file," ",1);
559 Render Postscript with the Ghostscript delegate.
561 if ((image_info->ping != MagickFalse) ||
562 (image_info->monochrome != MagickFalse))
563 delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
565 if (cmyk != MagickFalse)
566 delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
568 #if defined(MAGICKCORE_PNG_DELEGATE)
569 delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
571 delegate_info=GetDelegateInfo("ps:color",(char *) NULL,exception);
573 if (delegate_info == (const DelegateInfo *) NULL)
575 (void) RelinquishUniqueFileResource(postscript_filename);
576 image=DestroyImage(image);
577 return((Image *) NULL);
580 (void) FormatMagickString(density,MaxTextExtent,"%gx%g",image->x_resolution,
581 image->y_resolution);
582 if (image_info->page != (char *) NULL)
584 (void) ParseAbsoluteGeometry(image_info->page,&page);
585 page.width=(unsigned long) (page.width*image->x_resolution/delta.x+0.5);
586 page.height=(unsigned long) (page.height*image->y_resolution/delta.y+0.5);
587 (void) FormatMagickString(options,MaxTextExtent,"-g%lux%lu ",page.width,
590 if (cmyk != MagickFalse)
591 (void) ConcatenateMagickString(options,"-dUseCIEColor ",MaxTextExtent);
592 if (cropbox != MagickFalse)
593 (void) ConcatenateMagickString(options,"-dUseCropBox ",MaxTextExtent);
594 if (trimbox != MagickFalse)
595 (void) ConcatenateMagickString(options,"-dUseTrimBox ",MaxTextExtent);
596 read_info=CloneImageInfo(image_info);
597 *read_info->magick='\0';
598 if (read_info->number_scenes != 0)
601 pages[MaxTextExtent];
603 (void) FormatMagickString(pages,MaxTextExtent,"-dFirstPage=%lu "
604 "-dLastPage=%lu",read_info->scene+1,read_info->scene+
605 read_info->number_scenes);
606 (void) ConcatenateMagickString(options,pages,MaxTextExtent);
607 read_info->number_scenes=0;
608 if (read_info->scenes != (char *) NULL)
609 *read_info->scenes='\0';
611 if (read_info->authenticate != (char *) NULL)
612 (void) FormatMagickString(options+strlen(options),MaxTextExtent,
613 " -sPDFPassword=%s",read_info->authenticate);
614 (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
615 (void) AcquireUniqueFilename(read_info->filename);
616 (void) FormatMagickString(command,MaxTextExtent,
617 GetDelegateCommands(delegate_info),
618 read_info->antialias != MagickFalse ? 4 : 1,
619 read_info->antialias != MagickFalse ? 4 : 1,density,options,
620 read_info->filename,postscript_filename,input_filename);
621 status=InvokePostscriptDelegate(read_info->verbose,command,exception);
622 pdf_image=(Image *) NULL;
623 if ((status == MagickFalse) &&
624 (IsPDFRendered(read_info->filename) != MagickFalse))
625 pdf_image=ReadImage(read_info,exception);
626 (void) RelinquishUniqueFileResource(postscript_filename);
627 (void) RelinquishUniqueFileResource(read_info->filename);
628 (void) RelinquishUniqueFileResource(input_filename);
629 read_info=DestroyImageInfo(read_info);
630 if (pdf_image == (Image *) NULL)
632 ThrowFileException(exception,DelegateError,"PostscriptDelegateFailed",
633 image_info->filename);
634 return((Image *) NULL);
636 if (LocaleCompare(pdf_image->magick,"BMP") == 0)
641 cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
642 if (cmyk_image != (Image *) NULL)
644 pdf_image=DestroyImageList(pdf_image);
645 pdf_image=cmyk_image;
648 if (image_info->number_scenes != 0)
657 Add place holder images to meet the subimage specification requirement.
659 for (i=0; i < (long) image_info->scene; i++)
661 clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
662 if (clone_image != (Image *) NULL)
663 PrependImageToList(&pdf_image,clone_image);
668 (void) CopyMagickString(pdf_image->filename,filename,MaxTextExtent);
669 pdf_image->page=page;
670 (void) CloneImageProfiles(pdf_image,image);
671 (void) CloneImageProperties(pdf_image,image);
672 next=SyncNextImageInList(pdf_image);
673 if (next != (Image *) NULL)
675 } while (next != (Image *) NULL);
676 image=DestroyImage(image);
678 for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
681 next=GetNextImageInList(next);
683 return(GetFirstImageInList(pdf_image));
687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
691 % R e g i s t e r P D F I m a g e %
695 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 % RegisterPDFImage() adds properties for the PDF image format to
698 % the list of supported formats. The properties include the image format
699 % tag, a method to read and/or write the format, whether the format
700 % supports the saving of more than one frame to the same file or blob,
701 % whether the format supports native in-memory I/O, and a brief
702 % description of the format.
704 % The format of the RegisterPDFImage method is:
706 % unsigned long RegisterPDFImage(void)
709 ModuleExport unsigned long RegisterPDFImage(void)
714 entry=SetMagickInfo("AI");
715 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
716 entry->encoder=(EncodeImageHandler *) WritePDFImage;
717 entry->adjoin=MagickFalse;
718 entry->blob_support=MagickFalse;
719 entry->seekable_stream=MagickTrue;
720 entry->thread_support=EncoderThreadSupport;
721 entry->description=ConstantString("Adobe Illustrator CS2");
722 entry->module=ConstantString("PDF");
723 (void) RegisterMagickInfo(entry);
724 entry=SetMagickInfo("EPDF");
725 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
726 entry->encoder=(EncodeImageHandler *) WritePDFImage;
727 entry->adjoin=MagickFalse;
728 entry->blob_support=MagickFalse;
729 entry->seekable_stream=MagickTrue;
730 entry->thread_support=EncoderThreadSupport;
731 entry->description=ConstantString("Encapsulated Portable Document Format");
732 entry->module=ConstantString("PDF");
733 (void) RegisterMagickInfo(entry);
734 entry=SetMagickInfo("PDF");
735 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
736 entry->encoder=(EncodeImageHandler *) WritePDFImage;
737 entry->magick=(IsImageFormatHandler *) IsPDF;
738 entry->blob_support=MagickFalse;
739 entry->seekable_stream=MagickTrue;
740 entry->thread_support=EncoderThreadSupport;
741 entry->description=ConstantString("Portable Document Format");
742 entry->module=ConstantString("PDF");
743 (void) RegisterMagickInfo(entry);
744 entry=SetMagickInfo("PDFA");
745 entry->decoder=(DecodeImageHandler *) ReadPDFImage;
746 entry->encoder=(EncodeImageHandler *) WritePDFImage;
747 entry->magick=(IsImageFormatHandler *) IsPDF;
748 entry->blob_support=MagickFalse;
749 entry->seekable_stream=MagickTrue;
750 entry->thread_support=EncoderThreadSupport;
751 entry->description=ConstantString("Portable Document Archive Format");
752 entry->module=ConstantString("PDF");
753 (void) RegisterMagickInfo(entry);
754 return(MagickImageCoderSignature);
758 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 % U n r e g i s t e r P D F I m a g e %
766 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 % UnregisterPDFImage() removes format registrations made by the
769 % PDF module from the list of supported formats.
771 % The format of the UnregisterPDFImage method is:
773 % UnregisterPDFImage(void)
776 ModuleExport void UnregisterPDFImage(void)
778 (void) UnregisterMagickInfo("AI");
779 (void) UnregisterMagickInfo("EPDF");
780 (void) UnregisterMagickInfo("PDF");
781 (void) UnregisterMagickInfo("PDFA");
785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789 % W r i t e P D F I m a g e %
793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 % WritePDFImage() writes an image in the Portable Document image
798 % The format of the WritePDFImage method is:
800 % MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
802 % A description of each parameter follows.
804 % o image_info: the image info.
806 % o image: The image.
810 static inline size_t MagickMax(const size_t x,const size_t y)
817 static inline size_t MagickMin(const size_t x,const size_t y)
824 static char *EscapeParenthesis(const char *text)
833 buffer[MaxTextExtent];
840 for (i=0; i < (long) MagickMin(strlen(text),(MaxTextExtent-escapes-1)); i++)
842 if ((text[i] == '(') || (text[i] == ')'))
853 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
855 #define CFormat "/Filter [ /%s ]\n"
856 #define ObjectsPerImage 14
861 "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
862 "<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"
863 " <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
864 " <rdf:Description rdf:about=\"\"\n"
865 " xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
866 " <xap:ModifyDate>%s</xap:ModifyDate>\n"
867 " <xap:CreateDate>%s</xap:CreateDate>\n"
868 " <xap:MetadataDate>%s</xap:MetadataDate>\n"
869 " <xap:CreatorTool>%s</xap:CreatorTool>\n"
870 " </rdf:Description>\n"
871 " <rdf:Description rdf:about=\"\"\n"
872 " xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
873 " <dc:format>application/pdf</dc:format>\n"
874 " </rdf:Description>\n"
875 " <rdf:Description rdf:about=\"\"\n"
876 " xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
877 " <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
878 " <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
879 " </rdf:Description>\n"
880 " <rdf:Description rdf:about=\"\"\n"
881 " xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
882 " <pdf:Producer>%s</pdf:Producer>\n"
883 " </rdf:Description>\n"
884 " <rdf:Description rdf:about=\"\"\n"
885 " xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
886 " <pdfaid:part>1</pdfaid:part>\n"
887 " <pdfaid:conformance>B</pdfaid:conformance>\n"
888 " </rdf:Description>\n"
891 "<?xpacket end=\"w\"?>\n"
893 XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
896 buffer[MaxTextExtent],
899 page_geometry[MaxTextExtent];
945 register const IndexPacket
948 register const PixelPacket
951 register unsigned char
979 Open output image file.
981 assert(image_info != (const ImageInfo *) NULL);
982 assert(image_info->signature == MagickSignature);
983 assert(image != (Image *) NULL);
984 assert(image->signature == MagickSignature);
985 if (image->debug != MagickFalse)
986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
987 status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
988 if (status == MagickFalse)
991 Allocate X ref memory.
993 xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
994 if (xref == (MagickOffsetType *) NULL)
995 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
996 (void) ResetMagickMemory(xref,0,2048UL*sizeof(*xref));
1002 if (image_info->compression == JPEG2000Compression)
1003 version=(unsigned long) MagickMax(version,5);
1004 for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1005 if (next->matte != MagickFalse)
1006 version=(unsigned long) MagickMax(version,4);
1007 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1008 version=(unsigned long) MagickMax(version,6);
1009 (void) FormatMagickString(buffer,MaxTextExtent,"%%PDF-1.%lu \n",version);
1010 (void) WriteBlobString(image,buffer);
1011 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1012 (void) WriteBlobString(image,"%âãÏÓ\n");
1014 Write Catalog object.
1016 xref[object++]=TellBlob(image);
1018 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1019 (void) WriteBlobString(image,buffer);
1020 (void) WriteBlobString(image,"<<\n");
1021 if (LocaleCompare(image_info->magick,"PDFA") != 0)
1022 (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %lu 0 R\n",
1026 (void) FormatMagickString(buffer,MaxTextExtent,"/Metadata %lu 0 R\n",
1028 (void) WriteBlobString(image,buffer);
1029 (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %lu 0 R\n",
1032 (void) WriteBlobString(image,buffer);
1033 (void) WriteBlobString(image,"/Type /Catalog\n");
1034 (void) WriteBlobString(image,">>\n");
1035 (void) WriteBlobString(image,"endobj\n");
1036 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1039 create_date[MaxTextExtent],
1040 modify_date[MaxTextExtent],
1041 timestamp[MaxTextExtent],
1042 xmp_profile[MaxTextExtent];
1050 xref[object++]=TellBlob(image);
1051 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1052 (void) WriteBlobString(image,buffer);
1053 (void) WriteBlobString(image,"<<\n");
1054 (void) WriteBlobString(image,"/Subtype /XML\n");
1056 value=GetImageProperty(image,"date:modify");
1057 if (value != (const char *) NULL)
1058 (void) CopyMagickString(modify_date,value,MaxTextExtent);
1060 value=GetImageProperty(image,"date:create");
1061 if (value != (const char *) NULL)
1062 (void) CopyMagickString(create_date,value,MaxTextExtent);
1063 (void) FormatMagickTime(time((time_t *) NULL),MaxTextExtent,timestamp);
1064 i=FormatMagickString(xmp_profile,MaxTextExtent,XMPProfile,
1065 XMPProfileMagick,modify_date,create_date,timestamp,
1066 GetMagickVersion(&version),GetMagickVersion(&version));
1067 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu\n",1UL*i);
1068 (void) WriteBlobString(image,buffer);
1069 (void) WriteBlobString(image,"/Type /Metadata\n");
1070 (void) WriteBlobString(image,">>\nstream\n");
1071 (void) WriteBlobString(image,xmp_profile);
1072 (void) WriteBlobString(image,"endstream\n");
1073 (void) WriteBlobString(image,"endobj\n");
1078 xref[object++]=TellBlob(image);
1080 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1081 (void) WriteBlobString(image,buffer);
1082 (void) WriteBlobString(image,"<<\n");
1083 (void) WriteBlobString(image,"/Type /Pages\n");
1084 (void) FormatMagickString(buffer,MaxTextExtent,"/Kids [ %lu 0 R ",object+1);
1085 (void) WriteBlobString(image,buffer);
1086 count=(long) (pages_id+ObjectsPerImage+1);
1087 if (image_info->adjoin != MagickFalse)
1093 Predict page object id's.
1096 for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1098 (void) FormatMagickString(buffer,MaxTextExtent,"%ld 0 R ",count);
1099 (void) WriteBlobString(image,buffer);
1100 kid_image=GetNextImageInList(kid_image);
1102 xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1104 if (xref == (MagickOffsetType *) NULL)
1105 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1107 (void) WriteBlobString(image,"]\n");
1108 (void) FormatMagickString(buffer,MaxTextExtent,"/Count %lu\n",
1109 (count-pages_id)/ObjectsPerImage);
1110 (void) WriteBlobString(image,buffer);
1111 (void) WriteBlobString(image,">>\n");
1112 (void) WriteBlobString(image,"endobj\n");
1116 compression=image->compression;
1117 if (image_info->compression != UndefinedCompression)
1118 compression=image_info->compression;
1119 switch (compression)
1121 case FaxCompression:
1122 case Group4Compression:
1124 if ((IsMonochromeImage(image,&image->exception) == MagickFalse) ||
1125 (image->matte != MagickFalse))
1126 compression=RLECompression;
1129 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1130 case JPEGCompression:
1132 compression=RLECompression;
1133 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1134 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1139 #if !defined(MAGICKCORE_JP2_DELEGATE)
1140 case JPEG2000Compression:
1142 compression=RLECompression;
1143 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1144 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1149 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1150 case ZipCompression:
1152 compression=RLECompression;
1153 (void) ThrowMagickException(&image->exception,GetMagickModule(),
1154 MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1159 case LZWCompression:
1161 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1162 compression=RLECompression; /* LZW compression is forbidden */
1167 if (LocaleCompare(image_info->magick,"PDFA") == 0)
1168 compression=RLECompression; /* ASCII 85 compression is forbidden */
1174 if (compression == JPEG2000Compression)
1176 if (image->colorspace != RGBColorspace)
1177 (void) TransformImageColorspace(image,RGBColorspace);
1180 Scale relative to dots-per-inch.
1182 delta.x=DefaultResolution;
1183 delta.y=DefaultResolution;
1184 resolution.x=image->x_resolution;
1185 resolution.y=image->y_resolution;
1186 if ((resolution.x == 0.0) || (resolution.y == 0.0))
1188 flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1189 resolution.x=geometry_info.rho;
1190 resolution.y=geometry_info.sigma;
1191 if ((flags & SigmaValue) == 0)
1192 resolution.y=resolution.x;
1194 if (image_info->density != (char *) NULL)
1196 flags=ParseGeometry(image_info->density,&geometry_info);
1197 resolution.x=geometry_info.rho;
1198 resolution.y=geometry_info.sigma;
1199 if ((flags & SigmaValue) == 0)
1200 resolution.y=resolution.x;
1202 if (image->units == PixelsPerCentimeterResolution)
1207 SetGeometry(image,&geometry);
1208 (void) FormatMagickString(page_geometry,MaxTextExtent,"%lux%lu",
1209 image->columns,image->rows);
1210 if (image_info->page != (char *) NULL)
1211 (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent);
1213 if ((image->page.width != 0) && (image->page.height != 0))
1214 (void) FormatMagickString(page_geometry,MaxTextExtent,"%lux%lu%+ld%+ld",
1215 image->page.width,image->page.height,image->page.x,image->page.y);
1217 if ((image->gravity != UndefinedGravity) &&
1218 (LocaleCompare(image_info->magick,"PDF") == 0))
1219 (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent);
1220 (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent);
1221 (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1222 &geometry.width,&geometry.height);
1223 scale.x=(double) (geometry.width*delta.x)/resolution.x;
1224 geometry.width=(unsigned long) (scale.x+0.5);
1225 scale.y=(double) (geometry.height*delta.y)/resolution.y;
1226 geometry.height=(unsigned long) (scale.y+0.5);
1227 (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1228 (void) ParseGravityGeometry(image,page_geometry,&page_info,
1230 if (image->gravity != UndefinedGravity)
1232 geometry.x=(-page_info.x);
1233 geometry.y=(long) (media_info.height+page_info.y-image->rows);
1236 if (image_info->pointsize != 0.0)
1237 pointsize=image_info->pointsize;
1239 value=GetImageProperty(image,"Label");
1240 if (value != (const char *) NULL)
1241 text_size=(unsigned long) (MultilineCensus(value)*pointsize+12);
1245 xref[object++]=TellBlob(image);
1246 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1247 (void) WriteBlobString(image,buffer);
1248 (void) WriteBlobString(image,"<<\n");
1249 (void) WriteBlobString(image,"/Type /Page\n");
1250 (void) FormatMagickString(buffer,MaxTextExtent,"/Parent %lu 0 R\n",
1252 (void) WriteBlobString(image,buffer);
1253 (void) WriteBlobString(image,"/Resources <<\n");
1254 labels=(char **) NULL;
1255 value=GetImageProperty(image,"Label");
1256 if (value != (const char *) NULL)
1257 labels=StringToList(value);
1258 if (labels != (char **) NULL)
1260 (void) FormatMagickString(buffer,MaxTextExtent,
1261 "/Font << /F%lu %lu 0 R >>\n",image->scene,object+4);
1262 (void) WriteBlobString(image,buffer);
1264 (void) FormatMagickString(buffer,MaxTextExtent,
1265 "/XObject << /Im%lu %lu 0 R >>\n",image->scene,object+5);
1266 (void) WriteBlobString(image,buffer);
1267 (void) FormatMagickString(buffer,MaxTextExtent,"/ProcSet %lu 0 R >>\n",
1269 (void) WriteBlobString(image,buffer);
1270 (void) FormatMagickString(buffer,MaxTextExtent,"/MediaBox [0 0 %g %g]\n",
1271 72.0*media_info.width/resolution.x,72.0*media_info.height/resolution.y);
1272 (void) WriteBlobString(image,buffer);
1273 (void) FormatMagickString(buffer,MaxTextExtent,"/CropBox [0 0 %g %g]\n",
1274 72.0*media_info.width/resolution.x,72.0*media_info.height/resolution.y);
1275 (void) WriteBlobString(image,buffer);
1276 (void) FormatMagickString(buffer,MaxTextExtent,"/Contents %lu 0 R\n",
1278 (void) WriteBlobString(image,buffer);
1279 (void) FormatMagickString(buffer,MaxTextExtent,"/Thumb %lu 0 R\n",
1281 (void) WriteBlobString(image,buffer);
1282 (void) WriteBlobString(image,">>\n");
1283 (void) WriteBlobString(image,"endobj\n");
1285 Write Contents object.
1287 xref[object++]=TellBlob(image);
1288 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1289 (void) WriteBlobString(image,buffer);
1290 (void) WriteBlobString(image,"<<\n");
1291 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
1293 (void) WriteBlobString(image,buffer);
1294 (void) WriteBlobString(image,">>\n");
1295 (void) WriteBlobString(image,"stream\n");
1296 offset=TellBlob(image);
1297 (void) WriteBlobString(image,"q\n");
1298 if (labels != (char **) NULL)
1299 for (i=0; labels[i] != (char *) NULL; i++)
1301 (void) WriteBlobString(image,"BT\n");
1302 (void) FormatMagickString(buffer,MaxTextExtent,"/F%lu %g Tf\n",
1303 image->scene,pointsize);
1304 (void) WriteBlobString(image,buffer);
1305 (void) FormatMagickString(buffer,MaxTextExtent,"%ld %ld Td\n",
1306 geometry.x,(long) (geometry.y+geometry.height+i*pointsize+12));
1307 (void) WriteBlobString(image,buffer);
1308 (void) FormatMagickString(buffer,MaxTextExtent,"(%s) Tj\n",labels[i]);
1309 (void) WriteBlobString(image,buffer);
1310 (void) WriteBlobString(image,"ET\n");
1311 labels[i]=DestroyString(labels[i]);
1313 (void) FormatMagickString(buffer,MaxTextExtent,"%g 0 0 %g %ld %ld cm\n",
1314 scale.x,scale.y,geometry.x,geometry.y);
1315 (void) WriteBlobString(image,buffer);
1316 (void) FormatMagickString(buffer,MaxTextExtent,"/Im%lu Do\n",image->scene);
1317 (void) WriteBlobString(image,buffer);
1318 (void) WriteBlobString(image,"Q\n");
1319 offset=TellBlob(image)-offset;
1320 (void) WriteBlobString(image,"endstream\n");
1321 (void) WriteBlobString(image,"endobj\n");
1323 Write Length object.
1325 xref[object++]=TellBlob(image);
1326 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1327 (void) WriteBlobString(image,buffer);
1328 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
1329 (unsigned long) offset);
1330 (void) WriteBlobString(image,buffer);
1331 (void) WriteBlobString(image,"endobj\n");
1333 Write Procset object.
1335 xref[object++]=TellBlob(image);
1336 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1337 (void) WriteBlobString(image,buffer);
1338 if ((image->storage_class == DirectClass) || (image->colors > 256))
1339 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MaxTextExtent);
1341 if ((compression == FaxCompression) || (compression == Group4Compression))
1342 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MaxTextExtent);
1344 (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MaxTextExtent);
1345 (void) WriteBlobString(image,buffer);
1346 (void) WriteBlobString(image," ]\n");
1347 (void) WriteBlobString(image,"endobj\n");
1351 xref[object++]=TellBlob(image);
1352 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1353 (void) WriteBlobString(image,buffer);
1354 (void) WriteBlobString(image,"<<\n");
1355 if (labels != (char **) NULL)
1357 (void) WriteBlobString(image,"/Type /Font\n");
1358 (void) WriteBlobString(image,"/Subtype /Type1\n");
1359 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /F%lu\n",
1361 (void) WriteBlobString(image,buffer);
1362 (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1363 (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1364 labels=(char **) RelinquishMagickMemory(labels);
1366 (void) WriteBlobString(image,">>\n");
1367 (void) WriteBlobString(image,"endobj\n");
1369 Write XObject object.
1371 xref[object++]=TellBlob(image);
1372 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1373 (void) WriteBlobString(image,buffer);
1374 (void) WriteBlobString(image,"<<\n");
1375 (void) WriteBlobString(image,"/Type /XObject\n");
1376 (void) WriteBlobString(image,"/Subtype /Image\n");
1377 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Im%lu\n",
1379 (void) WriteBlobString(image,buffer);
1380 switch (compression)
1384 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1387 case JPEGCompression:
1389 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1390 if (image->colorspace != CMYKColorspace)
1392 (void) WriteBlobString(image,buffer);
1393 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1397 case JPEG2000Compression:
1399 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1400 if (image->colorspace != CMYKColorspace)
1402 (void) WriteBlobString(image,buffer);
1403 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1407 case LZWCompression:
1409 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1412 case ZipCompression:
1414 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
1417 case FaxCompression:
1418 case Group4Compression:
1420 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1422 (void) WriteBlobString(image,buffer);
1423 (void) FormatMagickString(buffer,MaxTextExtent,
1424 "/DecodeParms [ << /K %s /Columns %ld /Rows %ld >> ]\n",
1425 CCITTParam,image->columns,image->rows);
1430 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
1435 (void) WriteBlobString(image,buffer);
1436 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
1438 (void) WriteBlobString(image,buffer);
1439 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",image->rows);
1440 (void) WriteBlobString(image,buffer);
1441 (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %lu 0 R\n",
1443 (void) WriteBlobString(image,buffer);
1444 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
1445 (compression == FaxCompression) || (compression == Group4Compression) ?
1447 (void) WriteBlobString(image,buffer);
1448 if (image->matte != MagickFalse)
1450 (void) FormatMagickString(buffer,MaxTextExtent,"/SMask %lu 0 R\n",
1452 (void) WriteBlobString(image,buffer);
1454 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
1456 (void) WriteBlobString(image,buffer);
1457 (void) WriteBlobString(image,">>\n");
1458 (void) WriteBlobString(image,"stream\n");
1459 offset=TellBlob(image);
1460 number_pixels=(MagickSizeType) image->columns*image->rows;
1461 if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1462 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1463 if ((compression == FaxCompression) || (compression == Group4Compression) ||
1464 ((image_info->type != TrueColorType) &&
1465 (IsGrayImage(image,&image->exception) != MagickFalse)))
1467 switch (compression)
1469 case FaxCompression:
1470 case Group4Compression:
1472 if (LocaleCompare(CCITTParam,"0") == 0)
1474 (void) HuffmanEncodeImage(image_info,image,image);
1477 (void) Huffman2DEncodeImage(image_info,image,image);
1480 case JPEGCompression:
1482 status=InjectImageBlob(image_info,image,image,"jpeg",
1484 if (status == MagickFalse)
1485 ThrowWriterException(CoderError,image->exception.reason);
1488 case JPEG2000Compression:
1490 status=InjectImageBlob(image_info,image,image,"jp2",
1492 if (status == MagickFalse)
1493 ThrowWriterException(CoderError,image->exception.reason);
1496 case RLECompression:
1500 Allocate pixel array.
1502 length=(size_t) number_pixels;
1503 pixels=(unsigned char *) AcquireQuantumMemory(length,
1505 if (pixels == (unsigned char *) NULL)
1506 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1508 Dump Runlength encoded pixels.
1511 for (y=0; y < (long) image->rows; y++)
1513 p=GetVirtualPixels(image,0,y,image->columns,1,
1515 if (p == (const PixelPacket *) NULL)
1517 for (x=0; x < (long) image->columns; x++)
1519 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
1522 if (image->previous == (Image *) NULL)
1524 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1525 if (status == MagickFalse)
1529 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1530 if (compression == ZipCompression)
1531 status=ZLIBEncodeImage(image,length,pixels);
1534 if (compression == LZWCompression)
1535 status=LZWEncodeImage(image,length,pixels);
1537 status=PackbitsEncodeImage(image,length,pixels);
1538 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1539 if (status == MagickFalse)
1541 (void) CloseBlob(image);
1542 return(MagickFalse);
1549 Dump uncompressed PseudoColor packets.
1551 Ascii85Initialize(image);
1552 for (y=0; y < (long) image->rows; y++)
1554 p=GetVirtualPixels(image,0,y,image->columns,1,
1556 if (p == (const PixelPacket *) NULL)
1558 for (x=0; x < (long) image->columns; x++)
1560 Ascii85Encode(image,
1561 ScaleQuantumToChar(PixelIntensityToQuantum(p)));
1564 if (image->previous == (Image *) NULL)
1566 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1567 if (status == MagickFalse)
1571 Ascii85Flush(image);
1577 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1578 (compression == JPEGCompression) ||
1579 (compression == JPEG2000Compression))
1580 switch (compression)
1582 case JPEGCompression:
1584 status=InjectImageBlob(image_info,image,image,"jpeg",
1586 if (status == MagickFalse)
1587 ThrowWriterException(CoderError,image->exception.reason);
1590 case JPEG2000Compression:
1592 status=InjectImageBlob(image_info,image,image,"jp2",
1594 if (status == MagickFalse)
1595 ThrowWriterException(CoderError,image->exception.reason);
1598 case RLECompression:
1602 Allocate pixel array.
1604 length=(size_t) number_pixels;
1605 pixels=(unsigned char *) AcquireQuantumMemory(length,
1607 length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
1608 if (pixels == (unsigned char *) NULL)
1609 ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1611 Dump runoffset encoded pixels.
1614 for (y=0; y < (long) image->rows; y++)
1616 p=GetVirtualPixels(image,0,y,image->columns,1,
1618 if (p == (const PixelPacket *) NULL)
1620 indexes=GetVirtualIndexQueue(image);
1621 for (x=0; x < (long) image->columns; x++)
1623 *q++=ScaleQuantumToChar(p->red);
1624 *q++=ScaleQuantumToChar(p->green);
1625 *q++=ScaleQuantumToChar(p->blue);
1626 if (image->colorspace == CMYKColorspace)
1627 *q++=ScaleQuantumToChar(indexes[x]);
1630 if (image->previous == (Image *) NULL)
1632 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1633 if (status == MagickFalse)
1637 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1638 if (compression == ZipCompression)
1639 status=ZLIBEncodeImage(image,length,pixels);
1642 if (compression == LZWCompression)
1643 status=LZWEncodeImage(image,length,pixels);
1645 status=PackbitsEncodeImage(image,length,pixels);
1646 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1647 if (status == MagickFalse)
1649 (void) CloseBlob(image);
1650 return(MagickFalse);
1657 Dump uncompressed DirectColor packets.
1659 Ascii85Initialize(image);
1660 for (y=0; y < (long) image->rows; y++)
1662 p=GetVirtualPixels(image,0,y,image->columns,1,
1664 if (p == (const PixelPacket *) NULL)
1666 indexes=GetVirtualIndexQueue(image);
1667 for (x=0; x < (long) image->columns; x++)
1669 Ascii85Encode(image,ScaleQuantumToChar(p->red));
1670 Ascii85Encode(image,ScaleQuantumToChar(p->green));
1671 Ascii85Encode(image,ScaleQuantumToChar(p->blue));
1672 if (image->colorspace == CMYKColorspace)
1673 Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
1676 if (image->previous == (Image *) NULL)
1678 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1679 if (status == MagickFalse)
1683 Ascii85Flush(image);
1690 Dump number of colors and colormap.
1692 switch (compression)
1694 case RLECompression:
1698 Allocate pixel array.
1700 length=(size_t) number_pixels;
1701 pixels=(unsigned char *) AcquireQuantumMemory(length,
1703 if (pixels == (unsigned char *) NULL)
1704 ThrowWriterException(ResourceLimitError,
1705 "MemoryAllocationFailed");
1707 Dump Runlength encoded pixels.
1710 for (y=0; y < (long) image->rows; y++)
1712 p=GetVirtualPixels(image,0,y,image->columns,1,
1714 if (p == (const PixelPacket *) NULL)
1716 indexes=GetVirtualIndexQueue(image);
1717 for (x=0; x < (long) image->columns; x++)
1718 *q++=(unsigned char) indexes[x];
1719 if (image->previous == (Image *) NULL)
1721 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1722 if (status == MagickFalse)
1726 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1727 if (compression == ZipCompression)
1728 status=ZLIBEncodeImage(image,length,pixels);
1731 if (compression == LZWCompression)
1732 status=LZWEncodeImage(image,length,pixels);
1734 status=PackbitsEncodeImage(image,length,pixels);
1735 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1736 if (status == MagickFalse)
1738 (void) CloseBlob(image);
1739 return(MagickFalse);
1746 Dump uncompressed PseudoColor packets.
1748 Ascii85Initialize(image);
1749 for (y=0; y < (long) image->rows; y++)
1751 p=GetVirtualPixels(image,0,y,image->columns,1,
1753 if (p == (const PixelPacket *) NULL)
1755 indexes=GetVirtualIndexQueue(image);
1756 for (x=0; x < (long) image->columns; x++)
1757 Ascii85Encode(image,(unsigned char) indexes[x]);
1758 if (image->previous == (Image *) NULL)
1760 status=SetImageProgress(image,SaveImageTag,y,image->rows);
1761 if (status == MagickFalse)
1765 Ascii85Flush(image);
1770 offset=TellBlob(image)-offset;
1771 (void) WriteBlobString(image,"\nendstream\n");
1772 (void) WriteBlobString(image,"endobj\n");
1774 Write Length object.
1776 xref[object++]=TellBlob(image);
1777 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1778 (void) WriteBlobString(image,buffer);
1779 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
1780 (unsigned long) offset);
1781 (void) WriteBlobString(image,buffer);
1782 (void) WriteBlobString(image,"endobj\n");
1784 Write Colorspace object.
1786 xref[object++]=TellBlob(image);
1787 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1788 (void) WriteBlobString(image,buffer);
1789 if (image->colorspace == CMYKColorspace)
1790 (void) CopyMagickString(buffer,"/DeviceCMYK\n",MaxTextExtent);
1792 if ((compression == FaxCompression) ||
1793 (compression == Group4Compression) ||
1794 ((image_info->type != TrueColorType) &&
1795 (IsGrayImage(image,&image->exception) != MagickFalse)))
1796 (void) CopyMagickString(buffer,"/DeviceGray\n",MaxTextExtent);
1798 if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1799 (compression == JPEGCompression) ||
1800 (compression == JPEG2000Compression))
1801 (void) CopyMagickString(buffer,"/DeviceRGB\n",MaxTextExtent);
1803 (void) FormatMagickString(buffer,MaxTextExtent,
1804 "[ /Indexed /DeviceRGB %lu %lu 0 R ]\n",
1805 image->colors-1,object+3);
1806 (void) WriteBlobString(image,buffer);
1807 (void) WriteBlobString(image,"endobj\n");
1811 SetGeometry(image,&geometry);
1812 (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
1813 &geometry.width,&geometry.height);
1814 tile_image=ThumbnailImage(image,geometry.width,geometry.height,
1816 if (tile_image == (Image *) NULL)
1817 ThrowWriterException(ResourceLimitError,image->exception.reason);
1818 xref[object++]=TellBlob(image);
1819 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1820 (void) WriteBlobString(image,buffer);
1821 (void) WriteBlobString(image,"<<\n");
1822 switch (compression)
1826 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1829 case JPEGCompression:
1831 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1832 if (image->colorspace != CMYKColorspace)
1834 (void) WriteBlobString(image,buffer);
1835 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1839 case JPEG2000Compression:
1841 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1842 if (image->colorspace != CMYKColorspace)
1844 (void) WriteBlobString(image,buffer);
1845 (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1849 case LZWCompression:
1851 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1854 case ZipCompression:
1856 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
1859 case FaxCompression:
1860 case Group4Compression:
1862 (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1864 (void) WriteBlobString(image,buffer);
1865 (void) FormatMagickString(buffer,MaxTextExtent,
1866 "/DecodeParms [ << /K %s /Columns %lu /Rows %lu >> ]\n",
1867 CCITTParam,tile_image->columns,tile_image->rows);
1872 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
1877 (void) WriteBlobString(image,buffer);
1878 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
1879 tile_image->columns);
1880 (void) WriteBlobString(image,buffer);
1881 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",
1883 (void) WriteBlobString(image,buffer);
1884 (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %lu 0 R\n",
1886 (void) WriteBlobString(image,buffer);
1887 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
1888 (compression == FaxCompression) || (compression == Group4Compression) ?
1890 (void) WriteBlobString(image,buffer);
1891 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
1893 (void) WriteBlobString(image,buffer);
1894 (void) WriteBlobString(image,">>\n");
1895 (void) WriteBlobString(image,"stream\n");
1896 offset=TellBlob(image);
1897 number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
1898 if ((compression == FaxCompression) ||
1899 (compression == Group4Compression) ||
1900 ((image_info->type != TrueColorType) &&
1901 (IsGrayImage(tile_image,&image->exception) != MagickFalse)))
1903 switch (compression)
1905 case FaxCompression:
1906 case Group4Compression:
1908 if (LocaleCompare(CCITTParam,"0") == 0)
1910 (void) HuffmanEncodeImage(image_info,image,tile_image);
1913 (void) Huffman2DEncodeImage(image_info,image,tile_image);
1916 case JPEGCompression:
1918 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
1920 if (status == MagickFalse)
1921 ThrowWriterException(CoderError,tile_image->exception.reason);
1924 case JPEG2000Compression:
1926 status=InjectImageBlob(image_info,image,tile_image,"jp2",
1928 if (status == MagickFalse)
1929 ThrowWriterException(CoderError,tile_image->exception.reason);
1932 case RLECompression:
1936 Allocate pixel array.
1938 length=(size_t) number_pixels;
1939 pixels=(unsigned char *) AcquireQuantumMemory(length,
1941 if (pixels == (unsigned char *) NULL)
1943 tile_image=DestroyImage(tile_image);
1944 ThrowWriterException(ResourceLimitError,
1945 "MemoryAllocationFailed");
1948 Dump Runlength encoded pixels.
1951 for (y=0; y < (long) tile_image->rows; y++)
1953 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
1954 &tile_image->exception);
1955 if (p == (const PixelPacket *) NULL)
1957 for (x=0; x < (long) tile_image->columns; x++)
1959 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
1963 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1964 if (compression == ZipCompression)
1965 status=ZLIBEncodeImage(image,length,pixels);
1968 if (compression == LZWCompression)
1969 status=LZWEncodeImage(image,length,pixels);
1971 status=PackbitsEncodeImage(image,length,pixels);
1972 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1973 if (status == MagickFalse)
1975 (void) CloseBlob(image);
1976 return(MagickFalse);
1983 Dump uncompressed PseudoColor packets.
1985 Ascii85Initialize(image);
1986 for (y=0; y < (long) tile_image->rows; y++)
1988 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
1989 &tile_image->exception);
1990 if (p == (const PixelPacket *) NULL)
1992 for (x=0; x < (long) tile_image->columns; x++)
1994 Ascii85Encode(image,
1995 ScaleQuantumToChar(PixelIntensityToQuantum(p)));
1999 Ascii85Flush(image);
2005 if ((tile_image->storage_class == DirectClass) ||
2006 (tile_image->colors > 256) || (compression == JPEGCompression) ||
2007 (compression == JPEG2000Compression))
2008 switch (compression)
2010 case JPEGCompression:
2012 status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2014 if (status == MagickFalse)
2015 ThrowWriterException(CoderError,tile_image->exception.reason);
2018 case JPEG2000Compression:
2020 status=InjectImageBlob(image_info,image,tile_image,"jp2",
2022 if (status == MagickFalse)
2023 ThrowWriterException(CoderError,tile_image->exception.reason);
2026 case RLECompression:
2030 Allocate pixel array.
2032 length=(size_t) number_pixels;
2033 pixels=(unsigned char *) AcquireQuantumMemory(length,4*
2035 length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2036 if (pixels == (unsigned char *) NULL)
2038 tile_image=DestroyImage(tile_image);
2039 ThrowWriterException(ResourceLimitError,
2040 "MemoryAllocationFailed");
2043 Dump runoffset encoded pixels.
2046 for (y=0; y < (long) tile_image->rows; y++)
2048 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2049 &tile_image->exception);
2050 if (p == (const PixelPacket *) NULL)
2052 indexes=GetVirtualIndexQueue(tile_image);
2053 for (x=0; x < (long) tile_image->columns; x++)
2055 *q++=ScaleQuantumToChar(p->red);
2056 *q++=ScaleQuantumToChar(p->green);
2057 *q++=ScaleQuantumToChar(p->blue);
2058 if (image->colorspace == CMYKColorspace)
2059 *q++=ScaleQuantumToChar(indexes[x]);
2063 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2064 if (compression == ZipCompression)
2065 status=ZLIBEncodeImage(image,length,pixels);
2068 if (compression == LZWCompression)
2069 status=LZWEncodeImage(image,length,pixels);
2071 status=PackbitsEncodeImage(image,length,pixels);
2072 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2073 if (status == MagickFalse)
2075 (void) CloseBlob(image);
2076 return(MagickFalse);
2083 Dump uncompressed DirectColor packets.
2085 Ascii85Initialize(image);
2086 for (y=0; y < (long) tile_image->rows; y++)
2088 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2089 &tile_image->exception);
2090 if (p == (const PixelPacket *) NULL)
2092 indexes=GetVirtualIndexQueue(tile_image);
2093 for (x=0; x < (long) tile_image->columns; x++)
2095 Ascii85Encode(image,ScaleQuantumToChar(p->red));
2096 Ascii85Encode(image,ScaleQuantumToChar(p->green));
2097 Ascii85Encode(image,ScaleQuantumToChar(p->blue));
2098 if (image->colorspace == CMYKColorspace)
2099 Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
2103 Ascii85Flush(image);
2110 Dump number of colors and colormap.
2112 switch (compression)
2114 case RLECompression:
2118 Allocate pixel array.
2120 length=(size_t) number_pixels;
2121 pixels=(unsigned char *) AcquireQuantumMemory(length,
2123 if (pixels == (unsigned char *) NULL)
2125 tile_image=DestroyImage(tile_image);
2126 ThrowWriterException(ResourceLimitError,
2127 "MemoryAllocationFailed");
2130 Dump Runlength encoded pixels.
2133 for (y=0; y < (long) tile_image->rows; y++)
2135 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2136 &tile_image->exception);
2137 if (p == (const PixelPacket *) NULL)
2139 indexes=GetVirtualIndexQueue(tile_image);
2140 for (x=0; x < (long) tile_image->columns; x++)
2141 *q++=(unsigned char) indexes[x];
2143 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2144 if (compression == ZipCompression)
2145 status=ZLIBEncodeImage(image,length,pixels);
2148 if (compression == LZWCompression)
2149 status=LZWEncodeImage(image,length,pixels);
2151 status=PackbitsEncodeImage(image,length,pixels);
2152 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2153 if (status == MagickFalse)
2155 (void) CloseBlob(image);
2156 return(MagickFalse);
2163 Dump uncompressed PseudoColor packets.
2165 Ascii85Initialize(image);
2166 for (y=0; y < (long) tile_image->rows; y++)
2168 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2169 &tile_image->exception);
2170 if (p == (const PixelPacket *) NULL)
2172 indexes=GetVirtualIndexQueue(tile_image);
2173 for (x=0; x < (long) tile_image->columns; x++)
2174 Ascii85Encode(image,(unsigned char) indexes[x]);
2176 Ascii85Flush(image);
2181 tile_image=DestroyImage(tile_image);
2182 offset=TellBlob(image)-offset;
2183 (void) WriteBlobString(image,"\nendstream\n");
2184 (void) WriteBlobString(image,"endobj\n");
2186 Write Length object.
2188 xref[object++]=TellBlob(image);
2189 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2190 (void) WriteBlobString(image,buffer);
2191 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2192 (unsigned long) offset);
2193 (void) WriteBlobString(image,buffer);
2194 (void) WriteBlobString(image,"endobj\n");
2195 xref[object++]=TellBlob(image);
2196 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2197 (void) WriteBlobString(image,buffer);
2198 if ((image->storage_class != DirectClass) && (image->colors <= 256) &&
2199 (compression != FaxCompression) && (compression != Group4Compression))
2202 Write Colormap object.
2204 (void) WriteBlobString(image,"<<\n");
2205 if (compression == NoCompression)
2206 (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2207 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
2209 (void) WriteBlobString(image,buffer);
2210 (void) WriteBlobString(image,">>\n");
2211 (void) WriteBlobString(image,"stream\n");
2212 offset=TellBlob(image);
2213 if (compression == NoCompression)
2214 Ascii85Initialize(image);
2215 for (i=0; i < (long) image->colors; i++)
2217 if (compression == NoCompression)
2219 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].red));
2220 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].green));
2221 Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].blue));
2224 (void) WriteBlobByte(image,
2225 ScaleQuantumToChar(image->colormap[i].red));
2226 (void) WriteBlobByte(image,
2227 ScaleQuantumToChar(image->colormap[i].green));
2228 (void) WriteBlobByte(image,
2229 ScaleQuantumToChar(image->colormap[i].blue));
2231 if (compression == NoCompression)
2232 Ascii85Flush(image);
2233 offset=TellBlob(image)-offset;
2234 (void) WriteBlobString(image,"\nendstream\n");
2236 (void) WriteBlobString(image,"endobj\n");
2238 Write Length object.
2240 xref[object++]=TellBlob(image);
2241 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2242 (void) WriteBlobString(image,buffer);
2243 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2244 (unsigned long) offset);
2245 (void) WriteBlobString(image,buffer);
2246 (void) WriteBlobString(image,"endobj\n");
2248 Write softmask object.
2250 xref[object++]=TellBlob(image);
2251 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2252 (void) WriteBlobString(image,buffer);
2253 (void) WriteBlobString(image,"<<\n");
2254 if (image->matte == MagickFalse)
2255 (void) WriteBlobString(image,">>\n");
2258 (void) WriteBlobString(image,"/Type /XObject\n");
2259 (void) WriteBlobString(image,"/Subtype /Image\n");
2260 (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Ma%lu\n",
2262 (void) WriteBlobString(image,buffer);
2263 switch (compression)
2267 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2271 case LZWCompression:
2273 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
2276 case ZipCompression:
2278 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2284 (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2289 (void) WriteBlobString(image,buffer);
2290 (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
2292 (void) WriteBlobString(image,buffer);
2293 (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",
2295 (void) WriteBlobString(image,buffer);
2296 (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2297 (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
2298 (compression == FaxCompression) || (compression == Group4Compression)
2300 (void) WriteBlobString(image,buffer);
2301 (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
2303 (void) WriteBlobString(image,buffer);
2304 (void) WriteBlobString(image,">>\n");
2305 (void) WriteBlobString(image,"stream\n");
2306 offset=TellBlob(image);
2307 number_pixels=(MagickSizeType) image->columns*image->rows;
2308 switch (compression)
2310 case RLECompression:
2314 Allocate pixel array.
2316 length=(size_t) number_pixels;
2317 pixels=(unsigned char *) AcquireQuantumMemory(length,
2319 if (pixels == (unsigned char *) NULL)
2321 image=DestroyImage(image);
2322 ThrowWriterException(ResourceLimitError,
2323 "MemoryAllocationFailed");
2326 Dump Runlength encoded pixels.
2329 for (y=0; y < (long) image->rows; y++)
2331 p=GetVirtualPixels(image,0,y,image->columns,1,
2333 if (p == (const PixelPacket *) NULL)
2335 for (x=0; x < (long) image->columns; x++)
2337 *q++=ScaleQuantumToChar((Quantum) (QuantumRange-p->opacity));
2341 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2342 if (compression == ZipCompression)
2343 status=ZLIBEncodeImage(image,length,pixels);
2346 if (compression == LZWCompression)
2347 status=LZWEncodeImage(image,length,pixels);
2349 status=PackbitsEncodeImage(image,length,pixels);
2350 pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2351 if (status == MagickFalse)
2353 (void) CloseBlob(image);
2354 return(MagickFalse);
2361 Dump uncompressed PseudoColor packets.
2363 Ascii85Initialize(image);
2364 for (y=0; y < (long) image->rows; y++)
2366 p=GetVirtualPixels(image,0,y,image->columns,1,
2368 if (p == (const PixelPacket *) NULL)
2370 for (x=0; x < (long) image->columns; x++)
2372 Ascii85Encode(image,ScaleQuantumToChar((Quantum) (QuantumRange-
2377 Ascii85Flush(image);
2381 offset=TellBlob(image)-offset;
2382 (void) WriteBlobString(image,"\nendstream\n");
2384 (void) WriteBlobString(image,"endobj\n");
2386 Write Length object.
2388 xref[object++]=TellBlob(image);
2389 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2390 (void) WriteBlobString(image,buffer);
2391 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
2393 (void) WriteBlobString(image,buffer);
2394 (void) WriteBlobString(image,"endobj\n");
2395 if (GetNextImageInList(image) == (Image *) NULL)
2397 image=SyncNextImageInList(image);
2398 status=SetImageProgress(image,SaveImagesTag,scene++,
2399 GetImageListLength(image));
2400 if (status == MagickFalse)
2402 } while (image_info->adjoin != MagickFalse);
2404 Write Metadata object.
2406 xref[object++]=TellBlob(image);
2408 (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2409 (void) WriteBlobString(image,buffer);
2410 (void) WriteBlobString(image,"<<\n");
2411 (void) FormatMagickString(buffer,MaxTextExtent,"/Title (%s)\n",
2412 EscapeParenthesis(image->filename));
2413 (void) WriteBlobString(image,buffer);
2414 seconds=time((time_t *) NULL);
2415 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2416 (void) localtime_r(&seconds,&local_time);
2418 (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2420 (void) FormatMagickString(date,MaxTextExtent,"D:%04d%02d%02d%02d%02d%02d",
2421 local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2422 local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2423 (void) FormatMagickString(buffer,MaxTextExtent,"/CreationDate (%s)\n",date);
2424 (void) WriteBlobString(image,buffer);
2425 (void) FormatMagickString(buffer,MaxTextExtent,"/ModDate (%s)\n",date);
2426 (void) WriteBlobString(image,buffer);
2427 (void) FormatMagickString(buffer,MaxTextExtent,"/Producer (%s)\n",
2428 EscapeParenthesis(GetMagickVersion((unsigned long *) NULL)));
2429 (void) WriteBlobString(image,buffer);
2430 (void) WriteBlobString(image,">>\n");
2431 (void) WriteBlobString(image,"endobj\n");
2435 offset=TellBlob(image)-xref[0]+10;
2436 (void) WriteBlobString(image,"xref\n");
2437 (void) FormatMagickString(buffer,MaxTextExtent,"0 %lu\n",object+1);
2438 (void) WriteBlobString(image,buffer);
2439 (void) WriteBlobString(image,"0000000000 65535 f \n");
2440 for (i=0; i < (long) object; i++)
2442 (void) FormatMagickString(buffer,MaxTextExtent,"%010lu 00000 n \n",
2443 (unsigned long) xref[i]);
2444 (void) WriteBlobString(image,buffer);
2446 (void) WriteBlobString(image,"trailer\n");
2447 (void) WriteBlobString(image,"<<\n");
2448 (void) FormatMagickString(buffer,MaxTextExtent,"/Size %lu\n",object+1);
2449 (void) WriteBlobString(image,buffer);
2450 (void) FormatMagickString(buffer,MaxTextExtent,"/Info %lu 0 R\n",info_id);
2451 (void) WriteBlobString(image,buffer);
2452 (void) FormatMagickString(buffer,MaxTextExtent,"/Root %lu 0 R\n",root_id);
2453 (void) WriteBlobString(image,buffer);
2454 (void) WriteBlobString(image,">>\n");
2455 (void) WriteBlobString(image,"startxref\n");
2456 (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2457 (unsigned long) offset);
2458 (void) WriteBlobString(image,buffer);
2459 (void) WriteBlobString(image,"%%EOF\n");
2460 xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2461 (void) CloseBlob(image);