ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/psketch.c
Revision: 2.1
Committed: Sat Aug 26 16:07:22 2017 UTC (6 years, 8 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Created psketch program for sketching out objects using named modifier(s)

File Contents

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