ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/pcompos.c
Revision: 2.31
Committed: Tue Jun 6 19:13:00 2006 UTC (17 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.30: +13 -19 lines
Log Message:
Fixed long-standing inaccuracy of +/-t threshold options

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: pcompos.c,v 2.30 2005/05/25 04:44:26 greg Exp $";
3 #endif
4 /*
5 * pcompos.c - program to composite pictures.
6 *
7 * 6/30/87
8 */
9
10 #include <stdio.h>
11 #include <math.h>
12 #include <time.h>
13 #include <string.h>
14
15 #include "copyright.h"
16
17 #include "platform.h"
18 #include "rtprocess.h"
19 #include "rterror.h"
20 #include "color.h"
21 #include "resolu.h"
22
23 #define MAXFILE 512
24
25 #define HASMIN 1
26 #define HASMAX 2
27
28 /* output picture size */
29 int xsiz = 0;
30 int ysiz = 0;
31 /* input dimensions */
32 int xmin = 0;
33 int ymin = 0;
34 int xmax = 0;
35 int ymax = 0;
36
37 COLR bgcolr = BLKCOLR; /* background color */
38
39 int labelht = 24; /* label height */
40
41 int checkthresh = 0; /* check threshold value */
42
43 char StandardInput[] = "<stdin>";
44 char Command[] = "<Command>";
45 char Label[] = "<Label>";
46
47 char *progname;
48
49 struct {
50 char *name; /* file or command name */
51 FILE *fp; /* stream pointer */
52 int xres, yres; /* picture size */
53 int xloc, yloc; /* anchor point */
54 int flags; /* HASMIN, HASMAX */
55 double thmin, thmax; /* thresholds */
56 } input[MAXFILE]; /* our input files */
57
58 int nfile; /* number of files */
59
60 char ourfmt[LPICFMT+1] = PICFMT;
61 int wrongformat = 0;
62
63
64 static gethfunc tabputs;
65 static void compos(void);
66 static int cmpcolr(COLR c1, double lv2);
67 static FILE * lblopen(char *s, int *xp, int *yp);
68
69
70
71 static int
72 tabputs( /* print line preceded by a tab */
73 char *s,
74 void *p
75 )
76 {
77 char fmt[32];
78
79 if (isheadid(s))
80 return(0);
81 if (formatval(fmt, s)) {
82 if (globmatch(ourfmt, fmt)) {
83 wrongformat = 0;
84 strcpy(ourfmt, fmt);
85 } else
86 wrongformat = 1;
87 } else {
88 putc('\t', stdout);
89 fputs(s, stdout);
90 }
91 return(0);
92 }
93
94
95 int
96 main(
97 int argc,
98 char *argv[]
99 )
100 {
101 int ncolumns = 0;
102 int autolabel = 0;
103 int curcol = 0, x0 = 0, curx = 0, cury = 0, spacing = 0;
104 int xsgn, ysgn;
105 char *thislabel;
106 int an;
107 SET_DEFAULT_BINARY();
108 SET_FILE_BINARY(stdin);
109 SET_FILE_BINARY(stdout);
110 progname = argv[0];
111
112 for (an = 1; an < argc && argv[an][0] == '-'; an++)
113 switch (argv[an][1]) {
114 case 'x':
115 xsiz = atoi(argv[++an]);
116 break;
117 case 'y':
118 ysiz = atoi(argv[++an]);
119 break;
120 case 'b':
121 setcolr(bgcolr, atof(argv[an+1]),
122 atof(argv[an+2]),
123 atof(argv[an+3]));
124 an += 3;
125 break;
126 case 'a':
127 ncolumns = atoi(argv[++an]);
128 break;
129 case 's':
130 spacing = atoi(argv[++an]);
131 break;
132 case 'o':
133 curx = x0 = atoi(argv[++an]);
134 cury = atoi(argv[++an]);
135 break;
136 case 'l':
137 switch (argv[an][2]) {
138 case 'a':
139 autolabel++;
140 break;
141 case 'h':
142 labelht = atoi(argv[++an]);
143 break;
144 case '\0':
145 goto dofiles;
146 default:
147 goto userr;
148 }
149 break;
150 case '\0':
151 case 't':
152 goto dofiles;
153 default:
154 goto userr;
155 }
156 dofiles:
157 newheader("RADIANCE", stdout);
158 fputnow(stdout);
159 for (nfile = 0; an < argc; nfile++) {
160 if (nfile >= MAXFILE)
161 goto toomany;
162 thislabel = NULL;
163 input[nfile].flags = 0;
164 xsgn = ysgn = '-';
165 while (an < argc && (argv[an][0] == '-' || argv[an][0] == '+'
166 || argv[an][0] == '=')) {
167 switch (argv[an][1]) {
168 case 't':
169 checkthresh = 1;
170 if (argv[an][0] == '-') {
171 input[nfile].flags |= HASMIN;
172 input[nfile].thmin = atof(argv[an+1]);
173 } else if (argv[an][0] == '+') {
174 input[nfile].flags |= HASMAX;
175 input[nfile].thmax = atof(argv[an+1]);
176 } else
177 goto userr;
178 an++;
179 break;
180 case 'l':
181 if (strcmp(argv[an], "-l"))
182 goto userr;
183 thislabel = argv[++an];
184 break;
185 case '+':
186 case '-':
187 case '0':
188 if (argv[an][0] != '=')
189 goto userr;
190 xsgn = argv[an][1];
191 ysgn = argv[an][2];
192 if (ysgn != '+' && ysgn != '-' && ysgn != '0')
193 goto userr;
194 break;
195 case '\0':
196 if (argv[an][0] == '-')
197 goto getfile;
198 goto userr;
199 default:
200 goto userr;
201 }
202 an++;
203 }
204 getfile:
205 if (argc-an < (ncolumns ? 1 : 3))
206 goto userr;
207 if (autolabel && thislabel == NULL)
208 thislabel = argv[an];
209 if (!strcmp(argv[an], "-")) {
210 input[nfile].name = StandardInput;
211 input[nfile].fp = stdin;
212 } else {
213 if (argv[an][0] == '!') {
214 input[nfile].name = Command;
215 input[nfile].fp = popen(argv[an]+1, "r");
216 } else {
217 input[nfile].name = argv[an];
218 input[nfile].fp = fopen(argv[an], "r");
219 }
220 if (input[nfile].fp == NULL) {
221 perror(argv[an]);
222 quit(1);
223 }
224 }
225 an++;
226 /* get header */
227 printf("%s:\n", input[nfile].name);
228 getheader(input[nfile].fp, tabputs, NULL);
229 if (wrongformat) {
230 fprintf(stderr, "%s: incompatible input format\n",
231 input[nfile].name);
232 quit(1);
233 }
234 /* get picture size */
235 if (fgetresolu(&input[nfile].xres, &input[nfile].yres,
236 input[nfile].fp) < 0) {
237 fprintf(stderr, "%s: bad picture size\n",
238 input[nfile].name);
239 quit(1);
240 }
241 if (ncolumns > 0) {
242 if (curcol >= ncolumns) {
243 cury = ymax + spacing;
244 curx = x0;
245 curcol = 0;
246 }
247 input[nfile].xloc = curx;
248 input[nfile].yloc = cury;
249 curx += input[nfile].xres + spacing;
250 curcol++;
251 } else {
252 input[nfile].xloc = atoi(argv[an++]);
253 if (xsgn == '+')
254 input[nfile].xloc -= input[nfile].xres;
255 else if (xsgn == '0')
256 input[nfile].xloc -= input[nfile].xres/2;
257 input[nfile].yloc = atoi(argv[an++]);
258 if (ysgn == '+')
259 input[nfile].yloc -= input[nfile].yres;
260 else if (ysgn == '0')
261 input[nfile].yloc -= input[nfile].yres/2;
262 }
263 if (input[nfile].xloc < xmin)
264 xmin = input[nfile].xloc;
265 if (input[nfile].yloc < ymin)
266 ymin = input[nfile].yloc;
267 if (input[nfile].xloc+input[nfile].xres > xmax)
268 xmax = input[nfile].xloc+input[nfile].xres;
269 if (input[nfile].yloc+input[nfile].yres > ymax)
270 ymax = input[nfile].yloc+input[nfile].yres;
271 if (thislabel != NULL) {
272 if (++nfile >= MAXFILE)
273 goto toomany;
274 input[nfile].name = Label;
275 input[nfile].flags = 0;
276 input[nfile].xres = input[nfile-1].xres;
277 input[nfile].yres = labelht;
278 if ((input[nfile].fp = lblopen(thislabel,
279 &input[nfile].xres,
280 &input[nfile].yres)) == NULL)
281 goto labelerr;
282 input[nfile].xloc = input[nfile-1].xloc;
283 input[nfile].yloc = input[nfile-1].yloc +
284 input[nfile-1].yres-input[nfile].yres;
285 }
286 }
287 if (xsiz <= 0)
288 xsiz = xmax;
289 else if (xsiz > xmax)
290 xmax = xsiz;
291 if (ysiz <= 0)
292 ysiz = ymax;
293 else if (ysiz > ymax)
294 ymax = ysiz;
295 /* add new header info. */
296 printargs(argc, argv, stdout);
297 if (strcmp(ourfmt, PICFMT))
298 fputformat(ourfmt, stdout); /* print format if known */
299 putchar('\n');
300 fprtresolu(xsiz, ysiz, stdout);
301
302 compos();
303
304 quit(0);
305 userr:
306 fprintf(stderr,
307 "Usage: %s [-x xr][-y yr][-b r g b][-a n][-s p][-o x0 y0][-la][-lh h] ",
308 progname);
309 fprintf(stderr, "[-t min1][+t max1][-l lab][=SS] pic1 x1 y1 ..\n");
310 quit(1);
311 toomany:
312 fprintf(stderr, "%s: only %d files and labels allowed\n",
313 progname, MAXFILE);
314 quit(1);
315 labelerr:
316 fprintf(stderr, "%s: error opening label\n", progname);
317 quit(1);
318 return 1; /* pro forma return */
319 }
320
321
322 static void
323 compos(void) /* composite pictures */
324 {
325 COLR *scanin, *scanout;
326 int y;
327 register int x, i;
328
329 scanin = (COLR *)malloc((xmax-xmin)*sizeof(COLR));
330 if (scanin == NULL)
331 goto memerr;
332 scanin -= xmin;
333 if (checkthresh) {
334 scanout = (COLR *)malloc(xsiz*sizeof(COLR));
335 if (scanout == NULL)
336 goto memerr;
337 } else
338 scanout = scanin;
339 for (y = ymax-1; y >= 0; y--) {
340 for (x = 0; x < xsiz; x++)
341 copycolr(scanout[x], bgcolr);
342 for (i = 0; i < nfile; i++) {
343 if (input[i].yloc > y ||
344 input[i].yloc+input[i].yres <= y)
345 continue;
346 if (freadcolrs(scanin+input[i].xloc,
347 input[i].xres, input[i].fp) < 0) {
348 fprintf(stderr, "%s: read error (y==%d)\n",
349 input[i].name,
350 y-input[i].yloc);
351 quit(1);
352 }
353 if (y >= ysiz)
354 continue;
355 if (checkthresh) {
356 x = input[i].xloc+input[i].xres;
357 if (x > xsiz)
358 x = xsiz;
359 for (x--; x >= 0 && x >= input[i].xloc; x--) {
360 if (input[i].flags & HASMIN &&
361 cmpcolr(scanin[x], input[i].thmin) <= 0)
362 continue;
363 if (input[i].flags & HASMAX &&
364 cmpcolr(scanin[x], input[i].thmax) >= 0)
365 continue;
366 copycolr(scanout[x], scanin[x]);
367 }
368 }
369 }
370 if (y >= ysiz)
371 continue;
372 if (fwritecolrs(scanout, xsiz, stdout) < 0) {
373 perror(progname);
374 quit(1);
375 }
376 }
377 /* read remainders from streams */
378 for (i = 0; i < nfile; i++)
379 if (input[i].name[0] == '<')
380 while (getc(input[i].fp) != EOF)
381 ;
382 return;
383 memerr:
384 perror(progname);
385 quit(1);
386 }
387
388
389 static int
390 cmpcolr( /* compare COLR to luminance */
391 register COLR c1,
392 double lv2
393 )
394 {
395 double lv1 = .0;
396
397 if (c1[EXP])
398 lv1 = ldexp((double)normbright(c1), (int)c1[EXP]-(COLXS+8));
399 if (lv1 < lv2) return(-1);
400 if (lv1 > lv2) return(1);
401 return(0);
402 }
403
404
405 static FILE *
406 lblopen( /* open pipe to label generator */
407 char *s,
408 int *xp,
409 int *yp
410 )
411 {
412 char com[PATH_MAX];
413 FILE *fp;
414
415 sprintf(com, "psign -s -.15 -a 2 -x %d -y %d '%.90s'", *xp, *yp, s);
416 if ((fp = popen(com, "r")) == NULL)
417 return(NULL);
418 if (checkheader(fp, COLRFMT, NULL) < 0)
419 goto err;
420 if (fgetresolu(xp, yp, fp) < 0)
421 goto err;
422 return(fp);
423 err:
424 pclose(fp);
425 return(NULL);
426 }
427
428
429 void
430 quit(code) /* exit gracefully */
431 int code;
432 {
433 register int i;
434 /* close input files */
435 for (i = 0; i < nfile; i++)
436 if (input[i].name == Command || input[i].name == Label)
437 pclose(input[i].fp);
438 else
439 fclose(input[i].fp);
440 exit(code);
441 }