tga.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // WARNING
  4. //
  5. // THIS DOES NOT DEAL WITH VERTICALLY FLIPPED DATA CORRECTLY
  6. //
  7. ////////////////////////////////////////////////////////////////////////////////
  8. /* This file is derived from (actually an earlier version of)... */
  9. /* The GIMP -- an image manipulation program
  10. * Copyright (C) 1995 Spencer Kimball and Peter Mattis
  11. *
  12. * $Id: tga.cpp,v 1.1.2.5 2007-05-10 02:10:07 elif Exp $
  13. * TrueVision Targa loading and saving file filter for the Gimp.
  14. * Targa code Copyright (C) 1997 Raphael FRANCOIS and Gordon Matzigkeit
  15. *
  16. * The Targa reading and writing code was written from scratch by
  17. * Raphael FRANCOIS <fraph@ibm.net> and Gordon Matzigkeit
  18. * <gord@gnu.ai.mit.edu> based on the TrueVision TGA File Format
  19. * Specification, Version 2.0:
  20. *
  21. * <URL:ftp://ftp.truevision.com/pub/TGA.File.Format.Spec/>
  22. *
  23. * It does not contain any code written for other TGA file loaders.
  24. * Not even the RLE handling. ;)
  25. *
  26. * This program is free software; you can redistribute it and/or modify
  27. * it under the terms of the GNU General Public License as published by
  28. * the Free Software Foundation; either version 2 of the License, or
  29. * (at your option) any later version.
  30. *
  31. * This program is distributed in the hope that it will be useful,
  32. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  33. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  34. * GNU General Public License for more details.
  35. *
  36. * You should have received a copy of the GNU General Public License
  37. * along with this program; if not, write to the Free Software
  38. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  39. */
  40. #include "tga.h"
  41. #include "../../opengl2/glext.h"
  42. #include <stdio.h>
  43. #include <stdlib.h>
  44. #include <string.h>
  45. #include <assert.h>
  46. static char error[256];
  47. static unsigned int _verbose = 0;
  48. static int totbytes = 0;
  49. typedef struct {
  50. unsigned char *statebuf;
  51. int statelen;
  52. int laststate;
  53. } RLEstate;
  54. IGL_INLINE static int
  55. std_fread(RLEstate * /*rleInfo*/, unsigned char *buf, size_t datasize, size_t nelems, FILE *fp)
  56. {
  57. if (_verbose > 1) {
  58. totbytes += nelems * datasize;
  59. printf("TGA: std_fread %d (total %d)\n",
  60. (int)(nelems * datasize), totbytes);
  61. }
  62. return fread(buf, datasize, nelems, fp);
  63. }
  64. #define MIN(a,b) (((a) < (b)) ? (a) : (b))
  65. #define RLE_PACKETSIZE 0x80
  66. /* Decode a bufferful of file. */
  67. IGL_INLINE static int
  68. rle_fread(RLEstate *rleInfo, unsigned char *vbuf, size_t datasize, size_t nelems, FILE *fp)
  69. {
  70. unsigned char *buf = vbuf;
  71. int j, k;
  72. int buflen, count, bytes, curbytes;
  73. unsigned char *p;
  74. /* Scale the buffer length. */
  75. buflen = nelems * datasize;
  76. j = 0;
  77. curbytes = totbytes;
  78. while (j < buflen) {
  79. if (rleInfo->laststate < rleInfo->statelen) {
  80. /* Copy bytes from our previously decoded buffer. */
  81. bytes = MIN(buflen - j, rleInfo->statelen - rleInfo->laststate);
  82. memcpy(buf + j, rleInfo->statebuf + rleInfo->laststate, bytes);
  83. j += bytes;
  84. rleInfo->laststate += bytes;
  85. /* If we used up all of our state bytes, then reset them. */
  86. if (rleInfo->laststate >= rleInfo->statelen) {
  87. rleInfo->laststate = 0;
  88. rleInfo->statelen = 0;
  89. }
  90. /* If we filled the buffer, then exit the loop. */
  91. if (j >= buflen) break;
  92. }
  93. /* Decode the next packet. */
  94. count = fgetc(fp);
  95. if (count == EOF) {
  96. if (_verbose) printf("TGA: hit EOF while looking for count\n");
  97. return j / datasize;
  98. }
  99. /* Scale the byte length to the size of the data. */
  100. bytes = ((count & ~RLE_PACKETSIZE) + 1) * datasize;
  101. if (j + bytes <= buflen) {
  102. /* We can copy directly into the image buffer. */
  103. p = buf + j;
  104. } else {
  105. #ifdef PROFILE
  106. printf("TGA: needed to use statebuf for %d bytes\n", buflen - j);
  107. #endif
  108. /* Allocate the state buffer if we haven't already. */
  109. if (!rleInfo->statebuf) {
  110. rleInfo->statebuf = (unsigned char *) malloc(RLE_PACKETSIZE * datasize);
  111. }
  112. p = rleInfo->statebuf;
  113. }
  114. if (count & RLE_PACKETSIZE) {
  115. /* Fill the buffer with the next value. */
  116. if (fread(p, datasize, 1, fp) != 1) {
  117. if (_verbose) {
  118. printf("TGA: EOF while reading %d/%d element RLE packet\n",
  119. bytes, (int)datasize);
  120. }
  121. return j / datasize;
  122. }
  123. /* Optimized case for single-byte encoded data. */
  124. if (datasize == 1) {
  125. memset(p + 1, *p, bytes - 1);
  126. } else {
  127. for (k = datasize; k < bytes; k += datasize) {
  128. memcpy(p + k, p, datasize);
  129. }
  130. }
  131. } else {
  132. /* Read in the buffer. */
  133. if (fread(p, bytes, 1, fp) != 1) {
  134. if (_verbose) {
  135. printf("TGA: EOF while reading %d/%d element raw packet\n",
  136. bytes, (int)datasize);
  137. }
  138. return j / datasize;
  139. }
  140. }
  141. if (_verbose > 1) {
  142. totbytes += bytes;
  143. if (_verbose > 2) {
  144. printf("TGA: %s packet %d/%d\n",
  145. (count & RLE_PACKETSIZE) ? "RLE" : "raw",
  146. bytes, totbytes);
  147. }
  148. }
  149. /* We may need to copy bytes from the state buffer. */
  150. if (p == rleInfo->statebuf) {
  151. rleInfo->statelen = bytes;
  152. } else {
  153. j += bytes;
  154. }
  155. }
  156. if (_verbose > 1) {
  157. printf("TGA: rle_fread %d/%d (total %d)\n",
  158. (int) ( nelems * datasize), totbytes - curbytes, totbytes);
  159. }
  160. return nelems;
  161. }
  162. IGL_INLINE igl::opengl::gliGenericImage *
  163. igl::opengl::gliReadTGA(FILE *fp, char *name, int /*hflip*/, int vflip)
  164. {
  165. igl::opengl::TgaHeader tgaHeader;
  166. igl::opengl::TgaFooter tgaFooter;
  167. char horzrev, vertrev;
  168. int width, height, bpp;
  169. int start, end, dir;
  170. int i, j, k;
  171. int pelbytes, wbytes;
  172. GLenum format;
  173. int components;
  174. RLEstate rleRec;
  175. RLEstate *rleInfo;
  176. int rle;
  177. int index, colors, length;
  178. GLubyte *cmap, *pixels, *data;
  179. int (*myfread)(RLEstate *rleInfo, unsigned char*, size_t, size_t, FILE*);
  180. igl::opengl::gliGenericImage *genericImage;
  181. /* Check the footer. */
  182. if (fseek(fp, 0L - sizeof(tgaFooter), SEEK_END)
  183. || fread(&tgaFooter, sizeof(tgaFooter), 1, fp) != 1) {
  184. sprintf(error, "TGA: Cannot read footer from \"%s\"", name);
  185. if (_verbose) printf("%s\n", error);
  186. return NULL;
  187. }
  188. /* Check the signature. */
  189. if (memcmp(tgaFooter.signature, TGA_SIGNATURE,
  190. sizeof(tgaFooter.signature)) == 0) {
  191. if (_verbose) printf("TGA: found New TGA\n");
  192. } else {
  193. if (_verbose) printf("TGA: found Original TGA\n");
  194. }
  195. if (fseek(fp, 0, SEEK_SET) ||
  196. fread(&tgaHeader, sizeof(tgaHeader), 1, fp) != 1) {
  197. sprintf(error, "TGA: Cannot read header from \"%s\"", name);
  198. if (_verbose) printf("%s\n", error);
  199. return NULL;
  200. }
  201. if (_verbose && tgaHeader.idLength) {
  202. char *idString = (char*) malloc(tgaHeader.idLength);
  203. if (fread(idString, tgaHeader.idLength, 1, fp) != 1) {
  204. sprintf(error, "TGA: Cannot read ID field in \"%s\"", name);
  205. printf("%s\n", error);
  206. } else {
  207. printf("TGA: ID field: \"%*s\"\n", tgaHeader.idLength, idString);
  208. }
  209. free(idString);
  210. } else {
  211. /* Skip the image ID field. */
  212. if (tgaHeader.idLength && fseek(fp, tgaHeader.idLength, SEEK_CUR)) {
  213. sprintf(error, "TGA: Cannot skip ID field in \"%s\"", name);
  214. if (_verbose) printf("%s\n", error);
  215. return NULL;
  216. }
  217. }
  218. /* Reassemble the multi-byte values correctly, regardless of
  219. host endianness. */
  220. width = (tgaHeader.widthHi << 8) | tgaHeader.widthLo;
  221. height = (tgaHeader.heightHi << 8) | tgaHeader.heightLo;
  222. bpp = tgaHeader.bpp;
  223. if (_verbose) {
  224. printf("TGA: width=%d, height=%d, bpp=%d\n", width, height, bpp);
  225. }
  226. horzrev = tgaHeader.descriptor & TGA_DESC_HORIZONTAL;
  227. vertrev = tgaHeader.descriptor & TGA_DESC_VERTICAL;
  228. //vertrev=0;
  229. // // JASON - we can force this stuff if we want
  230. // if( hflip )
  231. // horzrev = 1;
  232. if( vflip )
  233. vertrev = 1;
  234. if (_verbose && horzrev) printf("TGA: horizontal reversed\n");
  235. if (_verbose && vertrev) printf("TGA: vertical reversed\n");
  236. rle = 0;
  237. switch (tgaHeader.imageType) {
  238. case TGA_TYPE_MAPPED_RLE:
  239. rle = 1;
  240. if (_verbose) printf("TGA: run-length encoded\n");
  241. case TGA_TYPE_MAPPED:
  242. /* Test for alpha channel. */
  243. format = GL_COLOR_INDEX;
  244. components = 1;
  245. if (_verbose) {
  246. printf("TGA: %d bit indexed image (%d bit palette)\n",
  247. tgaHeader.colorMapSize, bpp);
  248. }
  249. break;
  250. case TGA_TYPE_GRAY_RLE:
  251. rle = 1;
  252. if (_verbose) printf("TGA: run-length encoded\n");
  253. case TGA_TYPE_GRAY:
  254. format = GL_LUMINANCE;
  255. components = 1;
  256. if (_verbose) printf("TGA: %d bit grayscale image\n", bpp);
  257. break;
  258. case TGA_TYPE_COLOR_RLE:
  259. rle = 1;
  260. if (_verbose) printf("TGA: run-length encoded\n");
  261. case TGA_TYPE_COLOR:
  262. /* Test for alpha channel. */
  263. if (bpp == 32) {
  264. format = GL_BGRA_EXT;
  265. components = 4;
  266. if (_verbose) {
  267. printf("TGA: %d bit color image with alpha channel\n", bpp);
  268. }
  269. } else {
  270. format = GL_BGR_EXT;
  271. components = 3;
  272. if (_verbose) printf("TGA: %d bit color image\n", bpp);
  273. }
  274. break;
  275. default:
  276. sprintf(error,
  277. "TGA: unrecognized image type %d\n", tgaHeader.imageType);
  278. if (_verbose) printf("%s\n", error);
  279. return NULL;
  280. }
  281. if ((format == GL_BGRA_EXT && bpp != 32) ||
  282. (format == GL_BGR_EXT && bpp != 24) ||
  283. ((format == GL_LUMINANCE || format == GL_COLOR_INDEX) && bpp != 8)) {
  284. /* FIXME: We haven't implemented bit-packed fields yet. */
  285. fprintf(stderr, "bpp %d, format %x\n", bpp, (unsigned int)format);
  286. sprintf(error, "TGA: channel sizes other than 8 bits are unimplemented");
  287. if (_verbose) printf("%s\n", error);
  288. return NULL;
  289. }
  290. /* Check that we have a color map only when we need it. */
  291. if (format == GL_COLOR_INDEX) {
  292. if (tgaHeader.colorMapType != 1) {
  293. sprintf(error, "TGA: indexed image has invalid color map type %d\n",
  294. tgaHeader.colorMapType);
  295. if (_verbose) printf("%s\n", error);
  296. return NULL;
  297. }
  298. } else if (tgaHeader.colorMapType != 0) {
  299. sprintf(error, "TGA: non-indexed image has invalid color map type %d\n",
  300. tgaHeader.colorMapType);
  301. if (_verbose) printf("%s\n", error);
  302. return NULL;
  303. }
  304. if (tgaHeader.colorMapType == 1) {
  305. /* We need to read in the colormap. */
  306. index = (tgaHeader.colorMapIndexHi << 8) | tgaHeader.colorMapIndexLo;
  307. length = (tgaHeader.colorMapLengthHi << 8) | tgaHeader.colorMapLengthLo;
  308. if (_verbose) {
  309. printf("TGA: reading color map (%d + %d) * (%d / 8)\n",
  310. index, length, tgaHeader.colorMapSize);
  311. }
  312. if (length == 0) {
  313. sprintf(error, "TGA: invalid color map length %d", length);
  314. if (_verbose) printf("%s\n", error);
  315. return NULL;
  316. }
  317. if (tgaHeader.colorMapSize != 24) {
  318. /* We haven't implemented bit-packed fields yet. */
  319. sprintf(error, "TGA: channel sizes other than 8 bits are unimplemented");
  320. if (_verbose) printf("%s\n", error);
  321. return NULL;
  322. }
  323. pelbytes = tgaHeader.colorMapSize / 8;
  324. colors = length + index;
  325. cmap = (GLubyte*)malloc (colors * pelbytes);
  326. /* Zero the entries up to the beginning of the map. */
  327. memset(cmap, 0, index * pelbytes);
  328. /* Read in the rest of the colormap. */
  329. if (fread(cmap, pelbytes, length, fp) != (size_t) length) {
  330. sprintf(error, "TGA: error reading colormap (ftell == %ld)\n",
  331. ftell (fp));
  332. if (_verbose) printf("%s\n", error);
  333. free(cmap);
  334. return NULL;
  335. }
  336. if (pelbytes >= 3) {
  337. /* Rearrange the colors from BGR to RGB. */
  338. int tmp;
  339. for (j = index; j < length * pelbytes; j += pelbytes) {
  340. tmp = cmap[j];
  341. cmap[j] = cmap[j + 2];
  342. cmap[j + 2] = tmp;
  343. }
  344. }
  345. } else {
  346. colors = 0;
  347. cmap = NULL;
  348. }
  349. /* Allocate the data. */
  350. pelbytes = bpp / 8;
  351. pixels = (unsigned char *) malloc (width * height * pelbytes);
  352. if (rle) {
  353. rleRec.statebuf = 0;
  354. rleRec.statelen = 0;
  355. rleRec.laststate = 0;
  356. rleInfo = &rleRec;
  357. myfread = rle_fread;
  358. } else {
  359. rleInfo = NULL;
  360. myfread = std_fread;
  361. }
  362. wbytes = width * pelbytes;
  363. if (vertrev) {
  364. start = 0;
  365. end = height;
  366. dir = 1;
  367. } else {
  368. /* We need to reverse loading order of rows. */
  369. start = height-1;
  370. end = -1;
  371. dir = -1;
  372. }
  373. for (i = start; i != end; i += dir) {
  374. data = pixels + i*wbytes;
  375. /* Suck in the data one row at a time. */
  376. if (myfread(rleInfo, data, pelbytes, width, fp) != width) {
  377. /* Probably premature end of file. */
  378. if (_verbose) {
  379. printf ("TGA: error reading (ftell == %ld, width=%d)\n",
  380. ftell(fp), width);
  381. }
  382. return NULL;
  383. }
  384. if (horzrev) {
  385. /* We need to mirror row horizontally. */
  386. for (j = 0; j < width/2; j++) {
  387. GLubyte tmp;
  388. for (k = 0; k < pelbytes; k++) {
  389. tmp = data[j*pelbytes+k];
  390. data[j*pelbytes+k] = data[(width-j-1)*pelbytes+k];
  391. data[(width-j-1)*pelbytes+k] = tmp;
  392. }
  393. }
  394. }
  395. }
  396. if (rle) {
  397. free(rleInfo->statebuf);
  398. }
  399. if (fgetc (fp) != EOF) {
  400. if (_verbose) printf ("TGA: too much input data, ignoring extra...\n");
  401. }
  402. genericImage = (igl::opengl::gliGenericImage*) malloc(sizeof(igl::opengl::gliGenericImage));
  403. genericImage->width = width;
  404. genericImage->height = height;
  405. genericImage->format = format;
  406. genericImage->components = components;
  407. genericImage->cmapEntries = colors;
  408. genericImage->cmapFormat = GL_BGR_EXT; // XXX fix me
  409. genericImage->cmap = cmap;
  410. genericImage->pixels = pixels;
  411. return genericImage;
  412. }
  413. IGL_INLINE int igl::opengl::gli_verbose(int new_verbose)
  414. {
  415. _verbose = new_verbose;
  416. return _verbose;
  417. }
  418. // added 10/2005, Denis Zorin
  419. // a very simple TGA output, supporting
  420. // uncompressed luminance RGB and RGBA
  421. // G22.2270 students: this is C (no C++)
  422. // so this is not the style I would encourage
  423. // you to use; I used it for consistency
  424. // with the rest of the code in this file
  425. // fixed header values for the subset of TGA we use for writing
  426. unsigned char TGAHeaderColor[12] =
  427. { 0,// 0 ID length = no id
  428. 0,// 1 color map type = no color map
  429. 2,// 2 image type = uncompressed true color
  430. 0, 0, 0, 0, 0,// color map spec = empty
  431. 0, 0, // x origin of image
  432. 0, 0 // y origin of image
  433. };
  434. unsigned char TGAHeaderBW[12] =
  435. { 0,// 0 ID length = no id
  436. 0,// 1 color map type = no color map
  437. 3,// 3 image type = uncompressed black and white
  438. 0, 0, 0, 0, 0,// color map spec = empty
  439. 0, 0, // x origin of image
  440. 0, 0 // y origin of image
  441. };
  442. // this makes sure that
  443. // image size is written in correct format
  444. // and byte order (least first)
  445. IGL_INLINE void write16bit(int n, FILE* fp) {
  446. unsigned char bytes[] = { static_cast<unsigned char>(n % 256), static_cast<unsigned char>(n / 256) };
  447. fwrite(bytes, 2, sizeof(unsigned char),fp);
  448. }
  449. IGL_INLINE void igl::opengl::writeTGA( igl::opengl::gliGenericImage* image, FILE *fp) {
  450. assert(!image->cmap); // we do not deal with color map images
  451. if(image->components == 3 || image->components == 4)
  452. fwrite(TGAHeaderColor, 12, sizeof(unsigned char),fp);
  453. else {
  454. if(image->components == 1 )
  455. fwrite(TGAHeaderBW, 12, sizeof(unsigned char),fp);
  456. else { fprintf(stderr,"Supported component number: 1,3 or 4\n"); exit(1); }
  457. }
  458. write16bit(image->width,fp);
  459. write16bit(image->height,fp);
  460. switch (image->components ) {
  461. case 1:
  462. putc(8,fp);
  463. break;
  464. case 3:
  465. putc(24,fp);
  466. break;
  467. case 4:
  468. putc(32,fp);
  469. break;
  470. default: fprintf(stderr,"Supported component number: 1,3 or 4\n"); exit(1);
  471. };
  472. if(image-> components == 4)
  473. putc(0x04,fp); // bottom left image (0x00) + 8 bit alpha (0x4)
  474. else
  475. putc(0x00,fp);
  476. fwrite(image->pixels, image->height*image->width*image->components, sizeof(char),fp);
  477. }