chromakey_fancy.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:8k
源码类别:

GIS编程

开发平台:

Visual C++

  1. #include <assert.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <GL/glut.h>
  6. #include "texture.h"
  7. static char defaultFile0[] = "../data/swamp.rgb";
  8. static char defaultFile1[] = "../data/swamp.rgb";
  9. static char defaultFile2[] = "../data/mandrill.rgb";
  10. GLuint *img0, *img1, *img2;
  11. GLsizei w, h;
  12. GLsizei w0, w1, w2, h0, h1, h2;
  13. GLint comp;
  14. GLfloat key[3] = {0, 0, 0};
  15. #define RW 0.3086
  16. #define GW 0.6094
  17. #define BW 0.0820
  18. /* key values less than or equal to lower fudge map to totally 
  19.  * transparent... */
  20. GLfloat lowerfudge = .2; 
  21. GLfloat upperfudge = .8;
  22. void init(void)
  23. {
  24. }
  25. GLuint *load_img(const char *fname, GLsizei *imgW, GLsizei *imgH)
  26. {
  27.   GLuint *img;
  28.   img = read_texture(fname, imgW, imgH, &comp);
  29.   if (!img) {
  30.     fprintf(stderr, "Could not open %sn", fname);
  31.     exit(1);
  32.   }
  33.   return img;
  34. }
  35. GLuint *
  36. resize_img(GLuint *img, GLsizei curW, GLsizei curH)
  37. {
  38.   glPixelZoom((float)w / (float)curW, (float)h / (float)curH);
  39.   glRasterPos2i(0, 0);
  40.   glDrawPixels(curW, curH, GL_RGBA, GL_UNSIGNED_BYTE, img);
  41.   free(img);
  42.   img = (GLuint *)malloc(w * h * sizeof(GLuint));
  43.   if (!img) {
  44.     fprintf(stderr, "Malloc of %d bytes failed.n", 
  45.     curW * curH * sizeof(GLuint));
  46.     exit(1);
  47.   }
  48.   glPixelZoom(1, 1);
  49.   glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img);
  50.   return img;
  51. }
  52. void reshape(GLsizei winW, GLsizei winH) 
  53. {
  54.     glViewport(0, 0, 2*w, 2*h);
  55.     glLoadIdentity();
  56.     glOrtho(0, 2*w, 0, 2*h, 0, 5);
  57. }
  58. void compute_matte(void)
  59. {
  60.   glClear(GL_ACCUM_BUFFER_BIT);
  61.   /* draw rectangle in (key color + 1) / 2 */
  62.   glBegin(GL_QUADS);
  63.   glColor3f(key[0], key[1], key[2]);
  64.   glVertex2f(0, 0);
  65.   glVertex2f(w, 0);
  66.   glVertex2f(w, h);
  67.   glVertex2f(0, h);
  68.   glEnd();
  69.   glFlush();
  70.   /* negate & accumulate  */
  71.   glAccum(GL_LOAD, -1);
  72.   /* compute & return (image - key) */
  73.   glRasterPos2f(0, 0);
  74.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img0);
  75.   glAccum(GL_ACCUM, 1);
  76.   glAccum(GL_RETURN, 1);
  77.   /* move to right hand side of window */
  78.   glRasterPos2f(w, 0);
  79.   glCopyPixels(0, 0, w, h, GL_COLOR);
  80.   /* compute & return (key - image) */
  81.   glEnable(GL_SCISSOR_TEST);
  82.   glScissor(0, 0, w, h);
  83.   glAccum(GL_MULT, -1);
  84.   glAccum(GL_RETURN, 1);
  85.   glScissor(0, 0, 2*w, h);
  86.   glDisable(GL_SCISSOR_TEST);
  87.   /* assemble to get fabs(key - image) */
  88.   glBlendFunc(GL_ONE, GL_ONE);
  89.   glEnable(GL_BLEND);
  90.   glRasterPos2i(0, 0);
  91.   glCopyPixels(w, 0, w, h, GL_COLOR);
  92.   glDisable(GL_BLEND);
  93.   /* assemble into alpha channel */
  94.   {
  95.     GLfloat mat[] = {
  96.       RW, RW, RW, RW,
  97.       GW, GW, GW, GW,
  98.       BW, BW, BW, BW,
  99.       0, 0, 0, 0,
  100.     };
  101.     glMatrixMode(GL_COLOR);
  102.     glLoadMatrixf(mat);
  103.     glRasterPos2i(w, 0);
  104.     glCopyPixels(0, 0, w, h, GL_COLOR);
  105.     glLoadIdentity();
  106.     glMatrixMode(GL_MODELVIEW);
  107.     /* do a second copy because sbias comes after color matrix in the
  108.      * transfer pipeline.  could avoid this by using the post color matrix
  109.      * scale bias... */
  110.     if (upperfudge - lowerfudge) {
  111.       glPixelTransferf(GL_ALPHA_SCALE, 1./(upperfudge - lowerfudge));
  112.       glPixelTransferf(GL_ALPHA_BIAS, -lowerfudge/(upperfudge - lowerfudge)); 
  113.     } else {
  114.       /* move such that upper/lowerfudge maps to .5, then quantize with
  115.        * 2-entry pixel map. */
  116.       GLushort quantize[] = {0, 0xffff};
  117.       glPixelTransferf(GL_ALPHA_BIAS, .5 - upperfudge);
  118.       glPixelMapusv(GL_PIXEL_MAP_A_TO_A, 2, quantize);
  119.       glPixelTransferi(GL_MAP_COLOR, 1);
  120.     }
  121.     glRasterPos2i(w, 0);
  122.     glCopyPixels(w, 0, w, h, GL_COLOR);
  123.     glPixelTransferf(GL_ALPHA_SCALE,  1);
  124.     glPixelTransferf(GL_ALPHA_BIAS, 0);
  125.     glPixelTransferi(GL_MAP_COLOR, 0);
  126.   }
  127.   /* copy matte to right */
  128.   glRasterPos2i(0, 0);
  129.   glCopyPixels(w, 0, w, h, GL_COLOR);
  130.   /* draw the third image */
  131.   glColorMask(1, 1, 1, 0);
  132.   glRasterPos2i(w, 0);
  133.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img2);
  134.   glColorMask(1, 1, 1, 1);
  135.   glBlendFunc(GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA);
  136.   glEnable(GL_BLEND);
  137.   glRasterPos2i(w, 0);
  138.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img1);
  139.   /* this is for matte display... */
  140.   glColor3f(1, 1, 1);
  141.   glBegin(GL_QUADS);
  142.   glVertex2f(0, 0);
  143.   glVertex2f(w, 0);
  144.   glVertex2f(w, h);
  145.   glVertex2f(0, h);
  146.   glEnd();
  147.   glDisable(GL_BLEND);
  148. }
  149. void draw(void)
  150. {
  151.   GLenum err;
  152.   static int first = 1;
  153.   
  154.   if (first) {
  155.     printf("Scaling images to %d by %dn", w, h);
  156.     if (w0 != w || h0 != h) {
  157.       img0 = resize_img(img0, w0, h0);
  158.     }
  159.     if (w1 != w || h1 != h) {
  160.       img1 = resize_img(img1, w1, h1);
  161.     }
  162.     if (w2 != w || h2 != h) {
  163.       img2 = resize_img(img2, w2, h2);
  164.     }
  165.     first = 0;
  166.   }
  167.   
  168.   
  169.   glClear(GL_COLOR_BUFFER_BIT);
  170.   compute_matte();
  171.   
  172.   glRasterPos2i(w/2, h);
  173.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img0);
  174.   err = glGetError();
  175.   if (err != GL_NO_ERROR) printf("Error:  %sn", gluErrorString(err));
  176. }
  177. /* ARGSUSED */
  178. void button(int button, int state, int xpos, int ypos)
  179. {
  180.   if (state != GLUT_UP) return;
  181.   ypos = 2*h - ypos;
  182.   glReadPixels(xpos, ypos, 1, 1, GL_RGB, GL_FLOAT, key);
  183.   printf("Key is (%f %f %f)n", key[0], key[1], key[2]);
  184.   draw();
  185. }
  186. /* ARGSUSED1 */
  187. void keyPress(unsigned char whichKey, int x, int y)
  188. {
  189.   if (whichKey == 27) exit(0);
  190. }
  191. void change_lower_fudge(int val)
  192. {
  193.   lowerfudge = (float)val / 100.;
  194.   if (upperfudge < lowerfudge) upperfudge = lowerfudge;
  195.   draw();
  196. }
  197. void change_upper_fudge(int val)
  198. {
  199.   upperfudge = (float)val / 100.;
  200.   if (lowerfudge > upperfudge) lowerfudge = upperfudge;
  201.   draw();
  202. }
  203. void show_usage(void) 
  204. {
  205.   fprintf(stderr, "Usage:n");
  206.   fprintf(stderr, "chromakey mattefile file0 file1 [matteR matteG matteB]n");
  207.   fprintf(stderr, "chromakey mattefileAndfile0 file1 [matteR matteG matteB]n");
  208. }
  209. main(int argc, char *argv[])
  210. {
  211.   char *fileName0 = defaultFile0, *fileName1 = defaultFile1, 
  212.   *fileName2 = defaultFile2;
  213.   
  214.   glutInit(&argc, argv);
  215.   if (argc > 1) {
  216.     fileName0 = fileName1 = argv[1];
  217.   }
  218.   if (argc > 2) {
  219.     fileName2 = argv[2];
  220.   }
  221.   if (argc > 3) {
  222.     fileName1 = fileName2;
  223.     fileName2 = argv[3];
  224.   }
  225.   if (argc > 4) {
  226.     if (argc == 6 || argc == 7) {
  227.       key[0] = atof(argv[argc-3]);
  228.       key[1] = atof(argv[argc-2]);
  229.       key[2] = atof(argv[argc-1]);
  230.     } else {
  231.       show_usage();
  232.       exit(1);
  233.     }
  234.   }
  235.   
  236.   printf("Matte file is %sn", fileName0);
  237.   printf("Image file 1 is %sn", fileName1);
  238.   printf("Image file 2 is %sn", fileName2);
  239.   printf("Key is (%f %f %f)n", key[0], key[1], key[2]);
  240.   printf("Transparent boundary is %fn", lowerfudge);
  241.   printf("Opaque boundary is %fn", upperfudge);
  242.   img0 = load_img(fileName0, &w0, &h0);
  243.   img1 = load_img(fileName1, &w1, &h1);
  244.   img2 = load_img(fileName2, &w2, &h2);
  245.   
  246. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  247.   w = MAX(MAX(w0, w1), w2);
  248.   h = MAX(MAX(h0, h1), h2);
  249.   
  250.   glutInitWindowSize(2*w, 2*h);
  251.   glutInitWindowPosition(0, 0);
  252.   glutInitDisplayMode(GLUT_RGBA | GLUT_ACCUM | GLUT_ALPHA);
  253.   glutCreateWindow(argv[0]);
  254.   glutDisplayFunc(draw);
  255.   glutKeyboardFunc(keyPress);
  256.   glutReshapeFunc(reshape);
  257.   glutMouseFunc(button);
  258.   {
  259.     int lowerFudgeMenu, upperFudgeMenu;
  260.     lowerFudgeMenu = glutCreateMenu(change_lower_fudge);
  261.     glutAddMenuEntry("0", 0);
  262.     glutAddMenuEntry(".1", 20);
  263.     glutAddMenuEntry(".25", 20);
  264.     glutAddMenuEntry(".5", 50);
  265.     glutAddMenuEntry(".75", 75);
  266.     upperFudgeMenu = glutCreateMenu(change_upper_fudge);
  267.     glutAddMenuEntry(".25", 20);
  268.     glutAddMenuEntry(".5", 50);
  269.     glutAddMenuEntry(".75", 75);    
  270.     glutAddMenuEntry(".9", 90);
  271.     glutAddMenuEntry("1", 100);
  272.     glutCreateMenu(0);
  273.     glutAddSubMenu("Transparent boundary", lowerFudgeMenu);
  274.     glutAddSubMenu("Opaque boundary", upperFudgeMenu);
  275.     glutAttachMenu(GLUT_RIGHT_BUTTON);
  276.   }
  277.   init();
  278.   
  279.   reshape(w, h);
  280.   glutMainLoop();
  281.   return 0;
  282. }