showtiff.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:9k
- /* Copyright (c) Mark J. Kilgard, 1997. */
- /* This program is freely distributable without licensing fees and is
- provided without guarantee or warrantee expressed or implied. This
- program is -not- in the public domain. */
- /* X compile line: cc -o showtiff showtiff.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
- /* showtiff is a simple TIFF file viewer using Sam Leffler's libtiff, GLUT,
- and OpenGL. If OpenGL the image processing extensions for convolution and
- color matrix are supported by your OpenGL implementation, showtiff will let
- you blur, sharpen, edge detect, and color convert to grayscale the TIFF
- file. You can also move around the image within the window. */
- #include <stdlib.h>
- #include <string.h>
- #include <GL/glut.h>
- #include <tiffio.h> /* Sam Leffler's libtiff library. */
- TIFFRGBAImage img;
- uint32 *raster;
- tsize_t npixels;
- int imgwidth, imgheight;
- int hasABGR = 0;
- int hasConvolve = 0;
- int hasColorMatrix = 0;
- int doubleBuffer = 1;
- char *filename = NULL;
- int ax = 0, ay = 0;
- int luminance = 0;
- GLfloat rgbBlur[7][7][3];
- GLfloat rgbEdgeDetect[3][3][3];
- GLfloat rgbSharpen[3][3][3];
- void
- initKernels(void)
- {
- int x, y, c;
- /* A 7x7 "blurring" convolution kernel. This kernel will uniformly spread
- each pixel with its surrounding 7x7 pixels. The sum of the kernel
- elements is 1.0. */
- for (x = 0; x < 7; x++) {
- for (y = 0; y < 7; y++) {
- for (c = 0; c < 3; c++) {
- rgbBlur[x][y][c] = 1.0 / 49.0;
- }
- }
- }
- /* A 3x3 edge detection covolution kernel. The kernel is shown below.
- Notice how the elements of the kernel add up to zero. */
- /**********
- -1 -1 -1
- -1 8 -1
- -1 -1 -1
- **********/
- for (x = 0; x < 3; x++) {
- for (y = 0; y < 3; y++) {
- for (c = 0; c < 3; c++) {
- rgbEdgeDetect[x][y][c] = -1.0;
- }
- }
- }
- for (c = 0; c < 3; c++) {
- rgbEdgeDetect[1][1][c] = 8.0;
- }
- /* A 3x3 "sharpening" convolution kernel. The kernel is shown below.
- Notice how surrounding information is subtracted out of the central
- pixel while the central pixel is weighted heavily. The sum of the
- kernel elements is 1.0. */
- /*************
- -.5 -.5 -.5
- -.5 5 -.5
- -.5 -.5 -.5
- *************/
- for (x = 0; x < 3; x++) {
- for (y = 0; y < 3; y++) {
- for (c = 0; c < 3; c++) {
- rgbSharpen[x][y][c] = -0.5;
- }
- }
- }
- for (c = 0; c < 3; c++) {
- rgbSharpen[1][1][c] = 5.0;
- }
- }
- /* If resize is called, enable drawing into the full screen area
- (glViewport). Then setup the modelview and projection matrices to map 2D
- x,y coodinates directly onto pixels in the window (lower left origin).
- Then set the raster position (where the image would be drawn) to be offset
- from the upper left corner, and then offset by the current offset (using a
- null glBitmap). */
- void
- reshape(int w, int h)
- {
- glViewport(0, 0, w, h);
- glMatrixMode(GL_PROJECTION);
- glLoadIdentity();
- gluOrtho2D(0, w, 0, h);
- glMatrixMode(GL_MODELVIEW);
- glLoadIdentity();
- glTranslatef(0, h - imgheight, 0);
- glRasterPos2i(0, 0);
- glBitmap(0, 0, 0, 0, ax, -ay, NULL);
- }
- void
- display(void)
- {
- /* Clear the color buffer. */
- glClear(GL_COLOR_BUFFER_BIT);
- #ifdef GL_EXT_abgr
- #define APPROPRIATE_FORMAT (hasABGR ? GL_ABGR_EXT : GL_RGBA)
- #else
- #define APPROPRIATE_FORMAT GL_RGBA
- #endif
- /* Re-blit the image. */
- glDrawPixels(imgwidth, imgheight,
- APPROPRIATE_FORMAT, GL_UNSIGNED_BYTE,
- raster);
- /* Swap the buffers if necessary. */
- if (doubleBuffer) {
- glutSwapBuffers();
- } else {
- glFlush();
- }
- }
- static int moving = 0, ox, oy;
- void
- mouse(int button, int state, int x, int y)
- {
- if (button == GLUT_LEFT_BUTTON) {
- if (state == GLUT_DOWN) {
- /* Left mouse button press. Update last seen mouse position. And set
- "moving" true since button is pressed. */
- ox = x;
- oy = y;
- moving = 1;
- } else {
- /* Left mouse button released; unset "moving" since button no longer
- pressed. */
- moving = 0;
- }
- }
- }
- void
- motion(int x, int y)
- {
- /* If there is mouse motion with the left button held down... */
- if (moving) {
- /* Figure out the offset from the last mouse position seen. */
- ax += (x - ox);
- ay += (y - oy);
- /* Offset the raster position based on the just calculated mouse position
- delta. Use a null glBitmap call to offset the raster position in
- window coordinates. */
- glBitmap(0, 0, 0, 0, x - ox, oy - y, NULL);
- /* Request a window redraw. */
- glutPostRedisplay();
- /* Update last seen mouse position. */
- ox = x;
- oy = y;
- }
- }
- void
- option(int value)
- {
- /* RGB to NTSC luminance color conversion matrix. */
- static GLfloat rgb2luminance[16] =
- {
- 0.30, 0.30, 0.30, 0.30, /* 30% red. */
- 0.59, 0.59, 0.59, 0.59, /* 59% green. */
- 0.11, 0.11, 0.11, 0.11, /* 11% blue. */
- 0.00, 0.00, 0.00, 0.00 /* 0% alpha. */
- };
- switch (value) {
- case 1:
- #ifdef GL_EXT_convolution
- glDisable(GL_CONVOLUTION_2D_EXT);
- break;
- case 2:
- glEnable(GL_CONVOLUTION_2D_EXT);
- glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
- GL_RGB, 7, 7, GL_RGB, GL_FLOAT, rgbBlur);
- break;
- case 3:
- glEnable(GL_CONVOLUTION_2D_EXT);
- glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
- GL_RGB, 3, 3, GL_RGB, GL_FLOAT, rgbSharpen);
- break;
- case 4:
- glEnable(GL_CONVOLUTION_2D_EXT);
- glConvolutionFilter2DEXT(GL_CONVOLUTION_2D_EXT,
- GL_RGB, 3, 3, GL_RGB, GL_FLOAT, rgbEdgeDetect);
- #endif
- break;
- #ifdef GL_SGI_color_matrix
- case 5:
- luminance = 1 - luminance; /* Toggle. */
- glMatrixMode(GL_COLOR);
- if (luminance) {
- glLoadMatrixf(rgb2luminance);
- } else {
- glLoadIdentity();
- }
- glMatrixMode(GL_MODELVIEW);
- #endif
- break;
- case 666:
- exit(0);
- break;
- }
- glutPostRedisplay();
- }
- int
- main(int argc, char **argv)
- {
- TIFF *tif;
- char emsg[1024];
- int i;
- glutInit(&argc, argv);
- for (i = 1; i < argc; i++) {
- if (!strcmp(argv[i], "-sb")) {
- doubleBuffer = 0;
- } else {
- filename = argv[i];
- }
- }
- if (filename == NULL) {
- fprintf(stderr, "usage: showtiff [GLUT-options] [-sb] TIFF-filen");
- exit(1);
- }
- tif = TIFFOpen(filename, "r");
- if (tif == NULL) {
- fprintf(stderr, "Problem showing %sn", filename);
- exit(1);
- }
- if (TIFFRGBAImageBegin(&img, tif, 0, emsg)) {
- npixels = (tsize_t) (img.width * img.height);
- raster = (uint32 *) _TIFFmalloc(npixels * (tsize_t) sizeof(uint32));
- if (raster != NULL) {
- if (TIFFRGBAImageGet(&img, raster, img.width, img.height) == 0) {
- TIFFError(filename, emsg);
- exit(1);
- }
- }
- TIFFRGBAImageEnd(&img);
- } else {
- TIFFError(filename, emsg);
- exit(1);
- }
- if (doubleBuffer) {
- glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE);
- } else {
- glutInitDisplayMode(GLUT_RGB | GLUT_SINGLE);
- }
- imgwidth = (int) img.width;
- imgheight = (int) img.height;
- glutInitWindowSize(imgwidth, imgheight);
- glutCreateWindow("showtiff");
- glutReshapeFunc(reshape);
- glutDisplayFunc(display);
- glutMouseFunc(mouse);
- glutMotionFunc(motion);
- #ifdef GL_EXT_abgr
- if (glutExtensionSupported("GL_EXT_abgr")) {
- hasABGR = 1;
- }
- #endif
- #ifdef GL_EXT_convolution
- if (glutExtensionSupported("GL_EXT_convolution")) {
- hasConvolve = 1;
- } else {
- while (glGetError() != GL_NO_ERROR); /* Clear any OpenGL errors. */
- /* The following glDisable would be a no-op whether done on a freshly
- initialized OpenGL context whether convolution is supported or not.
- The only difference should be an OpenGL error should be reported if
- the GL_CONVOLUTION_2D_EXT is not understood (ie, convolution is not
- supported at all). */
- glDisable(GL_CONVOLUTION_2D_EXT);
- if (glGetError() == GL_NO_ERROR) {
- /* RealityEngine only partially implements the convolve extension and
- hence does not advertise the extension in its extension string (See
- MACHINE DEPENDENCIES section of the glConvolutionFilter2DEXT man
- page). We limit this program to use only the convolve functionality
- supported by RealityEngine so we test if OpenGL lets us enable
- convolution without an error (the indication that convolution is
- partially supported). */
- hasConvolve = 1;
- }
- /* Clear any further OpenGL errors (hopefully there should have only been
- one or zero though). */
- while (glGetError() != GL_NO_ERROR);
- }
- #endif
- #ifdef GL_SGI_color_matrix
- if (glutExtensionSupported("GL_SGI_color_matrix")) {
- hasColorMatrix = 1;
- }
- #endif
- /* If cannot directly display ABGR format, we need to reverse the component
- ordering in each pixel. :-( */
- if (!hasABGR) {
- int i;
- for (i = 0; i < npixels; i++) {
- register unsigned char *cp = (unsigned char *) &raster[i];
- int t;
- t = cp[3];
- cp[3] = cp[0];
- cp[0] = t;
- t = cp[2];
- cp[2] = cp[1];
- cp[1] = t;
- }
- }
- glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
- initKernels();
- glutCreateMenu(option);
- glutAddMenuEntry("Normal", 1);
- #ifdef GL_EXT_convolution
- if (hasConvolve) {
- glutAddMenuEntry("7x7 Blur", 2);
- glutAddMenuEntry("3x3 Sharpen", 3);
- glutAddMenuEntry("3x3 Edge Detect", 4);
- }
- #endif
- #ifdef GL_SGI_color_matrix
- if (hasColorMatrix) {
- glutAddMenuEntry("Toggle Luminance/RGB", 5);
- }
- #endif
- glutAddMenuEntry("Quit", 666);
- glutAttachMenu(GLUT_RIGHT_BUTTON);
- /* Use a gray background so TIFF images with black backgrounds will
- show against textiff's background. */
- glClearColor(0.2, 0.2, 0.2, 1.0);
- glutMainLoop();
- return 0; /* ANSI C requires main to return int. */
- }