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, 9 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

# Content
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 }