1 /***********************************************************************/
2 /* Open Visualization Data Explorer */
3 /* (C) Copyright IBM Corp. 1989,1999 */
4 /* ALL RIGHTS RESERVED */
5 /* This code licensed under the */
6 /* "IBM PUBLIC LICENSE - Open Visualization Data Explorer" */
7 /***********************************************************************/
8 /*
9 * $Header: /src/master/dx/src/exec/dxmods/_postscript.c,v 1.9 2003/07/11 05:50:34 davidt Exp $
10 */
11
12 #include <dxconfig.h>
13
14
15 /*
16 * This file supports writing images to disk files in PostScript 3.0 format.
17 * We also support Encapsulated PostScript format 3.0.
18 * Images can be written out in either 24-bit color or 8-bit gray.
19 */
20
21 #include <stdio.h>
22 #include <fcntl.h>
23 #include <time.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <dx/dx.h>
27 #include "_helper_jea.h"
28 #include "_rw_image.h"
29 #include <sys/types.h>
30 #include <math.h>
31
32 struct ps_spec {
33 int filetype; /* PS or EPSF */
34 int colormode; /* FULLCOLOR or GRAY */
35 int width_dpi; /* dots per inch in image height */
36 int height_dpi; /* dots per inch in image width */
37 int image_width; /* width of image in pixels */
38 int image_height; /* height of image in pixels */
39 float page_width; /* width of page in inches */
40 float page_height; /* height of page in inches */
41 float page_margin; /* margin width */
42 int page_orient; /* LANDSCAPE or PORTRAIT */
43 int compress; /* Do postscript compression */
44 int data_size; /* For miff, size of data block */
45 long fptr; /* File pointer for data size text */
46 float gamma; /* gamma */
47 };
48 /*
49 * This taken from 1st Edition Foley and Van Dam, page 613
50 */
51 #define RGB_TO_BW(r,g,b) (.30*(r) + .59*(g) + .11*(b))
52
53 #define LINEOUT(s) if (fprintf(fout, s "\n") <= 0) goto bad_write;
54
55 #define UPI 72 /* Default units per inch */
56 #define PS 0 /* Regular PostScript */
57 #define EPS 1 /* Encapsulated PostScript */
58
59 #define RLE_BINARY 1
60 #define RLE_ASCII 0
61 #define RLE_COUNT_PRE 1
62 #define RLE_COUNT_POST 0
63 #define RLE_STUPID 1
64 #define RLE_COMPACT 0
65
66 #define FULLCOLOR 0
67 #define GRAY 1
68
69 #define FLOAT_COLOR 1
70 #define UBYTE_COLOR 2
71 #define MAPPED_COLOR 3
72
73 #define NSCENES_STRING "nscenes="
74 #define DATASIZE_STRING "data_size="
75
76 #define BUFFSIZE 256
77
78 static Error parse_format(char *format, struct ps_spec *spec);
79 static Error output_ps(RWImageArgs *iargs, int colormode,int filetype);
80 static Error put_ps_header(FILE *fout, char *filename,
81 int frames, struct ps_spec *spec);
82 static Error build_rle_row(ubyte *r, int n_pixels, int bytes_per_pixel,
83 int compress, ubyte *buff, int *byte_count, int binary, int order, int compact);
84 static Error put_ps_prolog(FILE *fout, struct ps_spec *spec);
85 static Error put_ps_setup(FILE *fout, int frames, struct ps_spec *spec) ;
86 static Error put_colorimage_function(FILE *fout);
87 static Error ps_new_page(FILE *fout, int page, int pages, struct ps_spec *spec);
88 static Error put_ps_page_setup(FILE *fout, struct ps_spec *spec);
89 static Error ps_image_header(FILE *fout, struct ps_spec *spec);
90 static Error ps_out_flc(FILE *fout,
91 Pointer pixels, RGBColor *map, int type, struct ps_spec *spec);
92 static Error ps_out_gry(FILE *fout,
93 Pointer pixels, RGBColor *map, int type, struct ps_spec *spec);
94 static Error ps_end_page(FILE *fout);
95 static Error put_ps_trailer(FILE *fout, struct ps_spec *spec);
96 static Error output_miff(RWImageArgs *iargs);
97 static Error put_miff_header(FILE *fout, char *filename,
98 int frame, struct ps_spec *spec, int type, int nframes);
99 static Error read_miff_header(FILE *in, int *frame, struct ps_spec *spec, int *type, int *nframes);
100 static Error miff_out_flc(FILE *fout,
101 Pointer pixels, RGBColor *map, int type, struct ps_spec *spec);
102
103 #define ORIENT_NOT_SET 0
104 #define LANDSCAPE 1
105 #define PORTRAIT 2
106 #define ORIENT_AUTO 3
107 static void orient_page(struct ps_spec *spec);
108
109 /*
110 * Jump table target, that writes out color PostScript file.
111 */
112 Error
_dxf_write_ps_color(RWImageArgs * iargs)113 _dxf_write_ps_color(RWImageArgs *iargs)
114 {
115 Error e;
116 e = output_ps(iargs,FULLCOLOR,PS);
117 return e;
118 }
119 /*
120 * Jump table target, that writes out gray level PostScript file.
121 */
122 Error
_dxf_write_ps_gray(RWImageArgs * iargs)123 _dxf_write_ps_gray(RWImageArgs *iargs)
124 {
125 Error e;
126 e = output_ps(iargs,GRAY,PS);
127 return e;
128 }
129 /*
130 * Jump table target, that writes out color Encapsulated PostScript file.
131 */
132 Error
_dxf_write_eps_color(RWImageArgs * iargs)133 _dxf_write_eps_color(RWImageArgs *iargs)
134 {
135 Error e;
136 e = output_ps(iargs,FULLCOLOR,EPS);
137 return e;
138 }
139 /*
140 * Jump table target, that writes out an gray level Encapsulated PostScript
141 * file.
142 */
143 Error
_dxf_write_eps_gray(RWImageArgs * iargs)144 _dxf_write_eps_gray(RWImageArgs *iargs)
145 {
146 Error e;
147 e = output_ps(iargs,GRAY,EPS);
148 return e;
149 }
150
151 /*
152 * Write out a "ps" (PostScript), formatted image file from the specified
153 * field. The input field should not be composite, but may be series.
154 * By the time we get called, it has been asserted that we can write
155 * the image to the device, be it ADASD or otherwise.
156 *
157 * NOTE: The semantics here differ from those for RGB images in that
158 * the frame number is ignored, a new file is always created and if
159 * given a series all images in the series are written out.
160 */
161 static Error
output_ps(RWImageArgs * iargs,int colormode,int filetype)162 output_ps(RWImageArgs *iargs, int colormode,int filetype)
163 {
164 char imagefilename[MAX_IMAGE_NAMELEN];
165 int firstframe, lastframe, i, series;
166 int frames, deleteable = 0;
167 struct ps_spec page_spec;
168 Pointer pixels;
169 FILE *fp = NULL;
170 Array colors, color_map;
171 int imageType=0;
172 RGBColor *map = NULL;
173 Type type;
174 int rank, shape[32];
175
176 SizeData image_sizes; /* Values as found in the image object itself */
177 Field img = NULL;
178
179 if (iargs->adasd)
180 DXErrorGoto(ERROR_NOT_IMPLEMENTED,
181 "PostScript format not supported on disk array");
182
183 series = iargs->imgclass == CLASS_SERIES;
184
185 if (series && (filetype == EPS))
186 DXErrorGoto(ERROR_DATA_INVALID,
187 "Series data cannot be written in 'Encapsulated PostScript' format");
188
189 if ( !_dxf_GetImageAttributes ( (Object)iargs->image, &image_sizes ) )
190 goto error;
191
192 /*
193 * Always write all frames of a series.
194 */
195 frames = (image_sizes.endframe - image_sizes.startframe + 1);
196 firstframe = 0;
197 lastframe = frames-1;
198
199
200 page_spec.width_dpi = 0;
201 page_spec.height_dpi = 0;
202 page_spec.page_height = 11.0;
203 page_spec.page_width = 8.5;
204 page_spec.page_orient = ORIENT_AUTO;
205 page_spec.image_height = image_sizes.height;
206 page_spec.image_width = image_sizes.width;
207 page_spec.page_margin = 0.5;
208 page_spec.gamma = 2.0;
209 if (iargs->format) {
210 if (!parse_format(iargs->format,&page_spec))
211 goto error;
212 }
213
214 /*
215 * Get some nice statistics
216 */
217 page_spec.colormode = colormode;
218 page_spec.filetype = filetype;
219 orient_page(&page_spec);
220
221 /*
222 * Attempt to open image file and position to start of frame(s).
223 */
224 if (iargs->pipe == NULL) {
225 /*
226 * Create an appropriate file name.
227 */
228 if (!_dxf_BuildImageFileName(imagefilename,MAX_IMAGE_NAMELEN,
229 iargs->basename, iargs->imgtyp,iargs->startframe,0))
230 goto error;
231 if ( (fp = fopen (imagefilename, "w" )) == 0 )
232 ErrorGotoPlus1 ( ERROR_DATA_INVALID,
233 "Can't open image file (%s)", imagefilename );
234 } else {
235 strcpy(imagefilename,"stdout");
236 fp = iargs->pipe;
237 }
238
239 /*
240 * Write out the PostScript header, prolog and setup sections.
241 */
242 if (!put_ps_header(fp, imagefilename, frames, &page_spec) ||
243 !put_ps_prolog(fp, &page_spec) ||
244 !put_ps_setup(fp, frames, &page_spec))
245 goto bad_write;
246
247
248 img = iargs->image;
249 for (i=firstframe ; i<=lastframe ; i++)
250 {
251 if (series) {
252 if (deleteable) DXDelete((Object)img);
253 img = _dxf_GetFlatSeriesImage((Series)iargs->image,i,
254 page_spec.image_width,page_spec.image_height,
255 &deleteable);
256 if (!img)
257 goto error;
258 }
259
260 colors = (Array)DXGetComponentValue(img, "colors");
261 if (! colors)
262 {
263 DXSetError(ERROR_DATA_INVALID,
264 "image does not contain colors component");
265 goto error;
266 }
267
268 DXGetArrayInfo(colors, NULL, &type, NULL, &rank, shape);
269
270 if (type == TYPE_FLOAT)
271 {
272 if (rank != 1 || shape[0] != 3)
273 {
274 DXSetError(ERROR_DATA_INVALID,
275 "floating-point colors component must be 3-vector");
276 goto error;
277 }
278
279 imageType = FLOAT_COLOR;
280 }
281 else if (type == TYPE_UBYTE)
282 {
283 if (rank == 0 || (rank == 1 && shape[0] == 1))
284 {
285 color_map = (Array)DXGetComponentValue(img, "color map");
286 if (! color_map)
287 {
288 DXSetError(ERROR_DATA_INVALID,
289 "single-valued ubyte colors component requires a %s",
290 "color map");
291 goto error;
292 }
293
294 DXGetArrayInfo(color_map, NULL, &type, NULL, &rank, shape);
295
296 if (type != TYPE_FLOAT || rank != 1 || shape[0] != 3)
297 {
298 DXSetError(ERROR_DATA_INVALID,
299 "color map must be floating point 3-vectors");
300 goto error;
301 }
302
303 map = (RGBColor *)DXGetArrayData(color_map);
304 imageType = MAPPED_COLOR;
305 }
306 else if (rank != 1 || shape[0] != 3)
307 {
308 DXSetError(ERROR_DATA_INVALID,
309 "unsigned byte colors component must be either single %s",
310 "valued with a color map or 3-vectors");
311 goto error;
312 }
313 else
314 imageType = UBYTE_COLOR;;
315 }
316
317 if (!(pixels = DXGetArrayData(colors)))
318 goto error;
319
320 /* Put out what ever is necessary for a new page */
321 if (!ps_new_page(fp, i+1,frames, &page_spec))
322 goto bad_write;
323
324 /*
325 * Write out the pixel data
326 */
327 if (page_spec.colormode == FULLCOLOR) {
328 if (!ps_out_flc(fp, pixels, map, imageType, &page_spec))
329 goto bad_write;
330 }
331 else if (!ps_out_gry(fp, pixels, map, imageType, &page_spec))
332 goto bad_write;
333
334 /* Put out what ever is necessary to close a page */
335 if (!ps_end_page(fp))
336 goto bad_write;
337 }
338
339 /*
340 * Write out anything that is needed to end the file. This may work
341 * as a compliment to some of what is done in pu_ps_header(),
342 * put_ps_prolog() and/or put_ps_setup().
343 */
344 if (!put_ps_trailer(fp,&page_spec))
345 goto bad_write;
346
347 if (fclose(fp) != 0)
348 goto bad_write;
349
350 if (deleteable && img) DXDelete((Object)img);
351
352 return OK;
353
354 bad_write:
355 if ( iargs->pipe == NULL )
356 DXErrorGoto
357 ( ERROR_DATA_INVALID,
358 "Can't write PostScript file." )
359 else
360 DXErrorGoto
361 ( ERROR_BAD_PARAMETER,
362 "Can't send image with specified command." );
363
364 error:
365 if ( fp ) fclose(fp);
366 if (deleteable && img) DXDelete((Object)img);
367 return ERROR;
368 }
369
370 /*
371 * Put out anything that is considered document 'setup' (i.e. created
372 * a global dictionary, scale/rotate/translate the origin, define global
373 * variables...).
374 *
375 */
376 static Error
put_ps_setup(FILE * fout,int frames,struct ps_spec * spec)377 put_ps_setup(FILE *fout, int frames, struct ps_spec *spec)
378 {
379 int bytesperpix;
380
381 bytesperpix = (spec->colormode == FULLCOLOR) ? 3 : 1;
382
383 if (fprintf(fout,"%%%%BeginSetup\n\n") < 0)
384 goto bad_write;
385
386 LINEOUT("DXDict begin" );
387 LINEOUT("" );
388 LINEOUT("%% inch scaling" );
389
390 if (fprintf(fout,"/inch {%d mul} bind def\n\n", UPI) < 0)
391 goto bad_write;
392
393 if (fprintf(fout,"/bytesperpix %d def\n", bytesperpix) < 0)
394 goto bad_write;
395
396 if (fprintf(fout,"%%%%EndSetup\n\n") < 0)
397 goto bad_write;
398
399 return OK;
400
401 bad_write:
402 DXErrorGoto(ERROR_DATA_INVALID, "Can't write PostScript file.")
403
404 error:
405 return ERROR;
406 }
407 /*
408 * Write out PS code to set up the page for an image of given width and height.
409 */
410 static Error
put_ps_page_setup(FILE * fout,struct ps_spec * spec)411 put_ps_page_setup(FILE *fout, struct ps_spec *spec)
412 {
413 if (fprintf(fout,"%%%%BeginPageSetup\n\n") < 0)
414 goto error;
415
416
417 if (fprintf(fout,"/pixperrow %d store\n",spec->image_width) < 0)
418 goto error;
419 if (fprintf(fout,"/nrows %d store\n",spec->image_height) < 0)
420 goto error;
421
422 LINEOUT("/outrow pixperrow bytesperpix mul string def");
423 LINEOUT("/grayrow pixperrow string def" );
424
425 if ((fprintf(fout,"%% Number of pixels/inch in image width\n/wppi %d def\n",
426 spec->width_dpi) <= 0) ||
427 (fprintf(fout,"%% Number of pixels/inch in image height\n/hppi %d def\n",
428 spec->height_dpi) <= 0) ||
429 (fprintf(fout,"%% Size of output in inches\n/width %f def\n",
430 spec->page_width ) <= 0) ||
431 (fprintf(fout,"/height %f def\n", spec->page_height) <= 0) ||
432 (fprintf(fout,"%% Size of image in units\n"
433 "/iwidth 1 inch wppi div %d mul def\n",
434 spec->image_width) <= 0) ||
435 (fprintf(fout,"/iheight 1 inch hppi div %d mul def\n",
436 spec->image_height) <= 0))
437 goto error;
438
439 if (spec->page_orient == LANDSCAPE) {
440 if ((fprintf(fout,"%% Rotate and translate into Landscape mode\n")
441 <= 0) ||
442 (fprintf(fout,"90 rotate\n0 width neg inch cvi translate\n\n")
443 <= 0))
444 goto error;
445 }
446
447 if ((fprintf(fout,"%% Locate lower left corner of image(s)\n") < 0))
448 goto error;
449 if (spec->page_orient == LANDSCAPE) {
450 if (fprintf(fout, "height inch iwidth sub 2 div cvi\n"
451 "width inch iheight sub 2 div cvi\n"
452 "translate\n\n") <= 0)
453 goto error;
454 } else {
455 if (fprintf(fout, "width inch iwidth sub 2 div cvi\n"
456 "height inch iheight sub 2 div cvi\n"
457 "translate\n\n") <= 0)
458 goto error;
459 }
460
461 if ((fprintf(fout,"%% Image size units \niwidth iheight scale\n\n") <= 0) ||
462 (fprintf(fout,"%%%%EndPageSetup\n\n") <= 0))
463 goto error;
464
465
466 return OK;
467 bad_write:
468 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
469 error:
470 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
471 }
472
473 /*
474 * If doing full color images, put out code to define the 'colorimage'
475 * function if it is not available.
476 *
477 */
478 static Error
put_ps_prolog(FILE * fout,struct ps_spec * spec)479 put_ps_prolog(FILE *fout, struct ps_spec *spec)
480 {
481 int bytesperpix=1;
482
483 if (fprintf(fout,"%%%%BeginProlog\n") <= 0) goto error;
484
485 if (fprintf(fout,"%%%%BeginResource: procset DXProcs 1.0 0\n") <= 0)
486 goto error;
487
488 if (fprintf(fout,"/origstate save def\n") <= 0) goto error;
489 if (fprintf(fout,"/DXDict 25 dict def\n") <= 0) goto error;
490 if (fprintf(fout,"DXDict begin\n\n") <= 0) goto error;
491
492 if (spec->colormode == FULLCOLOR) {
493 if (!put_colorimage_function(fout)) goto error;
494 bytesperpix = 3;
495 }
496
497 LINEOUT("/buffer 1 string def" );
498 LINEOUT("/count 0 def" );
499
500 if (fprintf(fout,"/rgbval %d string def\n\n", bytesperpix) <= 0)
501 goto error;
502
503 LINEOUT("/rlerow {" );
504 LINEOUT(" /count 0 store" );
505 LINEOUT(" {" );
506
507 if (bytesperpix == 1)
508 {
509 if (fprintf(fout," count pixperrow ge\n") <= 0)
510 goto error;
511 }
512 else
513 {
514 if (fprintf(fout," count pixperrow %d mul ge\n", bytesperpix) <= 0)
515 goto error;
516 }
517
518 LINEOUT(" {exit} if %% end of row" );
519 LINEOUT(" currentfile buffer readhexstring pop" );
520 LINEOUT(" /bcount exch 0 get store" );
521 LINEOUT(" bcount 128 ge" );
522 LINEOUT(" {" );
523 LINEOUT(" %% not a run block" );
524 LINEOUT(" bcount 128 sub {" );
525 LINEOUT(" currentfile rgbval readhexstring pop pop" );
526 LINEOUT(" outrow count rgbval putinterval" );
527
528 if (fprintf(fout," /count count %d add store\n", bytesperpix) <= 0)
529 goto error;
530
531 LINEOUT(" } repeat" );
532 LINEOUT(" }" );
533 LINEOUT(" {" );
534 LINEOUT(" %% run block" );
535 LINEOUT(" currentfile rgbval readhexstring pop pop" );
536 LINEOUT(" bcount {" );
537 LINEOUT(" outrow count rgbval putinterval" );
538
539 if (fprintf(fout," /count count %d add store\n", bytesperpix) <= 0)
540 goto error;
541
542 LINEOUT(" } repeat" );
543 LINEOUT(" } ifelse" );
544 LINEOUT(" } loop %% until end of row" );
545 LINEOUT(" outrow" );
546 LINEOUT("} bind def" );
547 LINEOUT("end %% DXDict" );
548 LINEOUT("" );
549
550 if (fprintf(fout,"%%%%EndResource\n") <= 0) goto error;
551
552 if (fprintf(fout,"%%%%EndProlog\n\n") <= 0) goto error;
553 return OK;
554 bad_write:
555 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
556 error:
557 return ERROR;
558 }
559
560
561 /*
562 * Output everything in a PostScript file up to and including the
563 * '%%EndComments' structuring comment. When doing Encapsulated
564 * PostScript, this must include the '%%BoundingBox:...' comment.
565 *
566 * Always returns OK.
567 */
568 static Error
put_ps_header(FILE * fout,char * filename,int frames,struct ps_spec * spec)569 put_ps_header(FILE *fout, char *filename, int frames, struct ps_spec *spec)
570 {
571 const time_t t = time(0);
572 char *tod = ctime((const time_t *)&t);
573 int major, minor, micro;
574
575 if (spec->filetype == PS) {
576 if (fprintf(fout, "%s", "%!PS-Adobe-3.0\n") <= 0) goto error;
577 } else { /* Encapsulated PostScript */
578 /* Required for EPSF-3.0 */
579 if (fprintf(fout, "%s", "%!PS-Adobe-3.0 EPSF-3.0\n") <= 0) goto error;
580 }
581
582 DXVersion(&major, &minor, µ);
583 if (fprintf(fout, "%%%%Creator: IBM/Data Explorer %d.%d.%d\n",
584 major,minor,micro) <= 0) goto error;
585 if (fprintf(fout, "%%%%CreationDate: %s", tod) <= 0) goto error;
586 if (fprintf(fout, "%%%%Title: %s\n", filename) <= 0) goto error;
587 if (fprintf(fout, "%%%%Pages: %d\n", frames) <= 0) goto error;
588
589 if (spec->filetype == EPS) {
590 /* Put a Bounding Box specification, required for EPSF-3.0 */
591 int beginx, beginy, endx, endy;
592
593 float wsize = UPI*spec->image_width / spec->width_dpi;
594 float hsize = UPI*spec->image_height / spec->height_dpi;
595
596 if (spec->page_orient == LANDSCAPE) {
597 beginx = (spec->page_width * UPI - hsize)/2 - .5;
598 beginy = (spec->page_height * UPI - wsize)/2 - .5;
599 endx = beginx + hsize + 1.0;
600 endy = beginy + wsize + 1.0;
601 } else {
602 beginx = (spec->page_width * UPI - wsize)/2 - .5;
603 beginy = (spec->page_height * UPI - hsize)/2 - .5;
604 endx = beginx + wsize + 1.0;
605 endy = beginy + hsize + 1.0;
606 }
607 if (fprintf(fout, "%%%%BoundingBox: %d %d %d %d\n",
608 beginx,beginy,endx,endy) <= 0)
609 goto error;
610 }
611
612 if (fprintf(fout, "%%%%EndComments\n\n") <= 0) goto error;
613
614 return OK;
615
616 error:
617 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
618 }
619
620
621 /******** RLE encoding routines ******************************************/
622 /******** Modified from buffer.c ******************************************/
623
624 #define DO_COMPRESSION 1
625
626 #define CHARS_PER_LINE 80
627
628 #define HEX "0123456789abcdef"
629 #define HEX1(b) (HEX[(b)/16])
630 #define HEX2(b) (HEX[(b)%16])
631
632 #define ADD_HEX(s, b, nn, binary) \
633 if (binary == RLE_ASCII) { \
634 *s++ = HEX1(b); \
635 *s++ = HEX2(b); \
636 nn += 2; \
637 if (!((nn+1)%(CHARS_PER_LINE+1))) \
638 { *s++ = '\n'; nn += 1; } \
639 } else { \
640 *s++ = b; \
641 nn++; \
642 }
643
644 /***************************************************************************/
645 #define CMP(A,B) (((char *)(A))[0] == ((char *)(B))[0] && \
646 ((char *)(A))[1] == ((char *)(B))[1] && \
647 ((char *)(A))[2] == ((char *)(B))[2])
648 #define ASGN(A,B) (((char *)(A))[0] = ((char *)(B))[0], \
649 ((char *)(A))[1] = ((char *)(B))[1], \
650 ((char *)(A))[2] = ((char *)(B))[2], \
651 ((char *)(A))[3] = ((char *)(B))[3])
652 #define PIXSIZE 3
653 #define ENCODE_NAME encode_24bit_row
654 /***************************************************************************/
ENCODE_NAME(ubyte * pix_row,int n_pix,ubyte * enc_row,int * n_out_bytes,int binary,int order,int compact)655 static Error ENCODE_NAME(ubyte *pix_row, int n_pix,
656 ubyte *enc_row, int *n_out_bytes, int binary, int order, int compact)
657 {
658 ubyte *start_p, *p;
659 int start_i, i, knt, size, k;
660 int out_length;
661 int x, y;
662 int image_size;
663 int totknt;
664 ubyte *segptr;
665 int max_knt = 127;
666
667 x = n_pix;
668 y = 1;
669 image_size = x*y;
670 segptr = enc_row;
671 start_p = pix_row;
672 start_i = 0;
673 totknt = 0;
674
675 if (compact == RLE_STUPID)
676 max_knt = 256;
677
678 while (start_i < image_size)
679 {
680 /*
681 * Look for run of identical pixels
682 */
683 i = start_i + 1;
684 p = start_p + PIXSIZE;
685
686 while (i < image_size)
687 {
688 if (! CMP(start_p, p))
689 break;
690
691 i++;
692 p += PIXSIZE;
693 }
694
695 knt = i - start_i;
696
697 /*
698 * if knt == 1 then two adjacent pixels differ. so instead we
699 * look for a run of differing pixels, broken when three
700 * identical pixels are found.
701 */
702 if (knt == 1)
703 {
704 /*
705 * terminate this loop before the comparison goes off
706 * the end of the image.
707 */
708 while ((i < image_size - 2) &&
709 (!CMP(p+0, p+PIXSIZE) || !CMP(p+0, p+2*PIXSIZE)))
710 i++, p += PIXSIZE;
711
712 /*
713 * Don't bother with rle for last couple of pixels
714 */
715 if (i == image_size-2)
716 i = image_size;
717
718 knt = i - start_i;
719
720 /*
721 * loop parcelling out total run in as many packets
722 * as are necessary
723 */
724 while (knt > 0)
725 {
726 /*
727 * Limit run length to packet size
728 */
729 int j;
730 int length = (knt > max_knt) ? max_knt : knt;
731 int size = length * PIXSIZE;
732
733 /*
734 * decrement total run length by packet run length
735 */
736 knt -= length;
737
738 if (compact == RLE_COMPACT)
739 {
740 if (order == RLE_COUNT_PRE) {
741 ADD_HEX(segptr,(0x80 | length), (*n_out_bytes), binary);
742 }
743 for (k=0; k<size; k++)
744 {
745 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
746 start_p++;
747 }
748 if (order == RLE_COUNT_POST) {
749 ADD_HEX(segptr,(0x80 | length), (*n_out_bytes), binary);
750 }
751 } else for (j=0; j<length; j++) {
752 if (order == RLE_COUNT_PRE) {
753 ADD_HEX(segptr, 0, (*n_out_bytes), binary);
754 }
755 for (k=0; k<PIXSIZE; k++) {
756 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
757 start_p++;
758 }
759 if (order == RLE_COUNT_POST) {
760 ADD_HEX(segptr, 0, (*n_out_bytes), binary);
761 }
762 }
763 }
764 }
765 else
766 {
767
768 while (knt > 0)
769 {
770 /*
771 * Limit run length to packet size
772 */
773 int length = (knt > max_knt) ? max_knt : knt;
774 size = PIXSIZE;
775
776 /*
777 * decrement total run length by packet run length
778 */
779 knt -= length;
780
781 out_length = length;
782 if (compact == RLE_STUPID) {
783 out_length--;
784 }
785
786 if (order == RLE_COUNT_PRE) {
787 ADD_HEX(segptr, out_length, (*n_out_bytes), binary);
788 }
789 for (k=0; k<size; k++)
790 {
791 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
792 start_p++;
793 }
794 if (order == RLE_COUNT_POST) {
795 ADD_HEX(segptr, out_length, (*n_out_bytes), binary);
796 }
797
798 }
799 }
800
801 start_i = i;
802 start_p = p;
803 }
804
805 DXDebug("Y", "compaction: %d bytes in %d bytes out",
806 image_size*PIXSIZE, totknt);
807
808 *segptr = '\0';
809 return totknt;
810
811 }
812
813 /***************************************************************************/
814 #undef CMP
815 #undef ASGN
816 #undef PIXSIZE
817 #undef ENCODE_NAME
818
819 #define CMP(A,B) (*((ubyte *)(A)) == *((ubyte *)(B)))
820 #define ASGN(A,B) (*((ubyte *)(A)) = *((ubyte *)(B)))
821 #define PIXSIZE 1
822 #define ENCODE_NAME encode_8bit_row
823 /***************************************************************************/
ENCODE_NAME(ubyte * pix_row,int n_pix,ubyte * enc_row,int * n_out_bytes,int binary,int order,int compact)824 static Error ENCODE_NAME(ubyte *pix_row, int n_pix,
825 ubyte *enc_row, int *n_out_bytes, int binary, int order, int compact)
826 {
827 ubyte *start_p, *p;
828 int start_i, i, knt, size, k;
829 int out_length;
830 int x, y;
831 int image_size;
832 int totknt;
833 ubyte *segptr;
834 int max_knt = 127;
835
836 x = n_pix;
837 y = 1;
838 image_size = x*y;
839 segptr = enc_row;
840 start_p = pix_row;
841 start_i = 0;
842 totknt = 0;
843
844 if (compact == RLE_STUPID)
845 max_knt = 256;
846
847 while (start_i < image_size)
848 {
849 /*
850 * Look for run of identical pixels
851 */
852 i = start_i + 1;
853 p = start_p + PIXSIZE;
854
855 while (i < image_size)
856 {
857 if (! CMP(start_p, p))
858 break;
859
860 i++;
861 p += PIXSIZE;
862 }
863
864 knt = i - start_i;
865
866 /*
867 * if knt == 1 then two adjacent pixels differ. so instead we
868 * look for a run of differing pixels, broken when three
869 * identical pixels are found.
870 */
871 if (knt == 1)
872 {
873 /*
874 * terminate this loop before the comparison goes off
875 * the end of the image.
876 */
877 while ((!CMP(p+0, p+PIXSIZE) ||
878 !CMP(p+0, p+2*PIXSIZE)) && i < image_size - 2)
879 i++, p += PIXSIZE;
880
881 /*
882 * Don't bother with rle for last couple of pixels
883 */
884 if (i == image_size-2)
885 i = image_size;
886
887 knt = i - start_i;
888
889 /*
890 * loop parcelling out total run in as many packets
891 * as are necessary
892 */
893 while (knt > 0)
894 {
895 /*
896 * Limit run length to packet size
897 */
898 int length = (knt > max_knt) ? max_knt : knt;
899 int size = length * PIXSIZE;
900
901 /*
902 * decrement total run length by packet run length
903 */
904 knt -= length;
905
906 if (compact == RLE_COMPACT)
907 {
908 if (order == RLE_COUNT_PRE) {
909 ADD_HEX(segptr,(0x80 | length), (*n_out_bytes), binary);
910 }
911 for (k=0; k<size; k++)
912 {
913 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
914 start_p++;
915 }
916 if (order == RLE_COUNT_POST) {
917 ADD_HEX(segptr,(0x80 | length), (*n_out_bytes), binary);
918 }
919 } else {
920 for (k=0; k<length; k++)
921 {
922 if (order == RLE_COUNT_PRE) {
923 ADD_HEX(segptr, 0, (*n_out_bytes), binary);
924 }
925 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
926 start_p++;
927 if (order == RLE_COUNT_POST) {
928 ADD_HEX(segptr, 0, (*n_out_bytes), binary);
929 }
930 }
931 }
932 }
933 }
934 else
935 {
936
937 while (knt > 0)
938 {
939 /*
940 * Limit run length to packet size
941 */
942 int length = (knt > max_knt) ? max_knt : knt;
943 size = PIXSIZE;
944
945 /*
946 * decrement total run length by packet run length
947 */
948 knt -= length;
949
950 out_length = length;
951 if (compact == RLE_STUPID) {
952 out_length--;
953 }
954
955 if (order == RLE_COUNT_PRE) {
956 ADD_HEX(segptr, out_length, (*n_out_bytes), binary);
957 }
958 for (k=0; k<size; k++)
959 {
960 ADD_HEX(segptr, (*start_p), (*n_out_bytes), binary);
961 start_p++;
962 }
963 if (order == RLE_COUNT_POST) {
964 ADD_HEX(segptr, out_length, (*n_out_bytes), binary);
965 }
966
967 }
968 }
969
970 start_i = i;
971 start_p = p;
972 }
973
974 DXDebug("Y", "compaction: %d bytes in %d bytes out",
975 image_size*PIXSIZE, totknt);
976
977
978 *segptr = '\0';
979 return totknt;
980
981 }
982 /***************************************************************************/
983 #undef CMP
984 #undef ASGN
985 #undef PIXSIZE
986 #undef ENCODE_NAME
987 /***************************************************************************/
988
989
build_rle_row(ubyte * r,int n_pixels,int bytes_per_pixel,int compress,ubyte * buff,int * byte_count,int binary,int order,int compact)990 static Error build_rle_row(ubyte *r, int n_pixels, int bytes_per_pixel,
991 int compress, ubyte *buff, int *byte_count, int binary, int order, int compact)
992 {
993 int i;
994
995 if (compress) {
996 if (bytes_per_pixel==1)
997 encode_8bit_row(r, n_pixels, buff, byte_count, binary, order, compact);
998 else
999 encode_24bit_row(r, n_pixels, buff, byte_count, binary, order, compact);
1000 }
1001 else
1002 for (i=0; i<n_pixels*bytes_per_pixel; i++) {
1003 ADD_HEX(buff, (*r), (*byte_count), RLE_ASCII);
1004 r++;
1005 }
1006 return OK;
1007 }
1008
1009
1010 #define CLAMP(p) ( ( (P=(p)) < 0 ) ? 0 : (P<=255) ? P : 255 )
1011
1012 /*
1013 * This routine writes out the full color image data to the PostScript
1014 * file. Each line of the image is written out in R, G and B
1015 * to records of length 80.
1016 *
1017 * Note, that PostScript expects its pixels from left to right and
1018 * top to bottom, just the way DX keeps them stored.
1019 *
1020 * Returns OK/ERROR on failure/success.
1021 */
1022 static Error
ps_out_flc(FILE * fout,Pointer pixels,RGBColor * map,int imageType,struct ps_spec * spec)1023 ps_out_flc(FILE *fout, Pointer pixels,
1024 RGBColor *map, int imageType, struct ps_spec *spec)
1025 {
1026 int i, j, P;
1027 ubyte *RGBbuff=NULL, *RGBptr;
1028 char *encbuff=NULL;
1029 int encbuff_size, RGBbuff_size;
1030 int byte_count;
1031 int row_str_length;
1032 ubyte gamma_table[256];
1033
1034 spec->compress = DO_COMPRESSION;
1035
1036 _dxf_make_gamma_table(gamma_table, spec->gamma);
1037
1038 if (!ps_image_header(fout, spec))
1039 goto error;
1040
1041 RGBbuff_size = spec->image_width*3;
1042 RGBbuff = DXAllocate(RGBbuff_size);
1043
1044 /* This is a worst-case row buffer size for no runs */
1045 encbuff_size = RGBbuff_size*128*2/127;
1046 /* now add room for newlines and some spare */
1047 encbuff_size += encbuff_size/CHARS_PER_LINE + 100;
1048 encbuff = DXAllocate(encbuff_size);
1049
1050 byte_count = 0;
1051
1052 if (imageType == FLOAT_COLOR)
1053 {
1054 RGBColor *fpixels = (RGBColor *)pixels;
1055 for (i=0; i<spec->image_height; i++) {
1056 for (j=0, RGBptr = RGBbuff; j<spec->image_width; j++, fpixels++) {
1057 float r = fpixels->r * 255;
1058 float g = fpixels->g * 255;
1059 float b = fpixels->b * 255;
1060 *RGBptr++ = gamma_table[CLAMP(r)];
1061 *RGBptr++ = gamma_table[CLAMP(g)];
1062 *RGBptr++ = gamma_table[CLAMP(b)];
1063 }
1064 build_rle_row(RGBbuff, spec->image_width, 3,
1065 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1066 row_str_length = strlen(encbuff);
1067 if (fprintf(fout, "%s", encbuff) != row_str_length)
1068 goto error;
1069
1070 /* force newlines after each row if no compression */
1071 if (!spec->compress)
1072 {
1073 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1074 && (fprintf(fout,"\n") != 1))
1075 goto error;
1076 byte_count = 0;
1077 }
1078 }
1079 }
1080 else if (imageType == UBYTE_COLOR)
1081 {
1082 RGBByteColor *upixels = (RGBByteColor *)pixels;
1083
1084 for (i=0; i<spec->image_height; i++) {
1085 for (j=0, RGBptr = RGBbuff; j<spec->image_width; j++, upixels++) {
1086 *RGBptr++ = gamma_table[upixels->r];
1087 *RGBptr++ = gamma_table[upixels->g];
1088 *RGBptr++ = gamma_table[upixels->b];
1089 }
1090 build_rle_row(RGBbuff, spec->image_width, 3,
1091 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1092 row_str_length = strlen(encbuff);
1093 if (fprintf(fout, "%s", encbuff) != row_str_length)
1094 goto error;
1095
1096 /* force newlines after each row if no compression */
1097 if (!spec->compress)
1098 {
1099 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1100 && (fprintf(fout,"\n") != 1))
1101 goto error;
1102 byte_count = 0;
1103 }
1104 }
1105 }
1106 else
1107 {
1108 ubyte *upixels = (ubyte *)pixels;
1109
1110 for (i=0; i<spec->image_height; i++) {
1111 for (j=0, RGBptr = RGBbuff; j<spec->image_width; j++, upixels++) {
1112 float r = map[*upixels].r * 255;
1113 float g = map[*upixels].g * 255;
1114 float b = map[*upixels].b * 255;
1115 *RGBptr++ = gamma_table[CLAMP(r)];
1116 *RGBptr++ = gamma_table[CLAMP(g)];
1117 *RGBptr++ = gamma_table[CLAMP(b)];
1118 }
1119 build_rle_row(RGBbuff, spec->image_width, 3,
1120 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1121 row_str_length = strlen(encbuff);
1122 if (fprintf(fout, "%s", encbuff) != row_str_length)
1123 goto error;
1124
1125 /* force newlines after each row if no compression */
1126 if (!spec->compress)
1127 {
1128 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1129 && (fprintf(fout,"\n") != 1))
1130 goto error;
1131 byte_count = 0;
1132 }
1133 }
1134 }
1135
1136 if (fprintf(fout,"\n") != 1)
1137 goto error;
1138
1139 DXFree(RGBbuff);
1140 DXFree(encbuff);
1141 return OK;
1142 error:
1143 DXFree(RGBbuff);
1144 DXFree(encbuff);
1145 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1146 }
1147
1148
1149 /*
1150 * This routine converts the RGB pixels to gray levels and writes out 8bits
1151 * per pixel to the PostScript.
1152 *
1153 * Note, that PostScript expects its pixels from left to right and
1154 * top to bottom, just the way DX keeps them stored.
1155 *
1156 * Returns OK/ERROR on failure/success.
1157 */
1158 static Error
ps_out_gry(FILE * fout,Pointer pixels,RGBColor * map,int imageType,struct ps_spec * spec)1159 ps_out_gry(FILE *fout,
1160 Pointer pixels, RGBColor *map, int imageType, struct ps_spec *spec)
1161 {
1162 int i, j, P;
1163 ubyte *BWbuff=NULL, *BWptr;
1164 char *encbuff=NULL;
1165 int encbuff_size, BWbuff_size;
1166 int byte_count;
1167 int row_str_length;
1168 ubyte gamma_table[256];
1169 float f;
1170 float g;
1171
1172 spec->compress = DO_COMPRESSION;
1173
1174 g = 1.0/spec->gamma;
1175 for (i=0; i<256; i++) {
1176 f = i/255.0;
1177 gamma_table[i] = 255*pow(f, g);
1178 }
1179
1180 if (!ps_image_header(fout, spec))
1181 goto error;
1182
1183 BWbuff_size = spec->image_width;
1184 BWbuff = DXAllocate(BWbuff_size);
1185
1186 /* This is a worst-case row buffer size for no runs */
1187 encbuff_size = spec->image_width*128*2/127;
1188 /* now add room for newlines and some spare */
1189 encbuff_size += encbuff_size/CHARS_PER_LINE + 100;
1190 encbuff = DXAllocate(encbuff_size);
1191
1192 byte_count = 0;
1193
1194 if (imageType == FLOAT_COLOR)
1195 {
1196 RGBColor *fpixels = (RGBColor *)pixels;
1197 for (i=0; i<spec->image_height; i++) {
1198 for (j=0, BWptr = BWbuff; j<spec->image_width; j++, fpixels++) {
1199 float r = fpixels->r;
1200 float g = fpixels->g;
1201 float b = fpixels->b;
1202 float gray = RGB_TO_BW(r, g, b) * 255;
1203 *BWptr++ = gamma_table[CLAMP(gray)];
1204 }
1205 build_rle_row(BWbuff, spec->image_width, 1,
1206 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1207 row_str_length = strlen(encbuff);
1208 if (fprintf(fout, "%s", encbuff) != row_str_length)
1209 goto error;
1210
1211 /* force newlines after each row if no compression */
1212 if (!spec->compress)
1213 {
1214 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1215 && (fprintf(fout,"\n") != 1))
1216 goto error;
1217 byte_count = 0;
1218 }
1219 }
1220 }
1221 else if (imageType == UBYTE_COLOR)
1222 {
1223 RGBByteColor *upixels = (RGBByteColor *)pixels;
1224
1225 for (i=0; i<spec->image_height; i++) {
1226 for (j=0, BWptr = BWbuff; j<spec->image_width; j++, upixels++) {
1227 float r = upixels->r;
1228 float g = upixels->g;
1229 float b = upixels->b;
1230 float gray = RGB_TO_BW(r, g, b);
1231 *BWptr++ = gamma_table[CLAMP(gray)];
1232 }
1233 build_rle_row(BWbuff, spec->image_width, 1,
1234 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1235 row_str_length = strlen(encbuff);
1236 if (fprintf(fout, "%s", encbuff) != row_str_length)
1237 goto error;
1238
1239 /* force newlines after each row if no compression */
1240 if (!spec->compress)
1241 {
1242 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1243 && (fprintf(fout,"\n") != 1))
1244 goto error;
1245 byte_count = 0;
1246 }
1247 }
1248 }
1249 else
1250 {
1251 ubyte *upixels = (ubyte *)pixels;
1252
1253 for (i=0; i<spec->image_height; i++) {
1254 for (j=0, BWptr = BWbuff; j<spec->image_width; j++, upixels++) {
1255 float r = map[*upixels].r;
1256 float g = map[*upixels].g;
1257 float b = map[*upixels].b;
1258 float gray = RGB_TO_BW(r, g, b) * 255;
1259 *BWptr++ = gamma_table[CLAMP(gray)];
1260 }
1261 build_rle_row(BWbuff, spec->image_width, 1,
1262 spec->compress, (ubyte *)encbuff, &byte_count, RLE_ASCII, RLE_COUNT_PRE, RLE_COMPACT);
1263 row_str_length = strlen(encbuff);
1264 if (fprintf(fout, "%s", encbuff) != row_str_length)
1265 goto error;
1266
1267 /* force newlines after each row if no compression */
1268 if (!spec->compress)
1269 {
1270 if ((encbuff) && (*encbuff) && (encbuff[strlen(encbuff)-1] != '\n')
1271 && (fprintf(fout,"\n") != 1))
1272 goto error;
1273 byte_count = 0;
1274 }
1275 }
1276 }
1277
1278 if (fprintf(fout,"\n") != 1)
1279 goto error;
1280
1281 DXFree(BWbuff);
1282 DXFree(encbuff);
1283 return OK;
1284 error:
1285 DXFree(BWbuff);
1286 DXFree(encbuff);
1287 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1288 }
1289
1290 /*
1291 * This routine writes out the trailer of the PostScript file
1292 * Undoes some of what was done in put_ps_header().
1293 */
1294 static Error
put_ps_trailer(FILE * fout,struct ps_spec * spec)1295 put_ps_trailer(FILE *fout, struct ps_spec *spec)
1296 {
1297
1298 if (fprintf(fout, "%%%%Trailer\n") <= 0)
1299 goto error;
1300 if (fprintf(fout, "\n%% Stop using temporary dictionary\nend\n\n") <= 0)
1301 goto error;
1302 if (fprintf(fout, "%% Restore original state\norigstate restore\n\n") <= 0)
1303 goto error;
1304 if (fprintf(fout, "%%%%EOF\n") <= 0)
1305 goto error;
1306 return OK;
1307
1308 error:
1309 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1310 }
1311
1312 /*
1313 * Put the arguments on the stack and call the correct imaging
1314 * function (either image or colorimage).
1315 * It is assumed that the data for the image will be written out
1316 * immediately following the output here.
1317 *
1318 * Always returns OK.
1319 */
1320 static Error
ps_image_header(FILE * fout,struct ps_spec * spec)1321 ps_image_header(FILE *fout, struct ps_spec *spec)
1322 {
1323
1324 if (fprintf(fout,"%% Dimensionality of data\n%d %d 8\n\n",
1325 spec->image_width,spec->image_height) <= 0)
1326 goto error;
1327 if (fprintf(fout,"%% Mapping matrix\n[ %d 0 0 %d 0 0 ]\n\n",
1328 spec->image_width,spec->image_height) <= 0)
1329 goto error;
1330 if (fprintf(fout, "%% Function to read pixels\n") <= 0)
1331 goto error;
1332 if (fprintf(fout, "{ rlerow }\n") <= 0)
1333 goto error;
1334
1335 if (spec->colormode == FULLCOLOR) {
1336 if (fprintf(fout, "false 3\t\t\t%% Single data source, 3 colors\n")<=0)
1337 goto error;
1338 if (fprintf(fout, "colorimage\n") <= 0)
1339 goto error;
1340 } else {
1341 if (fprintf(fout, "image\n") <= 0)
1342 goto error;
1343 }
1344 return OK;
1345
1346 error:
1347 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1348 }
1349
1350 /*
1351 * Write out code to test for the colorimage function and to define it
1352 * if it is not defined.
1353 */
1354 static Error
put_colorimage_function(FILE * fout)1355 put_colorimage_function(FILE *fout)
1356 {
1357 LINEOUT("%% Define colorimage procedure if not present" );
1358 LINEOUT("/colorimage where %% colorimage defined?" );
1359 LINEOUT(" { pop } %% yes: pop off dict returned" );
1360 LINEOUT(" { %% no: define one with grayscale conversion");
1361 LINEOUT(" /colorimage {" );
1362 LINEOUT(" pop" );
1363 LINEOUT(" pop" );
1364 LINEOUT(" /hexread exch store" );
1365 LINEOUT(" {" );
1366 LINEOUT(" hexread" );
1367 LINEOUT(" /rgbdata exch store %% call input row 'rgbdata'" );
1368 LINEOUT(" /rgbindx 0 store" );
1369 LINEOUT(" 0 1 pixperrow 2 sub {" );
1370 LINEOUT(" grayrow exch" );
1371 LINEOUT(" rgbdata rgbindx get 19 mul" );
1372 LINEOUT(" rgbdata rgbindx 1 add get 38 mul" );
1373 LINEOUT(" rgbdata rgbindx 2 add get 7 mul" );
1374 LINEOUT(" add add 64 idiv" );
1375 LINEOUT(" put" );
1376 LINEOUT(" /rgbindx rgbindx 3 add store" );
1377 LINEOUT(" } for" );
1378 LINEOUT(" grayrow %% output row converted to grayscale" );
1379 LINEOUT(" }" );
1380 LINEOUT(" image" );
1381 LINEOUT(" } bind def" );
1382 LINEOUT(" } ifelse" );
1383
1384 return OK;
1385
1386 bad_write:
1387 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1388 return ERROR;
1389 }
1390
1391 /*
1392 * Called before each new image to begin a new page.
1393 */
1394 static Error
ps_new_page(FILE * fout,int page,int pages,struct ps_spec * spec)1395 ps_new_page(FILE *fout,int page, int pages, struct ps_spec *spec)
1396 {
1397 if (fprintf(fout,"\n%%%%Page: %d %d\n\n",page,pages) <= 0)
1398 goto error;
1399 if (!put_ps_page_setup(fout,spec))
1400 goto error;
1401
1402 return OK;
1403 error:
1404 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1405 }
1406
1407 /*
1408 * Called after every image to end a page.
1409 */
1410 static Error
ps_end_page(FILE * fout)1411 ps_end_page(FILE *fout)
1412 {
1413 if (fprintf(fout, "\nshowpage\n") <= 0)
1414 goto error;
1415 else
1416 return OK;
1417 error:
1418 DXErrorReturn(ERROR_DATA_INVALID, "Can't write PostScript file.");
1419 }
1420
1421 /*
1422 * Determine the pagemode (PORTRAIT or LANDSCAPE) given the dimensions
1423 * of the image in spec.
1424 *
1425 */
1426 static void
orient_page(struct ps_spec * spec)1427 orient_page(struct ps_spec *spec)
1428 {
1429 int mode = PORTRAIT;
1430 int pagewidth_in_pixels;
1431 int pageheight_in_pixels;
1432 int badfit = 0;
1433 float wx, wy;
1434 float aspect;
1435 float page_aspect;
1436
1437 if (!spec->width_dpi) {
1438 wx = spec->page_width - 2*spec->page_margin;
1439 wy = spec->page_height - 2*spec->page_margin;
1440 page_aspect = wy/wx;
1441 aspect = spec->image_height*1.0/spec->image_width;
1442 if ((aspect>1 && page_aspect>1) || (aspect<1 && page_aspect<1)) {
1443 spec->width_dpi = spec->image_width/wx;
1444 spec->height_dpi = spec->image_height/wy;
1445 } else {
1446 spec->width_dpi = spec->image_height/wx;
1447 spec->height_dpi = spec->image_width/wy;
1448 }
1449 }
1450
1451 pagewidth_in_pixels = spec->width_dpi * spec->page_width;
1452 pageheight_in_pixels = spec->height_dpi * spec->page_height;
1453
1454 if (spec->image_width > pagewidth_in_pixels) {
1455 if (spec->image_height < pageheight_in_pixels) {
1456 mode = LANDSCAPE;
1457 } else
1458 badfit = 1;
1459 } else if (spec->image_height > pageheight_in_pixels) {
1460 if (spec->image_width < pagewidth_in_pixels) {
1461 mode = PORTRAIT;
1462 } else
1463 badfit = 1;
1464 }
1465
1466 if (badfit)
1467 DXWarning("PostScript image overflows page");
1468
1469 if (spec->page_orient == ORIENT_NOT_SET || spec->page_orient == ORIENT_AUTO)
1470 spec->page_orient = mode;
1471
1472 }
1473 #define SKIP_WHITE(p) while (*p && (*p == ' ' || *p == '\t')) p++
1474 #define FIND_EQUAL(p) while (*p && (*p != '=')) p++
1475
1476 static Error
parse_format(char * fmt,struct ps_spec * spec)1477 parse_format(char *fmt, struct ps_spec *spec)
1478 {
1479 char *format_modifier;
1480 float width,height;
1481 char *p;
1482 char format[1024];
1483 int i, len = strlen(fmt);
1484 int dpi_parsed = 0, width_parsed = 0;
1485 float g;
1486
1487 if (len >= 1024) {
1488 DXSetError(ERROR_BAD_PARAMETER,"'format' too long.");
1489 return ERROR;
1490 } else {
1491 /* Copy the pattern into a lower case buffer */
1492 for (i=0 ; i<len ; i++) {
1493 char b = fmt[i];
1494 format[i] = (isupper(b) ? tolower(b) : b);
1495 }
1496 format[len] = '\0';
1497 }
1498 /*
1499 * Parse the page size.
1500 */
1501 format_modifier = "page";
1502 if ((p=strstr(format," page"))) {
1503 p += 5;
1504 SKIP_WHITE(p);
1505 if (!p) goto format_error;
1506 FIND_EQUAL(p);
1507 if (!p) goto format_error;
1508 p++; /* Skip the '=' */
1509 SKIP_WHITE(p);
1510 if (p && (sscanf(p,"%fx%f",&width,&height) == 2)) {
1511 spec->page_width = width;
1512 spec->page_height = height;
1513 } else if (p && (sscanf(p,"%fX%f",&width,&height) == 2)) {
1514 spec->page_width = width;
1515 spec->page_height = height;
1516 } else {
1517 goto format_error;
1518 }
1519 }
1520 /*
1521 * Parse the dots per inch.
1522 */
1523 format_modifier = "dpi";
1524 if ((p=strstr(format," dpi"))) {
1525 int dpi;
1526 p += 4;
1527 SKIP_WHITE(p);
1528 if (!p) goto format_error;
1529 FIND_EQUAL(p);
1530 if (!p) goto format_error;
1531 p++; /* Skip the '=' */
1532 SKIP_WHITE(p);
1533 if (!p) goto error;
1534 if (sscanf(p,"%d",&dpi) == 1) {
1535 spec->width_dpi = dpi;
1536 spec->height_dpi = dpi;
1537 } else {
1538 goto format_error;
1539 }
1540 dpi_parsed = 1;
1541 }
1542 /*
1543 * Parse the gamma
1544 */
1545 format_modifier = "gamma";
1546 if ((p=strstr(format," gamma"))) {
1547 p += 4;
1548 SKIP_WHITE(p);
1549 if (!p) goto format_error;
1550 FIND_EQUAL(p);
1551 if (!p) goto format_error;
1552 p++; /* Skip the '=' */
1553 SKIP_WHITE(p);
1554 if (!p) goto error;
1555 if (sscanf(p,"%f",&g) == 1) {
1556 spec->gamma = g;
1557 } else {
1558 goto format_error;
1559 }
1560 }
1561 /*
1562 * Parse the page orientation.
1563 */
1564 format_modifier = "orient";
1565 if ((p=strstr(format," orient"))) {
1566 p += 7;
1567 SKIP_WHITE(p);
1568 if (!p) goto format_error;
1569 FIND_EQUAL(p);
1570 if (!p) goto format_error;
1571 p++; /* Skip the '=' */
1572 SKIP_WHITE(p);
1573 if (p && !strncmp(p,"landscape",9)) {
1574 spec->page_orient = LANDSCAPE;
1575 } else if (p && !strncmp(p,"portrait",8)) {
1576 spec->page_orient = PORTRAIT;
1577 } else if (p && !strncmp(p,"auto",4)) {
1578 spec->page_orient = ORIENT_AUTO;
1579 } else {
1580 goto format_error;
1581 }
1582 }
1583 /*
1584 * Parse the margin.
1585 */
1586 format_modifier = "margin";
1587 if ((p=strstr(format," margin"))) {
1588 p += 7;
1589 SKIP_WHITE(p);
1590 if (!p) goto format_error;
1591 FIND_EQUAL(p);
1592 if (!p) goto format_error;
1593 p++; /* Skip the '=' */
1594 SKIP_WHITE(p);
1595 if (!p) goto error;
1596 if (sscanf(p,"%f",&g) == 1) {
1597 spec->page_margin = g;
1598 } else {
1599 goto format_error;
1600 }
1601 }
1602 /*
1603 * Parse the width image dimensioning spec where width is in inches
1604 * and the width in this case means the dimension of the image that
1605 * goes across the screen. Width indicates a resolution in both
1606 * height and width (to keep the aspect ratio the same).
1607 * This option will cause the image's width as printed to be the
1608 * given number of inches.
1609 */
1610 format_modifier = "width";
1611 if ((p=strstr(format," width"))) {
1612 p += 6;
1613 SKIP_WHITE(p);
1614 if (!p) goto format_error;
1615 FIND_EQUAL(p);
1616 if (!p) goto format_error;
1617 p++; /* Skip the '=' */
1618 SKIP_WHITE(p);
1619 if (!p || (sscanf(p,"%f",&width) != 1)) {
1620 goto format_error;
1621 } else if (width == 0) {
1622 DXErrorGoto(ERROR_BAD_PARAMETER,
1623 "PostScript 'width' must be non-zero");
1624 }
1625 width_parsed = 1;
1626 spec->height_dpi = spec->width_dpi = spec->image_width / width;
1627 if (dpi_parsed)
1628 DXWarning(
1629 "'width' overrides 'dpi' PostScript format modifier");
1630 }
1631 /*
1632 * Parse the height image dimensioning spec where height is in inches
1633 * and the height in this case means the dimension of the image that
1634 * goes up and down the screen. If 'width' was not already given
1635 * then use the same dpi in the width directoin as the height (i.e.
1636 * keep the same aspect ratio).
1637 * This option will cause the image's height as printed to be the
1638 * given number of inches.
1639 */
1640 format_modifier = "height";
1641 if ((p=strstr(format," height"))) {
1642 p += 7;
1643 SKIP_WHITE(p);
1644 if (!p) goto format_error;
1645 FIND_EQUAL(p);
1646 if (!p) goto format_error;
1647 p++; /* Skip the '=' */
1648 SKIP_WHITE(p);
1649 if (!p || (sscanf(p,"%f",&height) != 1)) {
1650 goto format_error;
1651 } else if (height == 0) {
1652 DXErrorGoto(ERROR_BAD_PARAMETER,
1653 "PostScript 'height' must be non-zero");
1654 }
1655 spec->height_dpi = spec->image_height / height;
1656 if (!width_parsed) {
1657 spec->width_dpi = spec->height_dpi;
1658 if (dpi_parsed)
1659 DXWarning(
1660 "'height' overrides 'dpi' PostScript format modifier");
1661 }
1662 }
1663
1664 return OK;
1665
1666 format_error:
1667 DXSetError(ERROR_BAD_PARAMETER,
1668 "PostScript format modifier '%s' has incorrect format",
1669 format_modifier);
1670 error:
1671 return ERROR;
1672 }
1673
1674 static Error
put_miff_header(FILE * fout,char * filename,int frame,struct ps_spec * spec,int imageType,int nframes)1675 put_miff_header(FILE *fout, char *filename, int frame, struct ps_spec *spec, int imageType, int nframes)
1676 {
1677 const time_t t = time(0);
1678 char *tod = ctime((const time_t *)&t);
1679 int major, minor, micro;
1680
1681 if (fprintf(fout, "id=ImageMagick\n") <= 0) goto error;
1682 if (imageType != MAPPED_COLOR) {
1683 if (fprintf(fout, "class=DirectClass\n") <= 0) goto error;
1684 } else {
1685 if (fprintf(fout, "class=PseudoClass colors=256\n") <= 0) goto error;
1686 }
1687 /* Change gamma in the pixels themselves */
1688 #if 0
1689 if (spec->gamma != 1) {
1690 if (fprintf(fout, "gamma=%08.4f\n", spec->gamma) <= 0) goto error;
1691 }
1692 #endif
1693 if (fprintf(fout, "compression=RunlengthEncoded\n") <= 0) goto error;
1694 if (fprintf(fout, "columns=%d rows=%d depth=8\n",
1695 spec->image_width, spec->image_height) <= 0) goto error;
1696 if (fprintf(fout, "scene=%d\n", frame) <= 0) goto error;
1697 DXVersion(&major, &minor, µ);
1698 if (fprintf(fout, "{\nCreated by IBM Data Explorer %d.%d.%d",
1699 major,minor,micro) <= 0) goto error;
1700 if (fprintf(fout, " Date: %s", tod) <= 0) goto error;
1701 if (frame == 0) {
1702 if (fprintf(fout, "DO NOT ALTER NEXT LINE\n") <= 0) goto error;
1703 if (fprintf(fout, NSCENES_STRING) <= 0) goto error;
1704 if (fprintf(fout, "%06d\n", nframes) <= 0) goto error;
1705 }
1706 if (fprintf(fout, DATASIZE_STRING) <= 0) goto error;
1707 spec->fptr = ftell(fout);
1708 if (fprintf(fout, "%08d\n",0) <= 0) goto error;
1709 if (fprintf(fout, "}\n:\n") <= 0) goto error;
1710
1711 return OK;
1712
1713 error:
1714 DXErrorReturn(ERROR_DATA_INVALID, "Can't write miff file.");
1715 }
1716
1717 #define STAT_OK 0
1718 #define STAT_DONE 1
1719 #define STAT_COMPLETE 2
1720 #define STAT_ERROR 4
1721
1722 static int
get_token(char * b,char * t,char * v)1723 get_token(char *b, char *t, char *v)
1724 {
1725 int l;
1726 int p, q, r;
1727
1728 *t = *v = '\0';
1729 l = strlen(b);
1730 if (!l)
1731 return STAT_DONE;
1732 for (p = 0; p<l && isspace(b[p]); p++)
1733 ;
1734 if (b[p] == ':')
1735 return STAT_COMPLETE;
1736 if (p == l)
1737 return STAT_DONE;
1738 for (q = p+1; q<l && !isspace(b[q]) && b[q] != '='; q++)
1739 ;
1740 if (b[q] != '=')
1741 return STAT_ERROR;
1742 strncpy(t, &b[p], (q-p));
1743 t[q-p] = '\0';
1744 for (q++; q<l && isspace(b[q]); q++)
1745 ;
1746 if (q == l)
1747 return STAT_ERROR;
1748 for (r = q; r<l && !isspace(b[r]); r++)
1749 ;
1750 strncpy(v, &b[q], (r-q));
1751 v[r-q] = '\0';
1752 memmove(b, &b[r], l-r+1);
1753
1754 return STAT_OK;
1755 }
1756
1757
1758 static Error
read_miff_header(FILE * fin,int * frame,struct ps_spec * spec,int * imageType,int * nframes)1759 read_miff_header(FILE *fin, int *frame, struct ps_spec *spec, int *imageType, int *nframes)
1760 {
1761
1762 char buff[BUFFSIZE];
1763 char token[128], value[128];
1764 int found_frames = 0;
1765 int found_data = 0;
1766 int status = STAT_OK;
1767 int tmp;
1768
1769 for (;;) {
1770 if (!fgets(buff, BUFFSIZE, fin)) goto error;
1771 if (strstr(buff, "{")) {
1772 for (;;) {
1773 if (!fgets(buff, BUFFSIZE, fin)) goto error;
1774 if (strstr(buff, "}"))
1775 break;
1776 if (!found_frames && (1 == sscanf(buff, "nscenes=%d", &tmp))) {
1777 found_frames = 1;
1778 *nframes = tmp;
1779 }
1780 if (!found_data && (1 == sscanf(buff, "data_size=%d", &tmp))) {
1781 found_data = 1;
1782 spec->data_size = tmp;
1783 }
1784 }
1785 continue;
1786 }
1787 for (status = get_token(buff, token, value); status == STAT_OK;
1788 status = get_token(buff, token, value)) {
1789 if (!strcmp(token, "class")) {
1790 if (strcmp(value, "DirectClass")) {
1791 DXSetError(ERROR_DATA_INVALID, "MIFF: class=%s is not supported", value);
1792 goto error;
1793 }
1794 } else if (!strcmp(token, "columns")) {
1795 if (1 != sscanf(value, "%d", &spec->image_width)) {
1796 DXSetError(ERROR_DATA_INVALID, "MIFF: bad columns value, %s", value);
1797 goto error;
1798 }
1799 } else if (!strcmp(token, "compression")) {
1800 if (strcmp(value, "RunlengthEncoded")) {
1801 DXSetError(ERROR_DATA_INVALID, "MIFF: compression=%s is not supported", value);
1802 goto error;
1803 }
1804 } else if (!strcmp(token, "rows")) {
1805 if (1 != sscanf(value, "%d", &spec->image_height)) {
1806 DXSetError(ERROR_DATA_INVALID, "MIFF: bad rows value, %s", value);
1807 goto error;
1808 }
1809 } else if (!strcmp(token, "scene")) {
1810 if (1 != sscanf(value, "%d", frame)) {
1811 DXSetError(ERROR_DATA_INVALID, "MIFF: bad scene value, %s", value);
1812 goto error;
1813 }
1814 }
1815 }
1816 if (status == STAT_COMPLETE)
1817 break;
1818 if (status == STAT_ERROR) {
1819 DXSetError(ERROR_DATA_INVALID, "MIFF: error parsing line %s", buff);
1820 goto error;
1821 }
1822 }
1823
1824 return OK;
1825
1826 error:
1827 return ERROR;
1828 }
1829
_dxf_ReadImageSizesMIFF(char * name,int startframe,SizeData * data,int * use_numerics,int ext_sel,int * multiples)1830 SizeData * _dxf_ReadImageSizesMIFF(char *name,
1831 int startframe,
1832 SizeData *data,
1833 int *use_numerics,
1834 int ext_sel,
1835 int *multiples)
1836 {
1837 FILE *fin;
1838 struct ps_spec spec;
1839 int imgtype;
1840 int nframes;
1841
1842 memset(&spec, 0, sizeof(spec));
1843 if (NULL == (fin = fopen(name, "r")))
1844 goto error;
1845 if (ERROR == read_miff_header(fin, &startframe, &spec, &imgtype, &nframes))
1846 goto error;
1847 fclose(fin);
1848 data->height = spec.image_height;
1849 data->width = spec.image_width;
1850 *multiples = ((nframes>0)?1:0);
1851 data->startframe = 0;
1852 data->endframe = nframes-1;
1853 *use_numerics = 0;
1854
1855 return data;
1856
1857 error:
1858 return ERROR;
1859 }
1860
1861 static Error
miff_out_flc(FILE * fout,Pointer pixels,RGBColor * map,int imageType,struct ps_spec * spec)1862 miff_out_flc(FILE *fout, Pointer pixels,
1863 RGBColor *map, int imageType, struct ps_spec *spec)
1864 {
1865 int i, j, P;
1866 ubyte *encbuff, *RGBbuff, *RGBptr;
1867 int encbuff_size, RGBbuff_size;
1868 int byte_count;
1869 ubyte gamma_table[256];
1870
1871 spec->compress = DO_COMPRESSION;
1872
1873 _dxf_make_gamma_table(gamma_table, spec->gamma);
1874
1875 RGBbuff_size = spec->image_width*3;
1876 RGBbuff = DXAllocate(RGBbuff_size);
1877
1878 /* This is a worst-case row buffer size for no runs */
1879 encbuff_size = RGBbuff_size*2;
1880 /* now add some spare */
1881 encbuff_size += 100;
1882 encbuff = DXAllocate(encbuff_size);
1883
1884 if (imageType == FLOAT_COLOR)
1885 {
1886 RGBColor *fpixels = (RGBColor *)pixels;
1887 fpixels += spec->image_width*(spec->image_height-1);
1888 for (i=0; i<spec->image_height; i++) {
1889 for (j=0, RGBptr = RGBbuff; j<spec->image_width; j++, fpixels++) {
1890 float r = fpixels->r * 255;
1891 float g = fpixels->g * 255;
1892 float b = fpixels->b * 255;
1893 *RGBptr++ = gamma_table[CLAMP(r)];
1894 *RGBptr++ = gamma_table[CLAMP(g)];
1895 *RGBptr++ = gamma_table[CLAMP(b)];
1896 }
1897 byte_count = 0;
1898 build_rle_row(RGBbuff, spec->image_width, 3,
1899 spec->compress, encbuff, &byte_count, RLE_BINARY, RLE_COUNT_POST, RLE_STUPID);
1900 if (fwrite(encbuff, sizeof(ubyte), byte_count, fout) != byte_count)
1901 goto error;
1902 spec->data_size += byte_count;
1903 fpixels -= 2*spec->image_width;
1904
1905 }
1906 }
1907 else if (imageType == UBYTE_COLOR)
1908 {
1909 RGBByteColor *upixels = (RGBByteColor *)pixels;
1910 upixels += spec->image_width*(spec->image_height-1);
1911
1912 for (i=0; i<spec->image_height; i++) {
1913 for (j=0, RGBptr = RGBbuff; j<spec->image_width; j++, upixels++) {
1914 *RGBptr++ = gamma_table[upixels->r];
1915 *RGBptr++ = gamma_table[upixels->g];
1916 *RGBptr++ = gamma_table[upixels->b];
1917 }
1918 byte_count = 0;
1919 build_rle_row(RGBbuff, spec->image_width, 3,
1920 spec->compress, encbuff, &byte_count, RLE_BINARY, RLE_COUNT_POST, RLE_STUPID);
1921 if (fwrite(encbuff, sizeof(ubyte), byte_count, fout) != byte_count)
1922 goto error;
1923 spec->data_size += byte_count;
1924 upixels -= 2*spec->image_width;
1925 }
1926 }
1927 else
1928 {
1929 ubyte *upixels = (ubyte *)pixels;
1930 ubyte cmap[256*3];
1931 for (i=0, RGBptr = cmap; i<256; i++) {
1932 float r = map[i].r * 255;
1933 float g = map[i].g * 255;
1934 float b = map[i].b * 255;
1935 *RGBptr++ = gamma_table[CLAMP(r)];
1936 *RGBptr++ = gamma_table[CLAMP(g)];
1937 *RGBptr++ = gamma_table[CLAMP(b)];
1938 }
1939
1940 if (fwrite(cmap, sizeof(ubyte), 256*3, fout) != 256*3)
1941 goto error;
1942
1943 spec->data_size += 256*3;
1944 upixels += spec->image_width*(spec->image_height-1);
1945 for (i=0; i<spec->image_height; i++) {
1946 byte_count = 0;
1947 build_rle_row(upixels, spec->image_width, 1,
1948 spec->compress, encbuff, &byte_count, RLE_BINARY, RLE_COUNT_POST, RLE_STUPID);
1949 if (fwrite(encbuff, sizeof(ubyte), byte_count, fout) != byte_count)
1950 goto error;
1951 spec->data_size += byte_count;
1952 upixels -= spec->image_width;
1953 }
1954 }
1955
1956 DXFree(RGBbuff);
1957 DXFree(encbuff);
1958 return OK;
1959 error:
1960 DXFree(RGBbuff);
1961 DXFree(encbuff);
1962 DXErrorReturn(ERROR_DATA_INVALID, "Can't write miff pixel data.");
1963 }
1964
1965 Error
_dxf_write_miff(RWImageArgs * iargs)1966 _dxf_write_miff(RWImageArgs *iargs)
1967 {
1968 Error e;
1969 e = output_miff(iargs);
1970 return e;
1971 }
1972
1973 static Error
output_miff(RWImageArgs * iargs)1974 output_miff(RWImageArgs *iargs)
1975 {
1976 char imagefilename[MAX_IMAGE_NAMELEN];
1977 int firstframe, lastframe, i, series;
1978 int frames, deleteable = 0;
1979 struct ps_spec page_spec;
1980 Pointer pixels;
1981 FILE *fp = NULL;
1982 Array colors, color_map;
1983 RGBColor *map = NULL;
1984 int imageType=0;
1985 Type type;
1986 int rank, shape[32];
1987 char buff[BUFFSIZE];
1988 char *seqptr;
1989 long fptr = 0;
1990 int init_nframes = 0;
1991
1992 SizeData image_sizes; /* Values as found in the image object itself */
1993 Field img = NULL;
1994
1995 if (iargs->adasd)
1996 DXErrorGoto(ERROR_NOT_IMPLEMENTED,
1997 "MIFF format not supported on disk array");
1998
1999 series = iargs->imgclass == CLASS_SERIES;
2000
2001 if ( !_dxf_GetImageAttributes ( (Object)iargs->image, &image_sizes ) )
2002 goto error;
2003
2004 /*
2005 * Always write all frames of a series.
2006 */
2007 frames = (image_sizes.endframe - image_sizes.startframe + 1);
2008 firstframe = image_sizes.startframe;
2009 lastframe = image_sizes.endframe;
2010 page_spec.image_height = image_sizes.height;
2011 page_spec.image_width = image_sizes.width;
2012 page_spec.gamma = 2.0;
2013 if (iargs->format) {
2014 if (!parse_format(iargs->format,&page_spec))
2015 goto error;
2016 }
2017
2018 /*
2019 * Attempt to open image file and position to start of frame(s).
2020 */
2021 if (iargs->pipe == NULL) {
2022 /*
2023 * Create an appropriate file name.
2024 */
2025 if (!_dxf_BuildImageFileName(imagefilename,MAX_IMAGE_NAMELEN,
2026 iargs->basename, iargs->imgtyp,iargs->startframe,0))
2027 goto error;
2028 /*
2029 * Need to open the file if it exists, and find number of scenes present
2030 * as specified in the first header.
2031 * Then save pointer to this number string for later update.
2032 */
2033 if ((fp=fopen(imagefilename, "r+"))) {
2034 for ( ; ; ) {
2035 fptr = ftell(fp);
2036 if (!fgets(buff, BUFFSIZE, fp)) goto error;
2037 if ((seqptr=strstr(buff, NSCENES_STRING))) break;
2038 }
2039 seqptr += strlen(NSCENES_STRING);
2040 if (!sscanf(seqptr,"%d", &init_nframes)) goto error;
2041 if (fseek(fp, fptr, SEEK_SET)) goto error;
2042 if (fprintf(fp, NSCENES_STRING) < 0) goto error;
2043 if (fprintf(fp, "%06d\n", init_nframes+frames) < 0) goto error;
2044 if (fseek(fp, 0, SEEK_END)) goto error;
2045 fptr = ftell(fp);
2046 fclose(fp);
2047 }
2048
2049 if (!fptr)
2050 {
2051 if ( (fp = fopen (imagefilename, "w+" )) == 0 )
2052 ErrorGotoPlus1 ( ERROR_DATA_INVALID,
2053 "Can't open image file (%s)", imagefilename );
2054 } else {
2055 if ( (fp = fopen (imagefilename, "r+" )) == 0 )
2056 ErrorGotoPlus1 ( ERROR_DATA_INVALID,
2057 "Can't open image file (%s)", imagefilename );
2058 fseek(fp, fptr, SEEK_SET);
2059 }
2060
2061 } else {
2062 strcpy(imagefilename,"stdout");
2063 fp = iargs->pipe;
2064 }
2065
2066 img = iargs->image;
2067 for (i=firstframe ; i<=lastframe ; i++)
2068 {
2069 if (series) {
2070 if (deleteable) DXDelete((Object)img);
2071 img = _dxf_GetFlatSeriesImage((Series)iargs->image,i,
2072 page_spec.image_width,page_spec.image_height,
2073 &deleteable);
2074 if (!img)
2075 goto error;
2076 }
2077
2078 colors = (Array)DXGetComponentValue(img, "colors");
2079 if (! colors)
2080 {
2081 DXSetError(ERROR_DATA_INVALID,
2082 "image does not contain colors component");
2083 goto error;
2084 }
2085
2086 DXGetArrayInfo(colors, NULL, &type, NULL, &rank, shape);
2087
2088 if (type == TYPE_FLOAT)
2089 {
2090 if (rank != 1 || shape[0] != 3)
2091 {
2092 DXSetError(ERROR_DATA_INVALID,
2093 "floating-point colors component must be 3-vector");
2094 goto error;
2095 }
2096
2097 imageType = FLOAT_COLOR;
2098 }
2099 else if (type == TYPE_UBYTE)
2100 {
2101 if (rank == 0 || (rank == 1 && shape[0] == 1))
2102 {
2103 color_map = (Array)DXGetComponentValue(img, "color map");
2104 if (! color_map)
2105 {
2106 DXSetError(ERROR_DATA_INVALID,
2107 "single-valued ubyte colors component requires a %s",
2108 "color map");
2109 goto error;
2110 }
2111
2112 DXGetArrayInfo(color_map, NULL, &type, NULL, &rank, shape);
2113
2114 if (type != TYPE_FLOAT || rank != 1 || shape[0] != 3)
2115 {
2116 DXSetError(ERROR_DATA_INVALID,
2117 "color map must be floating point 3-vectors");
2118 goto error;
2119 }
2120
2121 map = (RGBColor *)DXGetArrayData(color_map);
2122 imageType = MAPPED_COLOR;
2123 }
2124 else if (rank != 1 || shape[0] != 3)
2125 {
2126 DXSetError(ERROR_DATA_INVALID,
2127 "unsigned byte colors component must be either single %s",
2128 "valued with a color map or 3-vectors");
2129 goto error;
2130 }
2131 else
2132 imageType = UBYTE_COLOR;;
2133 }
2134
2135 if (!(pixels = DXGetArrayData(colors)))
2136 goto error;
2137
2138 /*
2139 * Write out the miff header
2140 */
2141 if (!put_miff_header(fp, imagefilename, i+init_nframes, &page_spec, imageType, frames))
2142 goto bad_write;
2143
2144 /*
2145 * Write out the pixel data
2146 */
2147 page_spec.data_size = 0;
2148 if (!miff_out_flc(fp, pixels, map, imageType, &page_spec))
2149 goto bad_write;
2150 fptr = ftell(fp);
2151 if (fseek(fp, page_spec.fptr, SEEK_SET))
2152 goto error;
2153 if (fprintf(fp, "%08d", page_spec.data_size) < 0)
2154 goto error;
2155 if (fseek(fp, fptr, SEEK_SET))
2156 goto error;
2157 }
2158
2159 if (fclose(fp) != 0)
2160 goto bad_write;
2161
2162 if (deleteable && img) DXDelete((Object)img);
2163
2164 return OK;
2165
2166 bad_write:
2167 if ( iargs->pipe == NULL )
2168 DXErrorGoto
2169 ( ERROR_DATA_INVALID,
2170 "Can't write miff file." )
2171 else
2172 DXErrorGoto
2173 ( ERROR_BAD_PARAMETER,
2174 "Can't send image with specified command." );
2175
2176 error:
2177 if ( fp ) fclose(fp);
2178 if (deleteable && img) DXDelete((Object)img);
2179 return ERROR;
2180 }
2181
_dxf_InputMIFF(FILE ** fh,int width,int height,char * name,int relframe,int delayed,char * colortype)2182 Field _dxf_InputMIFF (FILE **fh, int width, int height, char *name,
2183 int relframe, int delayed, char *colortype)
2184 {
2185 int i;
2186 int frame, nframes;
2187 struct ps_spec page_spec;
2188 Pointer pixels;
2189 int imageType;
2190 Type type;
2191 int rank, shape[32];
2192 Field image = NULL;
2193 Array colorsArray;
2194 int npix = 0;
2195 int tot_pix;
2196 ubyte *pixptr;
2197
2198 struct {
2199 ubyte rgb[3];
2200 ubyte count;
2201 }rle_entry;
2202
2203 if (!*fh)
2204 if (NULL == (*fh = fopen(name, "r")))
2205 goto error;
2206
2207 read_miff_header(*fh, &frame, &page_spec, &imageType, &nframes);
2208 image = DXMakeImageFormat(width, height, "BYTE");
2209 if (!image)
2210 goto error;
2211
2212 tot_pix = width*height;
2213 colorsArray = (Array)DXGetComponentValue(image, "colors");
2214 DXGetArrayInfo(colorsArray, NULL, &type, NULL, &rank, shape);
2215 pixels = DXGetArrayData(colorsArray);
2216 pixptr = (ubyte *)pixels;
2217 pixptr += width*(height-1)*3*sizeof(ubyte);
2218 do {
2219 if (fread(&rle_entry, sizeof(rle_entry), 1, *fh) < 1)
2220 goto error;
2221 for (i=0; i<rle_entry.count+1; i++) {
2222 memcpy(pixptr, rle_entry.rgb, sizeof(rle_entry.rgb));
2223 pixptr += 3;
2224 }
2225 npix += rle_entry.count+1;
2226 if (npix % width == 0)
2227 pixptr -= 2*width*3*sizeof(ubyte);
2228 } while (npix < tot_pix);
2229
2230 return image;
2231
2232
2233 error:
2234 if (NULL != *fh)
2235 fclose(*fh);
2236 return ERROR;
2237 }
2238