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

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. /* Some <math.h> files do not define M_PI... */
  8. #ifndef M_PI
  9. #define M_PI 3.14159265358979323846
  10. #endif
  11. #ifndef __sgi
  12. #define trunc(x) ((double)((int)(x)))
  13. #endif
  14. #define RW 0.3086
  15. #define GW 0.6094
  16. #define BW 0.0820
  17. static char defaultFile0[] = "../data/mandrill.rgb";
  18. static char defaultFile1[] = "../data/sgi.bw";
  19. static char defaultBrushFile[] = "../data/brush.rgb";
  20. GLuint *img0, *img1, *brush;
  21. GLsizei w0, w1, wbrush, h0, h1, hbrush;
  22. GLsizei w, h;
  23. GLint comp;
  24. void init(void)
  25. {
  26.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  27. }
  28. GLuint *load_img(const char *fname, GLsizei *imgW, GLsizei *imgH)
  29. {
  30.   GLuint *img;
  31.   img = read_texture(fname, imgW, imgH, &comp);
  32.   if (!img) {
  33.     fprintf(stderr, "Could not open %sn", fname);
  34.     exit(1);
  35.   }
  36.   return img;
  37. }
  38. GLuint *
  39. resize_img(GLuint *img, GLsizei curW, GLsizei curH)
  40. {
  41.   /* save & set buffer settings */
  42.   glPushAttrib(GL_COLOR_BUFFER_BIT | GL_PIXEL_MODE_BIT);
  43.   glDrawBuffer(GL_BACK);
  44.   glReadBuffer(GL_BACK);
  45.   glPixelZoom((float)w / (float)curW, (float)h / (float)curH);
  46.   glRasterPos2i(0, 0);
  47.   glDrawPixels(curW, curH, GL_RGBA, GL_UNSIGNED_BYTE, img);
  48.   free(img);
  49.   img = (GLuint *)malloc(w * h * sizeof(GLuint));
  50.   if (!img) {
  51.     fprintf(stderr, "Malloc of %d bytes failed.n", 
  52.     curW * curH * sizeof(GLuint));
  53.     exit(1);
  54.   }
  55.   glPixelZoom(1, 1);
  56.   glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img);
  57.   glPopAttrib();
  58.   return img;
  59. }
  60. GLuint *
  61. convert_to_luminance(GLuint *img, GLsizei w, GLsizei h)
  62. {
  63.   GLubyte *newImg, *src, *dst;
  64.   GLfloat val;
  65.   int i;
  66.   newImg = (GLubyte *)malloc(w * h);
  67.   if (!newImg) {
  68.     fprintf(stderr, "malloc of %d bytes failedn", w*h);
  69.     exit(1);
  70.   }
  71.   src = (GLubyte *)img;
  72.   dst = newImg;
  73.   for (i = 0; i < w*h; i++) {
  74.     val = ((float)(*src++) * RW + 
  75.    (float)(*src++) * GW +
  76.    (float)(*src++) * BW);
  77.     src++;
  78.     if (val > 255) val = 255;
  79.     *dst++ = val;
  80.   }
  81.   free(img);
  82.   /* casting a ubyte ptr to a uint pointer is sloppy since it can
  83.    * lead to alignment errors, but since the pointer came from
  84.    * malloc we know it's legal in this case... */
  85.   return (GLuint *)newImg;
  86. }
  87. void reshape(GLsizei winW, GLsizei winH) 
  88. {
  89.     glViewport(0, 0, w, h);
  90.     glLoadIdentity();
  91.     glOrtho(0, winW, 0, winH, 0, 5);
  92. }
  93. void draw(void)
  94. {
  95.   static int first = 1;
  96.   GLenum err;
  97.   if (first) {
  98.     printf("Scaling images to %d by %dn", w, h);
  99.     if (w0 != w || h0 != h) {
  100.       img0 = resize_img(img0, w0, h0);
  101.     }
  102.     if (w1 != w || h1 != h) {
  103.       img1 = resize_img(img1, w1, h1);
  104.     }
  105.     first = 0;
  106.   }
  107.   
  108.   glClear(GL_COLOR_BUFFER_BIT);
  109.   glRasterPos2i(0, 0);
  110.   glDrawBuffer(GL_BACK);
  111.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img1);
  112.   glDrawBuffer(GL_FRONT);
  113.   glDrawPixels(w, h, GL_RGBA, GL_UNSIGNED_BYTE, img0);
  114.   
  115.   err = glGetError();
  116.   if (err != GL_NO_ERROR) printf("Error:  %sn", gluErrorString(err));
  117. }
  118. int lastX, lastY, curX, curY;
  119. int get_msecs(void)
  120. {
  121.   return glutGet(GLUT_ELAPSED_TIME) / 1000.0;
  122. }
  123. void idle(void)
  124. {
  125.   int x = curX - (wbrush/2);
  126.   int y = h - (curY + (hbrush/2));
  127.   int msecs;
  128.   static int last_msecs = -1;
  129.   /* do not do this more than 60 times a second.  Otherwise it's
  130.    * to fast for use on high-end systems */
  131.   msecs = get_msecs();
  132.   if (fabs(last_msecs - msecs) < 1000./60.) {
  133.     return;
  134.   }
  135.   last_msecs = msecs;
  136.   /* we draw the brush using a drawpixels command.  on systems with
  137.    * hardware-accelerated texture mapping it would be better to use
  138.    * that. 
  139.    * 
  140.    * we use the bitmap hack to set the rasterpos because we don't
  141.    * know that the position will be within the window. 
  142.    */
  143.   glRasterPos2i(0, 0);
  144.   glBitmap(0, 0, 0, 0, x, y, 0);
  145.   glColorMask(0, 0, 0, 1);
  146.   glDrawBuffer(GL_BACK);
  147.   glDrawPixels(wbrush, hbrush, GL_ALPHA, GL_UNSIGNED_BYTE, brush);
  148.   glColorMask(1, 1, 1, 1);
  149.   
  150.   glReadBuffer(GL_BACK);
  151.   glDrawBuffer(GL_FRONT);
  152.   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
  153.   glEnable(GL_BLEND);
  154.   glCopyPixels(x, y, wbrush, hbrush, GL_COLOR);
  155.   glDisable(GL_BLEND);
  156.   
  157.   glColorMask(1, 1, 1, 1);
  158. }
  159. void motion(int xpos, int ypos)
  160. {
  161.   curX = xpos;
  162.   curY = ypos;
  163. }
  164. /* ARGSUSED */
  165. void button(int button, int state, int xpos, int ypos)
  166. {
  167.   if (state == GLUT_DOWN) {
  168.     glutIdleFunc(idle); 
  169.     lastX = lastY = -1;
  170.     curX = xpos;
  171.     curY = ypos;
  172.     return;
  173.   } else {
  174.     glutIdleFunc(0);
  175.   }
  176. }
  177. /* ARGSUSED1 */
  178. void key(unsigned char key, int x, int y)
  179. {
  180.   if (key == 27) exit(0);
  181. }
  182. void 
  183. show_usage(void)
  184. {
  185.   fprintf(stderr, "Usage:n");
  186.   fprintf(stderr, "paint [imagefile0] [imagefile1] [brush]n");
  187. }
  188. main(int argc, char *argv[])
  189. {
  190.   const char *fileName0 = defaultFile0, *fileName1 = defaultFile1,
  191.   *brushName = defaultBrushFile;
  192.   
  193.   glutInit(&argc, argv);
  194.   if (argc > 1) {
  195.     fileName0 = argv[1];
  196.   } 
  197.   if (argc > 2) {
  198.     fileName1 = argv[2];
  199.   } 
  200.   if (argc > 3) {
  201.     brushName = argv[3];
  202.   } 
  203.   if (argc > 4) {
  204.     show_usage();
  205.     exit(1);
  206.   }
  207.   printf("Image file 1 is %sn", fileName0);
  208.   printf("Image file 2 is %sn", fileName1);
  209.   printf("Brush file is %sn", brushName);
  210.   img0 = load_img(fileName0, &w0, &h0);
  211.   img1 = load_img(fileName1, &w1, &h1);
  212.   brush = load_img(brushName, &wbrush, &hbrush);
  213.   brush = convert_to_luminance(brush, wbrush, hbrush);
  214. #define MAX(a, b) ((a) > (b) ? (a) : (b))
  215.   w = MAX(w0, w1);
  216.   h = MAX(h0, h1);
  217.   glutInitWindowSize(w, h);
  218.   glutInitWindowPosition(0, 0);
  219.   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_ALPHA);
  220.   glutCreateWindow(argv[0]);
  221.   glutDisplayFunc(draw);
  222.   glutKeyboardFunc(key);
  223.   glutReshapeFunc(reshape);
  224.   glutMouseFunc(button);
  225.   glutMotionFunc(motion);
  226.   init();
  227.   glutMainLoop();
  228.   return 0;
  229. }