ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/d48c.c
Revision: 1.3
Committed: Sat Feb 22 02:07:27 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R5
Changes since 1.2: +2 -4 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

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