ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/d48c.c
Revision: 1.5
Committed: Sun Mar 28 20:33:13 2004 UTC (20 years ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R6P1, rad3R6
Changes since 1.4: +59 -29 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: d48c.c,v 1.4 2003/10/27 10:24:51 schorsch Exp $";
3 #endif
4 /*
5 * d48c.c - driver for dicomed D48 film recorder w/ color optics.
6 *
7 * 3/26/87
8 */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <signal.h>
13
14 #include "paths.h"
15 #include "rterror.h"
16 #include "color.h"
17
18
19 #define HSIZE 4096 /* device width */
20 #define VSIZE 4096 /* device height */
21
22 #define MAXMULT 15 /* maximum element size */
23
24 /* dicomed commands */
25 #define O_ECS 0 /* encoded command select */
26 #define O_CONF 03400 /* configuration code */
27 #define O_FES 020000 /* function element select */
28 #define O_VPA 040000 /* vector or position absolute */
29 #define O_ICS 0100000 /* initial condition select */
30 #define O_PES 0120000 /* point element select */
31
32 /* ECS commands */
33 #define ECS_FA 07 /* film advance */
34 #define ECS_RED 011 /* select red filter */
35 #define ECS_GRN 012 /* select green filter */
36 #define ECS_BLU 014 /* select blue filter */
37 #define ECS_NEU 017 /* select neutral filter */
38 #define ECS_RAS 020 /* select raster mode */
39 #define ECS_COL 022 /* select color mode */
40 #define ECS_BW 023 /* select black and white mode */
41 #define ECS_BT 024 /* bypass translation tables */
42
43 /* FES functions */
44 #define FES_RE 030000 /* raster element */
45 #define FES_RL 0170000 /* run length */
46
47 /* ICS fields */
48 #define ICS_HVINT 040 /* interchange h and v axes */
49 #define ICS_VREV 0100 /* reverse v axis direction */
50 #define ICS_HREV 0200 /* reverse h axis direction */
51
52 int nrows; /* number of rows for output */
53 int ncols; /* number of columns for output */
54
55 int mult; /* number of h/v points per elem. */
56
57 int hhome; /* offset for h */
58 int vhome; /* offset for v */
59
60 /* dicomed configurations */
61 #define C_POLAROID 0 /* polaroid print */
62 #define C_35FRES 1 /* 35mm full resolution */
63 #define C_35FFRA 2 /* 35mm full frame */
64 #define C_SHEET 3 /* 4X5 sheet film */
65
66 #define NCONF 4 /* number of configurations */
67
68 struct config {
69 char *name; /* configuration name */
70 int ccode; /* configuration code */
71 int icsfield; /* initial condition select */
72 int hbeg, vbeg; /* coord. origin */
73 int hsiz, vsiz; /* dimensions */
74 } ctab[NCONF] = {
75 { "polaroid", 11, ICS_HVINT|ICS_VREV, 0, 0, 4096, 4096 },
76 { "35r", 5, 0, 0, 0, 4096, 4096 },
77 { "35f", 7, 0, 39, 692, 4018, 2712 },
78 { "sheet", 10, ICS_HVINT|ICS_VREV, 0, 0, 4096, 4096 },
79 };
80
81 #define NEU 3 /* neutral color */
82
83 struct filter {
84 float cv[3]; /* filter color vector */
85 char *fn; /* file name for this color */
86 FILE *fp; /* stream for this color */
87 } ftab[4] = {
88 { {1.0, 0.0, 0.0}, NULL, NULL }, /* red */
89 { {0.0, 1.0, 0.0}, NULL, NULL }, /* green */
90 { {0.0, 0.0, 1.0}, NULL, NULL }, /* blue */
91 { {0.3, 0.59, 0.11}, NULL, NULL }, /* neutral */
92 };
93
94 #define f_val(col,f) ( colval(col,0)*ftab[f].cv[0] + \
95 colval(col,1)*ftab[f].cv[1] + \
96 colval(col,2)*ftab[f].cv[2] )
97
98 float neumap[] = { /* neutral map, log w/ E6 */
99 .0, .0,
100 .0004, .059,
101 .0008, .122,
102 .0018, .184,
103 .0033, .247,
104 .0061, .310,
105 .0119, .373,
106 .0202, .435,
107 .0373, .498,
108 .065, .561,
109 .113, .624,
110 .199, .686,
111 .300, .749,
112 .432, .812,
113 .596, .875,
114 .767, .937,
115 1.000, 1.000,
116 };
117
118
119 int docolor = 1; /* color? */
120
121 int cftype = C_35FFRA; /* configuration type */
122
123 char *progname; /* program name */
124
125 static void settype(char *cname);
126 static void dofile(char *fname);
127 static void d_init(void);
128 static void scanout(COLOR *scan, int y);
129 static void d_done(void);
130 static void runlength(COLOR *scan, int f);
131 static double mapfilter(COLOR col, int f);
132 static void transfer(FILE *fin, FILE *fout);
133
134
135 int
136 main(
137 int argc,
138 char *argv[]
139 )
140 {
141 int i;
142
143 if (signal(SIGINT, quit) == SIG_IGN)
144 signal(SIGINT, SIG_IGN);
145 #ifdef SIGHUP
146 if (signal(SIGHUP, quit) == SIG_IGN)
147 signal(SIGINT, SIG_IGN);
148 #endif
149 signal(SIGTERM, quit);
150 #ifdef SIGPIPE
151 signal(SIGPIPE, quit);
152 #endif
153 #ifdef SIGXCPU
154 signal(SIGXCPU, quit);
155 #endif
156 #ifdef SIGXFSZ
157 signal(SIGXFSZ, quit);
158 #endif
159
160 progname = argv[0];
161
162 for (i = 1; i < argc && argv[i][0] == '-'; i++)
163 switch (argv[i][1]) {
164 case 'c': /* color */
165 docolor = 1;
166 break;
167 case 'b': /* black and white */
168 docolor = 0;
169 break;
170 case 't': /* type */
171 settype(argv[++i]);
172 break;
173 default:
174 fprintf(stderr, "%s: Unknown option: %s\n",
175 progname, argv[i]);
176 quit(1);
177 break;
178 }
179
180 if (i < argc)
181 for ( ; i < argc; i++)
182 dofile(argv[i]);
183 else
184 dofile(NULL);
185
186 quit(0);
187 return 0; /* pro forma return */
188 }
189
190
191 static void
192 settype( /* set configuration type */
193 char *cname
194 )
195 {
196 for (cftype = 0; cftype < NCONF; cftype++)
197 if (!strcmp(cname, ctab[cftype].name))
198 return;
199
200 fprintf(stderr, "%s: Unknown type: %s\n", progname, cname);
201 quit(1);
202 }
203
204
205 void
206 quit(int code) /* quit program */
207 {
208 int i;
209
210 for (i = 0; i < 4; i++)
211 if (ftab[i].fn != NULL)
212 unlink(ftab[i].fn);
213 exit(code);
214 }
215
216
217 static void
218 dofile( /* convert file to dicomed format */
219 char *fname
220 )
221 {
222 FILE *fin;
223 char sbuf[128];
224 COLOR scanline[HSIZE];
225 int i;
226
227 if (fname == NULL) {
228 fin = stdin;
229 fname = "<stdin>";
230 } else if ((fin = fopen(fname, "r")) == NULL) {
231 fprintf(stderr, "%s: Cannot open: %s\n", progname, fname);
232 quit(1);
233 }
234 /* discard header */
235 while (fgets(sbuf, sizeof(sbuf), fin) != NULL && sbuf[0] != '\n')
236 ;
237 /* get picture size */
238 if (fgets(sbuf, sizeof(sbuf), fin) == NULL ||
239 sscanf(sbuf, "-Y %d +X %d\n", &nrows, &ncols) != 2) {
240 fprintf(stderr, "%s: Bad picture size: %s\n", progname, fname);
241 quit(1);
242 }
243
244 mult = ctab[cftype].hsiz / ncols;
245 if (ctab[cftype].vsiz / nrows < mult)
246 mult = ctab[cftype].vsiz / nrows;
247
248 if (mult < 1) {
249 fprintf(stderr, "%s: Resolution mismatch: %s\n",
250 progname, fname);
251 quit(1);
252 }
253 if (mult > MAXMULT)
254 mult = MAXMULT; /* maximum element size */
255
256 hhome = ctab[cftype].hbeg + (ctab[cftype].hsiz - ncols*mult)/2;
257 vhome = ctab[cftype].vbeg + (ctab[cftype].vsiz - nrows*mult)/2;
258
259 d_init();
260
261 for (i = nrows-1; i >= 0; i--) {
262 if (freadscan(scanline, ncols, fin) < 0) {
263 fprintf(stderr, "%s: Read error in row %d: %s\n",
264 progname, i, fname);
265 quit(1);
266 }
267 scanout(scanline, i);
268 }
269
270 d_done();
271
272 fclose(fin);
273 }
274
275
276 static void
277 d_init(void) /* set up dicomed, files */
278 {
279 //char *mktemp();
280 /* initial condition select */
281 putw(O_ICS|ctab[cftype].icsfield, stdout);
282 /* configuration code */
283 putw(O_CONF|ctab[cftype].ccode, stdout);
284 /* select raster mode */
285 putw(O_ECS|ECS_RAS, stdout);
286 /* color or black and white */
287 putw(O_ECS|(docolor?ECS_COL:ECS_BW), stdout);
288 /* bypass translation tables */
289 putw(O_ECS|ECS_BT, stdout);
290 /* point element select */
291 putw(O_PES|mult<<9|010, stdout);
292 putw(mult<<9|010, stdout);
293 putw(mult<<4|mult, stdout);
294
295 if (docolor) { /* color output */
296 /* set up red file */
297 if (ftab[RED].fn == NULL)
298 ftab[RED].fn = mktemp(TEMPLATE);
299 if ((ftab[RED].fp = fopen(ftab[RED].fn, "w+")) == NULL) {
300 fprintf(stderr, "%s: Cannot open: %s\n",
301 progname, ftab[RED].fn);
302 quit(1);
303 }
304 putw(O_ECS|ECS_RED, ftab[RED].fp); /* red filter */
305 putw(O_VPA, ftab[RED].fp); /* home */
306 putw(hhome<<3, ftab[RED].fp);
307 putw(vhome<<3, ftab[RED].fp);
308 /* set up green file */
309 ftab[GRN].fp = stdout;
310 putw(O_ECS|ECS_GRN, ftab[GRN].fp); /* green filter */
311 putw(O_VPA, ftab[GRN].fp); /* home */
312 putw(hhome<<3, ftab[GRN].fp);
313 putw(vhome<<3, ftab[GRN].fp);
314 /* set up blue file */
315 if (ftab[BLU].fn == NULL)
316 ftab[BLU].fn = mktemp(TEMPLATE);
317 if ((ftab[BLU].fp = fopen(ftab[BLU].fn, "w+")) == NULL) {
318 fprintf(stderr, "%s: Cannot open: %s\n",
319 progname, ftab[BLU].fn);
320 quit(1);
321 }
322 putw(O_ECS|ECS_BLU, ftab[BLU].fp); /* blue filter */
323 putw(O_VPA, ftab[BLU].fp); /* home */
324 putw(hhome<<3, ftab[BLU].fp);
325 putw(vhome<<3, ftab[BLU].fp);
326
327 } else { /* black and white */
328 ftab[NEU].fp = stdout;
329 putw(O_ECS|ECS_NEU, ftab[NEU].fp); /* neutral filter */
330 putw(O_VPA, ftab[NEU].fp); /* home */
331 putw(hhome<<3, ftab[NEU].fp);
332 putw(vhome<<3, ftab[NEU].fp);
333 }
334 }
335
336
337 static void
338 scanout( /* output scan line */
339 COLOR *scan,
340 int y
341 )
342 {
343 int i;
344 /* uses horiz. flyback */
345 if (docolor)
346 for (i = 0; i < 3; i++)
347 runlength(scan, i);
348 else
349 runlength(scan, NEU);
350 }
351
352
353 static void
354 d_done(void) /* flush files, finish frame */
355 {
356 if (docolor) {
357 transfer(ftab[RED].fp, stdout);
358 transfer(ftab[BLU].fp, stdout);
359 }
360 putw(O_ECS|ECS_FA, stdout); /* film advance */
361 fflush(stdout);
362 if (ferror(stdout)) {
363 fprintf(stderr, "%s: Write error: <stdout>\n", progname);
364 quit(1);
365 }
366 }
367
368
369 static void
370 runlength( /* do scanline for filter f */
371 COLOR *scan,
372 int f
373 )
374 {
375 //double mapfilter();
376 BYTE ebuf[2*HSIZE];
377 register int j;
378 register BYTE *ep;
379
380 ep = ebuf;
381 ep[0] = mapfilter(scan[0], f) * 255.9999;
382 ep[1] = 1;
383 ep += 2;
384 for (j = 1; j < ncols; j++) {
385 ep[0] = mapfilter(scan[j], f) * 255.9999;
386 if (ep[0] == ep[-2] && ep[-1] < 255)
387 ep[-1]++;
388 else {
389 ep[1] = 1;
390 ep += 2;
391 }
392 }
393 j = ep - ebuf;
394 putw(O_FES, ftab[f].fp);
395 putw(FES_RL|j>>1, ftab[f].fp);
396 for (ep = ebuf; j-- > 0; ep++)
397 putc(*ep, ftab[f].fp);
398
399 if (ferror(ftab[f].fp)) {
400 fprintf(stderr, "%s: Write error: %s\n", progname,
401 ftab[f].fn==NULL ? "<stdout>" : ftab[f].fn);
402 quit(1);
403 }
404 }
405
406
407 static double
408 mapfilter( /* map filter value */
409 COLOR col,
410 register int f
411 )
412 {
413 static float *mp[4] = {neumap, neumap, neumap, neumap};
414 double x, y;
415
416 y = f_val(col,f);
417
418 if (y >= 1.0)
419 return(1.0);
420
421 while (y >= mp[f][2])
422 mp[f] += 2;
423 while (y < mp[f][0])
424 mp[f] -= 2;
425
426 x = (y - mp[f][0]) / (mp[f][2] - mp[f][0]);
427
428 return((1.0-x)*mp[f][1] + x*mp[f][3]);
429 }
430
431
432 /* XXX replaces putw() from stdio.h. Do we really need this? */
433 int
434 putw( /* output a (short) word */
435 int w,
436 register FILE *fp
437 )
438 {
439 putc(w&0377, fp); /* in proper order! */
440 putc(w>>8, fp);
441 return 0;
442 }
443
444
445 static void
446 transfer( /* transfer fin contents to fout, close fin */
447 register FILE *fin,
448 register FILE *fout
449 )
450 {
451 register int c;
452
453 fseek(fin, 0L, 0); /* rewind input */
454
455 while ((c = getc(fin)) != EOF) /* transfer file */
456 putc(c, fout);
457
458 fclose(fin); /* close input */
459 }