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

GIS编程

开发平台:

Visual C++

  1. /* Copyright (c) Mark J. Kilgard, 1997. */
  2. /* This program is freely distributable without licensing fees  and is
  3.    provided without guarantee or warrantee expressed or  implied. This
  4.    program is -not- in the public domain. */
  5. /* X compile line: cc -o showtiff showtiff.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
  6. /* showtiff is a simple TIFF file viewer using Sam Leffler's libtiff, GLUT,
  7.    and OpenGL.  If OpenGL the image processing extensions for convolution and
  8.    color matrix are supported by your OpenGL implementation, showtiff will let
  9.    you blur, sharpen, edge detect, and color convert to grayscale the TIFF
  10.    file.  You can also move around the image within the window. */
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <GL/glut.h>
  14. #include <tiffio.h>     /* Sam Leffler's libtiff library. */
  15. TIFFRGBAImage img;
  16. uint32 *raster;
  17. tsize_t npixels;
  18. int imgwidth, imgheight;
  19. int hasABGR = 0;
  20. int hasConvolve = 0;
  21. int hasColorMatrix = 0;
  22. int doubleBuffer = 1;
  23. char *filename = NULL;
  24. int ax = 0, ay = 0;
  25. int luminance = 0;
  26. GLfloat rgbBlur[7][7][3];
  27. GLfloat rgbEdgeDetect[3][3][3];
  28. GLfloat rgbSharpen[3][3][3];
  29. void
  30. initKernels(void)
  31. {
  32.   int x, y, c;
  33.   /* A 7x7 "blurring" convolution kernel.  This kernel will uniformly spread
  34.      each pixel with its surrounding 7x7 pixels.  The sum of the kernel
  35.      elements is 1.0. */
  36.   for (x = 0; x < 7; x++) {
  37.     for (y = 0; y < 7; y++) {
  38.       for (c = 0; c < 3; c++) {
  39.         rgbBlur[x][y][c] = 1.0 / 49.0;
  40.       }
  41.     }
  42.   }
  43.   /* A 3x3 edge detection covolution kernel.  The kernel is shown below.
  44.      Notice how the elements of the kernel add up to zero. */
  45.   /**********
  46.     -1 -1 -1
  47.     -1  8 -1
  48.     -1 -1 -1
  49.    **********/
  50.   for (x = 0; x < 3; x++) {
  51.     for (y = 0; y < 3; y++) {
  52.       for (c = 0; c < 3; c++) {
  53.         rgbEdgeDetect[x][y][c] = -1.0;
  54.       }
  55.     }
  56.   }
  57.   for (c = 0; c < 3; c++) {
  58.     rgbEdgeDetect[1][1][c] = 8.0;
  59.   }
  60.   /* A 3x3 "sharpening" convolution kernel.  The kernel is shown below.
  61.      Notice how surrounding information is subtracted out of the central
  62.      pixel while the central pixel is weighted heavily.  The sum of the
  63.      kernel elements is 1.0. */
  64.   /*************
  65.     -.5 -.5 -.5
  66.     -.5  5  -.5
  67.     -.5 -.5 -.5
  68.    *************/
  69.   for (x = 0; x < 3; x++) {
  70.     for (y = 0; y < 3; y++) {
  71.       for (c = 0; c < 3; c++) {
  72.         rgbSharpen[x][y][c] = -0.5;
  73.       }
  74.     }
  75.   }
  76.   for (c = 0; c < 3; c++) {
  77.     rgbSharpen[1][1][c] = 5.0;
  78.   }
  79. }
  80. /* If resize is called, enable drawing into the full screen area
  81.    (glViewport). Then setup the modelview and projection matrices to map 2D
  82.    x,y coodinates directly onto pixels in the window (lower left origin).
  83.    Then set the raster position (where the image would be drawn) to be offset
  84.    from the upper left corner, and then offset by the current offset (using a
  85.    null glBitmap). */
  86. void
  87. reshape(int w, int h)
  88. {
  89.   glViewport(0, 0, w, h);
  90.   glMatrixMode(GL_PROJECTION);
  91.   glLoadIdentity();
  92.   gluOrtho2D(0, w, 0, h);
  93.   glMatrixMode(GL_MODELVIEW);
  94.   glLoadIdentity();
  95.   glTranslatef(0, h - imgheight, 0);
  96.   glRasterPos2i(0, 0);
  97.   glBitmap(0, 0, 0, 0, ax, -ay, NULL);
  98. }
  99. void
  100. display(void)
  101. {
  102.   /* Clear the color buffer. */
  103.   glClear(GL_COLOR_BUFFER_BIT);
  104. #ifdef GL_EXT_abgr
  105. #define APPROPRIATE_FORMAT (hasABGR ? GL_ABGR_EXT : GL_RGBA)
  106. #else
  107. #define APPROPRIATE_FORMAT GL_RGBA
  108. #endif
  109.   /* Re-blit the image. */
  110.   glDrawPixels(imgwidth, imgheight,
  111.     APPROPRIATE_FORMAT, GL_UNSIGNED_BYTE,
  112.     raster);
  113.   /* Swap the buffers if necessary. */
  114.   if (doubleBuffer) {
  115.     glutSwapBuffers();
  116.   } else {
  117.     glFlush();
  118.   }
  119. }
  120. static int moving = 0, ox, oy;
  121. void
  122. mouse(int button, int state, int x, int y)
  123. {
  124.   if (button == GLUT_LEFT_BUTTON) {
  125.     if (state == GLUT_DOWN) {
  126.       /* Left mouse button press.  Update last seen mouse position. And set
  127.          "moving" true since button is pressed. */
  128.       ox = x;
  129.       oy = y;
  130.       moving = 1;
  131.     } else {
  132.       /* Left mouse button released; unset "moving" since button no longer
  133.          pressed. */
  134.       moving = 0;
  135.     }
  136.   }
  137. }
  138. void
  139. motion(int x, int y)
  140. {
  141.   /* If there is mouse motion with the left button held down... */
  142.   if (moving) {
  143.     /* Figure out the offset from the last mouse position seen. */
  144.     ax += (x - ox);
  145.     ay += (y - oy);
  146.     /* Offset the raster position based on the just calculated mouse position 
  147.        delta.  Use a null glBitmap call to offset the raster position in
  148.        window coordinates. */
  149.     glBitmap(0, 0, 0, 0, x - ox, oy - y, NULL);
  150.     /* Request a window redraw. */
  151.     glutPostRedisplay();
  152.     /* Update last seen mouse position. */
  153.     ox = x;
  154.     oy = y;
  155.   }
  156. }
  157. void
  158. option(int value)
  159. {
  160.   /* RGB to NTSC luminance color conversion matrix. */
  161.   static GLfloat rgb2luminance[16] =
  162.   {
  163.     0.30, 0.30, 0.30, 0.30,  /* 30% red. */
  164.     0.59, 0.59, 0.59, 0.59,  /* 59% green. */
  165.     0.11, 0.11, 0.11, 0.11,  /* 11% blue. */
  166.     0.00, 0.00, 0.00, 0.00  /* 0% alpha. */
  167.   };
  168.   switch (value) {
  169.   case 1:
  170. #ifdef GL_EXT_convolution
  171.     glDisable(GL_CONVOLUTION_2D_EXT);
  172.     break;
  173.   case 2:
  174.     glEnable(GL_CONVOLUTION_2D_EXT);
  175.     glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
  176.       GL_RGB, 7, 7, GL_RGB, GL_FLOAT, rgbBlur);
  177.     break;
  178.   case 3:
  179.     glEnable(GL_CONVOLUTION_2D_EXT);
  180.     glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
  181.       GL_RGB, 3, 3, GL_RGB, GL_FLOAT, rgbSharpen);
  182.     break;
  183.   case 4:
  184.     glEnable(GL_CONVOLUTION_2D_EXT);
  185.     glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
  186.       GL_RGB, 3, 3, GL_RGB, GL_FLOAT, rgbEdgeDetect);
  187. #endif
  188.     break;
  189. #ifdef GL_SGI_color_matrix
  190.   case 5:
  191.     luminance = 1 - luminance;  /* Toggle. */
  192.     glMatrixMode(GL_COLOR);
  193.     if (luminance) {
  194.       glLoadMatrixf(rgb2luminance);
  195.     } else {
  196.       glLoadIdentity();
  197.     }
  198.     glMatrixMode(GL_MODELVIEW);
  199. #endif
  200.     break;
  201.   case 666:
  202.     exit(0);
  203.     break;
  204.   }
  205.   glutPostRedisplay();
  206. }
  207. int
  208. main(int argc, char **argv)
  209. {
  210.   TIFF *tif;
  211.   char emsg[1024];
  212.   int i;
  213.   glutInit(&argc, argv);
  214.   for (i = 1; i < argc; i++) {
  215.     if (!strcmp(argv[i], "-sb")) {
  216.       doubleBuffer = 0;
  217.     } else {
  218.       filename = argv[i];
  219.     }
  220.   }
  221.   if (filename == NULL) {
  222.     fprintf(stderr, "usage: showtiff [GLUT-options] [-sb] TIFF-filen");
  223.     exit(1);
  224.   }
  225.   tif = TIFFOpen(filename, "r");
  226.   if (tif == NULL) {
  227.     fprintf(stderr, "Problem showing %sn", filename);
  228.     exit(1);
  229.   }
  230.   if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
  231.     npixels = (tsize_t) (img.width * img.height);
  232.     raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
  233.     if (raster != NULL) {
  234.       if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
  235.         TIFFError(filename, emsg);
  236.         exit(1);
  237.       }
  238.     }
  239.     TIFFRGBAImageEnd(&img);
  240.   } else {
  241.     TIFFError(filename, emsg);
  242.     exit(1);
  243.   }
  244.   if (doubleBuffer) {
  245.     glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
  246.   } else {
  247.     glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
  248.   }
  249.   imgwidth = (int) img.width;
  250.   imgheight = (int) img.height;
  251.   glutInitWindowSize(imgwidth, imgheight);
  252.   glutCreateWindow("showtiff");
  253.   glutReshapeFunc(reshape);
  254.   glutDisplayFunc(display);
  255.   glutMouseFunc(mouse);
  256.   glutMotionFunc(motion);
  257. #ifdef GL_EXT_abgr
  258.   if (glutExtensionSupported("GL_EXT_abgr")) {
  259.     hasABGR = 1;
  260.   }
  261. #endif
  262. #ifdef GL_EXT_convolution
  263.   if (glutExtensionSupported("GL_EXT_convolution")) {
  264.     hasConvolve = 1;
  265.   } else {
  266.     while (glGetError() != GL_NO_ERROR);  /* Clear any OpenGL errors. */
  267.     /* The following glDisable would be a no-op whether done on a freshly
  268.        initialized OpenGL context whether convolution is supported or not.
  269.        The only difference should be an OpenGL error should be reported if
  270.        the GL_CONVOLUTION_2D_EXT is not understood (ie, convolution is not
  271.        supported at all). */
  272.     glDisable(GL_CONVOLUTION_2D_EXT);
  273.     if (glGetError() == GL_NO_ERROR) {
  274.       /* RealityEngine only partially implements the convolve extension and
  275.          hence does not advertise the extension in its extension string (See
  276.          MACHINE DEPENDENCIES section of the glConvolutionFilter2DEXT man
  277.          page). We limit this program to use only the convolve functionality
  278.          supported by RealityEngine so we test if OpenGL lets us enable
  279.          convolution without an error (the indication that convolution is
  280.          partially supported). */
  281.       hasConvolve = 1;
  282.     }
  283.     /* Clear any further OpenGL errors (hopefully there should have only been 
  284.        one or zero though). */
  285.     while (glGetError() != GL_NO_ERROR);
  286.   }
  287. #endif
  288. #ifdef GL_SGI_color_matrix
  289.   if (glutExtensionSupported("GL_SGI_color_matrix")) {
  290.     hasColorMatrix = 1;
  291.   }
  292. #endif
  293.   /* If cannot directly display ABGR format, we need to reverse the component
  294.      ordering in each pixel. :-( */
  295.   if (!hasABGR) {
  296.     int i;
  297.     for (i = 0; i < npixels; i++) {
  298.       register unsigned char *cp = (unsigned char *) &raster[i];
  299.       int t;
  300.       t = cp[3];
  301.       cp[3] = cp[0];
  302.       cp[0] = t;
  303.       t = cp[2];
  304.       cp[2] = cp[1];
  305.       cp[1] = t;
  306.     }
  307.   }
  308.   glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
  309.   initKernels();
  310.   glutCreateMenu(option);
  311.   glutAddMenuEntry("Normal", 1);
  312. #ifdef GL_EXT_convolution
  313.   if (hasConvolve) {
  314.     glutAddMenuEntry("7x7 Blur", 2);
  315.     glutAddMenuEntry("3x3 Sharpen", 3);
  316.     glutAddMenuEntry("3x3 Edge Detect", 4);
  317.   }
  318. #endif
  319. #ifdef GL_SGI_color_matrix
  320.   if (hasColorMatrix) {
  321.     glutAddMenuEntry("Toggle Luminance/RGB", 5);
  322.   }
  323. #endif
  324.   glutAddMenuEntry("Quit", 666);
  325.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  326.   /* Use a gray background so TIFF images with black backgrounds will
  327.      show against textiff's background. */
  328.   glClearColor(0.2, 0.2, 0.2, 1.0);
  329.   glutMainLoop();
  330.   return 0;             /* ANSI C requires main to return int. */
  331. }