gradtool

annotate gradtool.c @ 2:3ac4d33e568f

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