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

GIS编程

开发平台:

Visual C++

  1. /* readtex.c */
  2. /* 
  3.  * Read an SGI .rgb image file and generate a mipmap texture set.
  4.  * Much of this code was borrowed from SGI's tk OpenGL toolkit.
  5.  */
  6. #include <GL/glut.h>
  7. #include <stdio.h>
  8. #include <stdlib.h>
  9. #include <string.h>
  10. #include "readtex.h"
  11. #ifndef SEEK_SET
  12. #define SEEK_SET 0
  13. #endif
  14. /* RGB Image Structure */
  15. typedef struct _TK_RGBImageRec {
  16.   GLint sizeX, sizeY;
  17.   GLint components;
  18.   unsigned char *data;
  19. } TK_RGBImageRec;
  20. /******************************************************************************/
  21. typedef struct _rawImageRec {
  22.   unsigned short imagic;
  23.   unsigned short type;
  24.   unsigned short dim;
  25.   unsigned short sizeX, sizeY, sizeZ;
  26.   unsigned long min, max;
  27.   unsigned long wasteBytes;
  28.   char name[80];
  29.   unsigned long colorMap;
  30.   FILE *file;
  31.   unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
  32.   unsigned long rleEnd;
  33.   GLuint *rowStart;
  34.   GLint *rowSize;
  35. } rawImageRec;
  36. /******************************************************************************/
  37. static void 
  38. ConvertShort(unsigned short *array, size_t length)
  39. {
  40.   unsigned short b1, b2;
  41.   unsigned char *ptr;
  42.   ptr = (unsigned char *) array;
  43.   while (length--) {
  44.     b1 = *ptr++;
  45.     b2 = *ptr++;
  46.     *array++ = (b1 << 8) | (b2);
  47.   }
  48. }
  49. static void 
  50. ConvertLong(GLuint * array, size_t length)
  51. {
  52.   unsigned long b1, b2, b3, b4;
  53.   unsigned char *ptr;
  54.   ptr = (unsigned char *) array;
  55.   while (length--) {
  56.     b1 = *ptr++;
  57.     b2 = *ptr++;
  58.     b3 = *ptr++;
  59.     b4 = *ptr++;
  60.     *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
  61.   }
  62. }
  63. static rawImageRec *
  64. RawImageOpen(const char *fileName)
  65. {
  66.   union {
  67.     int testWord;
  68.     char testByte[4];
  69.   } endianTest;
  70.   rawImageRec *raw;
  71.   GLenum swapFlag;
  72.   int x;
  73.   endianTest.testWord = 1;
  74.   if (endianTest.testByte[0] == 1) {
  75.     swapFlag = GL_TRUE;
  76.   } else {
  77.     swapFlag = GL_FALSE;
  78.   }
  79.   raw = (rawImageRec *) malloc(sizeof(rawImageRec));
  80.   if (raw == NULL) {
  81.     fprintf(stderr, "Out of memory!n");
  82.     return NULL;
  83.   }
  84.   if ((raw->file = fopen(fileName, "rb")) == NULL) {
  85.     perror(fileName);
  86.     return NULL;
  87.   }
  88.   fread(raw, 1, 12, raw->file);
  89.   if (swapFlag) {
  90.     ConvertShort(&raw->imagic, 6);
  91.   }
  92.   raw->tmp = (unsigned char *) malloc(raw->sizeX * 256);
  93.   if (raw->tmp == NULL) {
  94.     fprintf(stderr, "Out of memory!n");
  95.     return NULL;
  96.   }
  97.   raw->tmpR = (unsigned char *) malloc(raw->sizeX * 256);
  98.   if (raw->tmpR == NULL) {
  99.     fprintf(stderr, "Out of memory!n");
  100.     return NULL;
  101.   }
  102.   if (raw->sizeZ > 1) {
  103.     raw->tmpG = (unsigned char *) malloc(raw->sizeX * 256);
  104.     raw->tmpB = (unsigned char *) malloc(raw->sizeX * 256);
  105.     if (raw->tmpG == NULL || raw->tmpB == NULL) {
  106.       fprintf(stderr, "Out of memory!n");
  107.       return NULL;
  108.     }
  109.     if (raw->sizeZ == 4) {
  110.       raw->tmpA = (unsigned char *) malloc(raw->sizeX * 256);
  111.       if (raw->tmpA == NULL) {
  112.         fprintf(stderr, "Out of memory!n");
  113.         return NULL;
  114.       }
  115.     }
  116.   }
  117.   if ((raw->type & 0xFF00) == 0x0100) {
  118.     x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
  119.     raw->rowStart = (GLuint *) malloc(x);
  120.     raw->rowSize = (GLint *) malloc(x);
  121.     if (raw->rowStart == NULL || raw->rowSize == NULL) {
  122.       fprintf(stderr, "Out of memory!n");
  123.       return NULL;
  124.     }
  125.     raw->rleEnd = 512 + (2 * x);
  126.     fseek(raw->file, 512, SEEK_SET);
  127.     fread(raw->rowStart, 1, x, raw->file);
  128.     fread(raw->rowSize, 1, x, raw->file);
  129.     if (swapFlag) {
  130.       ConvertLong(raw->rowStart, x / sizeof(GLuint));
  131.       ConvertLong((GLuint *) raw->rowSize, x / sizeof(GLint));
  132.     }
  133.   }
  134.   return raw;
  135. }
  136. static void 
  137. RawImageClose(rawImageRec * raw)
  138. {
  139.   fclose(raw->file);
  140.   free(raw->tmp);
  141.   free(raw->tmpR);
  142.   free(raw->tmpG);
  143.   free(raw->tmpB);
  144.   if (raw->sizeZ > 3) {
  145.     free(raw->tmpA);
  146.   }
  147.   free(raw);
  148. }
  149. static void 
  150. RawImageGetRow(rawImageRec * raw, unsigned char *buf, int y, int z)
  151. {
  152.   unsigned char *iPtr, *oPtr, pixel;
  153.   int count;
  154.   if ((raw->type & 0xFF00) == 0x0100) {
  155.     fseek(raw->file, (long) raw->rowStart[y + z * raw->sizeY], SEEK_SET);
  156.     fread(raw->tmp, 1, (size_t) raw->rowSize[y + z * raw->sizeY],
  157.       raw->file);
  158.     iPtr = raw->tmp;
  159.     oPtr = buf;
  160.     for (;;) {
  161.       pixel = *iPtr++;
  162.       count = (int) (pixel & 0x7F);
  163.       if (!count) {
  164.         return;
  165.       }
  166.       if (pixel & 0x80) {
  167.         while (count--) {
  168.           *oPtr++ = *iPtr++;
  169.         }
  170.       } else {
  171.         pixel = *iPtr++;
  172.         while (count--) {
  173.           *oPtr++ = pixel;
  174.         }
  175.       }
  176.     }
  177.   } else {
  178.     fseek(raw->file, 512 + (y * raw->sizeX) + (z * raw->sizeX * raw->sizeY),
  179.       SEEK_SET);
  180.     fread(buf, 1, raw->sizeX, raw->file);
  181.   }
  182. }
  183. static void 
  184. RawImageGetData(rawImageRec * raw, TK_RGBImageRec * final)
  185. {
  186.   unsigned char *ptr;
  187.   int i, j;
  188.   final->data = (unsigned char *) malloc((raw->sizeX + 1) * (raw->sizeY + 1) * 4);
  189.   if (final->data == NULL) {
  190.     fprintf(stderr, "Out of memory!n");
  191.   }
  192.   ptr = final->data;
  193.   for (i = 0; i < (int) (raw->sizeY); i++) {
  194.     RawImageGetRow(raw, raw->tmpR, i, 0);
  195.     if (raw->sizeZ > 1) {
  196.       RawImageGetRow(raw, raw->tmpG, i, 1);
  197.       RawImageGetRow(raw, raw->tmpB, i, 2);
  198.       if (raw->sizeZ > 3) {
  199.         RawImageGetRow(raw, raw->tmpA, i, 3);
  200.       }
  201.     }
  202.     for (j = 0; j < (int) (raw->sizeX); j++) {
  203.       *ptr++ = *(raw->tmpR + j);
  204.       if (raw->sizeZ > 1) {
  205.         *ptr++ = *(raw->tmpG + j);
  206.         *ptr++ = *(raw->tmpB + j);
  207.         if (raw->sizeZ > 3) {
  208.           *ptr++ = *(raw->tmpA + j);
  209.         }
  210.       }
  211.     }
  212.   }
  213. }
  214. static TK_RGBImageRec *
  215. tkRGBImageLoad(const char *fileName)
  216. {
  217.   rawImageRec *raw;
  218.   TK_RGBImageRec *final;
  219.   raw = RawImageOpen(fileName);
  220.   final = (TK_RGBImageRec *) malloc(sizeof(TK_RGBImageRec));
  221.   if (final == NULL) {
  222.     fprintf(stderr, "Out of memory!n");
  223.     return NULL;
  224.   }
  225.   final->sizeX = raw->sizeX;
  226.   final->sizeY = raw->sizeY;
  227.   final->components = raw->sizeZ;
  228.   RawImageGetData(raw, final);
  229.   RawImageClose(raw);
  230.   return final;
  231. }
  232. static void 
  233. FreeImage(TK_RGBImageRec * image)
  234. {
  235.   free(image->data);
  236.   free(image);
  237. }
  238. /* 
  239.  * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
  240.  * Input:  imageFile - name of .rgb to read
  241.  *         intFormat - internal texture format to use, or number of components
  242.  * Return:  GL_TRUE if success, GL_FALSE if error.
  243.  */
  244. GLboolean 
  245. LoadRGBMipmaps(const char *imageFile, GLint intFormat)
  246. {
  247.   GLint error;
  248.   GLenum format;
  249.   TK_RGBImageRec *image;
  250.   image = tkRGBImageLoad(imageFile);
  251.   if (!image) {
  252.     return GL_FALSE;
  253.   }
  254.   if (image->components == 3) {
  255.     format = GL_RGB;
  256.   } else if (image->components == 4) {
  257.     format = GL_RGBA;
  258.   } else if (image->components == 1) {
  259.     format = GL_LUMINANCE;
  260.     intFormat = 1;
  261.   } else {
  262.     /* not implemented */
  263.     fprintf(stderr,
  264.       "Error in LoadRGBMipmaps %d-component images not implementedn",
  265.       image->components);
  266.     return GL_FALSE;
  267.   }
  268.   error = gluBuild2DMipmaps(GL_TEXTURE_2D,
  269.     intFormat,
  270.     image->sizeX, image->sizeY,
  271.     format,
  272.     GL_UNSIGNED_BYTE,
  273.     image->data);
  274.   FreeImage(image);
  275.   return error ? GL_FALSE : GL_TRUE;
  276. }