Coverage Report

Created: 2025-08-11 08:01

/src/graphicsmagick/coders/ept.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
% Copyright (C) 2003-2022 GraphicsMagick Group
3
% Copyright (C) 2002 ImageMagick Studio
4
% Copyright 1991-1999 E. I. du Pont de Nemours and Company
5
%
6
% This program is covered by multiple licenses, which are described in
7
% Copyright.txt. You should have received a copy of Copyright.txt with this
8
% package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9
%
10
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11
%                                                                             %
12
%                                                                             %
13
%                                                                             %
14
%                            EEEEE  PPPP   TTTTT                              %
15
%                            E      P   P    T                                %
16
%                            EEE    PPPP     T                                %
17
%                            E      P        T                                %
18
%                            EEEEE  P        T                                %
19
%                                                                             %
20
%                                                                             %
21
%           Read/Write Encapsulated Postscript Format (with preview).         %
22
%                                                                             %
23
%                                                                             %
24
%                              Software Design                                %
25
%                                John Cristy                                  %
26
%                                 July 1992                                   %
27
%                                                                             %
28
%                                                                             %
29
%                                                                             %
30
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31
%
32
%
33
*/
34

35
/*
36
  Include declarations.
37
*/
38
#include "magick/studio.h"
39
#include "magick/blob.h"
40
#include "magick/constitute.h"
41
#include "magick/delegate.h"
42
#include "magick/log.h"
43
#include "magick/magick.h"
44
#include "magick/monitor.h"
45
#include "magick/render.h"
46
#include "magick/tempfile.h"
47
#include "magick/utility.h"
48

49
/*
50
  Forward declarations.
51
*/
52
static unsigned int
53
  WriteEPTImage(const ImageInfo *,Image *);
54

55
/*
56
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
57
%                                                                             %
58
%                                                                             %
59
%                                                                             %
60
%   I s E P T                                                                 %
61
%                                                                             %
62
%                                                                             %
63
%                                                                             %
64
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
65
%
66
%  Method IsEPT returns True if the image format type, identified by the
67
%  magick string, is EPT.
68
%
69
%  The format of the IsEPT method is:
70
%
71
%      unsigned int IsEPT(const unsigned char *magick,const size_t length)
72
%
73
%  A description of each parameter follows:
74
%
75
%    o status:  Method IsEPT returns True if the image format type is EPT.
76
%
77
%    o magick: This string is generally the first few bytes of an image file
78
%      or blob.
79
%
80
%    o length: Specifies the length of the magick string.
81
%
82
%
83
*/
84
static unsigned int IsEPT(const unsigned char *magick,const size_t length)
85
0
{
86
0
  if (length < 4)
87
0
    return(False);
88
0
  if (memcmp(magick,"\305\320\323\306",4) == 0)
89
0
    return(True);
90
0
  return(False);
91
0
}
92

93
/*
94
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
95
%                                                                             %
96
%                                                                             %
97
%                                                                             %
98
%   R e a d E P T I m a g e                                                   %
99
%                                                                             %
100
%                                                                             %
101
%                                                                             %
102
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
103
%
104
%  Method ReadEPTImage reads a binary Adobe Postscript image file and returns
105
%  it.  It allocates the memory necessary for the new Image structure and
106
%  returns a pointer to the new image.
107
%
108
%  The format of the ReadEPTImage method is:
109
%
110
%      Image *ReadEPTImage(const ImageInfo *image_info,
111
%                          ExceptionInfo *exception)
112
%
113
%  A description of each parameter follows:
114
%
115
%    o image:  Method ReadEPTImage returns a pointer to the image after
116
%      reading.  A null image is returned if there is a memory shortage or
117
%      if the image cannot be read.
118
%
119
%    o image_info: Specifies a pointer to a ImageInfo structure.
120
%
121
%    o exception: return any errors or warnings in this structure.
122
%
123
%
124
*/
125
#if defined(HasGS)
126
static Image *ReadEPTImage(const ImageInfo *image_info,
127
  ExceptionInfo *exception)
128
257
{
129
257
#define BoundingBox  "%%BoundingBox:"
130
257
#define DocumentMedia  "%%DocumentMedia:"
131
257
#define PageBoundingBox  "%%PageBoundingBox:"
132
257
#define PostscriptLevel  "%!PS-"
133
257
#define RenderPostscriptText  "[%s] Rendering postscript..."
134
135
257
  char
136
257
    density[MaxTextExtent],
137
257
    command[MaxTextExtent],
138
257
    filename[MaxTextExtent],
139
257
    geometry[MaxTextExtent],
140
257
    postscript_filename[MaxTextExtent],
141
257
    translate_geometry[MaxTextExtent];
142
143
257
  const DelegateInfo
144
257
    *delegate_info;
145
146
257
  double
147
257
    dx_resolution,
148
257
    dy_resolution;
149
150
257
  FILE
151
257
    *file;
152
153
257
  Image
154
257
    *image,
155
257
    *next_image;
156
157
257
  int
158
257
    c,
159
257
    status;
160
161
257
  unsigned int
162
257
    antialias=4;
163
164
257
  magick_uint32_t
165
257
    filesize;
166
167
257
  RectangleInfo
168
257
    box,
169
257
    page;
170
171
257
  register char
172
257
    *p;
173
174
257
  register size_t
175
257
    i;
176
177
257
  SegmentInfo
178
257
    bounds;
179
180
257
  magick_uint32_t
181
257
    count;
182
183
257
  unsigned long
184
257
    height,
185
257
    width;
186
187
257
  assert(image_info != (const ImageInfo *) NULL);
188
257
  assert(image_info->signature == MagickSignature);
189
257
  assert(exception != (ExceptionInfo *) NULL);
190
257
  assert(exception->signature == MagickSignature);
191
192
  /*
193
    Select Postscript delegate driver
194
  */
195
257
  delegate_info=GetPostscriptDelegateInfo(image_info,&antialias,exception);
196
257
  if (delegate_info == (const DelegateInfo *) NULL)
197
257
    return((Image *) NULL);
198
  /*
199
    Open image file.
200
  */
201
0
  image=AllocateImage(image_info);
202
0
  status=OpenBlob(image_info,image,ReadBinaryBlobMode,exception);
203
0
  if (status == False)
204
0
    ThrowReaderException(FileOpenError,UnableToOpenFile,image);
205
  /*
206
    Set the page geometry.
207
  */
208
0
  dx_resolution=72.0;
209
0
  dy_resolution=72.0;
210
0
  if ((image->x_resolution == 0.0) || (image->y_resolution == 0.0))
211
0
    {
212
0
      (void) strlcpy(density,PSDensityGeometry,sizeof(density));
213
0
      count=GetMagickDimension(density,&image->x_resolution,
214
0
        &image->y_resolution,NULL,NULL);
215
0
      if (count != 2)
216
0
        image->y_resolution=image->x_resolution;
217
0
    }
218
0
  FormatString(density,"%gx%g",image->x_resolution,image->y_resolution);
219
0
  if (image->logging)
220
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
221
0
                          "Density: %s", density);
222
0
  SetGeometry(image,&page);
223
0
  page.width=612;
224
0
  page.height=792;
225
0
  (void) GetGeometry(PSPageGeometry,&page.x,&page.y,&page.width,&page.height);
226
  /*
227
    Determine page geometry from the Postscript bounding box.
228
  */
229
0
  (void) ReadBlobLSBLong(image);
230
0
  count=ReadBlobLSBLong(image);
231
0
  filesize=ReadBlobLSBLong(image);
232
0
  if (EOFBlob(image))
233
0
    ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
234
0
  if (image->logging)
235
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
236
0
                          "File Size: %u,  Offset: %u",
237
0
                          (unsigned int) filesize, (unsigned int) count);
238
0
  if ((count <= 12) || (filesize == 0))
239
0
    ThrowReaderException(CorruptImageError,ImproperImageHeader,image);
240
0
  for (i=0; i < (count-12); i++)
241
0
    if (ReadBlobByte(image) == EOF)
242
0
      ThrowReaderException(CorruptImageError,UnexpectedEndOfFile,image);
243
  /*
244
    Open temporary output file.
245
  */
246
0
  file=AcquireTemporaryFileStream(postscript_filename,BinaryFileIOMode);
247
0
  if (file == (FILE *) NULL)
248
0
      ThrowReaderTemporaryFileException(postscript_filename);
249
0
  FormatString(translate_geometry,"%g %g translate\n              ",0.0,0.0);
250
0
  (void) fputs(translate_geometry,file);
251
  /*
252
    Copy Postscript to temporary file.
253
  */
254
0
  box.width=0;
255
0
  box.height=0;
256
0
  p=command;
257
0
  if (image->logging)
258
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
259
0
                          "Copying Postscript to temporary file \"%s\" ...",
260
0
                          postscript_filename);
261
0
  bounds.x1=0.0;
262
0
  bounds.y1=0.0;
263
0
  bounds.x2=0.0;
264
0
  bounds.y2=0.0;
265
0
  for (i=0; i < filesize; i++)
266
0
  {
267
0
    if ((c=ReadBlobByte(image)) == EOF)
268
0
      break;
269
0
    (void) fputc(c,file);
270
0
    *p++=c;
271
0
    if ((c != '\n') && (c != '\r') && ((p-command) < (MaxTextExtent-1)))
272
0
      continue;
273
0
    *p='\0';
274
0
    p=command;
275
    /*
276
      Parse a bounding box statement.
277
    */
278
0
    count=0;
279
0
    if (LocaleNCompare(BoundingBox,command,strlen(BoundingBox)) == 0)
280
0
      count=sscanf(command,"%%%%BoundingBox: %lf %lf %lf %lf",&bounds.x1,
281
0
        &bounds.y1,&bounds.x2,&bounds.y2);
282
0
    if (LocaleNCompare(DocumentMedia,command,strlen(DocumentMedia)) == 0)
283
0
      count=sscanf(command,"%%%%DocumentMedia: %*s %lf %lf",&bounds.x2,
284
0
        &bounds.y2)+2;
285
0
    if (LocaleNCompare(PageBoundingBox,command,strlen(PageBoundingBox)) == 0)
286
0
      count=sscanf(command,"%%%%PageBoundingBox: %lf %lf %lf %lf",
287
0
        &bounds.x1,&bounds.y1,&bounds.x2,&bounds.y2);
288
0
    if (count != 4)
289
0
      continue;
290
0
    if ((bounds.x1 > bounds.x2) ||
291
0
        (bounds.y1 > bounds.y2))
292
0
      continue;
293
    /*
294
      Set Postscript render geometry.
295
    */
296
0
    FormatString(translate_geometry,"%g %g translate\n",-bounds.x1,-bounds.y1);
297
0
    width=(unsigned long) (bounds.x2-bounds.x1+0.5);
298
0
    height=(unsigned long) (bounds.y2-bounds.y1+0.5);
299
0
    if ((width <= box.width) && (height <= box.height))
300
0
      continue;
301
0
    page.width=width;
302
0
    page.height=height;
303
0
    box=page;
304
0
  }
305
0
  if (image->logging)
306
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
307
0
                          "Done copying.");
308
0
  if (image_info->page != (char *) NULL)
309
0
    (void) GetGeometry(image_info->page,&page.x,&page.y,&page.width,
310
0
      &page.height);
311
0
  FormatString(geometry,"%lux%lu",
312
0
    (unsigned long) ceil(page.width*image->x_resolution/dx_resolution-0.5),
313
0
    (unsigned long) ceil(page.height*image->y_resolution/dy_resolution-0.5));
314
0
  if (image->logging)
315
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
316
0
                          "Page geometry: %s",geometry);
317
0
  if (ferror(file))
318
0
    {
319
0
      (void) fclose(file);
320
0
      (void) LiberateTemporaryFile(postscript_filename);
321
0
      ThrowReaderException(CorruptImageError,AnErrorHasOccurredWritingToFile,
322
0
        image)
323
0
    }
324
0
  (void) rewind(file);
325
0
  (void) fputs(translate_geometry,file);
326
0
  (void) fclose(file);
327
0
  CloseBlob(image);
328
0
  filesize=GetBlobSize(image);
329
0
  DestroyImage(image);
330
0
  image=(Image *) NULL;
331
  /*
332
    Use Ghostscript to convert Postscript image.
333
  */
334
0
  {
335
0
    char
336
0
      options[MaxTextExtent];
337
338
0
    options[0]='\0';
339
    /*
340
      Append subrange.
341
    */
342
0
    if (image_info->subrange != 0)
343
0
      FormatString(options,"-dFirstPage=%lu -dLastPage=%lu",
344
0
                   image_info->subimage+1,image_info->subimage+image_info->subrange);
345
    /*
346
      Append bounding box.
347
    */
348
0
    FormatString(options+strlen(options)," -g%s",geometry);
349
0
    (void) strlcpy(filename,image_info->filename,MaxTextExtent);
350
0
    if (image_info->temporary)
351
0
      (void) LiberateTemporaryFile((char *) image_info->filename);
352
0
    if(!AcquireTemporaryFileName((char *)image_info->filename))
353
0
      {
354
0
        (void) LiberateTemporaryFile(postscript_filename);
355
0
        ThrowReaderTemporaryFileException(image_info->filename);
356
0
      }
357
0
    FormatString(command,delegate_info->commands,antialias,
358
0
                 antialias,density,options,image_info->filename,
359
0
                 postscript_filename);
360
0
  }
361
0
  (void) MagickMonitorFormatted(0,8,exception,RenderPostscriptText,
362
0
                                image_info->filename);
363
0
  status=InvokePostscriptDelegate(image_info->verbose,command,exception);
364
0
  if (!IsAccessibleAndNotEmpty(image_info->filename))
365
0
    {
366
      /*
367
        Ghostscript requires a showpage operator.
368
      */
369
0
      file=fopen(postscript_filename,"ab");
370
0
      if (file == (FILE *) NULL)
371
0
        {
372
0
          (void) LiberateTemporaryFile((char *) image_info->filename);
373
0
          ThrowReaderException(FileOpenError,UnableToWriteFile,image);
374
0
        }
375
0
      (void) fputs("showpage\n",file);
376
0
      (void) fclose(file);
377
0
      status=InvokePostscriptDelegate(image_info->verbose,command,exception);
378
0
    }
379
0
  (void) LiberateTemporaryFile(postscript_filename);
380
0
  (void) MagickMonitorFormatted(7,8,exception,RenderPostscriptText,
381
0
                                image_info->filename);
382
0
  if (IsAccessibleAndNotEmpty(image_info->filename))
383
0
    {
384
      /*
385
        Read Ghostscript output.
386
      */
387
0
      ImageInfo
388
0
        *clone_info;
389
390
0
      clone_info=CloneImageInfo(image_info);
391
0
      clone_info->blob=(void *) NULL;
392
0
      clone_info->length=0;
393
0
      clone_info->magick[0]='\0';
394
0
      image=ReadImage(clone_info,exception);
395
0
      DestroyImageInfo(clone_info);
396
0
    }
397
0
  (void) LiberateTemporaryFile((char *) image_info->filename);
398
0
  if (image == (Image *) NULL)
399
0
    if (UndefinedException == exception->severity)
400
0
      ThrowException(exception,DelegateError,PostscriptDelegateFailed,filename);
401
0
  if (image != (Image *) NULL)
402
0
    {
403
0
      do
404
0
        {
405
0
          (void) strlcpy(image->magick,"PS",sizeof(image->magick));
406
0
          (void) strlcpy(image->filename,filename,sizeof(image->filename));
407
0
          next_image=SyncNextImageInList(image);
408
0
          if (next_image != (Image *) NULL)
409
0
            image=next_image;
410
0
        } while (next_image != (Image *) NULL);
411
0
      while (image->previous != (Image *) NULL)
412
0
        image=image->previous;
413
0
    }
414
0
  return(image);
415
0
}
416
#endif /* if defined(HasGS) */
417

418
/*
419
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
420
%                                                                             %
421
%                                                                             %
422
%                                                                             %
423
%   R e g i s t e r E P T I m a g e                                           %
424
%                                                                             %
425
%                                                                             %
426
%                                                                             %
427
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
428
%
429
%  Method RegisterEPTImage adds attributes for the EPT image format to
430
%  the list of supported formats.  The attributes include the image format
431
%  tag, a method to read and/or write the format, whether the format
432
%  supports the saving of more than one frame to the same file or blob,
433
%  whether the format supports native in-memory I/O, and a brief
434
%  description of the format.
435
%
436
%  The format of the RegisterEPTImage method is:
437
%
438
%      RegisterEPTImage(void)
439
%
440
*/
441
ModuleExport void RegisterEPTImage(void)
442
3
{
443
3
  MagickInfo
444
3
    *entry;
445
446
3
  entry=SetMagickInfo("EPT");
447
3
#if defined(HasGS)
448
3
  entry->decoder=(DecoderHandler) ReadEPTImage;
449
3
#endif /* if defined(HasGS) */
450
3
  entry->encoder=(EncoderHandler) WriteEPTImage;
451
3
  entry->magick=(MagickHandler) IsEPT;
452
3
  entry->adjoin=False;
453
3
  entry->blob_support=MagickFalse;
454
3
  entry->description="Adobe Encapsulated PostScript with MS-DOS TIFF preview";
455
3
  entry->module="EPT";
456
3
  entry->coder_class=PrimaryCoderClass;
457
3
  (void) RegisterMagickInfo(entry);
458
459
3
  entry=SetMagickInfo("EPT2");
460
3
#if defined(HasGS)
461
3
  entry->decoder=(DecoderHandler) ReadEPTImage;
462
3
#endif /* if defined(HasGS) */
463
3
  entry->encoder=(EncoderHandler) WriteEPTImage;
464
3
  entry->magick=(MagickHandler) IsEPT;
465
3
  entry->adjoin=False;
466
3
  entry->blob_support=MagickFalse;
467
3
  entry->description="Adobe Level II Encapsulated PostScript with MS-DOS TIFF preview";
468
3
  entry->module="EPT";
469
3
  entry->coder_class=PrimaryCoderClass;
470
3
  (void) RegisterMagickInfo(entry);
471
472
3
  entry=SetMagickInfo("EPT3");
473
3
#if defined(HasGS)
474
3
  entry->decoder=(DecoderHandler) ReadEPTImage;
475
3
#endif /* if defined(HasGS) */
476
3
  entry->encoder=(EncoderHandler) WriteEPTImage;
477
3
  entry->magick=(MagickHandler) IsEPT;
478
3
  entry->adjoin=False;
479
3
  entry->blob_support=MagickFalse;
480
3
  entry->description="Adobe Level III Encapsulated PostScript with MS-DOS TIFF preview";
481
3
  entry->module="EPT";
482
3
  entry->coder_class=PrimaryCoderClass;
483
3
  (void) RegisterMagickInfo(entry);
484
3
}
485

486
/*
487
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
488
%                                                                             %
489
%                                                                             %
490
%                                                                             %
491
%   U n r e g i s t e r E P T I m a g e                                       %
492
%                                                                             %
493
%                                                                             %
494
%                                                                             %
495
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
496
%
497
%  Method UnregisterEPTImage removes format registrations made by the
498
%  EPT module from the list of supported formats.
499
%
500
%  The format of the UnregisterEPTImage method is:
501
%
502
%      UnregisterEPTImage(void)
503
%
504
*/
505
ModuleExport void UnregisterEPTImage(void)
506
0
{
507
0
  (void) UnregisterMagickInfo("EPT");
508
0
  (void) UnregisterMagickInfo("EPT2");
509
0
  (void) UnregisterMagickInfo("EPT3");
510
0
}
511

512
/*
513
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
514
%                                                                             %
515
%                                                                             %
516
%                                                                             %
517
%   W r i t e E P T I m a g e                                                 %
518
%                                                                             %
519
%                                                                             %
520
%                                                                             %
521
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
522
%
523
%  Method WriteEPTImage writes an image in the Adobe Encapsulated Postscript
524
%  format with a TIFF preview.
525
%
526
%  The format of the WriteEPTImage method is:
527
%
528
%      unsigned int WriteEPTImage(const ImageInfo *image_info,Image *image)
529
%
530
%  A description of each parameter follows.
531
%
532
%    o status: Method WriteEPTImage return True if the image is written.
533
%      False is returned is there is a memory shortage or if the image file
534
%      fails to write.
535
%
536
%    o image_info: Specifies a pointer to a ImageInfo structure.
537
%
538
%    o image:  A pointer to an Image structure.
539
%
540
%
541
*/
542
static unsigned int WriteEPTImage(const ImageInfo *image_info,Image *image)
543
0
{
544
0
  char
545
0
    filename[MaxTextExtent],
546
0
    ps_filename[MaxTextExtent],
547
0
    tiff_filename[MaxTextExtent];
548
549
0
  FILE
550
0
    *ps_file,
551
0
    *tiff_file;
552
553
0
  unsigned int
554
0
    logging,
555
0
    status;
556
557
0
  assert(image_info != (const ImageInfo *) NULL);
558
0
  assert(image_info->signature == MagickSignature);
559
0
  assert(image != (Image *) NULL);
560
0
  assert(image->signature == MagickSignature);
561
562
0
  logging=IsEventLogged(CoderEvent);
563
564
0
  (void) strlcpy(filename,image->filename,MaxTextExtent);
565
0
  (void) strlcpy(ps_filename,image->magick_filename,MaxTextExtent);
566
0
  if (LocaleCompare(image_info->magick,"EPS") != 0)
567
0
    {
568
      /*
569
        Write image as Encapsulated Postscript to a temporary file.
570
      */
571
0
      char
572
0
        subformat[MaxTextExtent];
573
574
0
      if(!AcquireTemporaryFileName(ps_filename))
575
0
        ThrowWriterTemporaryFileException(ps_filename);
576
577
      /* Select desired EPS level */
578
0
      (void) strlcpy(subformat,"eps",sizeof(subformat));
579
0
      if (LocaleCompare(image_info->magick,"EPT2") == 0)
580
0
        (void) strlcpy(subformat,"eps2",sizeof(subformat));
581
0
      else if (LocaleCompare(image_info->magick,"EPT3") == 0)
582
0
        (void) strlcpy(subformat,"eps3",sizeof(subformat));
583
584
      /* JPEG compression requires at least EPS2 */
585
0
      if ((image->compression == JPEGCompression) &&
586
0
          (LocaleCompare(subformat,"EPS") == 0))
587
0
        (void) strlcpy(subformat,"eps2",sizeof(subformat));
588
589
0
      FormatString(image->filename,"%s:%.1024s",subformat,ps_filename);
590
0
      if (logging)
591
0
        (void) LogMagickEvent(CoderEvent,GetMagickModule(),
592
0
                              "Writing temporary EPS file \"%s\"",ps_filename);
593
0
      (void) WriteImage(image_info,image);
594
0
    }
595
  /*
596
    Write image as TIFF to a temporary file.
597
  */
598
0
  if(!AcquireTemporaryFileName(tiff_filename))
599
0
    {
600
0
      (void) LiberateTemporaryFile(ps_filename);
601
0
      ThrowWriterTemporaryFileException(tiff_filename);
602
0
    }
603
604
0
  FormatString(image->filename,"tiff:%.1024s",tiff_filename);
605
0
  image->compression=RLECompression;
606
0
  if (logging)
607
0
    (void) LogMagickEvent(CoderEvent,GetMagickModule(),
608
0
                          "Writing temporary TIFF preview file \"%s\"",tiff_filename);
609
0
  (void) WriteImage(image_info,image);
610
  /*
611
    Write EPT image.
612
  */
613
0
  (void) strlcpy(image->filename,filename,MaxTextExtent);
614
0
  status=MagickFail;
615
0
  if (OpenBlob(image_info,image,WriteBinaryBlobMode,&image->exception) != MagickFail)
616
0
    {
617
0
      if ((ps_file=fopen(ps_filename,"rb")) != (FILE *) NULL)
618
0
        {
619
0
          if ((tiff_file=fopen(tiff_filename,"rb")) != (FILE *) NULL)
620
0
            {
621
0
              int
622
0
                c;
623
624
0
              struct stat
625
0
                attributes;
626
627
              /*
628
                Write EPT image.
629
              */
630
631
              /* MS-DOS EPS binary file magic signature */
632
0
              (void) WriteBlobLSBLong(image,0xc6d3d0c5ul);
633
              /* Byte position in file for start of Postscript language code
634
                 section */
635
0
              (void) WriteBlobLSBLong(image,30);
636
0
              if (logging)
637
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
638
0
                                      "EPS section offset is %lu bytes",(unsigned long) 30);
639
              /* Byte length of PostScript language section. */
640
0
              attributes.st_size=0;
641
0
              (void) fstat(fileno(ps_file),&attributes);
642
0
              if (logging)
643
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
644
0
                                      "EPS section is %lu bytes long",
645
0
                                      (unsigned long)attributes.st_size);
646
0
              (void) WriteBlobLSBLong(image,(unsigned long) attributes.st_size);
647
              /* Byte position in file for start of Metafile screen
648
                 representation (none provided). */
649
0
              (void) WriteBlobLSBLong(image,0);
650
              /* Byte length of Metafile section (PSize). (none provided) */
651
0
              (void) WriteBlobLSBLong(image,0);
652
              /* Byte position of TIFF representation. */
653
0
              (void) WriteBlobLSBLong(image,(unsigned long) attributes.st_size+30);
654
0
              if (logging)
655
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
656
0
                                      "TIFF section offset is %lu bytes",
657
0
                                      (unsigned long) attributes.st_size+30);
658
              /* Byte length of TIFF section. */
659
0
              (void) fstat(fileno(tiff_file),&attributes);
660
0
              if (logging)
661
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
662
0
                                      "TIFF section is %lu bytes long",
663
0
                                      (unsigned long) attributes.st_size);
664
0
              (void) WriteBlobLSBLong(image,(long) attributes.st_size);
665
              /* Checksum of header (XOR of bytes 0-27). If Checksum is FFFF
666
                 then ignore it. This is lazy code. */
667
0
              (void) WriteBlobLSBShort(image,0xffff);
668
              /* EPS section */
669
0
              if (logging)
670
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
671
0
                                      "Writing EPS section at offset %ld",
672
0
                                      (long) TellBlob(image));
673
0
              for (c=fgetc(ps_file); c != EOF; c=fgetc(ps_file))
674
0
                (void) WriteBlobByte(image,c);
675
              /* TIFF section */
676
0
              if (logging)
677
0
                (void) LogMagickEvent(CoderEvent,GetMagickModule(),
678
0
                                      "Writing TIFF section at offset %ld",
679
0
                                      (long) TellBlob(image));
680
0
              for (c=fgetc(tiff_file); c != EOF; c=fgetc(tiff_file))
681
0
                (void) WriteBlobByte(image,c);
682
0
              (void) fclose(tiff_file);
683
0
              status=MagickPass;
684
0
            }
685
0
          else
686
0
            {
687
0
              (void) LogMagickEvent(CoderEvent,GetMagickModule(),
688
0
                                    "Failed to open \"%s\" for read",
689
0
                                    tiff_filename);
690
0
            }
691
0
          (void) fclose(ps_file);
692
0
        }
693
0
      else
694
0
        {
695
0
          (void) LogMagickEvent(CoderEvent,GetMagickModule(),
696
0
                                "Failed to open \"%s\" for read",ps_filename);
697
0
        }
698
699
0
      status &= CloseBlob(image);
700
0
    }
701
0
  else
702
0
    {
703
0
      (void) LogMagickEvent(CoderEvent,GetMagickModule(),
704
0
                                "Failed to open \"%s\" for write",
705
0
                            image->filename);
706
0
    }
707
0
  if (LocaleCompare(image_info->magick,"EPS") != 0)
708
0
    (void) LiberateTemporaryFile(ps_filename);
709
0
  (void) LiberateTemporaryFile(tiff_filename);
710
0
  if (status == MagickFail)
711
0
    ThrowWriterException(FileOpenError,UnableToOpenFile,image);
712
0
  return(status);
713
0
}