ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/psketch.c
Revision: 2.3
Committed: Tue Aug 29 16:31:32 2017 UTC (6 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +2 -1 lines
Log Message:
Fixes for Windows

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.3 static const char RCSid[] = "$Id: psketch.c,v 2.2 2017/08/26 18:26:56 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * psketch.c - modify picture to sketch objects with named modifiers
6     *
7     * 9/23/2017
8     */
9    
10     #include "copyright.h"
11    
12     #include <string.h>
13    
14     #include "standard.h"
15     #include "platform.h"
16 greg 2.3 #include "paths.h"
17 greg 2.1 #include "resolu.h"
18     #include "color.h"
19    
20     #define MAXMOD 2048 /* maximum number of modifiers */
21     #define USESORT 12 /* switch to sorted search */
22    
23 greg 2.2 double smoothing = 0.8; /* weight for moving average filter */
24     double mixfact = 0.3; /* amount to mix above/below */
25    
26 greg 2.1 char *modlist[MAXMOD]; /* (sorted) modifier list */
27     int nmods = 0; /* number of modifiers */
28    
29 greg 2.2 unsigned char *hasmod; /* scanline bitmap */
30     unsigned char *hasmod1;
31     COLOR *scan[2]; /* i/o scanlines */
32 greg 2.1 RESOLU pres; /* input resolution */
33     int bmwidth; /* bytes per bitmap */
34 greg 2.2
35     #undef tstbit /* conflicting def's in param.h */
36 greg 2.1 #undef setbit
37     #undef clrbit
38     #undef tglbit
39    
40     #define bitop(bm,x,op) ((bm)[(x)>>3] op (1<<((x)&7)))
41     #define tstbit(bm,x) bitop(bm,x,&)
42     #define setbit(bm,x) bitop(bm,x,|=)
43     #define clrbit(bm,x) bitop(bm,x,&=~)
44     #define tglbit(bm,x) bitop(bm,x,^=)
45    
46     const char *octree, *infname; /* input octree and picture names */
47     FILE *infp; /* picture input stream */
48     FILE *mafp; /* pipe from rtrace with modifiers */
49     int linesread = 0; /* scanlines read so far */
50    
51     static int
52     find_mod(const char *s)
53     {
54     int ilower, iupper;
55     int c, i;
56    
57     if (nmods < USESORT) { /* linear search */
58     for (i = nmods; i-- > 0; )
59     if (!strcmp(s, modlist[i]))
60     return(i);
61     return(-1);
62     }
63     ilower = 0; iupper = nmods;
64     c = iupper; /* binary search */
65     while ((i = (iupper + ilower) >> 1) != c) {
66     c = strcmp(s, modlist[i]);
67     if (c > 0)
68     ilower = i;
69     else if (c < 0)
70     iupper = i;
71     else
72     return(i);
73     c = i;
74     }
75     return(-1);
76     }
77    
78     static int
79     read_scan(void)
80     {
81 greg 2.2 const int spread = (int)(smoothing*10);
82 greg 2.1 int x, width = scanlen(&pres);
83     unsigned char *tbmp;
84 greg 2.2 COLOR *tscn;
85 greg 2.1 char modbuf[516];
86 greg 2.2 /* advance buffer */
87 greg 2.1 tscn = scan[0];
88     scan[0] = scan[1];
89     scan[1] = tscn;
90     /* check if we are at the end */
91     if (linesread >= numscans(&pres))
92     return(0);
93 greg 2.2 /* set scanline bitmap */
94     if (linesread) {
95 greg 2.1 /* load & check materials */
96 greg 2.2 memset(hasmod1, 0, bmwidth);
97     for (x = 0; x < width; x++) {
98     int len;
99     if (fgets(modbuf, sizeof(modbuf), mafp) == NULL) {
100     fprintf(stderr, "Error reading from rtrace!\n");
101     return(-1);
102     }
103     len = strlen(modbuf);
104     if (len < 3 || (modbuf[len-1] != '\n') |
105     (modbuf[len-2] != '\t')) {
106     fprintf(stderr, "Garbled rtrace output: %s", modbuf);
107     return(-1);
108     }
109     modbuf[len-2] = '\0';
110     if (find_mod(modbuf) >= 0)
111     setbit(hasmod1, x);
112 greg 2.1 }
113 greg 2.2 /* smear to cover around object */
114     memset(hasmod, 0, bmwidth);
115     for (x = spread; x < width-spread; x++) {
116     int ox;
117     if (!tstbit(hasmod1,x)) continue;
118     for (ox = -spread; ox <= spread; ox++)
119     setbit(hasmod,x+ox);
120 greg 2.1 }
121     }
122     /* read next picture scanline */
123 greg 2.2 if (freadscan(scan[1], width, infp) < 0) {
124 greg 2.1 fprintf(stderr, "%s: error reading scanline %d\n",
125     infname, linesread);
126     return(-1);
127     }
128     return(++linesread);
129     }
130    
131     static int
132     spcmp(const void *p1, const void *p2)
133     {
134     return strcmp(*(const char **)p1, *(const char **)p2);
135     }
136    
137     static int
138     get_started(void)
139     {
140     char combuf[1024];
141    
142     if (nmods >= USESORT) /* need to sort for search? */
143     qsort(modlist, nmods, sizeof(char *), &spcmp);
144     /* open pipe from rtrace */
145     sprintf(combuf, "vwrays -fd %s | rtrace -h -fda -om %s",
146     infname, octree);
147     mafp = popen(combuf, "r");
148     if (mafp == NULL) {
149     perror("popen");
150     return(0);
151     }
152     /* allocate bitmaps & buffers */
153     bmwidth = (scanlen(&pres)+7) >> 3;
154     hasmod = (unsigned char *)malloc(bmwidth);
155 greg 2.2 hasmod1 = (unsigned char *)malloc(bmwidth);
156     scan[0] = (COLOR *)malloc(scanlen(&pres)*sizeof(COLOR));
157     scan[1] = (COLOR *)malloc(scanlen(&pres)*sizeof(COLOR));
158     if (!hasmod | !hasmod1 | !scan[0] | !scan[1]) {
159 greg 2.1 perror("malloc");
160     return(0);
161     }
162     if (!read_scan()) /* read first scanline */
163     return(0);
164     return(1);
165     }
166    
167     static int
168     advance_scanline(void)
169     {
170     static int alldone = 0;
171     int width = scanlen(&pres);
172     int height = numscans(&pres);
173     int x, xstart = 0, xstop = width, xstep = 1;
174 greg 2.2 COLOR cmavg;
175 greg 2.1
176     if (alldone) /* finished last scanline? */
177     return(0);
178     alldone = (linesread >= height);
179     /* advance scanline */
180     if (read_scan() < !alldone)
181     return(-1);
182     if (linesread & 1) { /* process in horizontal zig-zag */
183     xstart = width-1;
184     xstop = -1;
185     xstep = -1;
186 greg 2.2 }
187     setcolor(cmavg, .0f, .0f, .0f); /* process this scanline */
188 greg 2.1 for (x = xstart; x != xstop; x += xstep) {
189 greg 2.2 COLOR cmix;
190     if (!tstbit(hasmod,x)) continue;
191     /* apply moving average */
192     scalecolor(scan[0][x], 1.-smoothing);
193     scalecolor(cmavg, smoothing);
194     addcolor(cmavg, scan[0][x]);
195     copycolor(scan[0][x], cmavg);
196     /* mix pixel into next scanline */
197     copycolor(cmix, scan[0][x]);
198     scalecolor(cmix, mixfact);
199     scalecolor(scan[1][x], 1.-mixfact);
200     addcolor(scan[1][x], cmix);
201 greg 2.1 }
202 greg 2.2 /* write out result */
203     if (fwritescan(scan[0], width, stdout) < 0) {
204 greg 2.1 perror("write error");
205     return(-1);
206     }
207     return(1);
208     }
209    
210     static int
211     clean_up(void)
212     {
213     char linebuf[128];
214     /* read unused materials */
215     while (fgets(linebuf, sizeof(linebuf), mafp) != NULL)
216     ;
217     if (pclose(mafp) != 0) {
218     fprintf(stderr, "Error running rtrace!\n");
219     return(0);
220     }
221     fclose(infp);
222     free(hasmod);
223 greg 2.2 free(hasmod1);
224 greg 2.1 free(scan[0]);
225     free(scan[1]);
226     return(1);
227     }
228    
229     int
230     main(int argc, char *argv[])
231     {
232     int i, rval;
233     char pfmt[LPICFMT+1];
234     /* process options */
235     for (i = 1; i < argc && argv[i][0] == '-'; i++)
236     switch (argv[i][1]) {
237     case 'm': /* new modifier name */
238     if (nmods >= MAXMOD) {
239     fprintf(stderr, "%s: too many modifiers\n", argv[0]);
240     return(1);
241     }
242     modlist[nmods++] = argv[++i];
243     break;
244     case 'M': /* modifier file */
245     rval = wordfile(modlist, MAXMOD-nmods, argv[++i]);
246     if (rval < 0) {
247     fprintf(stderr, "%s: cannot open modifier file '%s'\n",
248     argv[0], argv[i]);
249     return(1);
250     }
251     nmods += rval;
252     break;
253 greg 2.2 case 's': /* filter smoothing amount */
254     smoothing = atof(argv[++i]);
255     if ((smoothing <= FTINY) | (smoothing >= 1.-FTINY)) {
256     fprintf(stderr, "%s: smoothing factor must be in (0,1) range\n",
257     argv[0]);
258     return(1);
259     }
260     break;
261 greg 2.1 default:
262     fprintf(stderr, "%s: unknown option '%s'\n",
263     argv[0], argv[i]);
264     return(1);
265     }
266     if ((argc-i < 2) | (argc-i > 3)) {
267 greg 2.2 fprintf(stderr, "Usage: %s [-m modname][-M modfile][-s smoothing] octree input.hdr [output.hdr]\n",
268 greg 2.1 argv[0]);
269     return(1);
270     }
271     if (!nmods) {
272     fprintf(stderr, "%s: at least one '-m' or '-M' option needed\n",
273     argv[0]);
274     return(1);
275     }
276     octree = argv[i];
277     infname = argv[i+1]; /* open input picture */
278     infp = fopen(infname, "rb");
279     if (infp == NULL) {
280     fprintf(stderr, "%s: cannot open input '%s' for reading\n",
281     argv[0], argv[i+1]);
282     return(1);
283     }
284     if (i+2 < argc && /* open output picture */
285     freopen(argv[i+2], "w", stdout) == NULL) {
286     fprintf(stderr, "%s: cannot open output '%s' for writing\n",
287     argv[0], argv[i+2]);
288     return(1);
289     }
290     SET_FILE_BINARY(stdout);
291     strcpy(pfmt, PICFMT); /* copy format/resolution */
292     if (checkheader(infp, pfmt, stdout) < 0 || !fgetsresolu(&pres, infp)) {
293     fprintf(stderr, "%s: bad format for input picture\n",
294     argv[0]);
295     return(1);
296     }
297     printargs(argc, argv, stdout); /* complete header */
298     fputformat(pfmt, stdout);
299     fputc('\n', stdout);
300     fputsresolu(&pres, stdout); /* resolution does not change */
301     if (!get_started())
302     return(1);
303     while ((rval = advance_scanline()))
304     if (rval < 0)
305     return(1);
306     if (!clean_up())
307     return(1);
308     return(0);
309     }