Clone of mesa.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

readtex.c 8.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367
  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/gl.h>
  7. #include <GL/glu.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include "readtex.h"
  12. #ifndef SEEK_SET
  13. # define SEEK_SET 0
  14. #endif
  15. /*
  16. ** RGB Image Structure
  17. */
  18. typedef struct _TK_RGBImageRec {
  19. GLint sizeX, sizeY;
  20. GLint components;
  21. unsigned char *data;
  22. } TK_RGBImageRec;
  23. /******************************************************************************/
  24. typedef struct _rawImageRec {
  25. unsigned short imagic;
  26. unsigned short type;
  27. unsigned short dim;
  28. unsigned short sizeX, sizeY, sizeZ;
  29. unsigned long min, max;
  30. unsigned long wasteBytes;
  31. char name[80];
  32. unsigned long colorMap;
  33. FILE *file;
  34. unsigned char *tmp, *tmpR, *tmpG, *tmpB, *tmpA;
  35. unsigned long rleEnd;
  36. GLuint *rowStart;
  37. GLint *rowSize;
  38. } rawImageRec;
  39. /******************************************************************************/
  40. static void ConvertShort(unsigned short *array, long length)
  41. {
  42. unsigned long b1, b2;
  43. unsigned char *ptr;
  44. ptr = (unsigned char *)array;
  45. while (length--) {
  46. b1 = *ptr++;
  47. b2 = *ptr++;
  48. *array++ = (unsigned short) ((b1 << 8) | (b2));
  49. }
  50. }
  51. static void ConvertLong(GLuint *array, long length)
  52. {
  53. unsigned long b1, b2, b3, b4;
  54. unsigned char *ptr;
  55. ptr = (unsigned char *)array;
  56. while (length--) {
  57. b1 = *ptr++;
  58. b2 = *ptr++;
  59. b3 = *ptr++;
  60. b4 = *ptr++;
  61. *array++ = (b1 << 24) | (b2 << 16) | (b3 << 8) | (b4);
  62. }
  63. }
  64. static rawImageRec *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. raw->tmpR = (unsigned char *)malloc(raw->sizeX*256);
  94. raw->tmpG = (unsigned char *)malloc(raw->sizeX*256);
  95. raw->tmpB = (unsigned char *)malloc(raw->sizeX*256);
  96. if (raw->sizeZ==4) {
  97. raw->tmpA = (unsigned char *)malloc(raw->sizeX*256);
  98. }
  99. if (raw->tmp == NULL || raw->tmpR == NULL || raw->tmpG == NULL ||
  100. raw->tmpB == NULL) {
  101. fprintf(stderr, "Out of memory!\n");
  102. return NULL;
  103. }
  104. if ((raw->type & 0xFF00) == 0x0100) {
  105. x = raw->sizeY * raw->sizeZ * sizeof(GLuint);
  106. raw->rowStart = (GLuint *)malloc(x);
  107. raw->rowSize = (GLint *)malloc(x);
  108. if (raw->rowStart == NULL || raw->rowSize == NULL) {
  109. fprintf(stderr, "Out of memory!\n");
  110. return NULL;
  111. }
  112. raw->rleEnd = 512 + (2 * x);
  113. fseek(raw->file, 512, SEEK_SET);
  114. fread(raw->rowStart, 1, x, raw->file);
  115. fread(raw->rowSize, 1, x, raw->file);
  116. if (swapFlag) {
  117. ConvertLong(raw->rowStart, (long) (x/sizeof(GLuint)));
  118. ConvertLong((GLuint *)raw->rowSize, (long) (x/sizeof(GLint)));
  119. }
  120. }
  121. return raw;
  122. }
  123. static void RawImageClose(rawImageRec *raw)
  124. {
  125. fclose(raw->file);
  126. free(raw->tmp);
  127. free(raw->tmpR);
  128. free(raw->tmpG);
  129. free(raw->tmpB);
  130. if (raw->sizeZ>3) {
  131. free(raw->tmpA);
  132. }
  133. free(raw);
  134. }
  135. static void RawImageGetRow(rawImageRec *raw, unsigned char *buf, int y, int z)
  136. {
  137. unsigned char *iPtr, *oPtr, pixel;
  138. int count, done = 0;
  139. if ((raw->type & 0xFF00) == 0x0100) {
  140. fseek(raw->file, (long) raw->rowStart[y+z*raw->sizeY], SEEK_SET);
  141. fread(raw->tmp, 1, (unsigned int)raw->rowSize[y+z*raw->sizeY],
  142. raw->file);
  143. iPtr = raw->tmp;
  144. oPtr = buf;
  145. while (!done) {
  146. pixel = *iPtr++;
  147. count = (int)(pixel & 0x7F);
  148. if (!count) {
  149. done = 1;
  150. return;
  151. }
  152. if (pixel & 0x80) {
  153. while (count--) {
  154. *oPtr++ = *iPtr++;
  155. }
  156. } else {
  157. pixel = *iPtr++;
  158. while (count--) {
  159. *oPtr++ = pixel;
  160. }
  161. }
  162. }
  163. } else {
  164. fseek(raw->file, 512+(y*raw->sizeX)+(z*raw->sizeX*raw->sizeY),
  165. SEEK_SET);
  166. fread(buf, 1, raw->sizeX, raw->file);
  167. }
  168. }
  169. static void RawImageGetData(rawImageRec *raw, TK_RGBImageRec *final)
  170. {
  171. unsigned char *ptr;
  172. int i, j;
  173. final->data = (unsigned char *)malloc((raw->sizeX+1)*(raw->sizeY+1)*4);
  174. if (final->data == NULL) {
  175. fprintf(stderr, "Out of memory!\n");
  176. }
  177. ptr = final->data;
  178. for (i = 0; i < (int)(raw->sizeY); i++) {
  179. RawImageGetRow(raw, raw->tmpR, i, 0);
  180. RawImageGetRow(raw, raw->tmpG, i, 1);
  181. RawImageGetRow(raw, raw->tmpB, i, 2);
  182. if (raw->sizeZ>3) {
  183. RawImageGetRow(raw, raw->tmpA, i, 3);
  184. }
  185. for (j = 0; j < (int)(raw->sizeX); j++) {
  186. *ptr++ = *(raw->tmpR + j);
  187. *ptr++ = *(raw->tmpG + j);
  188. *ptr++ = *(raw->tmpB + j);
  189. if (raw->sizeZ>3) {
  190. *ptr++ = *(raw->tmpA + j);
  191. }
  192. }
  193. }
  194. }
  195. static TK_RGBImageRec *tkRGBImageLoad(const char *fileName)
  196. {
  197. rawImageRec *raw;
  198. TK_RGBImageRec *final;
  199. raw = RawImageOpen(fileName);
  200. if (!raw) {
  201. fprintf(stderr, "File not found\n");
  202. return NULL;
  203. }
  204. final = (TK_RGBImageRec *)malloc(sizeof(TK_RGBImageRec));
  205. if (final == NULL) {
  206. fprintf(stderr, "Out of memory!\n");
  207. return NULL;
  208. }
  209. final->sizeX = raw->sizeX;
  210. final->sizeY = raw->sizeY;
  211. final->components = raw->sizeZ;
  212. RawImageGetData(raw, final);
  213. RawImageClose(raw);
  214. return final;
  215. }
  216. static void FreeImage( TK_RGBImageRec *image )
  217. {
  218. free(image->data);
  219. free(image);
  220. }
  221. /*
  222. * Load an SGI .rgb file and generate a set of 2-D mipmaps from it.
  223. * Input: imageFile - name of .rgb to read
  224. * intFormat - internal texture format to use, or number of components
  225. * Return: GL_TRUE if success, GL_FALSE if error.
  226. */
  227. GLboolean LoadRGBMipmaps( const char *imageFile, GLint intFormat )
  228. {
  229. GLint w, h;
  230. return LoadRGBMipmaps2( imageFile, GL_TEXTURE_2D, intFormat, &w, &h );
  231. }
  232. GLboolean LoadRGBMipmaps2( const char *imageFile, GLenum target,
  233. GLint intFormat, GLint *width, GLint *height )
  234. {
  235. GLint error;
  236. GLenum format;
  237. TK_RGBImageRec *image;
  238. image = tkRGBImageLoad( imageFile );
  239. if (!image) {
  240. return GL_FALSE;
  241. }
  242. if (image->components==3) {
  243. format = GL_RGB;
  244. }
  245. else if (image->components==4) {
  246. format = GL_RGBA;
  247. }
  248. else {
  249. /* not implemented */
  250. fprintf(stderr,
  251. "Error in LoadRGBMipmaps %d-component images not implemented\n",
  252. image->components );
  253. return GL_FALSE;
  254. }
  255. error = gluBuild2DMipmaps( target,
  256. intFormat,
  257. image->sizeX, image->sizeY,
  258. format,
  259. GL_UNSIGNED_BYTE,
  260. image->data );
  261. *width = image->sizeX;
  262. *height = image->sizeY;
  263. FreeImage(image);
  264. return error ? GL_FALSE : GL_TRUE;
  265. }
  266. /*
  267. * Load an SGI .rgb file and return a pointer to the image data.
  268. * Input: imageFile - name of .rgb to read
  269. * Output: width - width of image
  270. * height - height of image
  271. * format - format of image (GL_RGB or GL_RGBA)
  272. * Return: pointer to image data or NULL if error
  273. */
  274. GLubyte *LoadRGBImage( const char *imageFile, GLint *width, GLint *height,
  275. GLenum *format )
  276. {
  277. TK_RGBImageRec *image;
  278. GLint bytes;
  279. GLubyte *buffer;
  280. image = tkRGBImageLoad( imageFile );
  281. if (!image) {
  282. return NULL;
  283. }
  284. if (image->components==3) {
  285. *format = GL_RGB;
  286. }
  287. else if (image->components==4) {
  288. *format = GL_RGBA;
  289. }
  290. else {
  291. /* not implemented */
  292. fprintf(stderr,
  293. "Error in LoadRGBImage %d-component images not implemented\n",
  294. image->components );
  295. return NULL;
  296. }
  297. *width = image->sizeX;
  298. *height = image->sizeY;
  299. bytes = image->sizeX * image->sizeY * image->components;
  300. buffer = (GLubyte *) malloc(bytes);
  301. if (!buffer)
  302. return NULL;
  303. memcpy( (void *) buffer, (void *) image->data, bytes );
  304. FreeImage(image);
  305. return buffer;
  306. }