]> granicus.if.org Git - imagemagick/blob - coders/pdf.c
13bfb24f03337c3dea41c4fb7a5ee1d7e1d3741a
[imagemagick] / coders / pdf.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 %                                                                             %
4 %                                                                             %
5 %                                                                             %
6 %                            PPPP   DDDD   FFFFF                              %
7 %                            P   P  D   D  F                                  %
8 %                            PPPP   D   D  FFF                                %
9 %                            P      D   D  F                                  %
10 %                            P      DDDD   F                                  %
11 %                                                                             %
12 %                                                                             %
13 %                   Read/Write Portable Document Format                       %
14 %                                                                             %
15 %                              Software Design                                %
16 %                                John Cristy                                  %
17 %                                 July 1992                                   %
18 %                                                                             %
19 %                                                                             %
20 %  Copyright 1999-2009 ImageMagick Studio LLC, a non-profit organization      %
21 %  dedicated to making software imaging solutions freely available.           %
22 %                                                                             %
23 %  You may not use this file except in compliance with the License.  You may  %
24 %  obtain a copy of the License at                                            %
25 %                                                                             %
26 %    http://www.imagemagick.org/script/license.php                            %
27 %                                                                             %
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.                                             %
33 %                                                                             %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 \f
39 /*
40   Include declarations.
41 */
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 #if defined(MAGICKCORE_HAVE_TIFFCONF_H)
78 #include "tiffconf.h"
79 #endif
80 #include "tiffio.h"
81 #define CCITTParam  "-1"
82 #else
83 #define CCITTParam  "0"
84 #endif
85 \f
86 /*
87   Forward declarations.
88 */
89 static MagickBooleanType
90   WritePDFImage(const ImageInfo *,Image *);
91 \f
92 /*
93 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
94 %                                                                             %
95 %                                                                             %
96 %                                                                             %
97 %   I n v o k e P D F D e l e g a t e                                         %
98 %                                                                             %
99 %                                                                             %
100 %                                                                             %
101 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
102 %
103 %  InvokePDFDelegate() executes the PDF interpreter with the specified command.
104 %
105 %  The format of the InvokePDFDelegate method is:
106 %
107 %      MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
108 %        const char *command,ExceptionInfo *exception)
109 %
110 %  A description of each parameter follows:
111 %
112 %    o verbose: A value other than zero displays the command prior to
113 %      executing it.
114 %
115 %    o command: the address of a character string containing the command to
116 %      execute.
117 %
118 %    o exception: return any errors or warnings in this structure.
119 %
120 */
121 static MagickBooleanType InvokePDFDelegate(const MagickBooleanType verbose,
122   const char *command,ExceptionInfo *exception)
123 {
124   int
125     status;
126
127 #if defined(MAGICKCORE_GS_DELEGATE) || defined(__WINDOWS__)
128   char
129     **argv;
130
131   const GhostInfo
132     *ghost_info;
133
134   gs_main_instance
135     *interpreter;
136
137   int
138     argc,
139     code;
140
141   register long
142     i;
143
144 #if defined(__WINDOWS__)
145   ghost_info=NTGhostscriptDLLVectors();
146 #else
147   GhostInfo
148     ghost_info_struct;
149
150   ghost_info=(&ghost_info_struct);
151   (void) ResetMagickMemory(&ghost_info,0,sizeof(ghost_info));
152   ghost_info_struct.new_instance=(int (*)(gs_main_instance **,void *))
153     gsapi_new_instance;
154   ghost_info_struct.init_with_args=(int (*)(gs_main_instance *,int,char **))
155     gsapi_init_with_args;
156   ghost_info_struct.run_string=(int (*)(gs_main_instance *,const char *,int,
157     int *)) gsapi_run_string;
158   ghost_info_struct.delete_instance=(void (*)(gs_main_instance *))
159     gsapi_delete_instance;
160   ghost_info_struct.exit=(int (*)(gs_main_instance *)) gsapi_exit;
161 #endif
162   if (ghost_info == (GhostInfo *) NULL)
163     {
164       status=SystemCommand(verbose,command,exception);
165       return(status == 0 ? MagickTrue : MagickFalse);
166     }
167   if (verbose != MagickFalse)
168     {
169       (void) fputs("[ghostscript library]",stdout);
170       (void) fputs(strchr(command,' '),stdout);
171     }
172   status=(ghost_info->new_instance)(&interpreter,(void *) NULL);
173   if (status < 0)
174     {
175       status=SystemCommand(verbose,command,exception);
176       return(status == 0 ? MagickTrue : MagickFalse);
177     }
178   argv=StringToArgv(command,&argc);
179   status=(ghost_info->init_with_args)(interpreter,argc-1,argv+1);
180   if (status == 0)
181     status=(ghost_info->run_string)(interpreter,"systemdict /start get exec\n",
182       0,&code);
183   (ghost_info->exit)(interpreter);
184   (ghost_info->delete_instance)(interpreter);
185 #if defined(__WINDOWS__)
186   NTGhostscriptUnLoadDLL();
187 #endif
188   for (i=0; i < (long) argc; i++)
189     argv[i]=DestroyString(argv[i]);
190   argv=(char **) RelinquishMagickMemory(argv);
191   if ((status != 0) && (status != -101))
192     {
193       char
194         *message;
195
196       message=GetExceptionMessage(errno);
197       (void) ThrowMagickException(exception,GetMagickModule(),DelegateError,
198         "`%s': %s",command,message);
199       message=DestroyString(message);
200       (void) LogMagickEvent(CoderEvent,GetMagickModule(),
201         "Ghostscript returns status %d, exit code %d",status,code);
202       return(MagickFalse);
203     }
204   return(MagickTrue);
205 #else
206   status=SystemCommand(verbose,command,exception);
207   return(status == 0 ? MagickTrue : MagickFalse);
208 #endif
209 }
210 \f
211 /*
212 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
213 %                                                                             %
214 %                                                                             %
215 %                                                                             %
216 %   I s P D F                                                                 %
217 %                                                                             %
218 %                                                                             %
219 %                                                                             %
220 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
221 %
222 %  IsPDF() returns MagickTrue if the image format type, identified by the
223 %  magick string, is PDF.
224 %
225 %  The format of the IsPDF method is:
226 %
227 %      MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
228 %
229 %  A description of each parameter follows:
230 %
231 %    o magick: compare image format pattern against these bytes.
232 %
233 %    o offset: Specifies the offset of the magick string.
234 %
235 */
236 static MagickBooleanType IsPDF(const unsigned char *magick,const size_t offset)
237 {
238   if (offset < 5)
239     return(MagickFalse);
240   if (LocaleNCompare((const char *) magick,"%PDF-",5) == 0)
241     return(MagickTrue);
242   return(MagickFalse);
243 }
244 \f
245 /*
246 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
247 %                                                                             %
248 %                                                                             %
249 %                                                                             %
250 %   R e a d P D F I m a g e                                                   %
251 %                                                                             %
252 %                                                                             %
253 %                                                                             %
254 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
255 %
256 %  ReadPDFImage() reads a Portable Document Format image file and
257 %  returns it.  It allocates the memory necessary for the new Image structure
258 %  and returns a pointer to the new image.
259 %
260 %  The format of the ReadPDFImage method is:
261 %
262 %      Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
263 %
264 %  A description of each parameter follows:
265 %
266 %    o image_info: the image info.
267 %
268 %    o exception: return any errors or warnings in this structure.
269 %
270 */
271
272 static MagickBooleanType IsPDFRendered(const char *path)
273 {
274   MagickBooleanType
275     status;
276
277   struct stat
278     attributes;
279
280   if ((path == (const char *) NULL) || (*path == '\0'))
281     return(MagickFalse);
282   status=GetPathAttributes(path,&attributes);
283   if ((status != MagickFalse) && S_ISREG(attributes.st_mode) &&
284       (attributes.st_size > 0))
285     return(MagickTrue);
286   return(MagickFalse);
287 }
288
289 static Image *ReadPDFImage(const ImageInfo *image_info,ExceptionInfo *exception)
290 {
291 #define CropBox  "CropBox"
292 #define DeviceCMYK  "DeviceCMYK"
293 #define MediaBox  "MediaBox"
294 #define RenderPostscriptText  "Rendering Postscript...  "
295 #define PDFRotate  "Rotate"
296 #define SpotColor  "Separation"
297 #define TrimBox  "TrimBox"
298 #define PDFVersion  "PDF-"
299
300   char
301     command[MaxTextExtent],
302     density[MaxTextExtent],
303     filename[MaxTextExtent],
304     geometry[MaxTextExtent],
305     options[MaxTextExtent],
306     input_filename[MaxTextExtent],
307     postscript_filename[MaxTextExtent];
308
309   const char
310     *option;
311
312   const DelegateInfo
313     *delegate_info;
314
315   double
316     angle;
317
318   Image
319     *image,
320     *next,
321     *pdf_image;
322
323   ImageInfo
324     *read_info;
325
326   int
327     file;
328
329   MagickBooleanType
330     cmyk,
331     cropbox,
332     trimbox,
333     status;
334
335   PointInfo
336     delta;
337
338   RectangleInfo
339     bounding_box,
340     page;
341
342   register char
343     *p;
344
345   register int
346     c;
347
348   SegmentInfo
349     bounds,
350     hires_bounds;
351
352   ssize_t
353     count;
354
355   unsigned long
356     scene,
357     spotcolor;
358
359   assert(image_info != (const ImageInfo *) NULL);
360   assert(image_info->signature == MagickSignature);
361   if (image_info->debug != MagickFalse)
362     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
363       image_info->filename);
364   assert(exception != (ExceptionInfo *) NULL);
365   assert(exception->signature == MagickSignature);
366   /*
367     Open image file.
368   */
369   image=AcquireImage(image_info);
370   status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
371   if (status == MagickFalse)
372     {
373       image=DestroyImageList(image);
374       return((Image *) NULL);
375     }
376   status=AcquireUniqueSymbolicLink(image_info->filename,input_filename);
377   if (status == MagickFalse)
378     {
379       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
380         image_info->filename);
381       image=DestroyImageList(image);
382       return((Image *) NULL);
383     }
384   /*
385     Set the page density.
386   */
387   delta.x=DefaultResolution;
388   delta.y=DefaultResolution;
389   if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
390     {
391       GeometryInfo
392         geometry_info;
393
394       MagickStatusType
395         flags;
396
397       flags=ParseGeometry(PSDensityGeometry,&geometry_info);
398       image->x_resolution=geometry_info.rho;
399       image->y_resolution=geometry_info.sigma;
400       if ((flags & SigmaValue) == 0)
401         image->y_resolution=image->x_resolution;
402     }
403   /*
404     Determine page geometry from the PDF media box.
405   */
406   cmyk=image_info->colorspace == CMYKColorspace ? MagickTrue : MagickFalse;
407   cropbox=MagickFalse;
408   option=GetImageOption(image_info,"pdf:use-cropbox");
409   if (option != (const char *) NULL)
410     cropbox=IsMagickTrue(option);
411   trimbox=MagickFalse;
412   option=GetImageOption(image_info,"pdf:use-trimbox");
413   if (option != (const char *) NULL)
414     trimbox=IsMagickTrue(option);
415   count=0;
416   spotcolor=0;
417   (void) ResetMagickMemory(&bounding_box,0,sizeof(bounding_box));
418   (void) ResetMagickMemory(&bounds,0,sizeof(bounds));
419   (void) ResetMagickMemory(&hires_bounds,0,sizeof(hires_bounds));
420   (void) ResetMagickMemory(&page,0,sizeof(page));
421   (void) ResetMagickMemory(command,0,sizeof(command));
422   hires_bounds.x2=0.0;
423   hires_bounds.y2=0.0;
424   angle=0.0;
425   p=command;
426   for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
427   {
428     /*
429       Note PDF elements.
430     */
431     if (c == '\n')
432       c=' ';
433     *p++=(char) c;
434     if ((c != (int) '/') && (c != (int) '%') && 
435         ((size_t) (p-command) < (MaxTextExtent-1)))
436       continue;
437     *(--p)='\0';
438     p=command;
439     if (LocaleNCompare(PDFRotate,command,strlen(PDFRotate)) == 0)
440       count=(ssize_t) sscanf(command,"Rotate %lf",&angle);
441     /*
442       Is this a CMYK document?
443     */
444     if (LocaleNCompare(DeviceCMYK,command,strlen(DeviceCMYK)) == 0)
445       cmyk=MagickTrue;
446     if (LocaleNCompare(SpotColor,command,strlen(SpotColor)) == 0)
447       {
448         char
449           name[MaxTextExtent],
450           property[MaxTextExtent],
451           *value;
452
453         register long
454           i;
455
456         /*
457           Note spot names.
458         */
459         (void) FormatMagickString(property,MaxTextExtent,"pdf:SpotColor-%lu",
460           spotcolor++);
461         i=0;
462         for (c=ReadBlobByte(image); c != EOF; c=ReadBlobByte(image))
463         {
464           if ((isspace(c) != 0) || (c == '/') || ((i+1) == MaxTextExtent))
465             break;
466           name[i++]=(char) c;
467         }
468         name[i]='\0';
469         value=AcquireString(name);
470         (void) SubstituteString(&value,"#20"," ");
471         (void) SetImageProperty(image,property,value);
472         value=DestroyString(value);
473         continue;
474       }
475     if (LocaleNCompare(PDFVersion,command,strlen(PDFVersion)) == 0)
476       (void) SetImageProperty(image,"pdf:Version",command);
477     count=0;
478     if (cropbox != MagickFalse)
479       {
480         if (LocaleNCompare(CropBox,command,strlen(CropBox)) == 0)
481           {
482             /*
483               Note region defined by crop box.
484             */
485             count=(ssize_t) sscanf(command,"CropBox [%lf %lf %lf %lf",
486               &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
487             if (count != 4)
488               count=(ssize_t) sscanf(command,"CropBox[%lf %lf %lf %lf",
489                 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
490           }
491       }
492     else
493       if (trimbox != MagickFalse)
494         {
495           if (LocaleNCompare(TrimBox,command,strlen(TrimBox)) == 0)
496             {
497               /*
498                 Note region defined by trim box.
499               */
500               count=(ssize_t) sscanf(command,"TrimBox [%lf %lf %lf %lf",
501                 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
502               if (count != 4)
503                 count=(ssize_t) sscanf(command,"TrimBox[%lf %lf %lf %lf",
504                   &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
505             }
506         }
507       else
508         if (LocaleNCompare(MediaBox,command,strlen(MediaBox)) == 0)
509           {
510             /*
511               Note region defined by media box.
512             */
513             count=(ssize_t) sscanf(command,"MediaBox [%lf %lf %lf %lf",
514               &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
515             if (count != 4)
516               count=(ssize_t) sscanf(command,"MediaBox[%lf %lf %lf %lf",
517                 &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
518           }
519     if (count != 4)
520       continue;
521     if (((bounds.x2 > hires_bounds.x2) && (bounds.y2 > hires_bounds.y2)) ||
522         ((hires_bounds.x2 == 0.0) && (hires_bounds.y2 == 0.0)))
523       {
524         /*
525           Set PDF render geometry.
526         */
527         (void) FormatMagickString(geometry,MaxTextExtent,"%gx%g%+g%+g",
528           bounds.x2-bounds.x1,bounds.y2-bounds.y1,bounds.x1,bounds.y1);
529         (void) SetImageProperty(image,"pdf:HiResBoundingBox",geometry);
530         page.width=(unsigned long) (bounds.x2-bounds.x1+0.5);
531         page.height=(unsigned long) (bounds.y2-bounds.y1+0.5);
532         hires_bounds=bounds;
533       }
534   }
535   (void) CloseBlob(image);
536   if ((fabs(angle) == 90.0) || (fabs(angle) == 270.0))
537     {
538       unsigned long
539         swap;
540
541       swap=page.width;
542       page.width=page.height;
543       page.height=swap;
544     }
545   if (image_info->colorspace == RGBColorspace)
546     cmyk=MagickFalse;
547   /*
548     Create Ghostscript control file.
549   */
550   file=AcquireUniqueFileResource(postscript_filename);
551   if (file == -1)
552     {
553       ThrowFileException(exception,FileOpenError,"UnableToCreateTemporaryFile",
554         image_info->filename);
555       image=DestroyImage(image);
556       return((Image *) NULL);
557     }
558   count=write(file," ",1);
559   file=close(file)-1;
560   /*
561     Render Postscript with the Ghostscript delegate.
562   */
563   if ((image_info->ping != MagickFalse) ||
564       (image_info->monochrome != MagickFalse))
565     delegate_info=GetDelegateInfo("ps:mono",(char *) NULL,exception);
566   else
567      if (cmyk != MagickFalse)
568        delegate_info=GetDelegateInfo("ps:cmyk",(char *) NULL,exception);
569      else
570        if (LocaleCompare(image_info->magick,"AI") == 0)
571          delegate_info=GetDelegateInfo("ps:alpha",(char *) NULL,exception);
572        else
573          delegate_info=GetDelegateInfo("ps:color",(char *) NULL,exception);
574   if (delegate_info == (const DelegateInfo *) NULL)
575     {
576       (void) RelinquishUniqueFileResource(postscript_filename);
577       image=DestroyImage(image);
578       return((Image *) NULL);
579     }
580   *options='\0';
581   (void) FormatMagickString(density,MaxTextExtent,"%gx%g",image->x_resolution,
582     image->y_resolution);
583   if (image_info->page != (char *) NULL)
584     {
585       (void) ParseAbsoluteGeometry(image_info->page,&page);
586       page.width=(unsigned long) (page.width*image->x_resolution/delta.x+0.5);
587       page.height=(unsigned long) (page.height*image->y_resolution/delta.y+0.5);
588       (void) FormatMagickString(options,MaxTextExtent,"-g%lux%lu ",page.width,
589         page.height);
590     }
591   if (cmyk != MagickFalse)
592     (void) ConcatenateMagickString(options,"-dUseCIEColor ",MaxTextExtent);
593   if (cropbox != MagickFalse)
594     (void) ConcatenateMagickString(options,"-dUseCropBox ",MaxTextExtent);
595   if (trimbox != MagickFalse)
596     (void) ConcatenateMagickString(options,"-dUseTrimBox ",MaxTextExtent);
597   read_info=CloneImageInfo(image_info);
598   *read_info->magick='\0';
599   if (read_info->number_scenes != 0)
600     {
601       char
602         pages[MaxTextExtent];
603
604       (void) FormatMagickString(pages,MaxTextExtent,"-dFirstPage=%lu "
605         "-dLastPage=%lu",read_info->scene+1,read_info->scene+
606         read_info->number_scenes);
607       (void) ConcatenateMagickString(options,pages,MaxTextExtent);
608       read_info->number_scenes=0;
609       if (read_info->scenes != (char *) NULL)
610         *read_info->scenes='\0';
611     }
612   if (read_info->authenticate != (char *) NULL)
613     (void) FormatMagickString(options+strlen(options),MaxTextExtent,
614       " -sPDFPassword=%s",read_info->authenticate);
615   (void) CopyMagickString(filename,read_info->filename,MaxTextExtent);
616   (void) AcquireUniqueFilename(read_info->filename);
617   (void) FormatMagickString(command,MaxTextExtent,
618     GetDelegateCommands(delegate_info),
619     read_info->antialias != MagickFalse ? 4 : 1,
620     read_info->antialias != MagickFalse ? 4 : 1,density,options,
621     read_info->filename,postscript_filename,input_filename);
622   status=InvokePDFDelegate(read_info->verbose,command,exception);
623   pdf_image=(Image *) NULL;
624   if ((status != MagickFalse) &&
625       (IsPDFRendered(read_info->filename) != MagickFalse))
626     pdf_image=ReadImage(read_info,exception);
627   (void) RelinquishUniqueFileResource(postscript_filename);
628   (void) RelinquishUniqueFileResource(read_info->filename);
629   (void) RelinquishUniqueFileResource(input_filename);
630   read_info=DestroyImageInfo(read_info);
631   if (pdf_image == (Image *) NULL)
632     {
633       ThrowFileException(exception,DelegateError,"PostscriptDelegateFailed",
634         image_info->filename);
635       return((Image *) NULL);
636     }
637   if (LocaleCompare(pdf_image->magick,"BMP") == 0)
638     {
639       Image
640         *cmyk_image;
641
642       cmyk_image=ConsolidateCMYKImages(pdf_image,exception);
643       if (cmyk_image != (Image *) NULL)
644         {
645           pdf_image=DestroyImageList(pdf_image);
646           pdf_image=cmyk_image;
647         }
648     }
649   if (image_info->number_scenes != 0)
650     {
651       Image
652         *clone_image;
653
654       register long
655         i;
656
657       /*
658         Add place holder images to meet the subimage specification requirement.
659       */
660       for (i=0; i < (long) image_info->scene; i++)
661       {
662         clone_image=CloneImage(pdf_image,1,1,MagickTrue,exception);
663         if (clone_image != (Image *) NULL)
664           PrependImageToList(&pdf_image,clone_image);
665       }
666     }
667   do
668   {
669     (void) CopyMagickString(pdf_image->filename,filename,MaxTextExtent);
670     pdf_image->page=page;
671     (void) CloneImageProfiles(pdf_image,image);
672     (void) CloneImageProperties(pdf_image,image);
673     next=SyncNextImageInList(pdf_image);
674     if (next != (Image *) NULL)
675       pdf_image=next;
676   } while (next != (Image *) NULL);
677   image=DestroyImage(image);
678   scene=0;
679   for (next=GetFirstImageInList(pdf_image); next != (Image *) NULL; )
680   {
681     next->scene=scene++;
682     next=GetNextImageInList(next);
683   }
684   return(GetFirstImageInList(pdf_image));
685 }
686 \f
687 /*
688 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
689 %                                                                             %
690 %                                                                             %
691 %                                                                             %
692 %   R e g i s t e r P D F I m a g e                                           %
693 %                                                                             %
694 %                                                                             %
695 %                                                                             %
696 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
697 %
698 %  RegisterPDFImage() adds properties for the PDF image format to
699 %  the list of supported formats.  The properties include the image format
700 %  tag, a method to read and/or write the format, whether the format
701 %  supports the saving of more than one frame to the same file or blob,
702 %  whether the format supports native in-memory I/O, and a brief
703 %  description of the format.
704 %
705 %  The format of the RegisterPDFImage method is:
706 %
707 %      unsigned long RegisterPDFImage(void)
708 %
709 */
710 ModuleExport unsigned long RegisterPDFImage(void)
711 {
712   MagickInfo
713     *entry;
714
715   entry=SetMagickInfo("AI");
716   entry->decoder=(DecodeImageHandler *) ReadPDFImage;
717   entry->encoder=(EncodeImageHandler *) WritePDFImage;
718   entry->adjoin=MagickFalse;
719   entry->blob_support=MagickFalse;
720   entry->seekable_stream=MagickTrue;
721   entry->thread_support=EncoderThreadSupport;
722   entry->description=ConstantString("Adobe Illustrator CS2");
723   entry->module=ConstantString("PDF");
724   (void) RegisterMagickInfo(entry);
725   entry=SetMagickInfo("EPDF");
726   entry->decoder=(DecodeImageHandler *) ReadPDFImage;
727   entry->encoder=(EncodeImageHandler *) WritePDFImage;
728   entry->adjoin=MagickFalse;
729   entry->blob_support=MagickFalse;
730   entry->seekable_stream=MagickTrue;
731   entry->thread_support=EncoderThreadSupport;
732   entry->description=ConstantString("Encapsulated Portable Document Format");
733   entry->module=ConstantString("PDF");
734   (void) RegisterMagickInfo(entry);
735   entry=SetMagickInfo("PDF");
736   entry->decoder=(DecodeImageHandler *) ReadPDFImage;
737   entry->encoder=(EncodeImageHandler *) WritePDFImage;
738   entry->magick=(IsImageFormatHandler *) IsPDF;
739   entry->blob_support=MagickFalse;
740   entry->seekable_stream=MagickTrue;
741   entry->thread_support=EncoderThreadSupport;
742   entry->description=ConstantString("Portable Document Format");
743   entry->module=ConstantString("PDF");
744   (void) RegisterMagickInfo(entry);
745   entry=SetMagickInfo("PDFA");
746   entry->decoder=(DecodeImageHandler *) ReadPDFImage;
747   entry->encoder=(EncodeImageHandler *) WritePDFImage;
748   entry->magick=(IsImageFormatHandler *) IsPDF;
749   entry->blob_support=MagickFalse;
750   entry->seekable_stream=MagickTrue;
751   entry->thread_support=EncoderThreadSupport;
752   entry->description=ConstantString("Portable Document Archive Format");
753   entry->module=ConstantString("PDF");
754   (void) RegisterMagickInfo(entry);
755   return(MagickImageCoderSignature);
756 }
757 \f
758 /*
759 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
760 %                                                                             %
761 %                                                                             %
762 %                                                                             %
763 %   U n r e g i s t e r P D F I m a g e                                       %
764 %                                                                             %
765 %                                                                             %
766 %                                                                             %
767 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
768 %
769 %  UnregisterPDFImage() removes format registrations made by the
770 %  PDF module from the list of supported formats.
771 %
772 %  The format of the UnregisterPDFImage method is:
773 %
774 %      UnregisterPDFImage(void)
775 %
776 */
777 ModuleExport void UnregisterPDFImage(void)
778 {
779   (void) UnregisterMagickInfo("AI");
780   (void) UnregisterMagickInfo("EPDF");
781   (void) UnregisterMagickInfo("PDF");
782   (void) UnregisterMagickInfo("PDFA");
783 }
784 \f
785 /*
786 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787 %                                                                             %
788 %                                                                             %
789 %                                                                             %
790 %   W r i t e P D F I m a g e                                                 %
791 %                                                                             %
792 %                                                                             %
793 %                                                                             %
794 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
795 %
796 %  WritePDFImage() writes an image in the Portable Document image
797 %  format.
798 %
799 %  The format of the WritePDFImage method is:
800 %
801 %      MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
802 %
803 %  A description of each parameter follows.
804 %
805 %    o image_info: the image info.
806 %
807 %    o image:  The image.
808 %
809 */
810
811 static inline size_t MagickMax(const size_t x,const size_t y)
812 {
813   if (x > y)
814     return(x);
815   return(y);
816 }
817
818 static inline size_t MagickMin(const size_t x,const size_t y)
819 {
820   if (x < y)
821     return(x);
822   return(y);
823 }
824
825 static char *EscapeParenthesis(const char *text)
826 {
827   register char
828     *p;
829
830   register long
831     i;
832
833   static char
834     buffer[MaxTextExtent];
835
836   unsigned long
837     escapes;
838
839   escapes=0;
840   p=buffer;
841   for (i=0; i < (long) MagickMin(strlen(text),(MaxTextExtent-escapes-1)); i++)
842   {
843     if ((text[i] == '(') || (text[i] == ')'))
844       {
845         *p++='\\';
846         escapes++;
847       }
848     *p++=text[i];
849   }
850   *p='\0';
851   return(buffer);
852 }
853
854 #if defined(MAGICKCORE_TIFF_DELEGATE)
855 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
856   Image *image,Image *inject_image)
857 {
858   char
859     filename[MaxTextExtent];
860
861   FILE
862     *file;
863
864   Image
865     *huffman_image;
866
867   ImageInfo
868     *write_info;
869
870   int
871     unique_file;
872
873   MagickBooleanType
874     status;
875
876   register long
877     i;
878
879   ssize_t
880     count;
881
882   TIFF
883     *tiff;
884
885   uint16
886     fillorder;
887
888   uint32
889     *byte_count,
890     strip_size;
891
892   unsigned char
893     *buffer;
894
895   /*
896     Write image as CCITTFax4 TIFF image to a temporary file.
897   */
898   assert(image_info != (const ImageInfo *) NULL);
899   assert(image_info->signature == MagickSignature);
900   assert(image != (Image *) NULL);
901   assert(image->signature == MagickSignature);
902   if (image->debug != MagickFalse)
903     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
904   assert(inject_image != (Image *) NULL);
905   assert(inject_image->signature == MagickSignature);
906   huffman_image=CloneImage(inject_image,0,0,MagickTrue,&image->exception);
907   if (huffman_image == (Image *) NULL)
908     return(MagickFalse);
909   file=(FILE *) NULL;
910   unique_file=AcquireUniqueFileResource(filename);
911   if (unique_file != -1)
912     file=fdopen(unique_file,"wb"); 
913   if ((unique_file == -1) || (file == (FILE *) NULL))
914     {
915       ThrowFileException(&image->exception,FileOpenError,
916         "UnableToCreateTemporaryFile",filename);
917       return(MagickFalse);
918     }
919   (void) FormatMagickString(huffman_image->filename,MaxTextExtent,"tiff:%s",
920     filename);
921   write_info=CloneImageInfo(image_info);
922   SetImageInfoFile(write_info,file);
923   write_info->compression=Group4Compression;
924   (void) SetImageOption(write_info,"quantum:polarity","min-is-white");
925   status=WriteImage(write_info,huffman_image);
926   (void) fflush(file);
927   write_info=DestroyImageInfo(write_info);
928   if (status == MagickFalse)
929     return(MagickFalse);
930   tiff=TIFFOpen(filename,"rb");
931   if (tiff == (TIFF *) NULL)
932     {
933       huffman_image=DestroyImage(huffman_image);
934       (void) fclose(file);
935       (void) RelinquishUniqueFileResource(filename);
936       ThrowFileException(&image->exception,FileOpenError,"UnableToOpenFile",
937         image_info->filename);
938       return(MagickFalse);
939     }
940   /*
941     Allocate raw strip buffer.
942   */
943   byte_count=0;
944   (void) TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count);
945   strip_size=byte_count[0];
946   for (i=1; i < (long) TIFFNumberOfStrips(tiff); i++)
947     if (byte_count[i] > strip_size)
948       strip_size=byte_count[i];
949   buffer=(unsigned char *) AcquireQuantumMemory((size_t) strip_size,
950     sizeof(*buffer));
951   if (buffer == (unsigned char *) NULL)
952     {
953       TIFFClose(tiff);
954       huffman_image=DestroyImage(huffman_image);
955       (void) fclose(file);
956       (void) RelinquishUniqueFileResource(filename);
957       ThrowBinaryException(ResourceLimitError,"MemoryAllocationFailed",
958         image_info->filename);
959     }
960   /*
961     Compress runlength encoded to 2D Huffman pixels.
962   */
963   fillorder=FILLORDER_LSB2MSB;
964   (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fillorder);
965   for (i=0; i < (long) TIFFNumberOfStrips(tiff); i++)
966   {
967     count=(ssize_t) TIFFReadRawStrip(tiff,(uint32) i,buffer,(long)
968       byte_count[i]);
969     if (fillorder == FILLORDER_LSB2MSB)
970       TIFFReverseBits(buffer,(unsigned long) count);
971     (void) WriteBlob(image,(size_t) count,buffer);
972   }
973   buffer=(unsigned char *) RelinquishMagickMemory(buffer);
974   TIFFClose(tiff);
975   huffman_image=DestroyImage(huffman_image);
976   (void) fclose(file);
977   (void) RelinquishUniqueFileResource(filename);
978   return(MagickTrue);
979 }
980 #else
981 static MagickBooleanType Huffman2DEncodeImage(const ImageInfo *image_info,
982   Image *image,Image *inject_image)
983 {
984   assert(image_info != (const ImageInfo *) NULL);
985   assert(image_info->signature == MagickSignature);
986   assert(image != (Image *) NULL);
987   assert(image->signature == MagickSignature);
988   if (image->debug != MagickFalse)
989     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
990   assert(inject_image != (Image *) NULL);
991   assert(inject_image->signature == MagickSignature);
992   (void) ThrowMagickException(&image->exception,GetMagickModule(),
993     MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (TIFF)",
994     image->filename);
995   return(MagickFalse);
996 }
997 #endif
998
999 static MagickBooleanType WritePDFImage(const ImageInfo *image_info,Image *image)
1000 {
1001 #define CFormat  "/Filter [ /%s ]\n"
1002 #define ObjectsPerImage  14
1003
1004   static const char
1005     XMPProfile[]=
1006     {
1007       "<?xpacket begin=\"%s\" id=\"W5M0MpCehiHzreSzNTczkc9d\"?>\n"
1008       "<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"
1009       "   <rdf:RDF xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\">\n"
1010       "      <rdf:Description rdf:about=\"\"\n"
1011       "            xmlns:xap=\"http://ns.adobe.com/xap/1.0/\">\n"
1012       "         <xap:ModifyDate>%s</xap:ModifyDate>\n"
1013       "         <xap:CreateDate>%s</xap:CreateDate>\n"
1014       "         <xap:MetadataDate>%s</xap:MetadataDate>\n"
1015       "         <xap:CreatorTool>%s</xap:CreatorTool>\n"
1016       "      </rdf:Description>\n"
1017       "      <rdf:Description rdf:about=\"\"\n"
1018       "            xmlns:dc=\"http://purl.org/dc/elements/1.1/\">\n"
1019       "         <dc:format>application/pdf</dc:format>\n"
1020       "      </rdf:Description>\n"
1021       "      <rdf:Description rdf:about=\"\"\n"
1022       "            xmlns:xapMM=\"http://ns.adobe.com/xap/1.0/mm/\">\n"
1023       "         <xapMM:DocumentID>uuid:6ec119d7-7982-4f56-808d-dfe64f5b35cf</xapMM:DocumentID>\n"
1024       "         <xapMM:InstanceID>uuid:a79b99b4-6235-447f-9f6c-ec18ef7555cb</xapMM:InstanceID>\n"
1025       "      </rdf:Description>\n"
1026       "      <rdf:Description rdf:about=\"\"\n"
1027       "            xmlns:pdf=\"http://ns.adobe.com/pdf/1.3/\">\n"
1028       "         <pdf:Producer>%s</pdf:Producer>\n"
1029       "      </rdf:Description>\n"
1030       "      <rdf:Description rdf:about=\"\"\n"
1031       "            xmlns:pdfaid=\"http://www.aiim.org/pdfa/ns/id/\">\n"
1032       "         <pdfaid:part>1</pdfaid:part>\n"
1033       "         <pdfaid:conformance>B</pdfaid:conformance>\n"
1034       "      </rdf:Description>\n"
1035       "   </rdf:RDF>\n"
1036       "</x:xmpmeta>\n"
1037       "<?xpacket end=\"w\"?>\n"
1038     },
1039     XMPProfileMagick[4]= { (char) 0xef, (char) 0xbb, (char) 0xbf, (char) 0x00 };
1040
1041   char
1042     buffer[MaxTextExtent],
1043     date[MaxTextExtent],
1044     **labels,
1045     page_geometry[MaxTextExtent];
1046
1047   CompressionType
1048     compression;
1049
1050   const char
1051     *value;
1052
1053   double
1054     pointsize;
1055
1056   GeometryInfo
1057     geometry_info;
1058
1059   long
1060     count,
1061     y;
1062
1063   Image
1064     *next,
1065     *tile_image;
1066
1067   MagickBooleanType
1068     status;
1069
1070   MagickOffsetType
1071     offset,
1072     scene,
1073     *xref;
1074
1075   MagickSizeType
1076     number_pixels;
1077
1078   MagickStatusType
1079     flags;
1080
1081   PointInfo
1082     delta,
1083     resolution,
1084     scale;
1085
1086   RectangleInfo
1087     geometry,
1088     media_info,
1089     page_info;
1090
1091   register const IndexPacket
1092     *indexes;
1093
1094   register const PixelPacket
1095     *p;
1096
1097   register unsigned char
1098     *q;
1099
1100   register long
1101     i,
1102     x;
1103
1104   size_t
1105     length;
1106
1107   struct tm
1108     local_time;
1109
1110   time_t
1111     seconds;
1112
1113   unsigned char
1114     *pixels;
1115
1116   unsigned long
1117     info_id,
1118     object,
1119     pages_id,
1120     root_id,
1121     text_size,
1122     version;
1123
1124   /*
1125     Open output image file.
1126   */
1127   assert(image_info != (const ImageInfo *) NULL);
1128   assert(image_info->signature == MagickSignature);
1129   assert(image != (Image *) NULL);
1130   assert(image->signature == MagickSignature);
1131   if (image->debug != MagickFalse)
1132     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",image->filename);
1133   status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
1134   if (status == MagickFalse)
1135     return(status);
1136   /*
1137     Allocate X ref memory.
1138   */
1139   xref=(MagickOffsetType *) AcquireQuantumMemory(2048UL,sizeof(*xref));
1140   if (xref == (MagickOffsetType *) NULL)
1141     ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1142   (void) ResetMagickMemory(xref,0,2048UL*sizeof(*xref));
1143   /*
1144     Write Info object.
1145   */
1146   object=0;
1147   version=3;
1148   if (image_info->compression == JPEG2000Compression)
1149     version=(unsigned long) MagickMax(version,5);
1150   for (next=image; next != (Image *) NULL; next=GetNextImageInList(next))
1151     if (next->matte != MagickFalse)
1152       version=(unsigned long) MagickMax(version,4);
1153   if (LocaleCompare(image_info->magick,"PDFA") == 0)
1154     version=(unsigned long) MagickMax(version,6);
1155   (void) FormatMagickString(buffer,MaxTextExtent,"%%PDF-1.%lu \n",version);
1156   (void) WriteBlobString(image,buffer);
1157   if (LocaleCompare(image_info->magick,"PDFA") == 0)
1158     (void) WriteBlobString(image,"%âãÏÓ\n");
1159   /*
1160     Write Catalog object.
1161   */
1162   xref[object++]=TellBlob(image);
1163   root_id=object;
1164   (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1165   (void) WriteBlobString(image,buffer);
1166   (void) WriteBlobString(image,"<<\n");
1167   if (LocaleCompare(image_info->magick,"PDFA") != 0)
1168     (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %lu 0 R\n",
1169       object+1);
1170   else
1171     {
1172       (void) FormatMagickString(buffer,MaxTextExtent,"/Metadata %lu 0 R\n",
1173         object+1);
1174       (void) WriteBlobString(image,buffer);
1175       (void) FormatMagickString(buffer,MaxTextExtent,"/Pages %lu 0 R\n",
1176         object+2);
1177     }
1178   (void) WriteBlobString(image,buffer);
1179   (void) WriteBlobString(image,"/Type /Catalog\n");
1180   (void) WriteBlobString(image,">>\n");
1181   (void) WriteBlobString(image,"endobj\n");
1182   if (LocaleCompare(image_info->magick,"PDFA") == 0)
1183     {
1184       char
1185         create_date[MaxTextExtent],
1186         modify_date[MaxTextExtent],
1187         timestamp[MaxTextExtent],
1188         xmp_profile[MaxTextExtent];
1189
1190       unsigned long
1191         version;
1192
1193       /*
1194         Write XMP object.
1195       */
1196       xref[object++]=TellBlob(image);
1197       (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1198       (void) WriteBlobString(image,buffer);
1199       (void) WriteBlobString(image,"<<\n");
1200       (void) WriteBlobString(image,"/Subtype /XML\n");
1201       *modify_date='\0';
1202       value=GetImageProperty(image,"date:modify");
1203       if (value != (const char *) NULL)
1204         (void) CopyMagickString(modify_date,value,MaxTextExtent);
1205       *create_date='\0';
1206       value=GetImageProperty(image,"date:create");
1207       if (value != (const char *) NULL)
1208         (void) CopyMagickString(create_date,value,MaxTextExtent);
1209       (void) FormatMagickTime(time((time_t *) NULL),MaxTextExtent,timestamp);
1210       i=FormatMagickString(xmp_profile,MaxTextExtent,XMPProfile,
1211         XMPProfileMagick,modify_date,create_date,timestamp,
1212         GetMagickVersion(&version),GetMagickVersion(&version));
1213       (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu\n",1UL*i);
1214       (void) WriteBlobString(image,buffer);
1215       (void) WriteBlobString(image,"/Type /Metadata\n");
1216       (void) WriteBlobString(image,">>\nstream\n");
1217       (void) WriteBlobString(image,xmp_profile);
1218       (void) WriteBlobString(image,"endstream\n");
1219       (void) WriteBlobString(image,"endobj\n");
1220     }
1221   /*
1222     Write Pages object.
1223   */
1224   xref[object++]=TellBlob(image);
1225   pages_id=object;
1226   (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1227   (void) WriteBlobString(image,buffer);
1228   (void) WriteBlobString(image,"<<\n");
1229   (void) WriteBlobString(image,"/Type /Pages\n");
1230   (void) FormatMagickString(buffer,MaxTextExtent,"/Kids [ %lu 0 R ",object+1);
1231   (void) WriteBlobString(image,buffer);
1232   count=(long) (pages_id+ObjectsPerImage+1);
1233   if (image_info->adjoin != MagickFalse)
1234     {
1235       Image
1236         *kid_image;
1237
1238       /*
1239         Predict page object id's.
1240       */
1241       kid_image=image;
1242       for ( ; GetNextImageInList(kid_image) != (Image *) NULL; count+=ObjectsPerImage)
1243       {
1244         (void) FormatMagickString(buffer,MaxTextExtent,"%ld 0 R ",count);
1245         (void) WriteBlobString(image,buffer);
1246         kid_image=GetNextImageInList(kid_image);
1247       }
1248       xref=(MagickOffsetType *) ResizeQuantumMemory(xref,(size_t) count+2048UL,
1249         sizeof(*xref));
1250       if (xref == (MagickOffsetType *) NULL)
1251         ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1252     }
1253   (void) WriteBlobString(image,"]\n");
1254   (void) FormatMagickString(buffer,MaxTextExtent,"/Count %lu\n",
1255     (count-pages_id)/ObjectsPerImage);
1256   (void) WriteBlobString(image,buffer);
1257   (void) WriteBlobString(image,">>\n");
1258   (void) WriteBlobString(image,"endobj\n");
1259   scene=0;
1260   do
1261   {
1262     compression=image->compression;
1263     if (image_info->compression != UndefinedCompression)
1264       compression=image_info->compression;
1265     switch (compression)
1266     {
1267       case FaxCompression:
1268       case Group4Compression:
1269       {
1270         if ((IsMonochromeImage(image,&image->exception) == MagickFalse) ||
1271             (image->matte != MagickFalse))
1272           compression=RLECompression;
1273         break;
1274       }
1275 #if !defined(MAGICKCORE_JPEG_DELEGATE)
1276       case JPEGCompression:
1277       {
1278         compression=RLECompression;
1279         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1280           MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JPEG)",
1281           image->filename);
1282         break;
1283       }
1284 #endif
1285 #if !defined(MAGICKCORE_JP2_DELEGATE)
1286       case JPEG2000Compression:
1287       {
1288         compression=RLECompression;
1289         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1290           MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (JP2)",
1291           image->filename);
1292         break;
1293       }
1294 #endif
1295 #if !defined(MAGICKCORE_ZLIB_DELEGATE)
1296       case ZipCompression:
1297       {
1298         compression=RLECompression;
1299         (void) ThrowMagickException(&image->exception,GetMagickModule(),
1300           MissingDelegateError,"DelegateLibrarySupportNotBuiltIn","`%s' (ZLIB)",
1301           image->filename);
1302         break;
1303       }
1304 #endif
1305       case LZWCompression:
1306       {
1307         if (LocaleCompare(image_info->magick,"PDFA") == 0)
1308           compression=RLECompression;  /* LZW compression is forbidden */
1309         break;
1310       }
1311       case NoCompression:
1312       {
1313         if (LocaleCompare(image_info->magick,"PDFA") == 0)
1314           compression=RLECompression; /* ASCII 85 compression is forbidden */
1315         break;
1316       }
1317       default:
1318         break;
1319     }
1320     if (compression == JPEG2000Compression)
1321       {
1322         if (image->colorspace != RGBColorspace)
1323           (void) TransformImageColorspace(image,RGBColorspace);
1324       }
1325     /*
1326       Scale relative to dots-per-inch.
1327     */
1328     delta.x=DefaultResolution;
1329     delta.y=DefaultResolution;
1330     resolution.x=image->x_resolution;
1331     resolution.y=image->y_resolution;
1332     if ((resolution.x == 0.0) || (resolution.y == 0.0))
1333       {
1334         flags=ParseGeometry(PSDensityGeometry,&geometry_info);
1335         resolution.x=geometry_info.rho;
1336         resolution.y=geometry_info.sigma;
1337         if ((flags & SigmaValue) == 0)
1338           resolution.y=resolution.x;
1339       }
1340     if (image_info->density != (char *) NULL)
1341       {
1342         flags=ParseGeometry(image_info->density,&geometry_info);
1343         resolution.x=geometry_info.rho;
1344         resolution.y=geometry_info.sigma;
1345         if ((flags & SigmaValue) == 0)
1346           resolution.y=resolution.x;
1347       }
1348     if (image->units == PixelsPerCentimeterResolution)
1349       {
1350         resolution.x*=2.54;
1351         resolution.y*=2.54;
1352       }
1353     SetGeometry(image,&geometry);
1354     (void) FormatMagickString(page_geometry,MaxTextExtent,"%lux%lu",
1355       image->columns,image->rows);
1356     if (image_info->page != (char *) NULL)
1357       (void) CopyMagickString(page_geometry,image_info->page,MaxTextExtent);
1358     else
1359       if ((image->page.width != 0) && (image->page.height != 0))
1360         (void) FormatMagickString(page_geometry,MaxTextExtent,"%lux%lu%+ld%+ld",
1361           image->page.width,image->page.height,image->page.x,image->page.y);
1362       else
1363         if ((image->gravity != UndefinedGravity) &&
1364             (LocaleCompare(image_info->magick,"PDF") == 0))
1365           (void) CopyMagickString(page_geometry,PSPageGeometry,MaxTextExtent);
1366     (void) ConcatenateMagickString(page_geometry,">",MaxTextExtent);
1367     (void) ParseMetaGeometry(page_geometry,&geometry.x,&geometry.y,
1368       &geometry.width,&geometry.height);
1369     scale.x=(double) (geometry.width*delta.x)/resolution.x;
1370     geometry.width=(unsigned long) (scale.x+0.5);
1371     scale.y=(double) (geometry.height*delta.y)/resolution.y;
1372     geometry.height=(unsigned long) (scale.y+0.5);
1373     (void) ParseAbsoluteGeometry(page_geometry,&media_info);
1374     (void) ParseGravityGeometry(image,page_geometry,&page_info,
1375       &image->exception);
1376     if (image->gravity != UndefinedGravity)
1377       {
1378         geometry.x=(-page_info.x);
1379         geometry.y=(long) (media_info.height+page_info.y-image->rows);
1380       }
1381     pointsize=12.0;
1382     if (image_info->pointsize != 0.0)
1383       pointsize=image_info->pointsize;
1384     text_size=0;
1385     value=GetImageProperty(image,"Label");
1386     if (value != (const char *) NULL)
1387       text_size=(unsigned long) (MultilineCensus(value)*pointsize+12);
1388     /*
1389       Write Page object.
1390     */
1391     xref[object++]=TellBlob(image);
1392     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1393     (void) WriteBlobString(image,buffer);
1394     (void) WriteBlobString(image,"<<\n");
1395     (void) WriteBlobString(image,"/Type /Page\n");
1396     (void) FormatMagickString(buffer,MaxTextExtent,"/Parent %lu 0 R\n",
1397       pages_id);
1398     (void) WriteBlobString(image,buffer);
1399     (void) WriteBlobString(image,"/Resources <<\n");
1400     labels=(char **) NULL;
1401     value=GetImageProperty(image,"Label");
1402     if (value != (const char *) NULL)
1403       labels=StringToList(value);
1404     if (labels != (char **) NULL)
1405       {
1406         (void) FormatMagickString(buffer,MaxTextExtent,
1407           "/Font << /F%lu %lu 0 R >>\n",image->scene,object+4);
1408         (void) WriteBlobString(image,buffer);
1409       }
1410     (void) FormatMagickString(buffer,MaxTextExtent,
1411       "/XObject << /Im%lu %lu 0 R >>\n",image->scene,object+5);
1412     (void) WriteBlobString(image,buffer);
1413     (void) FormatMagickString(buffer,MaxTextExtent,"/ProcSet %lu 0 R >>\n",
1414       object+3);
1415     (void) WriteBlobString(image,buffer);
1416     (void) FormatMagickString(buffer,MaxTextExtent,"/MediaBox [0 0 %g %g]\n",
1417       72.0*media_info.width/resolution.x,72.0*media_info.height/resolution.y);
1418     (void) WriteBlobString(image,buffer);
1419     (void) FormatMagickString(buffer,MaxTextExtent,"/CropBox [0 0 %g %g]\n",
1420       72.0*media_info.width/resolution.x,72.0*media_info.height/resolution.y);
1421     (void) WriteBlobString(image,buffer);
1422     (void) FormatMagickString(buffer,MaxTextExtent,"/Contents %lu 0 R\n",
1423       object+1);
1424     (void) WriteBlobString(image,buffer);
1425     (void) FormatMagickString(buffer,MaxTextExtent,"/Thumb %lu 0 R\n",
1426       object+8);
1427     (void) WriteBlobString(image,buffer);
1428     (void) WriteBlobString(image,">>\n");
1429     (void) WriteBlobString(image,"endobj\n");
1430     /*
1431       Write Contents object.
1432     */
1433     xref[object++]=TellBlob(image);
1434     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1435     (void) WriteBlobString(image,buffer);
1436     (void) WriteBlobString(image,"<<\n");
1437     (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
1438       object+1);
1439     (void) WriteBlobString(image,buffer);
1440     (void) WriteBlobString(image,">>\n");
1441     (void) WriteBlobString(image,"stream\n");
1442     offset=TellBlob(image);
1443     (void) WriteBlobString(image,"q\n");
1444     if (labels != (char **) NULL)
1445       for (i=0; labels[i] != (char *) NULL; i++)
1446       {
1447         (void) WriteBlobString(image,"BT\n");
1448         (void) FormatMagickString(buffer,MaxTextExtent,"/F%lu %g Tf\n",
1449           image->scene,pointsize);
1450         (void) WriteBlobString(image,buffer);
1451         (void) FormatMagickString(buffer,MaxTextExtent,"%ld %ld Td\n",
1452           geometry.x,(long) (geometry.y+geometry.height+i*pointsize+12));
1453         (void) WriteBlobString(image,buffer);
1454         (void) FormatMagickString(buffer,MaxTextExtent,"(%s) Tj\n",labels[i]);
1455         (void) WriteBlobString(image,buffer);
1456         (void) WriteBlobString(image,"ET\n");
1457         labels[i]=DestroyString(labels[i]);
1458       }
1459     (void) FormatMagickString(buffer,MaxTextExtent,"%g 0 0 %g %ld %ld cm\n",
1460       scale.x,scale.y,geometry.x,geometry.y);
1461     (void) WriteBlobString(image,buffer);
1462     (void) FormatMagickString(buffer,MaxTextExtent,"/Im%lu Do\n",image->scene);
1463     (void) WriteBlobString(image,buffer);
1464     (void) WriteBlobString(image,"Q\n");
1465     offset=TellBlob(image)-offset;
1466     (void) WriteBlobString(image,"endstream\n");
1467     (void) WriteBlobString(image,"endobj\n");
1468     /*
1469       Write Length object.
1470     */
1471     xref[object++]=TellBlob(image);
1472     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1473     (void) WriteBlobString(image,buffer);
1474     (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
1475       (unsigned long) offset);
1476     (void) WriteBlobString(image,buffer);
1477     (void) WriteBlobString(image,"endobj\n");
1478     /*
1479       Write Procset object.
1480     */
1481     xref[object++]=TellBlob(image);
1482     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1483     (void) WriteBlobString(image,buffer);
1484     if ((image->storage_class == DirectClass) || (image->colors > 256))
1485       (void) CopyMagickString(buffer,"[ /PDF /Text /ImageC",MaxTextExtent);
1486     else
1487       if ((compression == FaxCompression) || (compression == Group4Compression))
1488         (void) CopyMagickString(buffer,"[ /PDF /Text /ImageB",MaxTextExtent);
1489       else
1490         (void) CopyMagickString(buffer,"[ /PDF /Text /ImageI",MaxTextExtent);
1491     (void) WriteBlobString(image,buffer);
1492     (void) WriteBlobString(image," ]\n");
1493     (void) WriteBlobString(image,"endobj\n");
1494     /*
1495       Write Font object.
1496     */
1497     xref[object++]=TellBlob(image);
1498     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1499     (void) WriteBlobString(image,buffer);
1500     (void) WriteBlobString(image,"<<\n");
1501     if (labels != (char **) NULL)
1502       {
1503         (void) WriteBlobString(image,"/Type /Font\n");
1504         (void) WriteBlobString(image,"/Subtype /Type1\n");
1505         (void) FormatMagickString(buffer,MaxTextExtent,"/Name /F%lu\n",
1506           image->scene);
1507         (void) WriteBlobString(image,buffer);
1508         (void) WriteBlobString(image,"/BaseFont /Helvetica\n");
1509         (void) WriteBlobString(image,"/Encoding /MacRomanEncoding\n");
1510         labels=(char **) RelinquishMagickMemory(labels);
1511       }
1512     (void) WriteBlobString(image,">>\n");
1513     (void) WriteBlobString(image,"endobj\n");
1514     /*
1515       Write XObject object.
1516     */
1517     xref[object++]=TellBlob(image);
1518     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1519     (void) WriteBlobString(image,buffer);
1520     (void) WriteBlobString(image,"<<\n");
1521     (void) WriteBlobString(image,"/Type /XObject\n");
1522     (void) WriteBlobString(image,"/Subtype /Image\n");
1523     (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Im%lu\n",
1524       image->scene);
1525     (void) WriteBlobString(image,buffer);
1526     switch (compression)
1527     {
1528       case NoCompression:
1529       {
1530         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1531         break;
1532       }
1533       case JPEGCompression:
1534       {
1535         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1536         if (image->colorspace != CMYKColorspace)
1537           break;
1538         (void) WriteBlobString(image,buffer);
1539         (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1540           MaxTextExtent);
1541         break;
1542       }
1543       case JPEG2000Compression:
1544       {
1545         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1546         if (image->colorspace != CMYKColorspace)
1547           break;
1548         (void) WriteBlobString(image,buffer);
1549         (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1550           MaxTextExtent);
1551         break;
1552       }
1553       case LZWCompression:
1554       {
1555         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1556         break;
1557       }
1558       case ZipCompression:
1559       {
1560         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
1561         break;
1562       }
1563       case FaxCompression:
1564       case Group4Compression:
1565       {
1566         (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
1567           MaxTextExtent);
1568         (void) WriteBlobString(image,buffer);
1569         (void) FormatMagickString(buffer,MaxTextExtent,"/DecodeParms [ << "
1570           "/K %s /BlackIs1 true /Columns %ld /Rows %ld >> ]\n",CCITTParam,
1571           image->columns,image->rows);
1572         break;
1573       }
1574       default:
1575       {
1576         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
1577           "RunLengthDecode");
1578         break;
1579       }
1580     }
1581     (void) WriteBlobString(image,buffer);
1582     (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
1583       image->columns);
1584     (void) WriteBlobString(image,buffer);
1585     (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",image->rows);
1586     (void) WriteBlobString(image,buffer);
1587     (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %lu 0 R\n",
1588       object+2);
1589     (void) WriteBlobString(image,buffer);
1590     (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
1591       (compression == FaxCompression) || (compression == Group4Compression) ?
1592       1 : 8);
1593     (void) WriteBlobString(image,buffer);
1594     if (image->matte != MagickFalse)
1595       {
1596         (void) FormatMagickString(buffer,MaxTextExtent,"/SMask %lu 0 R\n",
1597           object+7);
1598         (void) WriteBlobString(image,buffer);
1599       }
1600     (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
1601       object+1);
1602     (void) WriteBlobString(image,buffer);
1603     (void) WriteBlobString(image,">>\n");
1604     (void) WriteBlobString(image,"stream\n");
1605     offset=TellBlob(image);
1606     number_pixels=(MagickSizeType) image->columns*image->rows;
1607     if ((4*number_pixels) != (MagickSizeType) ((size_t) (4*number_pixels)))
1608       ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1609     if ((compression == FaxCompression) || (compression == Group4Compression) ||
1610         ((image_info->type != TrueColorType) &&
1611          (IsGrayImage(image,&image->exception) != MagickFalse)))
1612       {
1613         switch (compression)
1614         {
1615           case FaxCompression:
1616           case Group4Compression:
1617           {
1618             if (LocaleCompare(CCITTParam,"0") == 0)
1619               {
1620                 (void) HuffmanEncodeImage(image_info,image,image);
1621                 break;
1622               }
1623             (void) Huffman2DEncodeImage(image_info,image,image);
1624             break;
1625           }
1626           case JPEGCompression:
1627           {
1628             status=InjectImageBlob(image_info,image,image,"jpeg",
1629               &image->exception);
1630             if (status == MagickFalse)
1631               ThrowWriterException(CoderError,image->exception.reason);
1632             break;
1633           }
1634           case JPEG2000Compression:
1635           {
1636             status=InjectImageBlob(image_info,image,image,"jp2",
1637               &image->exception);
1638             if (status == MagickFalse)
1639               ThrowWriterException(CoderError,image->exception.reason);
1640             break;
1641           }
1642           case RLECompression:
1643           default:
1644           {
1645             /*
1646               Allocate pixel array.
1647             */
1648             length=(size_t) number_pixels;
1649             pixels=(unsigned char *) AcquireQuantumMemory(length,
1650               sizeof(*pixels));
1651             if (pixels == (unsigned char *) NULL)
1652               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1653             /*
1654               Dump Runlength encoded pixels.
1655             */
1656             q=pixels;
1657             for (y=0; y < (long) image->rows; y++)
1658             {
1659               p=GetVirtualPixels(image,0,y,image->columns,1,
1660                 &image->exception);
1661               if (p == (const PixelPacket *) NULL)
1662                 break;
1663               for (x=0; x < (long) image->columns; x++)
1664               {
1665                 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
1666                 p++;
1667               }
1668               if (image->previous == (Image *) NULL)
1669                 {
1670                   status=SetImageProgress(image,SaveImageTag,y,image->rows);
1671                   if (status == MagickFalse)
1672                     break;
1673                 }
1674             }
1675 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1676             if (compression == ZipCompression)
1677               status=ZLIBEncodeImage(image,length,pixels);
1678             else
1679 #endif
1680               if (compression == LZWCompression)
1681                 status=LZWEncodeImage(image,length,pixels);
1682               else
1683                 status=PackbitsEncodeImage(image,length,pixels);
1684             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1685             if (status == MagickFalse)
1686               {
1687                 (void) CloseBlob(image);
1688                 return(MagickFalse);
1689               }
1690             break;
1691           }
1692           case NoCompression:
1693           {
1694             /*
1695               Dump uncompressed PseudoColor packets.
1696             */
1697             Ascii85Initialize(image);
1698             for (y=0; y < (long) image->rows; y++)
1699             {
1700               p=GetVirtualPixels(image,0,y,image->columns,1,
1701                 &image->exception);
1702               if (p == (const PixelPacket *) NULL)
1703                 break;
1704               for (x=0; x < (long) image->columns; x++)
1705               {
1706                 Ascii85Encode(image,
1707                   ScaleQuantumToChar(PixelIntensityToQuantum(p)));
1708                 p++;
1709               }
1710               if (image->previous == (Image *) NULL)
1711                 {
1712                   status=SetImageProgress(image,SaveImageTag,y,image->rows);
1713                   if (status == MagickFalse)
1714                     break;
1715                 }
1716             }
1717             Ascii85Flush(image);
1718             break;
1719           }
1720         }
1721       }
1722     else
1723       if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1724           (compression == JPEGCompression) ||
1725           (compression == JPEG2000Compression))
1726         switch (compression)
1727         {
1728           case JPEGCompression:
1729           {
1730             status=InjectImageBlob(image_info,image,image,"jpeg",
1731               &image->exception);
1732             if (status == MagickFalse)
1733               ThrowWriterException(CoderError,image->exception.reason);
1734             break;
1735           }
1736           case JPEG2000Compression:
1737           {
1738             status=InjectImageBlob(image_info,image,image,"jp2",
1739               &image->exception);
1740             if (status == MagickFalse)
1741               ThrowWriterException(CoderError,image->exception.reason);
1742             break;
1743           }
1744           case RLECompression:
1745           default:
1746           {
1747             /*
1748               Allocate pixel array.
1749             */
1750             length=(size_t) number_pixels;
1751             pixels=(unsigned char *) AcquireQuantumMemory(length,
1752               4*sizeof(*pixels));
1753             length*=image->colorspace == CMYKColorspace ? 4UL : 3UL;
1754             if (pixels == (unsigned char *) NULL)
1755               ThrowWriterException(ResourceLimitError,"MemoryAllocationFailed");
1756             /*
1757               Dump runoffset encoded pixels.
1758             */
1759             q=pixels;
1760             for (y=0; y < (long) image->rows; y++)
1761             {
1762               p=GetVirtualPixels(image,0,y,image->columns,1,
1763                 &image->exception);
1764               if (p == (const PixelPacket *) NULL)
1765                 break;
1766               indexes=GetVirtualIndexQueue(image);
1767               for (x=0; x < (long) image->columns; x++)
1768               {
1769                 *q++=ScaleQuantumToChar(p->red);
1770                 *q++=ScaleQuantumToChar(p->green);
1771                 *q++=ScaleQuantumToChar(p->blue);
1772                 if (image->colorspace == CMYKColorspace)
1773                   *q++=ScaleQuantumToChar(indexes[x]);
1774                 p++;
1775               }
1776               if (image->previous == (Image *) NULL)
1777                 {
1778                   status=SetImageProgress(image,SaveImageTag,y,image->rows);
1779                   if (status == MagickFalse)
1780                     break;
1781                 }
1782             }
1783 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1784             if (compression == ZipCompression)
1785               status=ZLIBEncodeImage(image,length,pixels);
1786             else
1787 #endif
1788               if (compression == LZWCompression)
1789                 status=LZWEncodeImage(image,length,pixels);
1790               else
1791                 status=PackbitsEncodeImage(image,length,pixels);
1792             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1793             if (status == MagickFalse)
1794               {
1795                 (void) CloseBlob(image);
1796                 return(MagickFalse);
1797               }
1798             break;
1799           }
1800           case NoCompression:
1801           {
1802             /*
1803               Dump uncompressed DirectColor packets.
1804             */
1805             Ascii85Initialize(image);
1806             for (y=0; y < (long) image->rows; y++)
1807             {
1808               p=GetVirtualPixels(image,0,y,image->columns,1,
1809                 &image->exception);
1810               if (p == (const PixelPacket *) NULL)
1811                 break;
1812               indexes=GetVirtualIndexQueue(image);
1813               for (x=0; x < (long) image->columns; x++)
1814               {
1815                 Ascii85Encode(image,ScaleQuantumToChar(p->red));
1816                 Ascii85Encode(image,ScaleQuantumToChar(p->green));
1817                 Ascii85Encode(image,ScaleQuantumToChar(p->blue));
1818                 if (image->colorspace == CMYKColorspace)
1819                   Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
1820                 p++;
1821               }
1822               if (image->previous == (Image *) NULL)
1823                 {
1824                   status=SetImageProgress(image,SaveImageTag,y,image->rows);
1825                   if (status == MagickFalse)
1826                     break;
1827                 }
1828             }
1829             Ascii85Flush(image);
1830             break;
1831           }
1832         }
1833       else
1834         {
1835           /*
1836             Dump number of colors and colormap.
1837           */
1838           switch (compression)
1839           {
1840             case RLECompression:
1841             default:
1842             {
1843               /*
1844                 Allocate pixel array.
1845               */
1846               length=(size_t) number_pixels;
1847               pixels=(unsigned char *) AcquireQuantumMemory(length,
1848                 sizeof(*pixels));
1849               if (pixels == (unsigned char *) NULL)
1850                 ThrowWriterException(ResourceLimitError,
1851                   "MemoryAllocationFailed");
1852               /*
1853                 Dump Runlength encoded pixels.
1854               */
1855               q=pixels;
1856               for (y=0; y < (long) image->rows; y++)
1857               {
1858                 p=GetVirtualPixels(image,0,y,image->columns,1,
1859                   &image->exception);
1860                 if (p == (const PixelPacket *) NULL)
1861                   break;
1862                 indexes=GetVirtualIndexQueue(image);
1863                 for (x=0; x < (long) image->columns; x++)
1864                   *q++=(unsigned char) indexes[x];
1865                 if (image->previous == (Image *) NULL)
1866                   {
1867                     status=SetImageProgress(image,SaveImageTag,y,image->rows);
1868                     if (status == MagickFalse)
1869                       break;
1870                   }
1871               }
1872 #if defined(MAGICKCORE_ZLIB_DELEGATE)
1873               if (compression == ZipCompression)
1874                 status=ZLIBEncodeImage(image,length,pixels);
1875               else
1876 #endif
1877                 if (compression == LZWCompression)
1878                   status=LZWEncodeImage(image,length,pixels);
1879                 else
1880                   status=PackbitsEncodeImage(image,length,pixels);
1881               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
1882               if (status == MagickFalse)
1883                 {
1884                   (void) CloseBlob(image);
1885                   return(MagickFalse);
1886                 }
1887               break;
1888             }
1889             case NoCompression:
1890             {
1891               /*
1892                 Dump uncompressed PseudoColor packets.
1893               */
1894               Ascii85Initialize(image);
1895               for (y=0; y < (long) image->rows; y++)
1896               {
1897                 p=GetVirtualPixels(image,0,y,image->columns,1,
1898                   &image->exception);
1899                 if (p == (const PixelPacket *) NULL)
1900                   break;
1901                 indexes=GetVirtualIndexQueue(image);
1902                 for (x=0; x < (long) image->columns; x++)
1903                   Ascii85Encode(image,(unsigned char) indexes[x]);
1904                 if (image->previous == (Image *) NULL)
1905                   {
1906                     status=SetImageProgress(image,SaveImageTag,y,image->rows);
1907                     if (status == MagickFalse)
1908                       break;
1909                   }
1910               }
1911               Ascii85Flush(image);
1912               break;
1913             }
1914           }
1915         }
1916     offset=TellBlob(image)-offset;
1917     (void) WriteBlobString(image,"\nendstream\n");
1918     (void) WriteBlobString(image,"endobj\n");
1919     /*
1920       Write Length object.
1921     */
1922     xref[object++]=TellBlob(image);
1923     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1924     (void) WriteBlobString(image,buffer);
1925     (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
1926       (unsigned long) offset);
1927     (void) WriteBlobString(image,buffer);
1928     (void) WriteBlobString(image,"endobj\n");
1929     /*
1930       Write Colorspace object.
1931     */
1932     xref[object++]=TellBlob(image);
1933     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1934     (void) WriteBlobString(image,buffer);
1935     if (image->colorspace == CMYKColorspace)
1936       (void) CopyMagickString(buffer,"/DeviceCMYK\n",MaxTextExtent);
1937     else
1938       if ((compression == FaxCompression) ||
1939           (compression == Group4Compression) ||
1940           ((image_info->type != TrueColorType) &&
1941            (IsGrayImage(image,&image->exception) != MagickFalse)))
1942           (void) CopyMagickString(buffer,"/DeviceGray\n",MaxTextExtent);
1943       else
1944         if ((image->storage_class == DirectClass) || (image->colors > 256) ||
1945             (compression == JPEGCompression) ||
1946             (compression == JPEG2000Compression))
1947           (void) CopyMagickString(buffer,"/DeviceRGB\n",MaxTextExtent);
1948         else
1949           (void) FormatMagickString(buffer,MaxTextExtent,
1950             "[ /Indexed /DeviceRGB %lu %lu 0 R ]\n",
1951             image->colors-1,object+3);
1952     (void) WriteBlobString(image,buffer);
1953     (void) WriteBlobString(image,"endobj\n");
1954     /*
1955       Write Thumb object.
1956     */
1957     SetGeometry(image,&geometry);
1958     (void) ParseMetaGeometry("106x106+0+0>",&geometry.x,&geometry.y,
1959       &geometry.width,&geometry.height);
1960     tile_image=ThumbnailImage(image,geometry.width,geometry.height,
1961       &image->exception);
1962     if (tile_image == (Image *) NULL)
1963       ThrowWriterException(ResourceLimitError,image->exception.reason);
1964     xref[object++]=TellBlob(image);
1965     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
1966     (void) WriteBlobString(image,buffer);
1967     (void) WriteBlobString(image,"<<\n");
1968     switch (compression)
1969     {
1970       case NoCompression:
1971       {
1972         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"ASCII85Decode");
1973         break;
1974       }
1975       case JPEGCompression:
1976       {
1977         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"DCTDecode");
1978         if (image->colorspace != CMYKColorspace)
1979           break;
1980         (void) WriteBlobString(image,buffer);
1981         (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1982           MaxTextExtent);
1983         break;
1984       }
1985       case JPEG2000Compression:
1986       {
1987         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"JPXDecode");
1988         if (image->colorspace != CMYKColorspace)
1989           break;
1990         (void) WriteBlobString(image,buffer);
1991         (void) CopyMagickString(buffer,"/Decode [1 0 1 0 1 0 1 0]\n",
1992           MaxTextExtent);
1993         break;
1994       }
1995       case LZWCompression:
1996       {
1997         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
1998         break;
1999       }
2000       case ZipCompression:
2001       {
2002         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"FlateDecode");
2003         break;
2004       }
2005       case FaxCompression:
2006       case Group4Compression:
2007       {
2008         (void) CopyMagickString(buffer,"/Filter [ /CCITTFaxDecode ]\n",
2009           MaxTextExtent);
2010         (void) WriteBlobString(image,buffer);
2011         (void) FormatMagickString(buffer,MaxTextExtent,"/DecodeParms [ << "
2012           "/K %s /BlackIs1 true /Columns %lu /Rows %lu >> ]\n",CCITTParam,
2013           tile_image->columns,tile_image->rows);
2014         break;
2015       }
2016       default:
2017       {
2018         (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2019           "RunLengthDecode");
2020         break;
2021       }
2022     }
2023     (void) WriteBlobString(image,buffer);
2024     (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
2025       tile_image->columns);
2026     (void) WriteBlobString(image,buffer);
2027     (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",
2028       tile_image->rows);
2029     (void) WriteBlobString(image,buffer);
2030     (void) FormatMagickString(buffer,MaxTextExtent,"/ColorSpace %lu 0 R\n",
2031       object-1);
2032     (void) WriteBlobString(image,buffer);
2033     (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
2034       (compression == FaxCompression) || (compression == Group4Compression) ?
2035       1 : 8);
2036     (void) WriteBlobString(image,buffer);
2037     (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
2038       object+1);
2039     (void) WriteBlobString(image,buffer);
2040     (void) WriteBlobString(image,">>\n");
2041     (void) WriteBlobString(image,"stream\n");
2042     offset=TellBlob(image);
2043     number_pixels=(MagickSizeType) tile_image->columns*tile_image->rows;
2044     if ((compression == FaxCompression) ||
2045         (compression == Group4Compression) ||
2046         ((image_info->type != TrueColorType) &&
2047          (IsGrayImage(tile_image,&image->exception) != MagickFalse)))
2048       {
2049         switch (compression)
2050         {
2051           case FaxCompression:
2052           case Group4Compression:
2053           {
2054             if (LocaleCompare(CCITTParam,"0") == 0)
2055               {
2056                 (void) HuffmanEncodeImage(image_info,image,tile_image);
2057                 break;
2058               }
2059             (void) Huffman2DEncodeImage(image_info,image,tile_image);
2060             break;
2061           }
2062           case JPEGCompression:
2063           {
2064             status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2065               &image->exception);
2066             if (status == MagickFalse)
2067               ThrowWriterException(CoderError,tile_image->exception.reason);
2068             break;
2069           }
2070           case JPEG2000Compression:
2071           {
2072             status=InjectImageBlob(image_info,image,tile_image,"jp2",
2073               &image->exception);
2074             if (status == MagickFalse)
2075               ThrowWriterException(CoderError,tile_image->exception.reason);
2076             break;
2077           }
2078           case RLECompression:
2079           default:
2080           {
2081             /*
2082               Allocate pixel array.
2083             */
2084             length=(size_t) number_pixels;
2085             pixels=(unsigned char *) AcquireQuantumMemory(length,
2086               sizeof(*pixels));
2087             if (pixels == (unsigned char *) NULL)
2088               {
2089                 tile_image=DestroyImage(tile_image);
2090                 ThrowWriterException(ResourceLimitError,
2091                   "MemoryAllocationFailed");
2092               }
2093             /*
2094               Dump Runlength encoded pixels.
2095             */
2096             q=pixels;
2097             for (y=0; y < (long) tile_image->rows; y++)
2098             {
2099               p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2100                 &tile_image->exception);
2101               if (p == (const PixelPacket *) NULL)
2102                 break;
2103               for (x=0; x < (long) tile_image->columns; x++)
2104               {
2105                 *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
2106                 p++;
2107               }
2108             }
2109 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2110             if (compression == ZipCompression)
2111               status=ZLIBEncodeImage(image,length,pixels);
2112             else
2113 #endif
2114               if (compression == LZWCompression)
2115                 status=LZWEncodeImage(image,length,pixels);
2116               else
2117                 status=PackbitsEncodeImage(image,length,pixels);
2118             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2119             if (status == MagickFalse)
2120               {
2121                 (void) CloseBlob(image);
2122                 return(MagickFalse);
2123               }
2124             break;
2125           }
2126           case NoCompression:
2127           {
2128             /*
2129               Dump uncompressed PseudoColor packets.
2130             */
2131             Ascii85Initialize(image);
2132             for (y=0; y < (long) tile_image->rows; y++)
2133             {
2134               p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2135                 &tile_image->exception);
2136               if (p == (const PixelPacket *) NULL)
2137                 break;
2138               for (x=0; x < (long) tile_image->columns; x++)
2139               {
2140                 Ascii85Encode(image,
2141                   ScaleQuantumToChar(PixelIntensityToQuantum(p)));
2142                 p++;
2143               }
2144             }
2145             Ascii85Flush(image);
2146             break;
2147           }
2148         }
2149       }
2150     else
2151       if ((tile_image->storage_class == DirectClass) ||
2152           (tile_image->colors > 256) || (compression == JPEGCompression) ||
2153           (compression == JPEG2000Compression))
2154         switch (compression)
2155         {
2156           case JPEGCompression:
2157           {
2158             status=InjectImageBlob(image_info,image,tile_image,"jpeg",
2159               &image->exception);
2160             if (status == MagickFalse)
2161               ThrowWriterException(CoderError,tile_image->exception.reason);
2162             break;
2163           }
2164           case JPEG2000Compression:
2165           {
2166             status=InjectImageBlob(image_info,image,tile_image,"jp2",
2167               &image->exception);
2168             if (status == MagickFalse)
2169               ThrowWriterException(CoderError,tile_image->exception.reason);
2170             break;
2171           }
2172           case RLECompression:
2173           default:
2174           {
2175             /*
2176               Allocate pixel array.
2177             */
2178             length=(size_t) number_pixels;
2179             pixels=(unsigned char *) AcquireQuantumMemory(length,4*
2180               sizeof(*pixels));
2181             length*=tile_image->colorspace == CMYKColorspace ? 4UL : 3UL;
2182             if (pixels == (unsigned char *) NULL)
2183               {
2184                 tile_image=DestroyImage(tile_image);
2185                 ThrowWriterException(ResourceLimitError,
2186                   "MemoryAllocationFailed");
2187               }
2188             /*
2189               Dump runoffset encoded pixels.
2190             */
2191             q=pixels;
2192             for (y=0; y < (long) tile_image->rows; y++)
2193             {
2194               p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2195                 &tile_image->exception);
2196               if (p == (const PixelPacket *) NULL)
2197                 break;
2198               indexes=GetVirtualIndexQueue(tile_image);
2199               for (x=0; x < (long) tile_image->columns; x++)
2200               {
2201                 *q++=ScaleQuantumToChar(p->red);
2202                 *q++=ScaleQuantumToChar(p->green);
2203                 *q++=ScaleQuantumToChar(p->blue);
2204                 if (image->colorspace == CMYKColorspace)
2205                   *q++=ScaleQuantumToChar(indexes[x]);
2206                 p++;
2207               }
2208             }
2209 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2210             if (compression == ZipCompression)
2211               status=ZLIBEncodeImage(image,length,pixels);
2212             else
2213 #endif
2214               if (compression == LZWCompression)
2215                 status=LZWEncodeImage(image,length,pixels);
2216               else
2217                 status=PackbitsEncodeImage(image,length,pixels);
2218             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2219             if (status == MagickFalse)
2220               {
2221                 (void) CloseBlob(image);
2222                 return(MagickFalse);
2223               }
2224             break;
2225           }
2226           case NoCompression:
2227           {
2228             /*
2229               Dump uncompressed DirectColor packets.
2230             */
2231             Ascii85Initialize(image);
2232             for (y=0; y < (long) tile_image->rows; y++)
2233             {
2234               p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2235                 &tile_image->exception);
2236               if (p == (const PixelPacket *) NULL)
2237                 break;
2238               indexes=GetVirtualIndexQueue(tile_image);
2239               for (x=0; x < (long) tile_image->columns; x++)
2240               {
2241                 Ascii85Encode(image,ScaleQuantumToChar(p->red));
2242                 Ascii85Encode(image,ScaleQuantumToChar(p->green));
2243                 Ascii85Encode(image,ScaleQuantumToChar(p->blue));
2244                 if (image->colorspace == CMYKColorspace)
2245                   Ascii85Encode(image,ScaleQuantumToChar(indexes[x]));
2246                 p++;
2247               }
2248             }
2249             Ascii85Flush(image);
2250             break;
2251           }
2252         }
2253       else
2254         {
2255           /*
2256             Dump number of colors and colormap.
2257           */
2258           switch (compression)
2259           {
2260             case RLECompression:
2261             default:
2262             {
2263               /*
2264                 Allocate pixel array.
2265               */
2266               length=(size_t) number_pixels;
2267               pixels=(unsigned char *) AcquireQuantumMemory(length,
2268                 sizeof(*pixels));
2269               if (pixels == (unsigned char *) NULL)
2270                 {
2271                   tile_image=DestroyImage(tile_image);
2272                   ThrowWriterException(ResourceLimitError,
2273                     "MemoryAllocationFailed");
2274                 }
2275               /*
2276                 Dump Runlength encoded pixels.
2277               */
2278               q=pixels;
2279               for (y=0; y < (long) tile_image->rows; y++)
2280               {
2281                 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2282                   &tile_image->exception);
2283                 if (p == (const PixelPacket *) NULL)
2284                   break;
2285                 indexes=GetVirtualIndexQueue(tile_image);
2286                 for (x=0; x < (long) tile_image->columns; x++)
2287                   *q++=(unsigned char) indexes[x];
2288               }
2289 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2290               if (compression == ZipCompression)
2291                 status=ZLIBEncodeImage(image,length,pixels);
2292               else
2293 #endif
2294                 if (compression == LZWCompression)
2295                   status=LZWEncodeImage(image,length,pixels);
2296                 else
2297                   status=PackbitsEncodeImage(image,length,pixels);
2298               pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2299               if (status == MagickFalse)
2300                 {
2301                   (void) CloseBlob(image);
2302                   return(MagickFalse);
2303                 }
2304               break;
2305             }
2306             case NoCompression:
2307             {
2308               /*
2309                 Dump uncompressed PseudoColor packets.
2310               */
2311               Ascii85Initialize(image);
2312               for (y=0; y < (long) tile_image->rows; y++)
2313               {
2314                 p=GetVirtualPixels(tile_image,0,y,tile_image->columns,1,
2315                   &tile_image->exception);
2316                 if (p == (const PixelPacket *) NULL)
2317                   break;
2318                 indexes=GetVirtualIndexQueue(tile_image);
2319                 for (x=0; x < (long) tile_image->columns; x++)
2320                   Ascii85Encode(image,(unsigned char) indexes[x]);
2321               }
2322               Ascii85Flush(image);
2323               break;
2324             }
2325           }
2326         }
2327     tile_image=DestroyImage(tile_image);
2328     offset=TellBlob(image)-offset;
2329     (void) WriteBlobString(image,"\nendstream\n");
2330     (void) WriteBlobString(image,"endobj\n");
2331     /*
2332       Write Length object.
2333     */
2334     xref[object++]=TellBlob(image);
2335     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2336     (void) WriteBlobString(image,buffer);
2337     (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2338       (unsigned long) offset);
2339     (void) WriteBlobString(image,buffer);
2340     (void) WriteBlobString(image,"endobj\n");
2341     xref[object++]=TellBlob(image);
2342     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2343     (void) WriteBlobString(image,buffer);
2344     if ((image->storage_class != DirectClass) && (image->colors <= 256) &&
2345         (compression != FaxCompression) && (compression != Group4Compression))
2346       {
2347         /*
2348           Write Colormap object.
2349         */
2350         (void) WriteBlobString(image,"<<\n");
2351         if (compression == NoCompression)
2352           (void) WriteBlobString(image,"/Filter [ /ASCII85Decode ]\n");
2353         (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
2354           object+1);
2355         (void) WriteBlobString(image,buffer);
2356         (void) WriteBlobString(image,">>\n");
2357         (void) WriteBlobString(image,"stream\n");
2358         offset=TellBlob(image);
2359         if (compression == NoCompression)
2360           Ascii85Initialize(image);
2361         for (i=0; i < (long) image->colors; i++)
2362         {
2363           if (compression == NoCompression)
2364             {
2365               Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].red));
2366               Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].green));
2367               Ascii85Encode(image,ScaleQuantumToChar(image->colormap[i].blue));
2368               continue;
2369             }
2370           (void) WriteBlobByte(image,
2371             ScaleQuantumToChar(image->colormap[i].red));
2372           (void) WriteBlobByte(image,
2373             ScaleQuantumToChar(image->colormap[i].green));
2374           (void) WriteBlobByte(image,
2375             ScaleQuantumToChar(image->colormap[i].blue));
2376         }
2377         if (compression == NoCompression)
2378           Ascii85Flush(image);
2379        offset=TellBlob(image)-offset;
2380        (void) WriteBlobString(image,"\nendstream\n");
2381       }
2382     (void) WriteBlobString(image,"endobj\n");
2383     /*
2384       Write Length object.
2385     */
2386     xref[object++]=TellBlob(image);
2387     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2388     (void) WriteBlobString(image,buffer);
2389     (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2390       (unsigned long) offset);
2391     (void) WriteBlobString(image,buffer);
2392     (void) WriteBlobString(image,"endobj\n");
2393     /*
2394       Write softmask object.
2395     */
2396     xref[object++]=TellBlob(image);
2397     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2398     (void) WriteBlobString(image,buffer);
2399     (void) WriteBlobString(image,"<<\n");
2400     if (image->matte == MagickFalse)
2401       (void) WriteBlobString(image,">>\n");
2402     else
2403       {
2404         (void) WriteBlobString(image,"/Type /XObject\n");
2405         (void) WriteBlobString(image,"/Subtype /Image\n");
2406         (void) FormatMagickString(buffer,MaxTextExtent,"/Name /Ma%lu\n",
2407           image->scene);
2408         (void) WriteBlobString(image,buffer);
2409         switch (compression)
2410         {
2411           case NoCompression:
2412           {
2413             (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2414               "ASCII85Decode");
2415             break;
2416           }
2417           case LZWCompression:
2418           {
2419             (void) FormatMagickString(buffer,MaxTextExtent,CFormat,"LZWDecode");
2420             break;
2421           }
2422           case ZipCompression:
2423           {
2424             (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2425               "FlateDecode");
2426             break;
2427           }
2428           default:
2429           {
2430             (void) FormatMagickString(buffer,MaxTextExtent,CFormat,
2431               "RunLengthDecode");
2432             break;
2433           }
2434         }
2435         (void) WriteBlobString(image,buffer);
2436         (void) FormatMagickString(buffer,MaxTextExtent,"/Width %lu\n",
2437           image->columns);
2438         (void) WriteBlobString(image,buffer);
2439         (void) FormatMagickString(buffer,MaxTextExtent,"/Height %lu\n",
2440           image->rows);
2441         (void) WriteBlobString(image,buffer);
2442         (void) WriteBlobString(image,"/ColorSpace /DeviceGray\n");
2443         (void) FormatMagickString(buffer,MaxTextExtent,"/BitsPerComponent %d\n",
2444           (compression == FaxCompression) || (compression == Group4Compression)
2445           ? 1 : 8);
2446         (void) WriteBlobString(image,buffer);
2447         (void) FormatMagickString(buffer,MaxTextExtent,"/Length %lu 0 R\n",
2448           object+1);
2449         (void) WriteBlobString(image,buffer);
2450         (void) WriteBlobString(image,">>\n");
2451         (void) WriteBlobString(image,"stream\n");
2452         offset=TellBlob(image);
2453         number_pixels=(MagickSizeType) image->columns*image->rows;
2454         switch (compression)
2455         {
2456           case RLECompression:
2457           default:
2458           {
2459             /*
2460               Allocate pixel array.
2461             */
2462             length=(size_t) number_pixels;
2463             pixels=(unsigned char *) AcquireQuantumMemory(length,
2464               sizeof(*pixels));
2465             if (pixels == (unsigned char *) NULL)
2466               {
2467                 image=DestroyImage(image);
2468                 ThrowWriterException(ResourceLimitError,
2469                   "MemoryAllocationFailed");
2470               }
2471             /*
2472               Dump Runlength encoded pixels.
2473             */
2474             q=pixels;
2475             for (y=0; y < (long) image->rows; y++)
2476             {
2477               p=GetVirtualPixels(image,0,y,image->columns,1,
2478                 &image->exception);
2479               if (p == (const PixelPacket *) NULL)
2480                 break;
2481               for (x=0; x < (long) image->columns; x++)
2482               {
2483                 *q++=ScaleQuantumToChar((Quantum) (QuantumRange-p->opacity));
2484                 p++;
2485               }
2486             }
2487 #if defined(MAGICKCORE_ZLIB_DELEGATE)
2488             if (compression == ZipCompression)
2489               status=ZLIBEncodeImage(image,length,pixels);
2490             else
2491 #endif
2492               if (compression == LZWCompression)
2493                 status=LZWEncodeImage(image,length,pixels);
2494               else
2495                 status=PackbitsEncodeImage(image,length,pixels);
2496             pixels=(unsigned char *) RelinquishMagickMemory(pixels);
2497             if (status == MagickFalse)
2498               {
2499                 (void) CloseBlob(image);
2500                 return(MagickFalse);
2501               }
2502             break;
2503           }
2504           case NoCompression:
2505           {
2506             /*
2507               Dump uncompressed PseudoColor packets.
2508             */
2509             Ascii85Initialize(image);
2510             for (y=0; y < (long) image->rows; y++)
2511             {
2512               p=GetVirtualPixels(image,0,y,image->columns,1,
2513                 &image->exception);
2514               if (p == (const PixelPacket *) NULL)
2515                 break;
2516               for (x=0; x < (long) image->columns; x++)
2517               {
2518                 Ascii85Encode(image,ScaleQuantumToChar((Quantum) (QuantumRange-
2519                   p->opacity)));
2520                 p++;
2521               }
2522             }
2523             Ascii85Flush(image);
2524             break;
2525           }
2526         }
2527         offset=TellBlob(image)-offset;
2528         (void) WriteBlobString(image,"\nendstream\n");
2529       }
2530     (void) WriteBlobString(image,"endobj\n");
2531     /*
2532       Write Length object.
2533     */
2534     xref[object++]=TellBlob(image);
2535     (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2536     (void) WriteBlobString(image,buffer);
2537     (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",(unsigned long)
2538       offset);
2539     (void) WriteBlobString(image,buffer);
2540     (void) WriteBlobString(image,"endobj\n");
2541     if (GetNextImageInList(image) == (Image *) NULL)
2542       break;
2543     image=SyncNextImageInList(image);
2544     status=SetImageProgress(image,SaveImagesTag,scene++,
2545       GetImageListLength(image));
2546     if (status == MagickFalse)
2547       break;
2548   } while (image_info->adjoin != MagickFalse);
2549   /*
2550     Write Metadata object.
2551   */
2552   xref[object++]=TellBlob(image);
2553   info_id=object;
2554   (void) FormatMagickString(buffer,MaxTextExtent,"%lu 0 obj\n",object);
2555   (void) WriteBlobString(image,buffer);
2556   (void) WriteBlobString(image,"<<\n");
2557   (void) FormatMagickString(buffer,MaxTextExtent,"/Title (%s)\n",
2558     EscapeParenthesis(image->filename));
2559   (void) WriteBlobString(image,buffer);
2560   seconds=time((time_t *) NULL);
2561 #if defined(MAGICKCORE_HAVE_LOCALTIME_R)
2562   (void) localtime_r(&seconds,&local_time);
2563 #else
2564   (void) memcpy(&local_time,localtime(&seconds),sizeof(local_time));
2565 #endif
2566   (void) FormatMagickString(date,MaxTextExtent,"D:%04d%02d%02d%02d%02d%02d",
2567     local_time.tm_year+1900,local_time.tm_mon+1,local_time.tm_mday,
2568     local_time.tm_hour,local_time.tm_min,local_time.tm_sec);
2569   (void) FormatMagickString(buffer,MaxTextExtent,"/CreationDate (%s)\n",date);
2570   (void) WriteBlobString(image,buffer);
2571   (void) FormatMagickString(buffer,MaxTextExtent,"/ModDate (%s)\n",date);
2572   (void) WriteBlobString(image,buffer);
2573   (void) FormatMagickString(buffer,MaxTextExtent,"/Producer (%s)\n",
2574     EscapeParenthesis(GetMagickVersion((unsigned long *) NULL)));
2575   (void) WriteBlobString(image,buffer);
2576   (void) WriteBlobString(image,">>\n");
2577   (void) WriteBlobString(image,"endobj\n");
2578   /*
2579     Write Xref object.
2580   */
2581   offset=TellBlob(image)-xref[0]+10;
2582   (void) WriteBlobString(image,"xref\n");
2583   (void) FormatMagickString(buffer,MaxTextExtent,"0 %lu\n",object+1);
2584   (void) WriteBlobString(image,buffer);
2585   (void) WriteBlobString(image,"0000000000 65535 f \n");
2586   for (i=0; i < (long) object; i++)
2587   {
2588     (void) FormatMagickString(buffer,MaxTextExtent,"%010lu 00000 n \n",
2589       (unsigned long) xref[i]);
2590     (void) WriteBlobString(image,buffer);
2591   }
2592   (void) WriteBlobString(image,"trailer\n");
2593   (void) WriteBlobString(image,"<<\n");
2594   (void) FormatMagickString(buffer,MaxTextExtent,"/Size %lu\n",object+1);
2595   (void) WriteBlobString(image,buffer);
2596   (void) FormatMagickString(buffer,MaxTextExtent,"/Info %lu 0 R\n",info_id);
2597   (void) WriteBlobString(image,buffer);
2598   (void) FormatMagickString(buffer,MaxTextExtent,"/Root %lu 0 R\n",root_id);
2599   (void) WriteBlobString(image,buffer);
2600   (void) WriteBlobString(image,">>\n");
2601   (void) WriteBlobString(image,"startxref\n");
2602   (void) FormatMagickString(buffer,MaxTextExtent,"%lu\n",
2603     (unsigned long) offset);
2604   (void) WriteBlobString(image,buffer);
2605   (void) WriteBlobString(image,"%%EOF\n");
2606   xref=(MagickOffsetType *) RelinquishMagickMemory(xref);
2607   (void) CloseBlob(image);
2608   return(MagickTrue);
2609 }