gradtool

view gradtool.c @ 1:c438411b801b

latest changes from svn (saving grad files)
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 09 Oct 2015 01:45:12 +0300
parents 960cea2731c4
children 3ac4d33e568f
line source
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <errno.h>
5 #ifdef __APPLE__
6 #include <GLUT/glut.h>
7 #else
8 #include <GL/glut.h>
9 #endif
11 #define MAX_POS 512
13 typedef struct key {
14 int pos;
15 float val;
16 struct key *next;
17 } key_t;
19 struct track {
20 key_t *keys;
21 int count;
22 };
24 void redraw(void);
25 void draw_curves(void);
26 void draw_grad(void);
28 void set_val(struct track *track, float pos, float val);
29 void rm_val(struct track *track, float pos);
30 float get_val(struct track *track, float pos);
32 int save_ppm(const char *fname, int img_width);
33 int save_grad(const char *fname);
35 void key_handler(unsigned char key, int x, int y);
36 void skey_handler(int key, int x, int y);
37 void mbutton_handler(int bn, int state, int x, int y);
38 void drag_handler(int x, int y);
39 void reshape_handler(int x, int y);
41 int view_xsz = 640;
42 int view_ysz = 480;
44 struct track tred, tgreen, tblue;
46 int main(int argc, char **argv)
47 {
48 glutInit(&argc, argv);
49 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);
50 glutInitWindowSize(view_xsz, view_ysz);
51 glutCreateWindow("Mindlapse gradiant editor");
53 glutDisplayFunc(redraw);
54 glutKeyboardFunc(key_handler);
55 glutSpecialFunc(skey_handler);
56 glutMouseFunc(mbutton_handler);
57 glutMotionFunc(drag_handler);
58 glutReshapeFunc(reshape_handler);
60 glClearColor(0, 0, 0, 0);
61 glEnable(GL_POINT_SMOOTH);
63 glMatrixMode(GL_PROJECTION);
64 glOrtho(0, 1, 0, 1, -1, 1);
65 glMatrixMode(GL_MODELVIEW);
67 tred.keys = malloc(sizeof *tred.keys);
68 tred.keys->next = 0;
70 tgreen.keys = malloc(sizeof *tgreen.keys);
71 tgreen.keys->next = 0;
73 tblue.keys = malloc(sizeof *tblue.keys);
74 tblue.keys->next = 0;
76 glutMainLoop();
77 return 0;
78 }
80 void redraw(void)
81 {
82 glClear(GL_COLOR_BUFFER_BIT);
84 draw_curves();
86 draw_grad();
88 glutSwapBuffers();
89 }
91 void draw_curves(void)
92 {
93 int i;
94 key_t *ptr;
96 glLoadIdentity();
97 glTranslatef(0, 0.25, 0);
98 glScalef(1, 0.75, 1);
100 glBegin(GL_LINES);
101 /* draw grid */
102 glColor3f(0.5, 0.5, 0.5);
103 glVertex2f(0, 0); glVertex2f(0, 1);
104 glVertex2f(1, 0); glVertex2f(1, 1);
105 glVertex2f(0, 0); glVertex2f(1, 0);
106 glVertex2f(0, 1); glVertex2f(1, 1);
108 glVertex2f(0, 0.25); glVertex2f(1, 0.25);
109 glVertex2f(0, 0.5); glVertex2f(1, 0.5);
110 glVertex2f(0, 0.75); glVertex2f(1, 0.75);
112 glVertex2f(0.25, 0); glVertex2f(0.25, 1);
113 glVertex2f(0.5, 0); glVertex2f(0.5, 1);
114 glVertex2f(0.75, 0); glVertex2f(0.75, 1);
115 glEnd();
117 glEnable(GL_BLEND);
118 glBlendFunc(GL_ONE, GL_ONE);
120 glBegin(GL_LINES);
121 for(i=0; i<3; i++) {
122 glColor3f(i == 0, i == 1, i == 2);
123 ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next));
125 if(ptr && ptr->pos > 0) {
126 glVertex2f(0, ptr->val);
127 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
128 }
130 while(ptr && ptr->next) {
131 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
132 glVertex2f(ptr->next->pos / (float)MAX_POS, ptr->next->val);
133 ptr = ptr->next;
134 }
136 if(ptr && ptr->pos != MAX_POS) {
137 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
138 glVertex2f(1, ptr->val);
139 }
140 }
141 glEnd();
143 glPointSize(5);
144 glBegin(GL_POINTS);
145 for(i=0; i<3; i++) {
146 glColor3f(i == 0, i == 1, i == 2);
147 ptr = (i == 0 ? tred.keys->next : (i == 1 ? tgreen.keys->next : tblue.keys->next));
149 while(ptr) {
150 glVertex2f(ptr->pos / (float)MAX_POS, ptr->val);
151 ptr = ptr->next;
152 }
153 }
154 glEnd();
156 glDisable(GL_BLEND);
157 }
159 #define GRAD_SAMPLES MAX_POS
160 void draw_grad(void)
161 {
162 int i;
164 glLoadIdentity();
165 glScalef(1, 0.25, 1);
167 glBegin(GL_QUADS);
168 for(i=0; i<GRAD_SAMPLES-1; i++) {
169 float t = (float)i / (float)GRAD_SAMPLES;
170 glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t));
171 glVertex2f(t, 0);
172 glVertex2f(t, 1);
174 t = (float)(i + 1) / (float)GRAD_SAMPLES;
175 glColor3f(get_val(&tred, t), get_val(&tgreen, t), get_val(&tblue, t));
176 glVertex2f(t, 1);
177 glVertex2f(t, 0);
178 }
179 glEnd();
180 }
182 void set_val(struct track *tr, float pos, float val)
183 {
184 key_t *nkey;
185 key_t *ptr = tr->keys;
186 int ipos = (int)(pos * MAX_POS);
188 if(!ptr->next || ptr->next->pos > ipos) {
189 nkey = malloc(sizeof *nkey);
190 nkey->pos = ipos;
191 nkey->val = val;
192 nkey->next = ptr->next;
193 ptr->next = nkey;
194 return;
195 }
197 while(ptr->next && ptr->next->pos < ipos) {
198 ptr = ptr->next;
199 }
201 if(ptr->pos == ipos) {
202 ptr->val = val;
203 } else {
204 nkey = malloc(sizeof *nkey);
205 nkey->pos = ipos;
206 nkey->val = val;
207 nkey->next = ptr->next;
208 ptr->next = nkey;
209 }
210 }
212 void rm_val(struct track *tr, float pos)
213 {
214 key_t *ptr = tr->keys;
215 int ipos = (int)(pos * MAX_POS);
217 while(ptr->next && ptr->next->pos <= ipos) {
218 if(ptr->next->pos == ipos) {
219 key_t *tmp = ptr->next;
220 ptr->next = ptr->next->next;
221 free(tmp);
222 return;
223 }
224 ptr = ptr->next;
225 }
226 }
228 float get_val(struct track *tr, float pos)
229 {
230 float t;
231 key_t *ptr = tr->keys->next;
232 int ipos = (int)(pos * MAX_POS);
234 if(!ptr) {
235 return 0.0;
236 }
238 while(ptr && ptr->pos <= ipos) {
239 if(ptr->pos == ipos || !ptr->next) {
240 return ptr->val;
241 }
243 if(ptr->next->pos > ipos) {
244 t = (float)(ipos - ptr->pos) / (float)(ptr->next->pos - ptr->pos);
245 return ptr->val + (ptr->next->val - ptr->val) * t;
246 }
248 ptr = ptr->next;
249 }
251 return tr->keys->next->val;
252 }
254 void clear_track(struct track *tr)
255 {
256 key_t *ptr = tr->keys->next;
257 while(ptr) {
258 key_t *tmp = ptr;
259 ptr = ptr->next;
260 free(tmp);
261 }
262 tr->keys->next = 0;
263 }
266 int save_ppm(const char *fname, int img_width)
267 {
268 int i;
269 FILE *fp;
271 if(!(fp = fopen(fname, "wb"))) {
272 fprintf(stderr, "failed to write %s: %s\n", fname, strerror(errno));
273 return -1;
274 }
276 fprintf(fp, "P6\n%d 1\n255\n", img_width);
278 for(i=0; i<img_width; i++) {
279 float t = (float)i / (float)img_width;
280 int r = get_val(&tred, t) * 255.0;
281 int g = get_val(&tgreen, t) * 255.0;
282 int b = get_val(&tblue, t) * 255.0;
284 fputc(r, fp);
285 fputc(g, fp);
286 fputc(b, fp);
287 }
289 fclose(fp);
290 return 0;
291 }
293 int save_grad(const char *fname)
294 {
295 int i;
296 FILE *fp;
297 struct track *tr[] = {&tred, &tgreen, &tblue};
299 if(!(fp = fopen(fname, "w"))) {
300 return -1;
301 }
303 fprintf(fp, "GRAD\n");
305 for(i=0; i<3; i++) {
306 key_t *ptr = tr[i]->keys->next;
308 while(ptr) {
309 float t = (float)ptr->pos / (float)MAX_POS;
310 float r = get_val(&tred, t);
311 float g = get_val(&tgreen, t);
312 float b = get_val(&tblue, t);
314 fprintf(fp, "%f\t%f %f %f\n", t, r, g, b);
315 ptr = ptr->next;
316 }
317 }
319 fclose(fp);
320 return 0;
321 }
324 void key_handler(unsigned char key, int x, int y)
325 {
326 skey_handler(key, x, y);
327 }
329 void skey_handler(int key, int x, int y)
330 {
331 switch(key) {
332 case 27:
333 exit(0);
335 case 's':
336 case 'S':
337 save_ppm("grad.ppm", 256);
338 break;
340 case 'g':
341 case 'G':
342 save_grad("grad.grad");
343 break;
345 case 'c':
346 clear_track(&tred);
347 clear_track(&tgreen);
348 clear_track(&tblue);
349 glutPostRedisplay();
350 break;
352 default:
353 break;
354 }
355 }
357 static int px, py;
358 static float ppos, pval;
359 static struct track *tr;
361 void mbutton_handler(int bn, int state, int x, int y)
362 {
363 float pos, val;
365 pos = (float)x / (float)view_xsz;
366 val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0);
368 if(bn == GLUT_LEFT_BUTTON) {
369 tr = &tred;
370 } else if(bn == GLUT_MIDDLE_BUTTON) {
371 tr = &tgreen;
372 } else if(bn == GLUT_RIGHT_BUTTON) {
373 tr = &tblue;
374 } else {
375 return;
376 }
378 if(glutGetModifiers() & GLUT_ACTIVE_CTRL) {
379 tr = 0;
380 }
382 if(state == 0) {
383 px = x;
384 py = y;
385 ppos = pos;
386 pval = val;
387 } else {
388 if(px == -1 || abs(x - px) > 2 || abs(y - py) > 2) {
389 return;
390 }
391 if(val < 0.0 || val > 1.0) return;
394 if(glutGetModifiers() & GLUT_ACTIVE_SHIFT) {
395 if(tr) {
396 rm_val(tr, pos);
397 } else {
398 rm_val(&tred, pos);
399 rm_val(&tgreen, pos);
400 rm_val(&tblue, pos);
401 }
402 } else {
403 if(tr) {
404 set_val(tr, pos, val);
405 } else {
406 set_val(&tred, pos, val);
407 set_val(&tgreen, pos, val);
408 set_val(&tblue, pos, val);
409 }
410 }
412 px = -1;
413 py = -1;
414 glutPostRedisplay();
415 }
416 }
418 void drag_handler(int x, int y)
419 {
420 float pos = (float)x / (float)view_xsz;
421 float val = 1.0 - (float)y / (float)(view_ysz - view_ysz / 4.0);
423 if(pos < 0.0) pos = 0.0;
424 if(pos > 1.0) pos = 1.0;
425 if(val < 0.0) val = 0.0;
426 if(val > 1.0) val = 1.0;
428 if(tr) {
429 rm_val(tr, ppos);
430 rm_val(tr, ppos - 1.0 / (float)view_xsz);
431 rm_val(tr, ppos + 1.0 / (float)view_xsz);
432 set_val(tr, pos, val);
433 } else {
434 rm_val(&tred, ppos);
435 rm_val(&tgreen, ppos);
436 rm_val(&tblue, ppos);
437 rm_val(&tred, ppos - 1.0 / (float)view_xsz);
438 rm_val(&tgreen, ppos - 1.0 / (float)view_xsz);
439 rm_val(&tblue, ppos - 1.0 / (float)view_xsz);
440 rm_val(&tred, ppos + 1.0 / (float)view_xsz);
441 rm_val(&tgreen, ppos + 1.0 / (float)view_xsz);
442 rm_val(&tblue, ppos + 1.0 / (float)view_xsz);
443 set_val(&tred, pos, val);
444 set_val(&tgreen, pos, val);
445 set_val(&tblue, pos, val);
446 }
448 ppos = pos;
449 pval = val;
451 glutPostRedisplay();
452 }
454 void reshape_handler(int x, int y)
455 {
456 view_xsz = x;
457 view_ysz = y;
459 glViewport(0, 0, x, y);
460 }