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