tga.h 18 KB

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