Coverage Report

Created: 2026-10-28 07:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/graphicsmagick/coders/ps2.c
Line
Count
Source
1
/*
2
% Copyright (C) 2003-2026 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
% SPDX-License-Identifier: MIT
6
%
7
% This program is covered by multiple licenses, which are described in
8
% Copyright.txt. You should have received a copy of Copyright.txt with this
9
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
10
%
11
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
12
%                                                                             %
13
%                                                                             %
14
%                                                                             %
15
%                            PPPP   SSSSS  22222                              %
16
%                            P   P  SS        22                              %
17
%                            PPPP    SSS    222                               %
18
%                            P         SS  22                                 %
19
%                            P      SSSSS  22222                              %
20
%                                                                             %
21
%                                                                             %
22
%                     Write Postscript Level II Format.                       %
23
%                                                                             %
24
%                                                                             %
25
%                              Software Design                                %
26
%                                John Cristy                                  %
27
%                                 July 1992                                   %
28
%                                                                             %
29
%                                                                             %
30
%                                                                             %
31
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
32
%
33
%
34
*/
35

36
/*
37
  Include declarations.
38
*/
39
#include "magick/studio.h"
40
#include "magick/analyze.h"
41
#include "magick/attribute.h"
42
#include "magick/blob.h"
43
#include "magick/pixel_cache.h"
44
#include "magick/color.h"
45
#include "magick/constitute.h"
46
#include "magick/compress.h"
47
#include "magick/enum_strings.h"
48
#include "magick/magick.h"
49
#include "magick/monitor.h"
50
#include "magick/tempfile.h"
51
#include "magick/utility.h"
52
#include "magick/static.h"
53
#if defined(HasTIFF)
54
0
#define CCITTParam  "-1"
55
#else
56
#define CCITTParam  "0"
57
#endif
58

59
/*
60
  Forward declarations.
61
*/
62
static unsigned int
63
  WritePS2Image(const ImageInfo *,Image *);
64

65
#if defined(HasTIFF)
66
#if defined(HAVE_TIFFCONF_H)
67
#  include "tiffconf.h"
68
#endif
69
#include "tiffio.h"
70
71
#if (TIFFLIB_VERSION >= 20201219)
72
#  undef uint16
73
0
#  define uint16 uint16_t
74
#  undef uint32
75
#  define uint32 uint32_t
76
#endif /* TIFFLIB_VERSION */
77
78
/*
79
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
80
%                                                                             %
81
%                                                                             %
82
%                                                                             %
83
%   H u f f m a n 2 D E n c o d e I m a g e                                   %
84
%                                                                             %
85
%                                                                             %
86
%                                                                             %
87
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
88
%
89
%  Method Huffman2DEncodeImage compresses an image via two-dimensional
90
%  Huffman-coding.
91
%
92
%  The format of the Huffman2DEncodeImage method is:
93
%
94
%      MagickPassFail Huffman2DEncodeImage(const ImageInfo *image_info,
95
%        Image *image)
96
%
97
%  A description of each parameter follows:
98
%
99
%    o status:  Method Huffman2DEncodeImage returns True if all the pixels are
100
%      compressed without error, otherwise False.
101
%
102
%    o image_info: The image info..
103
%
104
%    o image: The image.
105
%
106
*/
107
static MagickPassFail Huffman2DEncodeImage(const ImageInfo *image_info,
108
                                           Image *image)
109
0
{
110
0
  char
111
0
    filename[MaxTextExtent];
112
113
0
  Image
114
0
    *huffman_image;
115
116
0
  ImageInfo
117
0
    *clone_info;
118
119
0
  long
120
0
    count,
121
0
    j;
122
123
0
  register long
124
0
    i;
125
126
0
  TIFF
127
0
    *tiff;
128
129
0
  uint16
130
0
    fillorder;
131
132
0
  unsigned char
133
0
    *buffer;
134
135
0
  unsigned int
136
0
    status;
137
138
0
  unsigned long
139
0
    *byte_count,
140
0
    strip_size;
141
142
  /*
143
    Write image as CCITTFax4 TIFF image to a temporary file.
144
  */
145
0
  assert(image_info != (ImageInfo *) NULL);
146
0
  assert(image_info->signature == MagickSignature);
147
0
  assert(image != (Image *) NULL);
148
0
  assert(image->signature == MagickSignature);
149
0
  huffman_image=CloneImage(image,0,0,True,&image->exception);
150
0
  if (huffman_image == (Image *) NULL)
151
0
    return MagickFail;
152
0
  if (SetImageType(huffman_image,BilevelType) == MagickFail)
153
0
    {
154
0
      CopyException(&image->exception,&huffman_image->exception);
155
0
      DestroyImage(huffman_image);
156
0
      return MagickFail;
157
0
    }
158
0
  if(!AcquireTemporaryFileName(filename))
159
0
    {
160
0
      DestroyImage(huffman_image);
161
0
      ThrowBinaryException(FileOpenError,UnableToCreateTemporaryFile,
162
0
                           filename);
163
0
    }
164
0
  MagickFormatString(huffman_image->filename,sizeof(huffman_image->filename),"tiff:%s",filename);
165
0
  clone_info=CloneImageInfo(image_info);
166
0
  clone_info->compression=Group4Compression;
167
0
  clone_info->type=BilevelType;
168
0
  (void) AddDefinitions(clone_info,"tiff:fill-order=msb2lsb",
169
0
                        &image->exception);
170
0
  status=WriteImage(clone_info,huffman_image);
171
0
  DestroyImageInfo(clone_info);
172
0
  DestroyImage(huffman_image);
173
0
  if (status == MagickFail)
174
0
    return(MagickFail);
175
0
  tiff=TIFFOpen(filename,"rb");
176
0
  if (tiff == (TIFF *) NULL)
177
0
    {
178
0
      (void) LiberateTemporaryFile(filename);
179
0
      ThrowBinaryException(FileOpenError,UnableToOpenFile,
180
0
                           image_info->filename);
181
0
    }
182
  /*
183
    Allocate raw strip buffer.
184
  */
185
0
  (void) TIFFGetField(tiff,TIFFTAG_STRIPBYTECOUNTS,&byte_count);
186
0
  strip_size=byte_count[0];
187
0
  for (i=1; i < (long) TIFFNumberOfStrips(tiff); i++)
188
0
    if (byte_count[i] > strip_size)
189
0
      strip_size=byte_count[i];
190
0
  buffer=MagickAllocateResourceLimitedMemory(unsigned char *,strip_size);
191
0
  if (buffer == (unsigned char *) NULL)
192
0
    {
193
0
      TIFFClose(tiff);
194
0
      (void) LiberateTemporaryFile(filename);
195
0
      ThrowBinaryException(ResourceLimitError,MemoryAllocationFailed,
196
0
                           (char *) NULL);
197
0
    }
198
  /*
199
    Compress runlength encoded to 2D Huffman pixels.
200
  */
201
0
  (void) TIFFGetFieldDefaulted(tiff,TIFFTAG_FILLORDER,&fillorder);
202
0
  for (i=0; i < (long) TIFFNumberOfStrips(tiff); i++)
203
0
    {
204
0
      Ascii85Initialize(image);
205
0
      count=TIFFReadRawStrip(tiff,(uint32) i,buffer,(long) byte_count[i]);
206
0
      if (fillorder == FILLORDER_LSB2MSB)
207
0
        TIFFReverseBits(buffer,count);
208
0
      for (j=0; j < count; j++)
209
0
        Ascii85Encode(image,(unsigned long) buffer[j]);
210
0
      Ascii85Flush(image);
211
0
    }
212
0
  MagickFreeResourceLimitedMemory(unsigned char *,buffer);
213
0
  TIFFClose(tiff);
214
0
  (void) LiberateTemporaryFile(filename);
215
0
  return(MagickPass);
216
0
}
217
#else
218
static MagickPassFail Huffman2DEncodeImage(const ImageInfo *image_info,
219
  Image *image)
220
{
221
  ARG_NOT_USED(image_info);
222
  assert(image != (Image *) NULL);
223
  assert(image->signature == MagickSignature);
224
  ThrowBinaryException(MissingDelegateError,TIFFLibraryIsNotAvailable,image->filename);
225
}
226
#endif
227

228
/*
229
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
230
%                                                                             %
231
%                                                                             %
232
%                                                                             %
233
%   R e g i s t e r P S 2 I m a g e                                           %
234
%                                                                             %
235
%                                                                             %
236
%                                                                             %
237
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
238
%
239
%  Method RegisterPS2Image adds attributes for the PS2 image format to
240
%  the list of supported formats.  The attributes include the image format
241
%  tag, a method to read and/or write the format, whether the format
242
%  supports the saving of more than one frame to the same file or blob,
243
%  whether the format supports native in-memory I/O, and a brief
244
%  description of the format.
245
%
246
%  The format of the RegisterPS2Image method is:
247
%
248
%      RegisterPS2Image(void)
249
%
250
*/
251
ModuleExport void RegisterPS2Image(void)
252
0
{
253
0
  MagickInfo
254
0
    *entry;
255
256
0
  entry=SetMagickInfo("EPS2");
257
0
  entry->encoder=(EncoderHandler) WritePS2Image;
258
0
  entry->adjoin=False;
259
0
  entry->seekable_stream=True;
260
0
  entry->description="Adobe Level II Encapsulated PostScript";
261
0
  entry->module="PS2";
262
0
  entry->coder_class=PrimaryCoderClass;
263
0
  (void) RegisterMagickInfo(entry);
264
265
0
  entry=SetMagickInfo("PS2");
266
0
  entry->encoder=(EncoderHandler) WritePS2Image;
267
0
  entry->seekable_stream=True;
268
0
  entry->description="Adobe Level II PostScript";
269
0
  entry->module="PS2";
270
0
  entry->coder_class=PrimaryCoderClass;
271
0
  (void) RegisterMagickInfo(entry);
272
0
}
273

274
/*
275
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
276
%                                                                             %
277
%                                                                             %
278
%                                                                             %
279
%   U n r e g i s t e r P S 2 I m a g e                                       %
280
%                                                                             %
281
%                                                                             %
282
%                                                                             %
283
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
284
%
285
%  Method UnregisterPS2Image removes format registrations made by the
286
%  PS2 module from the list of supported formats.
287
%
288
%  The format of the UnregisterPS2Image method is:
289
%
290
%      UnregisterPS2Image(void)
291
%
292
*/
293
ModuleExport void UnregisterPS2Image(void)
294
0
{
295
0
  (void) UnregisterMagickInfo("EPS2");
296
0
  (void) UnregisterMagickInfo("PS2");
297
0
}
298

299
/*
300
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
301
%                                                                             %
302
%                                                                             %
303
%                                                                             %
304
%   W r i t e P S 2 I m a g e                                                 %
305
%                                                                             %
306
%                                                                             %
307
%                                                                             %
308
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
309
%
310
%  Method WritePS2Image translates an image to encapsulated Postscript
311
%  Level II for printing.  If the supplied geometry is null, the image is
312
%  centered on the Postscript page.  Otherwise, the image is positioned as
313
%  specified by the geometry.
314
%
315
%  The format of the WritePS2Image method is:
316
%
317
%      MagickPassFail WritePS2Image(const ImageInfo *image_info,Image *image)
318
%
319
%  A description of each parameter follows:
320
%
321
%    o status: Method WritePS2Image return True if the image is printed.
322
%      False is returned if the image file cannot be opened for printing.
323
%
324
%    o image_info: Specifies a pointer to a ImageInfo structure.
325
%
326
%    o image: The address of a structure of type Image;  returned from
327
%      ReadImage.
328
%
329
%
330
*/
331
static MagickPassFail WritePS2Image(const ImageInfo *image_info,Image *image)
332
0
{
333
0
  char
334
0
    buffer[MaxTextExtent],
335
0
    date[MaxTextExtent],
336
0
    density[MaxTextExtent],
337
0
    page_geometry[MaxTextExtent],
338
0
    **labels;
339
340
0
  CompressionType
341
0
    compression;
342
343
0
  const ImageAttribute
344
0
    *attribute;
345
346
0
  double
347
0
    dx_resolution,
348
0
    dy_resolution,
349
0
    x_resolution,
350
0
    x_scale,
351
0
    y_resolution,
352
0
    y_scale;
353
354
0
  magick_off_t
355
0
    current,
356
0
    start,
357
0
    stop;
358
359
0
  int
360
0
    count,
361
0
    status;
362
363
0
  long
364
0
    j,
365
0
    y;
366
367
0
  RectangleInfo
368
0
    geometry;
369
370
0
  register const PixelPacket
371
0
    *p;
372
373
0
  register const IndexPacket
374
0
    *indexes;
375
376
0
  register long
377
0
    x;
378
379
0
  register long
380
0
    i;
381
382
0
  SegmentInfo
383
0
    bounds={0.0,0.0,0.0,0.0};
384
385
0
  size_t
386
0
    length;
387
388
0
  time_t
389
0
    timer;
390
391
0
  unsigned char
392
0
    *pixels;
393
394
0
  unsigned long
395
0
    number_pixels,
396
0
    page,
397
0
    scene,
398
0
    text_size;
399
400
0
  void
401
0
    *blob;
402
403
0
  size_t
404
0
    image_list_length;
405
406
  /*
407
    Open output image file.
408
  */
409
0
  assert(image_info != (const ImageInfo *) NULL);
410
0
  assert(image_info->signature == MagickSignature);
411
0
  assert(image != (Image *) NULL);
412
0
  assert(image->signature == MagickSignature);
413
0
  image_list_length=GetImageListLength(image);
414
0
  status=OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception);
415
0
  if (status == MagickFail)
416
0
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
417
0
  compression=image->compression;
418
0
  if (image_info->compression != UndefinedCompression)
419
0
    compression=image_info->compression;
420
0
  switch (compression)
421
0
    {
422
#if !defined(HasJPEG)
423
    case JPEGCompression:
424
      {
425
        compression=RLECompression;
426
        ThrowException(&image->exception,MissingDelegateError,JPEGLibraryIsNotAvailable,image->filename);
427
        break;
428
      }
429
#endif
430
#if !defined(HasZLIB)
431
    case ZipCompression:
432
      {
433
        compression=RLECompression;
434
        ThrowException(&image->exception,MissingDelegateError,ZipLibraryIsNotAvailable,image->filename);
435
        break;
436
      }
437
#endif
438
0
    default:
439
0
      break;
440
0
    }
441
0
  page=1;
442
0
  scene=0;
443
0
  do
444
0
    {
445
0
      ImageCharacteristics
446
0
        characteristics;
447
448
      /*
449
        Analyze image to be written.
450
      */
451
0
      if (GetImageCharacteristics(image,&characteristics,
452
0
                                  (OptimizeType == image_info->type),
453
0
                                  &image->exception) == MagickFail)
454
0
        ThrowWriterException(CoderError,UnableToGetImageCharacteristics,image);
455
456
      /*
457
        Scale image to size of Postscript page.
458
      */
459
0
      text_size=0;
460
0
      attribute=GetImageAttribute(image,"label");
461
0
      if (attribute != (const ImageAttribute *) NULL)
462
0
        text_size=(unsigned int)
463
0
          (MultilineCensus(attribute->value)*image_info->pointsize+12);
464
0
      SetGeometry(image,&geometry);
465
0
      geometry.y=(long) text_size;
466
0
      MagickFormatString(page_geometry,sizeof(page_geometry),"%lux%lu",image->columns,image->rows);
467
0
      if (image_info->page != (char *) NULL)
468
0
        (void) strlcpy(page_geometry,image_info->page,MaxTextExtent);
469
0
      else
470
0
        if ((image->page.width != 0) && (image->page.height != 0))
471
0
          (void) MagickFormatString(page_geometry,sizeof(page_geometry),"%lux%lu%+ld%+ld",image->page.width,
472
0
                                    image->page.height,image->page.x,image->page.y);
473
0
        else
474
0
          if (LocaleCompare(image_info->magick,"PS2") == 0)
475
0
            (void) strlcpy(page_geometry,PSPageGeometry,sizeof(page_geometry));
476
0
      (void) GetMagickGeometry(page_geometry,&geometry.x,&geometry.y,
477
0
                               &geometry.width,&geometry.height);
478
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
479
0
                            "Image Resolution: %gx%g %s",
480
0
                            image->x_resolution,
481
0
                            image->y_resolution,
482
0
                            ResolutionTypeToString(image->units));
483
      /*
484
        Scale relative to dots-per-inch.
485
      */
486
0
      dx_resolution=72.0;
487
0
      dy_resolution=72.0;
488
0
      x_resolution=72.0;
489
0
      (void) strlcpy(density,PSDensityGeometry,sizeof(density));
490
0
      count=GetMagickDimension(density,&x_resolution,&y_resolution,NULL,NULL);
491
0
      if (count != 2)
492
0
        y_resolution=x_resolution;
493
      /*
494
        Use override resolution information if it appears to be valid.
495
      */
496
0
      if ((image_info->density != (char *) NULL) &&
497
0
          ((image_info->units == PixelsPerInchResolution) ||
498
0
           (image_info->units == PixelsPerCentimeterResolution)))
499
0
        {
500
0
          count=GetMagickDimension(image_info->density,&x_resolution,
501
0
                                   &y_resolution,NULL,NULL);
502
0
          if (count != 2)
503
0
            y_resolution=x_resolution;
504
0
          if (image_info->units == PixelsPerCentimeterResolution)
505
0
            {
506
0
              x_resolution *= 2.54;
507
0
              y_resolution *= 2.54;
508
0
            }
509
0
        }
510
      /*
511
        Use image resolution information if it appears to be valid.
512
      */
513
0
      else if ((image->x_resolution > 0.0) && (image->y_resolution > 0.0) &&
514
0
               ((image->units == PixelsPerInchResolution) ||
515
0
                (image->units == PixelsPerCentimeterResolution)))
516
0
        {
517
0
          x_resolution = image->x_resolution;
518
0
          y_resolution = image->y_resolution;
519
0
          if (image->units == PixelsPerCentimeterResolution)
520
0
            {
521
0
              x_resolution *= 2.54;
522
0
              y_resolution *= 2.54;
523
0
            }
524
0
        }
525
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
526
0
                            "Postscript Resolution: %gx%g DPI",
527
0
                            x_resolution,y_resolution);
528
0
      x_scale=(geometry.width*dx_resolution)/x_resolution;
529
0
      geometry.width=(unsigned long) (x_scale+0.5);
530
0
      y_scale=(geometry.height*dy_resolution)/y_resolution;
531
0
      geometry.height=(unsigned long) (y_scale+0.5);
532
      /*
533
        Enforce maximum Postscript dimensions to avoid denial of service
534
      */
535
0
      {
536
0
        magick_uint64_t
537
0
          pixels;
538
539
0
        if (AcquireMagickResource(WidthResource,geometry.width) != MagickPass)
540
0
          ThrowWriterException(ResourceLimitError,ImagePixelWidthLimitExceeded,image);
541
0
        if (AcquireMagickResource(HeightResource,geometry.height) != MagickPass)
542
0
          ThrowWriterException(ResourceLimitError,ImagePixelHeightLimitExceeded,image);
543
0
        pixels=(magick_uint64_t)geometry.width*geometry.height;
544
0
        if ((0 == pixels) || (pixels/geometry.width != geometry.height) ||
545
0
            (AcquireMagickResource(PixelsResource,pixels) != MagickPass))
546
0
          ThrowWriterException(ResourceLimitError,ImagePixelLimitExceeded,image);
547
0
      }
548
0
      if (page == 1)
549
0
        {
550
          /*
551
            Output Postscript header.
552
          */
553
0
#if defined(HAVE_CTIME_R)
554
0
          char time_buf[26];
555
0
#endif /* defined(HAVE_CTIME_R) */
556
0
          if (LocaleCompare(image_info->magick,"PS2") == 0)
557
0
            (void) strlcpy(buffer,"%!PS-Adobe-3.0\n",sizeof(buffer));
558
0
          else
559
0
            (void) strlcpy(buffer,"%!PS-Adobe-3.0 EPSF-3.0\n",sizeof(buffer));
560
0
          (void) WriteBlobString(image,buffer);
561
0
          (void) WriteBlobString(image,"%%Creator: (GraphicsMagick)\n");
562
0
          MagickFormatString(buffer,sizeof(buffer),"%%%%Title: (%.1024s)\n",image->filename);
563
0
          (void) WriteBlobString(image,buffer);
564
0
          timer=time((time_t *) NULL);
565
0
#if defined(HAVE_CTIME_R)
566
0
          (void) strlcpy(date,ctime_r(&timer,time_buf),MaxTextExtent);
567
#else
568
          (void) strlcpy(date,ctime(&timer),MaxTextExtent); /* Thread-unsafe version */
569
#endif /* defined(HAVE_CTIME_R) */
570
0
          date[strlen(date)-1]='\0';
571
0
          MagickFormatString(buffer,sizeof(buffer),"%%%%CreationDate: (%.1024s)\n",date);
572
0
          (void) WriteBlobString(image,buffer);
573
0
          bounds.x1=geometry.x;
574
0
          bounds.y1=geometry.y;
575
0
          bounds.x2=geometry.x+(size_t) geometry.width;
576
0
          bounds.y2=geometry.y+(size_t) geometry.height+text_size;
577
0
          if (image_info->adjoin && (image->next != (Image *) NULL))
578
0
            (void) strlcpy(buffer,"%%BoundingBox: (atend)\n",sizeof(buffer));
579
0
          else
580
0
            MagickFormatString(buffer,sizeof(buffer),"%%%%BoundingBox: %g %g %g %g\n",
581
0
                               floor(bounds.x1+0.5),floor(bounds.y1+0.5),ceil(bounds.x2-0.5),
582
0
                               ceil(bounds.y2-0.5));
583
0
          (void) WriteBlobString(image,buffer);
584
0
          attribute=GetImageAttribute(image,"label");
585
0
          if (attribute != (const ImageAttribute *) NULL)
586
0
            (void) WriteBlobString(image,
587
0
                                   "%%DocumentNeededResources: font Helvetica\n");
588
0
          (void) WriteBlobString(image,"%%LanguageLevel: 2\n");
589
0
          if (LocaleCompare(image_info->magick,"PS2") != 0)
590
0
            (void) WriteBlobString(image,"%%Pages: 1\n");
591
0
          else
592
0
            {
593
0
              (void) WriteBlobString(image,"%%Orientation: Portrait\n");
594
0
              (void) WriteBlobString(image,"%%PageOrder: Ascend\n");
595
0
              if (!image_info->adjoin)
596
0
                (void) strlcpy(buffer,"%%Pages: 1\n",sizeof(buffer));
597
0
              else
598
0
                MagickFormatString(buffer,sizeof(buffer),"%%%%Pages: %lu\n",(unsigned long)
599
0
                                   image_list_length);
600
0
              (void) WriteBlobString(image,buffer);
601
0
            }
602
0
          (void) WriteBlobString(image,"%%EndComments\n");
603
0
          (void) WriteBlobString(image,"\n%%BeginDefaults\n");
604
0
          (void) WriteBlobString(image,"%%EndDefaults\n\n");
605
          /*
606
            Output Postscript commands.
607
          */
608
0
          {
609
0
            const char * ps_compress;
610
611
0
            switch (compression)
612
0
              {
613
0
              case NoCompression: ps_compress="ASCII85Decode"; break;
614
0
              case JPEGCompression: ps_compress="DCTDecode"; break;
615
0
              case LZWCompression: ps_compress="LZWDecode"; break;
616
0
              case FaxCompression: ps_compress="ASCII85Decode"; break;
617
0
              default: ps_compress="RunLengthDecode"; break;
618
0
              }
619
0
            (void) WriteBlobString(image,
620
0
                                   "%%BeginProlog\n"
621
0
                                   "%\n"
622
0
                                   "% Display a color image.  The image is displayed in color on\n"
623
0
                                   "% Postscript viewers or printers that support color, otherwise\n"
624
0
                                   "% it is displayed as grayscale.\n"
625
0
                                   "%\n"
626
0
                                   "/DirectClassImage\n");
627
0
            MagickFormatString(buffer,sizeof(buffer),
628
0
                               "{\n"
629
0
                               "  %%\n"
630
0
                               "  %% Display a DirectClass image.\n"
631
0
                               "  %%\n"
632
0
                               "  colorspace 0 eq\n"
633
0
                               "  {\n"
634
0
                               "    /DeviceRGB setcolorspace\n"
635
0
                               "    <<\n"
636
0
                               "      /ImageType 1\n"
637
0
                               "      /Width columns\n"
638
0
                               "      /Height rows\n"
639
0
                               "      /BitsPerComponent 8\n"
640
0
                               "      /Decode [0 1 0 1 0 1]\n"
641
0
                               "      /ImageMatrix [columns 0 0 rows neg 0 rows]\n"
642
0
                               "      compression 0 gt\n"
643
0
                               "      { /DataSource pixel_stream /%.1024s filter }\n"
644
0
                               "      { /DataSource pixel_stream /%.1024s filter } ifelse\n"
645
0
                               "    >> image\n"
646
0
                               "  }\n",
647
0
                               ps_compress, ps_compress);
648
0
            (void) WriteBlobString(image,buffer);
649
0
            MagickFormatString(buffer,sizeof(buffer),
650
0
                               "  {\n"
651
0
                               "    /DeviceCMYK setcolorspace\n"
652
0
                               "    <<\n"
653
0
                               "      /ImageType 1\n"
654
0
                               "      /Width columns\n"
655
0
                               "      /Height rows\n"
656
0
                               "      /BitsPerComponent 8\n"
657
0
                               "      /Decode [1 0 1 0 1 0 1 0]\n"
658
0
                               "      /ImageMatrix [columns 0 0 rows neg 0 rows]\n"
659
0
                               "      compression 0 gt\n"
660
0
                               "      { /DataSource pixel_stream /%.1024s filter }\n"
661
0
                               "      { /DataSource pixel_stream /%.1024s filter } ifelse\n"
662
0
                               "    >> image\n"
663
0
                               "  } ifelse\n"
664
0
                               "} bind def\n"
665
0
                               "\n",
666
0
                               ps_compress, ps_compress);
667
0
            (void) WriteBlobString(image,buffer);
668
0
            MagickFormatString(buffer,sizeof(buffer),
669
0
                               "/PseudoClassImage\n"
670
0
                               "{\n"
671
0
                               "  %%\n"
672
0
                               "  %% Display a PseudoClass image.\n"
673
0
                               "  %%\n"
674
0
                               "  %% Parameters:\n"
675
0
                               "  %%   colors: number of colors in the colormap.\n"
676
0
                               "  %%\n"
677
0
                               "  currentfile buffer readline pop\n"
678
0
                               "  token pop /colors exch def pop\n"
679
0
                               "  colors 0 eq\n"
680
0
                               "  {\n"
681
0
                               "    %%\n"
682
0
                               "    %% Image is grayscale.\n"
683
0
                               "    %%\n"
684
0
                               "    currentfile buffer readline pop\n"
685
0
                               "    token pop /bits exch def pop\n"
686
0
                               "    /DeviceGray setcolorspace\n"
687
0
                               "    <<\n"
688
0
                               "      /ImageType 1\n"
689
0
                               "      /Width columns\n"
690
0
                               "      /Height rows\n"
691
0
                               "      /BitsPerComponent bits\n"
692
0
                               "      /Decode [0 1]\n"
693
0
                               "      /ImageMatrix [columns 0 0 rows neg 0 rows]\n"
694
0
                               "      compression 0 gt\n"
695
0
                               "      { /DataSource pixel_stream /%.1024s filter }\n"
696
0
                               "      {\n"
697
0
                               "        /DataSource pixel_stream /%.1024s filter\n"
698
0
                               "        <<\n"
699
0
                               "           /K " CCITTParam "\n"
700
0
                               "           /Columns columns\n"
701
0
                               "           /Rows rows\n"
702
0
                               "        >> /CCITTFaxDecode filter\n"
703
0
                               "      } ifelse\n"
704
0
                               "    >> image\n"
705
0
                               "  }\n",
706
0
                               ps_compress, ps_compress);
707
0
            (void) WriteBlobString(image,buffer);
708
0
            MagickFormatString(buffer,sizeof(buffer),
709
0
                               "  {\n"
710
0
                               "    %%\n"
711
0
                               "    %% Parameters:\n"
712
0
                               "    %%   colormap: red, green, blue color packets.\n"
713
0
                               "    %%\n"
714
0
                               "    /colormap colors 3 mul string def\n"
715
0
                               "    currentfile colormap readhexstring pop pop\n"
716
0
                               "    currentfile buffer readline pop\n"
717
0
                               "    [ /Indexed /DeviceRGB colors 1 sub colormap ] setcolorspace\n"
718
0
                               "    <<\n"
719
0
                               "      /ImageType 1\n"
720
0
                               "      /Width columns\n"
721
0
                               "      /Height rows\n"
722
0
                               "      /BitsPerComponent 8\n"
723
0
                               "      /Decode [0 255]\n"
724
0
                               "      /ImageMatrix [columns 0 0 rows neg 0 rows]\n"
725
0
                               "      compression 0 gt\n"
726
0
                               "      { /DataSource pixel_stream /%.1024s filter }\n"
727
0
                               "      { /DataSource pixel_stream /%.1024s filter } ifelse\n"
728
0
                               "    >> image\n"
729
0
                               "  } ifelse\n"
730
0
                               "} bind def\n"
731
0
                               "\n",
732
0
                               ps_compress, ps_compress);
733
0
            (void) WriteBlobString(image,buffer);
734
0
            (void) WriteBlobString(image,
735
0
                                   "/DisplayImage\n"
736
0
                                   "{\n"
737
0
                                   "  %\n"
738
0
                                   "  % Display a DirectClass or PseudoClass image.\n"
739
0
                                   "  %\n"
740
0
                                   "  % Parameters:\n"
741
0
                                   "  %   x & y translation.\n"
742
0
                                   "  %   x & y scale.\n"
743
0
                                   "  %   label pointsize.\n"
744
0
                                   "  %   image label.\n"
745
0
                                   "  %   image columns & rows.\n"
746
0
                                   "  %   class: 0-DirectClass or 1-PseudoClass.\n"
747
0
                                   "  %   colorspace: 0-RGB or 1-CMYK.\n"
748
0
                                   "  %   compression: 0-RLECompression or 1-NoCompression.\n"
749
0
                                   "  %   hex color packets.\n"
750
0
                                   "  %\n"
751
0
                                   "  gsave\n"
752
0
                                   "  /buffer 512 string def\n"
753
0
                                   "  /pixel_stream currentfile def\n"
754
0
                                   "\n"
755
0
                                   "  currentfile buffer readline pop\n"
756
0
                                   "  token pop /x exch def\n"
757
0
                                   "  token pop /y exch def pop\n"
758
0
                                   "  x y translate\n"
759
0
                                   "  currentfile buffer readline pop\n"
760
0
                                   "  token pop /x exch def\n"
761
0
                                   "  token pop /y exch def pop\n"
762
0
                                   "  currentfile buffer readline pop\n"
763
0
                                   "  token pop /pointsize exch def pop\n"
764
0
                                   "  /Helvetica findfont pointsize scalefont setfont\n"
765
0
                                   );
766
0
          }
767
0
          attribute=GetImageAttribute(image,"label");
768
0
          if (attribute != (const ImageAttribute *) NULL)
769
0
            for (j=(long) MultilineCensus(attribute->value)-1; j >= 0; j--)
770
0
              {
771
0
                (void) WriteBlobString(image,"  /label 512 string def\n");
772
0
                (void) WriteBlobString(image,"  currentfile label readline pop\n");
773
0
                MagickFormatString(buffer,sizeof(buffer),"  0 y %g add moveto label show pop\n",
774
0
                                   j*image_info->pointsize+12);
775
0
                (void) WriteBlobString(image,buffer);
776
0
              }
777
0
          (void) WriteBlobString(image,
778
0
                                 "  x y scale\n"
779
0
                                 "  currentfile buffer readline pop\n"
780
0
                                 "  token pop /columns exch def\n"
781
0
                                 "  token pop /rows exch def pop\n"
782
0
                                 "  currentfile buffer readline pop\n"
783
0
                                 "  token pop /class exch def pop\n"
784
0
                                 "  currentfile buffer readline pop\n"
785
0
                                 "  token pop /colorspace exch def pop\n"
786
0
                                 "  currentfile buffer readline pop\n"
787
0
                                 "  token pop /compression exch def pop\n"
788
0
                                 "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse\n"
789
0
                                 "  grestore\n");
790
0
          if (LocaleCompare(image_info->magick,"PS2") == 0)
791
0
            (void) WriteBlobString(image,"  showpage\n");
792
0
          (void) WriteBlobString(image,"} bind def\n");
793
0
          (void) WriteBlobString(image,"%%EndProlog\n");
794
0
        }
795
0
      MagickFormatString(buffer,sizeof(buffer),"%%%%Page:  1 %lu\n",page++);
796
0
      (void) WriteBlobString(image,buffer);
797
0
      MagickFormatString(buffer,sizeof(buffer),"%%%%PageBoundingBox: %ld %ld %ld %ld\n",geometry.x,
798
0
                         geometry.y,geometry.x+(long) geometry.width,geometry.y+(long)
799
0
                         (geometry.height+text_size));
800
0
      (void) WriteBlobString(image,buffer);
801
0
      if (geometry.x < bounds.x1)
802
0
        bounds.x1=geometry.x;
803
0
      if (geometry.y < bounds.y1)
804
0
        bounds.y1=geometry.y;
805
0
      if ((geometry.x+(size_t) geometry.width-1) > bounds.x2)
806
0
        bounds.x2=geometry.x+(size_t) geometry.width-1;
807
0
      if ((geometry.y+((size_t) geometry.height+text_size)-1) > bounds.y2)
808
0
        bounds.y2=geometry.y+((size_t) geometry.height+text_size)-1;
809
0
      attribute=GetImageAttribute(image,"label");
810
0
      if (attribute != (const ImageAttribute *) NULL)
811
0
        (void) WriteBlobString(image,"%%PageResources: font Times-Roman\n");
812
0
      if (LocaleCompare(image_info->magick,"PS2") != 0)
813
0
        (void) WriteBlobString(image,"userdict begin\n");
814
0
      start=TellBlob(image);
815
0
      if (start < 0)
816
0
        ThrowWriterException(BlobError,UnableToObtainOffset,image);
817
0
      MagickFormatString(buffer,sizeof(buffer),"%%%%BeginData:%13ld %s Bytes\n",0L,
818
0
                         compression == NoCompression ? "ASCII" : "Binary");
819
0
      (void) WriteBlobString(image,buffer);
820
0
      stop=TellBlob(image);
821
0
      if (stop < 0)
822
0
        ThrowWriterException(BlobError,UnableToObtainOffset,image);
823
0
      (void) WriteBlobString(image,"DisplayImage\n");
824
      /*
825
        Output image data.
826
      */
827
0
      MagickFormatString(buffer,sizeof(buffer),"%ld %ld\n%g %g\n%f\n",geometry.x,geometry.y,
828
0
                         x_scale,y_scale,image_info->pointsize);
829
0
      (void) WriteBlobString(image,buffer);
830
0
      labels=(char **) NULL;
831
0
      attribute=GetImageAttribute(image,"label");
832
0
      if (attribute != (const ImageAttribute *) NULL)
833
0
        labels=StringToList(attribute->value);
834
0
      if (labels != (char **) NULL)
835
0
        {
836
0
          for (i=0; labels[i] != (char *) NULL; i++)
837
0
            {
838
0
              MagickFormatString(buffer,sizeof(buffer),"%.1024s \n",labels[i]);
839
0
              (void) WriteBlobString(image,buffer);
840
0
              MagickFreeMemory(labels[i]);
841
0
            }
842
0
          MagickFreeMemory(labels);
843
0
        }
844
0
      number_pixels=image->columns*image->rows;
845
846
0
      if ((compression == FaxCompression) ||
847
0
          ((image_info->type != TrueColorType) &&
848
0
           (characteristics.grayscale)))
849
0
        {
850
0
          MagickFormatString(buffer,sizeof(buffer),"%lu %lu\n1\n%d\n",image->columns,image->rows,
851
0
                             (int) (image->colorspace == CMYKColorspace));
852
0
          (void) WriteBlobString(image,buffer);
853
0
          MagickFormatString(buffer,sizeof(buffer),"%d\n",(int) (compression != FaxCompression));
854
0
          (void) WriteBlobString(image,buffer);
855
0
          (void) WriteBlobString(image,"0\n");
856
0
          MagickFormatString(buffer,sizeof(buffer),"%d\n",compression == FaxCompression ? 1 : 8);
857
0
          (void) WriteBlobString(image,buffer);
858
0
          switch (compression)
859
0
            {
860
0
            case FaxCompression:
861
0
              {
862
0
                if (LocaleCompare(CCITTParam,"0") == 0)
863
0
                  {
864
0
                    (void) HuffmanEncodeImage(image_info,image);
865
0
                    break;
866
0
                  }
867
0
                (void) Huffman2DEncodeImage(image_info,image);
868
0
                break;
869
0
              }
870
0
            case JPEGCompression:
871
0
              {
872
                /*
873
                  Write image in JPEG format.
874
                */
875
0
                blob=ImageToJPEGBlob(image,image_info,&length,&image->exception);
876
0
                if (blob == (char *) NULL)
877
0
                  ThrowWriterException2(CoderError,image->exception.reason,image);
878
0
                (void) WriteBlob(image,length,blob);
879
0
                MagickFreeMemory(blob);
880
0
                break;
881
0
              }
882
0
            case RLECompression:
883
0
            default:
884
0
              {
885
0
                register unsigned char
886
0
                  *q;
887
888
                /*
889
                  Allocate pixel array.
890
                */
891
0
                length=number_pixels;
892
0
                pixels=MagickAllocateResourceLimitedMemory(unsigned char *,length);
893
0
                if (pixels == (unsigned char *) NULL)
894
0
                  ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,
895
0
                                       image);
896
                /*
897
                  Dump Runlength encoded pixels.
898
                */
899
0
                q=pixels;
900
0
                for (y=0; y < (long) image->rows; y++)
901
0
                  {
902
0
                    p=AcquireImagePixels(image,0,y,image->columns,1,
903
0
                                         &image->exception);
904
0
                    if (p == (const PixelPacket *) NULL)
905
0
                      break;
906
0
                    for (x=0; x < (long) image->columns; x++)
907
0
                      {
908
0
                        *q++=ScaleQuantumToChar(PixelIntensityToQuantum(p));
909
0
                        p++;
910
0
                      }
911
0
                    if (image->previous == (Image *) NULL)
912
0
                      if (QuantumTick(y,image->rows))
913
0
                        {
914
0
                          status=MagickMonitorFormatted(y,image->rows,
915
0
                                                        &image->exception,
916
0
                                                        SaveImageText,
917
0
                                                        image->filename,
918
0
                                                        image->columns,image->rows);
919
0
                          if (status == False)
920
0
                            break;
921
0
                        }
922
0
                  }
923
0
                if (compression == LZWCompression)
924
0
                  status=LZWEncodeImage(image,length,pixels);
925
0
                else
926
0
                  status=PackbitsEncodeImage(image,length,pixels);
927
0
                MagickFreeResourceLimitedMemory(unsigned char *,pixels);
928
0
                if (!status)
929
0
                  {
930
0
                    CloseBlob(image);
931
0
                    return(MagickFail);
932
0
                  }
933
0
                break;
934
0
              }
935
0
            case NoCompression:
936
0
              {
937
                /*
938
                  Dump uncompressed PseudoColor packets.
939
                */
940
0
                Ascii85Initialize(image);
941
0
                for (y=0; y < (long) image->rows; y++)
942
0
                  {
943
0
                    p=AcquireImagePixels(image,0,y,image->columns,1,
944
0
                                         &image->exception);
945
0
                    if (p == (const PixelPacket *) NULL)
946
0
                      break;
947
0
                    for (x=0; x < (long) image->columns; x++)
948
0
                      {
949
0
                        Ascii85Encode(image,
950
0
                                      ScaleQuantumToChar(PixelIntensityToQuantum(p)));
951
0
                        p++;
952
0
                      }
953
0
                    if (image->previous == (Image *) NULL)
954
0
                      if (QuantumTick(y,image->rows))
955
0
                        {
956
0
                          status=MagickMonitorFormatted(y,image->rows,
957
0
                                                        &image->exception,
958
0
                                                        SaveImageText,
959
0
                                                        image->filename,
960
0
                                                        image->columns,image->rows);
961
0
                          if (status == MagickFail)
962
0
                            break;
963
0
                        }
964
0
                  }
965
0
                Ascii85Flush(image);
966
0
                break;
967
0
              }
968
0
            }
969
0
        }
970
0
      else
971
0
        if ((image->storage_class == DirectClass) || (image->colors > 256) ||
972
0
            (compression == JPEGCompression))
973
0
          {
974
0
            MagickFormatString(buffer,sizeof(buffer),"%lu %lu\n0\n%d\n",image->columns,image->rows,
975
0
                               (int) (image->colorspace == CMYKColorspace));
976
0
            (void) WriteBlobString(image,buffer);
977
0
            MagickFormatString(buffer,sizeof(buffer),"%d\n",(int) (compression == NoCompression));
978
0
            (void) WriteBlobString(image,buffer);
979
0
            switch (compression)
980
0
              {
981
0
              case JPEGCompression:
982
0
                {
983
                  /*
984
                    Write image in JPEG format.
985
                  */
986
0
                  blob=ImageToJPEGBlob(image,image_info,&length,&image->exception);
987
0
                  if (blob == (char *) NULL)
988
0
                    ThrowWriterException2(CoderError,image->exception.reason,image);
989
0
                  (void) WriteBlob(image,length,blob);
990
0
                  MagickFreeMemory(blob);
991
0
                  break;
992
0
                }
993
0
              case RLECompression:
994
0
              default:
995
0
                {
996
0
                  register unsigned char
997
0
                    *q;
998
999
                  /*
1000
                    Allocate pixel array.
1001
                  */
1002
0
                  length=MagickArraySize(image->colorspace == CMYKColorspace ? 4 : 3,
1003
0
                                         number_pixels);
1004
0
                  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,length);
1005
0
                  if (pixels == (unsigned char *) NULL)
1006
0
                    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1007
                  /*
1008
                    Dump Packbit encoded pixels.
1009
                  */
1010
0
                  q=pixels;
1011
0
                  for (y=0; y < (long) image->rows; y++)
1012
0
                    {
1013
0
                      p=AcquireImagePixels(image,0,y,image->columns,1,
1014
0
                                           &image->exception);
1015
0
                      if (p == (const PixelPacket *) NULL)
1016
0
                        break;
1017
0
                      for (x=0; x < (long) image->columns; x++)
1018
0
                        {
1019
0
                          if (image->matte && (p->opacity == TransparentOpacity))
1020
0
                            {
1021
0
                              *q++=ScaleQuantumToChar(MaxRGB);
1022
0
                              *q++=ScaleQuantumToChar(MaxRGB);
1023
0
                              *q++=ScaleQuantumToChar(MaxRGB);
1024
0
                            }
1025
0
                          else
1026
0
                            if (image->colorspace != CMYKColorspace)
1027
0
                              {
1028
0
                                *q++=ScaleQuantumToChar(p->red);
1029
0
                                *q++=ScaleQuantumToChar(p->green);
1030
0
                                *q++=ScaleQuantumToChar(p->blue);
1031
0
                              }
1032
0
                            else
1033
0
                              {
1034
0
                                *q++=ScaleQuantumToChar(p->red);
1035
0
                                *q++=ScaleQuantumToChar(p->green);
1036
0
                                *q++=ScaleQuantumToChar(p->blue);
1037
0
                                *q++=ScaleQuantumToChar(p->opacity);
1038
0
                              }
1039
0
                          p++;
1040
0
                        }
1041
0
                      if (image->previous == (Image *) NULL)
1042
0
                        if (QuantumTick(y,image->rows))
1043
0
                          {
1044
0
                            status=MagickMonitorFormatted(y,image->rows,
1045
0
                                                          &image->exception,
1046
0
                                                          SaveImageText,
1047
0
                                                          image->filename,
1048
0
                                                          image->columns,image->rows);
1049
0
                            if (status == MagickFail)
1050
0
                              break;
1051
0
                          }
1052
0
                    }
1053
0
                  if (compression == LZWCompression)
1054
0
                    status=LZWEncodeImage(image,length,pixels);
1055
0
                  else
1056
0
                    status=PackbitsEncodeImage(image,length,pixels);
1057
0
                  if (!status)
1058
0
                    {
1059
0
                      CloseBlob(image);
1060
0
                      return(MagickFail);
1061
0
                    }
1062
0
                  MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1063
0
                  break;
1064
0
                }
1065
0
              case NoCompression:
1066
0
                {
1067
                  /*
1068
                    Dump uncompressed DirectColor packets.
1069
                  */
1070
0
                  Ascii85Initialize(image);
1071
0
                  for (y=0; y < (long) image->rows; y++)
1072
0
                    {
1073
0
                      p=AcquireImagePixels(image,0,y,image->columns,1,
1074
0
                                           &image->exception);
1075
0
                      if (p == (const PixelPacket *) NULL)
1076
0
                        break;
1077
0
                      for (x=0; x < (long) image->columns; x++)
1078
0
                        {
1079
0
                          if (image->matte && (p->opacity == TransparentOpacity))
1080
0
                            {
1081
0
                              Ascii85Encode(image,ScaleQuantumToChar(MaxRGB));
1082
0
                              Ascii85Encode(image,ScaleQuantumToChar(MaxRGB));
1083
0
                              Ascii85Encode(image,ScaleQuantumToChar(MaxRGB));
1084
0
                            }
1085
0
                          else
1086
0
                            if (image->colorspace != CMYKColorspace)
1087
0
                              {
1088
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->red));
1089
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->green));
1090
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->blue));
1091
0
                              }
1092
0
                            else
1093
0
                              {
1094
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->red));
1095
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->green));
1096
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->blue));
1097
0
                                Ascii85Encode(image,ScaleQuantumToChar(p->opacity));
1098
0
                              }
1099
0
                          p++;
1100
0
                        }
1101
0
                      if (image->previous == (Image *) NULL)
1102
0
                        if (QuantumTick(y,image->rows))
1103
0
                          {
1104
0
                            status=MagickMonitorFormatted(y,image->rows,
1105
0
                                                          &image->exception,
1106
0
                                                          SaveImageText,
1107
0
                                                          image->filename,
1108
0
                                                          image->columns,image->rows);
1109
0
                            if (status == MagickFail)
1110
0
                              break;
1111
0
                          }
1112
0
                    }
1113
0
                  Ascii85Flush(image);
1114
0
                  break;
1115
0
                }
1116
0
              }
1117
0
          }
1118
0
        else
1119
0
          {
1120
            /*
1121
              Dump number of colors and colormap.
1122
            */
1123
0
            MagickFormatString(buffer,sizeof(buffer),"%lu %lu\n1\n%d\n",image->columns,image->rows,
1124
0
                               (int) (image->colorspace == CMYKColorspace));
1125
0
            (void) WriteBlobString(image,buffer);
1126
0
            MagickFormatString(buffer,sizeof(buffer),"%d\n",(int) (compression == NoCompression));
1127
0
            (void) WriteBlobString(image,buffer);
1128
0
            MagickFormatString(buffer,sizeof(buffer),"%u\n",image->colors);
1129
0
            (void) WriteBlobString(image,buffer);
1130
0
            for (i=0; i < (long) image->colors; i++)
1131
0
              {
1132
0
                MagickFormatString(buffer,sizeof(buffer),"%02X%02X%02X\n",
1133
0
                                   ScaleQuantumToChar(image->colormap[i].red),
1134
0
                                   ScaleQuantumToChar(image->colormap[i].green),
1135
0
                                   ScaleQuantumToChar(image->colormap[i].blue));
1136
0
                (void) WriteBlobString(image,buffer);
1137
0
              }
1138
0
            switch (compression)
1139
0
              {
1140
0
              case RLECompression:
1141
0
              default:
1142
0
                {
1143
0
                  register unsigned char
1144
0
                    *q;
1145
1146
                  /*
1147
                    Allocate pixel array.
1148
                  */
1149
0
                  length=number_pixels;
1150
0
                  pixels=MagickAllocateResourceLimitedMemory(unsigned char *,length);
1151
0
                  if (pixels == (unsigned char *) NULL)
1152
0
                    ThrowWriterException(ResourceLimitError,MemoryAllocationFailed,image);
1153
                  /*
1154
                    Dump Runlength encoded pixels.
1155
                  */
1156
0
                  q=pixels;
1157
0
                  for (y=0; y < (long) image->rows; y++)
1158
0
                    {
1159
0
                      p=AcquireImagePixels(image,0,y,image->columns,1,
1160
0
                                           &image->exception);
1161
0
                      if (p == (const PixelPacket *) NULL)
1162
0
                        break;
1163
0
                      indexes=AccessImmutableIndexes(image);
1164
0
                      for (x=0; x < (long) image->columns; x++)
1165
0
                        *q++=indexes[x];
1166
0
                      if (image->previous == (Image *) NULL)
1167
0
                        if (QuantumTick(y,image->rows))
1168
0
                          {
1169
0
                            status=MagickMonitorFormatted(y,image->rows,
1170
0
                                                          &image->exception,
1171
0
                                                          SaveImageText,
1172
0
                                                          image->filename,
1173
0
                                                          image->columns,image->rows);
1174
0
                            if (status == MagickFail)
1175
0
                              break;
1176
0
                          }
1177
0
                    }
1178
0
                  if (compression == LZWCompression)
1179
0
                    status=LZWEncodeImage(image,length,pixels);
1180
0
                  else
1181
0
                    status=PackbitsEncodeImage(image,length,pixels);
1182
0
                  MagickFreeResourceLimitedMemory(unsigned char *,pixels);
1183
0
                  if (!status)
1184
0
                    {
1185
0
                      CloseBlob(image);
1186
0
                      return(MagickFail);
1187
0
                    }
1188
0
                  break;
1189
0
                }
1190
0
              case NoCompression:
1191
0
                {
1192
                  /*
1193
                    Dump uncompressed PseudoColor packets.
1194
                  */
1195
0
                  Ascii85Initialize(image);
1196
0
                  for (y=0; y < (long) image->rows; y++)
1197
0
                    {
1198
0
                      p=AcquireImagePixels(image,0,y,image->columns,1,
1199
0
                                           &image->exception);
1200
0
                      if (p == (const PixelPacket *) NULL)
1201
0
                        break;
1202
0
                      indexes=AccessImmutableIndexes(image);
1203
0
                      for (x=0; x < (long) image->columns; x++)
1204
0
                        Ascii85Encode(image,indexes[x]);
1205
0
                      if (image->previous == (Image *) NULL)
1206
0
                        if (QuantumTick(y,image->rows))
1207
0
                          {
1208
0
                            status=MagickMonitorFormatted(y,image->rows,
1209
0
                                                          &image->exception,
1210
0
                                                          SaveImageText,
1211
0
                                                          image->filename,
1212
0
                                                          image->columns,image->rows);
1213
0
                            if (status == MagickFail)
1214
0
                              break;
1215
0
                          }
1216
0
                    }
1217
0
                  Ascii85Flush(image);
1218
0
                  break;
1219
0
                }
1220
0
              }
1221
0
          }
1222
0
      (void) WriteBlobByte(image,'\n');
1223
0
      current=TellBlob(image);
1224
0
      if (current < 0)
1225
0
        ThrowWriterException(BlobError,UnableToObtainOffset,image);
1226
0
      length=current-stop;
1227
0
      stop=TellBlob(image);
1228
0
      if (stop < 0)
1229
0
        ThrowWriterException(BlobError,UnableToObtainOffset,image);
1230
0
      if (SeekBlob(image,start,SEEK_SET) != start)
1231
0
        ThrowWriterException(BlobError,UnableToSeekToOffset,image);
1232
0
      MagickFormatString(buffer,sizeof(buffer),"%%%%BeginData:%13ld %s Bytes\n",(long) length,
1233
0
                         compression == NoCompression ? "ASCII" : "Binary");
1234
0
      (void) WriteBlobString(image,buffer);
1235
0
      if (SeekBlob(image,stop,SEEK_SET) != stop)
1236
0
        ThrowWriterException(BlobError,UnableToSeekToOffset,image);
1237
0
      (void) WriteBlobString(image,"%%EndData\n");
1238
0
      if (LocaleCompare(image_info->magick,"PS2") != 0)
1239
0
        (void) WriteBlobString(image,"end\n");
1240
0
      (void) WriteBlobString(image,"%%PageTrailer\n");
1241
0
      if (image->next == (Image *) NULL)
1242
0
        break;
1243
0
      image=SyncNextImageInList(image);
1244
0
      status=MagickMonitorFormatted(scene++,image_list_length,
1245
0
                                    &image->exception,SaveImagesText,
1246
0
                                    image->filename);
1247
0
      if (status == MagickFail)
1248
0
        break;
1249
0
    } while (image_info->adjoin);
1250
0
  if (image_info->adjoin)
1251
0
    while (image->previous != (Image *) NULL)
1252
0
      image=image->previous;
1253
0
  (void) WriteBlobString(image,"%%Trailer\n");
1254
0
  if (page > 1)
1255
0
    {
1256
0
      MagickFormatString(buffer,sizeof(buffer),"%%%%BoundingBox: %g %g %g %g\n",floor(bounds.x1+0.5),
1257
0
                         floor(bounds.y1+0.5),ceil(bounds.x2-0.5),ceil(bounds.y2-0.5));
1258
0
      (void) WriteBlobString(image,buffer);
1259
0
    }
1260
0
  (void) WriteBlobString(image,"%%EOF\n");
1261
0
  status &= CloseBlob(image);
1262
0
  return(status);
1263
0
}