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

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 writetiff writetiff.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
  6. /* writetiff is a simple OpenGL program that writes out a TIFF file named
  7.    gears.tif containing an OpenGL-rendered scene containing 3 gears (the
  8.    gears rendering code is lifted from Brian Paul's gears.c Mesa demo.
  9.    writetiff uses Sam Leffler's libtiff library to write to a TIFF an image
  10.    grabbed from the screen with glReadPixels.  NOTE:  If the window is
  11.    obscured when the glReadPixels is performed, obscured pixels will be
  12.    undefined when written into the TIFF file. */
  13. #include <stdlib.h>
  14. #include <math.h>
  15. #include <GL/glut.h>
  16. #include <tiffio.h>     /* Sam Leffler's libtiff library. */
  17. /* Some <math.h> files do not define M_PI... */
  18. #ifndef M_PI
  19. #define M_PI 3.14159265358979323846
  20. #endif
  21. static int W, H;
  22. int
  23. writetiff(char *filename, char *description,
  24.   int x, int y, int width, int height, int compression)
  25. {
  26.   TIFF *file;
  27.   GLubyte *image, *p;
  28.   int i;
  29.   file = TIFFOpen(filename, "w");
  30.   if (file == NULL) {
  31.     return 1;
  32.   }
  33.   image = (GLubyte *) malloc(width * height * sizeof(GLubyte) * 3);
  34.   /* OpenGL's default 4 byte pack alignment would leave extra bytes at the
  35.      end of each image row so that each full row contained a number of bytes
  36.      divisible by 4.  Ie, an RGB row with 3 pixels and 8-bit componets would
  37.      be laid out like "RGBRGBRGBxxx" where the last three "xxx" bytes exist
  38.      just to pad the row out to 12 bytes (12 is divisible by 4). To make sure
  39.      the rows are packed as tight as possible (no row padding), set the pack
  40.      alignment to 1. */
  41.   glPixelStorei(GL_PACK_ALIGNMENT, 1);
  42.   glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
  43.   TIFFSetField(file, TIFFTAG_IMAGEWIDTH, (uint32) width);
  44.   TIFFSetField(file, TIFFTAG_IMAGELENGTH, (uint32) height);
  45.   TIFFSetField(file, TIFFTAG_BITSPERSAMPLE, 8);
  46.   TIFFSetField(file, TIFFTAG_COMPRESSION, compression);
  47.   TIFFSetField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  48.   TIFFSetField(file, TIFFTAG_SAMPLESPERPIXEL, 3);
  49.   TIFFSetField(file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  50.   TIFFSetField(file, TIFFTAG_ROWSPERSTRIP, 1);
  51.   TIFFSetField(file, TIFFTAG_IMAGEDESCRIPTION, description);
  52.   p = image;
  53.   for (i = height - 1; i >= 0; i--) {
  54.     if (TIFFWriteScanline(file, p, i, 0) < 0) {
  55.       free(image);
  56.       TIFFClose(file);
  57.       return 1;
  58.     }
  59.     p += width * sizeof(GLubyte) * 3;
  60.   }
  61.   TIFFClose(file);
  62.   return 0;
  63. }
  64. /**
  65.   Draw a gear wheel.  You'll probably want to call this function when
  66.   building a display list since we do a lot of trig here.
  67.  
  68.   Input:  inner_radius - radius of hole at center
  69.           outer_radius - radius at center of teeth
  70.           width - width of gear
  71.           teeth - number of teeth
  72.           tooth_depth - depth of tooth
  73.  **/
  74. static void
  75. gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
  76.   GLint teeth, GLfloat tooth_depth)
  77. {
  78.   GLint i;
  79.   GLfloat r0, r1, r2;
  80.   GLfloat angle, da;
  81.   GLfloat u, v, len;
  82.   r0 = inner_radius;
  83.   r1 = outer_radius - tooth_depth / 2.0;
  84.   r2 = outer_radius + tooth_depth / 2.0;
  85.   da = 2.0 * M_PI / teeth / 4.0;
  86.   glShadeModel(GL_FLAT);
  87.   glNormal3f(0.0, 0.0, 1.0);
  88.   /* draw front face */
  89.   glBegin(GL_QUAD_STRIP);
  90.   for (i = 0; i <= teeth; i++) {
  91.     angle = i * 2.0 * M_PI / teeth;
  92.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  93.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  94.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  95.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  96.   }
  97.   glEnd();
  98.   /* draw front sides of teeth */
  99.   glBegin(GL_QUADS);
  100.   da = 2.0 * M_PI / teeth / 4.0;
  101.   for (i = 0; i < teeth; i++) {
  102.     angle = i * 2.0 * M_PI / teeth;
  103.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  104.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
  105.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
  106.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  107.   }
  108.   glEnd();
  109.   glNormal3f(0.0, 0.0, -1.0);
  110.   /* draw back face */
  111.   glBegin(GL_QUAD_STRIP);
  112.   for (i = 0; i <= teeth; i++) {
  113.     angle = i * 2.0 * M_PI / teeth;
  114.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  115.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  116.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  117.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  118.   }
  119.   glEnd();
  120.   /* draw back sides of teeth */
  121.   glBegin(GL_QUADS);
  122.   da = 2.0 * M_PI / teeth / 4.0;
  123.   for (i = 0; i < teeth; i++) {
  124.     angle = i * 2.0 * M_PI / teeth;
  125.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  126.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
  127.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
  128.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  129.   }
  130.   glEnd();
  131.   /* draw outward faces of teeth */
  132.   glBegin(GL_QUAD_STRIP);
  133.   for (i = 0; i < teeth; i++) {
  134.     angle = i * 2.0 * M_PI / teeth;
  135.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  136.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  137.     u = r2 * cos(angle + da) - r1 * cos(angle);
  138.     v = r2 * sin(angle + da) - r1 * sin(angle);
  139.     len = sqrt(u * u + v * v);
  140.     u /= len;
  141.     v /= len;
  142.     glNormal3f(v, -u, 0.0);
  143.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
  144.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
  145.     glNormal3f(cos(angle), sin(angle), 0.0);
  146.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
  147.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
  148.     u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
  149.     v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
  150.     glNormal3f(v, -u, 0.0);
  151.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  152.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  153.     glNormal3f(cos(angle), sin(angle), 0.0);
  154.   }
  155.   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
  156.   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
  157.   glEnd();
  158.   glShadeModel(GL_SMOOTH);
  159.   /* draw inside radius cylinder */
  160.   glBegin(GL_QUAD_STRIP);
  161.   for (i = 0; i <= teeth; i++) {
  162.     angle = i * 2.0 * M_PI / teeth;
  163.     glNormal3f(-cos(angle), -sin(angle), 0.0);
  164.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  165.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  166.   }
  167.   glEnd();
  168. }
  169. static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
  170. static GLint gear1, gear2, gear3;
  171. static GLfloat angle = 0.0;
  172. static void
  173. draw(void)
  174. {
  175.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  176.   glPushMatrix();
  177.   glRotatef(view_rotx, 1.0, 0.0, 0.0);
  178.   glRotatef(view_roty, 0.0, 1.0, 0.0);
  179.   glRotatef(view_rotz, 0.0, 0.0, 1.0);
  180.   glPushMatrix();
  181.   glTranslatef(-3.0, -2.0, 0.0);
  182.   glRotatef(angle, 0.0, 0.0, 1.0);
  183.   glCallList(gear1);
  184.   glPopMatrix();
  185.   glPushMatrix();
  186.   glTranslatef(3.1, -2.0, 0.0);
  187.   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
  188.   glCallList(gear2);
  189.   glPopMatrix();
  190.   glPushMatrix();
  191.   glTranslatef(-3.1, 4.2, 0.0);
  192.   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
  193.   glCallList(gear3);
  194.   glPopMatrix();
  195.   glPopMatrix();
  196.   glFlush();
  197. }
  198. static void
  199. init(void)
  200. {
  201.   static GLfloat pos[4] =
  202.   {5.0, 5.0, 10.0, 0.0};
  203.   static GLfloat red[4] =
  204.   {0.8, 0.1, 0.0, 1.0};
  205.   static GLfloat green[4] =
  206.   {0.0, 0.8, 0.2, 1.0};
  207.   static GLfloat blue[4] =
  208.   {0.2, 0.2, 1.0, 1.0};
  209.   glLightfv(GL_LIGHT0, GL_POSITION, pos);
  210.   glEnable(GL_CULL_FACE);
  211.   glEnable(GL_LIGHTING);
  212.   glEnable(GL_LIGHT0);
  213.   glEnable(GL_DEPTH_TEST);
  214.   /* make the gears */
  215.   gear1 = glGenLists(1);
  216.   glNewList(gear1, GL_COMPILE);
  217.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
  218.   gear(1.0, 4.0, 1.0, 20, 0.7);
  219.   glEndList();
  220.   gear2 = glGenLists(1);
  221.   glNewList(gear2, GL_COMPILE);
  222.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
  223.   gear(0.5, 2.0, 2.0, 10, 0.7);
  224.   glEndList();
  225.   gear3 = glGenLists(1);
  226.   glNewList(gear3, GL_COMPILE);
  227.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
  228.   gear(1.3, 2.0, 0.5, 10, 0.7);
  229.   glEndList();
  230.   glEnable(GL_NORMALIZE);
  231.   glMatrixMode(GL_PROJECTION);
  232.   glLoadIdentity();
  233.   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0);
  234.   glMatrixMode(GL_MODELVIEW);
  235.   glLoadIdentity();
  236.   glTranslatef(0.0, 0.0, -40.0);
  237. }
  238. static void
  239. reshape(int width, int height)
  240. {
  241.   glViewport(0, 0, (GLint) width, (GLint) height);
  242.   W = width;
  243.   H = height;
  244. }
  245. static void
  246. menu(int value)
  247. {
  248.   switch (value) {
  249.   case 1:
  250.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_LZW);
  251.     break;
  252.   case 2:
  253.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_NONE);
  254.     break;
  255.   case 3:
  256.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_PACKBITS);
  257.     break;
  258.   }
  259. }
  260. main(int argc, char *argv[])
  261. {
  262.   glutInit(&argc, argv);
  263.   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
  264.   glutCreateWindow("writetiff");
  265.   init();
  266.   glutDisplayFunc(draw);
  267.   glutReshapeFunc(reshape);
  268.   glutCreateMenu(menu);
  269.   glutAddMenuEntry("Write gears.tiff (LZW compressed)", 1);
  270.   glutAddMenuEntry("Write gears.tiff (No compression)", 2);
  271.   glutAddMenuEntry("Write gears.tiff (Packbits)", 3);
  272.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  273.   glutMainLoop();
  274.   return 0;             /* ANSI C requires main to return int. */
  275. }