Open Source Tomb Raider Engine
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

tga.cpp 9.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493
  1. /*================================================================
  2. *
  3. * Project : Freyja
  4. * Author : Mongoose
  5. * Website : http://www.westga.edu/~stu7440/
  6. * Email : stu7440@westga.edu
  7. * Object :
  8. * License : GPL See file COPYING, also (C) 2000 Mongoose
  9. * Comments: TGA plug-in
  10. *
  11. * TODO: type should pass more info
  12. * 2 bits for RGBA | RGB | GREY
  13. * val for depth
  14. *
  15. * This file was generated using Mongoose's C++
  16. * template generator script. <stu7440@westga.edu>
  17. *
  18. *-- History ------------------------------------------------
  19. *
  20. * 2001-10-25:
  21. * Mongoose - support for screen origin bit
  22. *
  23. * 2000-10-15:
  24. * Mongoose - Created
  25. ================================================================*/
  26. #include <string.h>
  27. #include <stdarg.h>
  28. #include <TGA.h>
  29. #ifdef DEBUG_MEMORY
  30. #include <memory_test.h>
  31. #endif
  32. int mtk_image__tga_check(FILE *f)
  33. {
  34. char buffer[10];
  35. if (!f)
  36. {
  37. perror("tga_check> Passed invalid file.\n");
  38. return -1;
  39. }
  40. /* Read the header */
  41. fseek(f, 0, SEEK_SET);
  42. fread(buffer, 8, 1, f);
  43. // buffer[1] = 0 - Means not color mapped ( 1 would mean mapped )
  44. if (!(buffer[1] == 0 && (buffer[2] == TGA_TYPE__COLOR ||
  45. //buffer[2] == TGA_TYPE__GREYSCALE ||
  46. buffer[2] == TGA_TYPE__COLOR_RLE)))
  47. {
  48. printf("tga_check> Inavlid or unknown TGA format.\n");
  49. return -2;
  50. }
  51. return 0;
  52. }
  53. int mtk_image__tga_load(FILE *f, unsigned char **image,
  54. unsigned int *width, unsigned int *height, char *type)
  55. {
  56. mtk_image_tga_t header;
  57. char comment[256];
  58. unsigned char pixel[4];
  59. unsigned char *swap_row = NULL;
  60. unsigned char tmp, packet;
  61. bool must_flip = 0;
  62. unsigned int size;
  63. unsigned int i, j;
  64. if (!f)
  65. {
  66. fprintf(stderr, "mtk_image__tga_load> Invalid parameters.\n");
  67. return -1;
  68. }
  69. fseek(f, 0, SEEK_SET);
  70. // Read TGA header
  71. fread(&header.comment_lenght, 1, 1, f);
  72. fread(&header.colormap_type, 1, 1, f);
  73. fread(&header.image_type, 1, 1, f);
  74. fread(&header.colormap_index, 2, 1, f);
  75. fread(&header.colormap_lenght, 2, 1, f);
  76. fread(&header.colormap_bbp, 1, 1, f);
  77. fread(&tmp, 1, 1, f);
  78. header.origin_x = tmp;
  79. fread(&tmp, 1, 1, f);
  80. header.origin_x += tmp * 256;
  81. fread(&tmp, 1, 1, f);
  82. header.origin_y = tmp;
  83. fread(&tmp, 1, 1, f);
  84. header.origin_y += tmp * 256;
  85. fread(&tmp, 1, 1, f);
  86. header.width = tmp;
  87. fread(&tmp, 1, 1, f);
  88. header.width += tmp * 256;
  89. fread(&tmp, 1, 1, f);
  90. header.height = tmp;
  91. fread(&tmp, 1, 1, f);
  92. header.height += tmp * 256;
  93. fread(&header.bpp, 1, 1, f);
  94. fread(&header.desc_flags, 1, 1, f);
  95. *width = header.width;
  96. *height = header.height;
  97. switch (header.bpp)
  98. {
  99. case 32:
  100. *type = 2;//32;
  101. break;
  102. case 24:
  103. *type = 1;//24;
  104. break;
  105. case 8:
  106. *type = 0;//8;
  107. break;
  108. default:
  109. *type = 0;
  110. }
  111. #ifdef DEBUG_TGA
  112. printf("TGA [%ix%i@%ibpp, %it, %ix, %iy, %uf]\n",
  113. header.width, header.height, header.bpp, header.image_type,
  114. header.origin_x, header.origin_y,
  115. header.desc_flags);
  116. #endif
  117. // Comments can be 0 - 255
  118. if (header.comment_lenght)
  119. {
  120. fread(&comment, 1, header.comment_lenght, f);
  121. for (i = 0; i < 255; ++i)
  122. {
  123. if (comment[i] > 32 && comment[i] < 127)
  124. {
  125. }
  126. else
  127. {
  128. comment[i] = 183; // print a dot for invalid text
  129. }
  130. }
  131. comment[255] = 0;
  132. printf("Comment: '%s'\n", comment);
  133. }
  134. size = header.width * header.height;
  135. if (!size || (!(header.colormap_type == 0 &&
  136. (header.image_type == 2 || header.image_type == 10))))
  137. {
  138. fprintf(stderr, "mtk_image__tga_load> Unknown image format.\n");
  139. return -2;
  140. }
  141. *image = NULL;
  142. // Mongoose: Added 'screen origin bit' support back here
  143. if (!(header.desc_flags & 32))
  144. {
  145. must_flip = true;
  146. }
  147. switch (header.bpp)
  148. {
  149. case 32:
  150. size *= 4;
  151. *image = new unsigned char [size];
  152. switch (header.image_type)
  153. {
  154. case TGA_TYPE__COLOR_RLE:
  155. for (i = 0; i < size;)
  156. {
  157. fread(&packet, 1, 1, f);
  158. if (packet & 0x80) // Run Lenght
  159. {
  160. packet = (packet &0x7F) + 1;
  161. fread(&pixel, 4, 1, f);
  162. for (j = 0; j < packet; j++)
  163. {
  164. (*image)[i++] = pixel[2];
  165. (*image)[i++] = pixel[1];
  166. (*image)[i++] = pixel[0];
  167. (*image)[i++] = pixel[3];
  168. }
  169. }
  170. else // RAW
  171. {
  172. packet = (packet &0x7F) + 1;
  173. for (j = 0; j < packet; j++)
  174. {
  175. fread(&pixel, 4, 1, f);
  176. (*image)[i++] = pixel[2];
  177. (*image)[i++] = pixel[1];
  178. (*image)[i++] = pixel[0];
  179. (*image)[i++] = pixel[3];
  180. }
  181. }
  182. }
  183. break;
  184. case TGA_TYPE__COLOR:
  185. if (fread((*image), size, 1, f) < 1)
  186. {
  187. fprintf(stderr, "mtk_image__tga_load> Image fread failed.\n");
  188. delete [] *image;
  189. return -4;
  190. }
  191. for (i = 0; i < size; i += 4)
  192. {
  193. tmp = (*image)[i];
  194. (*image)[i] = (*image)[i + 2];
  195. (*image)[i + 2] = tmp;
  196. }
  197. break;
  198. default:
  199. ;
  200. }
  201. if (must_flip)
  202. {
  203. swap_row = new unsigned char [header.width * 4];
  204. for (i = 0, j = header.height-1; (int)i < header.height/2; i++, j--)
  205. {
  206. memcpy(swap_row, &(*image)[i*header.width*4], header.width*4);
  207. memcpy(&(*image)[i*header.width*4], &(*image)[j*header.width*4],
  208. header.width*4);
  209. memcpy(&(*image)[j*header.width*4], swap_row, header.width*4);
  210. }
  211. delete [] swap_row;
  212. }
  213. break;
  214. case 24:
  215. size *= 3;
  216. *image = new unsigned char [size];
  217. switch (header.image_type)
  218. {
  219. case TGA_TYPE__COLOR_RLE:
  220. for (i = 0; i < size;)
  221. {
  222. fread(&packet, 1, 1, f);
  223. if (packet & 0x80) // Run Lenght
  224. {
  225. packet = (packet &0x7F) + 1;
  226. fread(&pixel, 3, 1, f);
  227. for (j = 0; j < packet; j++)
  228. {
  229. (*image)[i++] = pixel[2];
  230. (*image)[i++] = pixel[1];
  231. (*image)[i++] = pixel[0];
  232. }
  233. }
  234. else // RAW
  235. {
  236. packet = (packet &0x7F) + 1;
  237. for (j = 0; j < packet; j++)
  238. {
  239. fread(&pixel, 3, 1, f);
  240. (*image)[i++] = pixel[2];
  241. (*image)[i++] = pixel[1];
  242. (*image)[i++] = pixel[0];
  243. }
  244. }
  245. }
  246. break;
  247. case TGA_TYPE__COLOR:
  248. if (fread((*image), size, 1, f) < 1)
  249. {
  250. fprintf(stderr, "mtk_image__tga_load> Image fread failed.\n");
  251. delete [] *image;
  252. return -4;
  253. }
  254. for (i = 0; i < size; i += 3)
  255. {
  256. tmp = (*image)[i];
  257. (*image)[i] = (*image)[i + 2];
  258. (*image)[i + 2] = tmp;
  259. }
  260. break;
  261. default:
  262. ;
  263. }
  264. if (must_flip)
  265. {
  266. swap_row = new unsigned char [header.width * 3];
  267. for (i = 0, j = header.height - 1; (int)i < header.height / 2; i++, j--)
  268. {
  269. memcpy(swap_row, &(*image)[i*header.width*3], header.width*3);
  270. memcpy(&(*image)[i*header.width*3], &(*image)[j*header.width*3],
  271. header.width*3);
  272. memcpy(&(*image)[j*header.width*3], swap_row, header.width*3);
  273. }
  274. delete [] swap_row;
  275. }
  276. break;
  277. case 8:
  278. printf("tga_load> 8bpp Not implemented\n");
  279. break;
  280. default:
  281. ;
  282. }
  283. #ifdef DEBUG_TGA
  284. char c;
  285. printf("Comment:\n");
  286. while (fread(&c, 1, 1, f) == 1)
  287. {
  288. printf("%c", c);
  289. }
  290. printf("\n");
  291. #endif
  292. return 0;
  293. }
  294. int mtk_image__tga_save(FILE *f, unsigned char *image,
  295. unsigned int width, unsigned int height, char type)
  296. {
  297. mtk_image_tga_t header;
  298. unsigned int size;
  299. // unsigned int i;
  300. // unsigned char tmp;
  301. char comment[64];
  302. if (!f || !image || !width || !height)
  303. {
  304. fprintf(stderr, "mtk_image__tga_save> Invalid parameters.\n");
  305. return -1;
  306. }
  307. // Mongoose 2002.01.10, Heh, kind of silly
  308. strncpy(comment, "Mongoose TGA 20030711", 63);
  309. comment[63] = 0;
  310. header.comment_lenght = strlen(comment);
  311. header.colormap_type = 0;
  312. // No colormaps
  313. header.colormap_index = 0;
  314. header.colormap_lenght = 0;
  315. header.colormap_bbp = 0;
  316. header.origin_x = header.origin_y = 0;
  317. header.width = width;
  318. header.height = height;
  319. header.desc_flags = 0;
  320. switch (type)
  321. {
  322. case 4:
  323. header.image_type = TGA_TYPE__COLOR;
  324. header.desc_flags = 32;
  325. header.bpp = 32;
  326. break;
  327. case 2:
  328. header.bpp = 32;
  329. break;
  330. case 1:
  331. header.image_type = TGA_TYPE__GREYSCALE;
  332. header.bpp = 8;
  333. break;
  334. default:
  335. header.image_type = TGA_TYPE__COLOR;
  336. header.bpp = 24;
  337. }
  338. // Write TGA header
  339. fwrite(&header.comment_lenght, 1, 1, f);
  340. fwrite(&header.colormap_type, 1, 1, f);
  341. fwrite(&header.image_type, 1, 1, f);
  342. fwrite(&header.colormap_index, 2, 1, f);
  343. fwrite(&header.colormap_lenght, 2, 1, f);
  344. fwrite(&header.colormap_bbp, 1, 1, f);
  345. fwrite(&header.origin_x, 2, 1, f);
  346. fwrite(&header.origin_y, 2, 1, f);
  347. fwrite(&header.width, 2, 1, f);
  348. fwrite(&header.height, 2, 1, f);
  349. fwrite(&header.bpp, 1, 1, f);
  350. fwrite(&header.desc_flags, 1, 1, f);
  351. // Write comment
  352. fwrite(&comment, 1, header.comment_lenght, f);
  353. size = header.width * header.height;
  354. switch (header.bpp)
  355. {
  356. case 32:
  357. size = header.width * header.height * 4;
  358. //for (i = 0; i < size; i += 4)
  359. //{
  360. // tmp = image[i];
  361. // image[i] = image[i + 2];
  362. // image[i + 2] = tmp;
  363. //}
  364. break;
  365. case 24:
  366. size = header.width * header.height * 3;
  367. //for (i = 0; i < size; i += 3)
  368. //{
  369. // tmp = image[i];
  370. // image[i] = image[i + 2];
  371. // image[i + 2] = tmp;
  372. //}
  373. break;
  374. case 8:
  375. size = header.width * header.height;
  376. break;
  377. }
  378. // Write image data
  379. if (fwrite(image, size, 1, f) < 1)
  380. {
  381. perror("mtk_image__tga_save> Disk write failed.\n");
  382. return -2;
  383. }
  384. return 0;
  385. }
  386. int mtk_image__tga_save_filename(unsigned char *image,
  387. unsigned int width, unsigned int height,
  388. char type,
  389. char *s, ...)
  390. {
  391. char buffer[1024];
  392. FILE *f;
  393. int v;
  394. va_list args;
  395. va_start(args, s);
  396. vsnprintf(buffer, 1023, s, args);
  397. va_end(args);
  398. f = fopen(buffer, "wb");
  399. if (!f)
  400. {
  401. perror(buffer);
  402. return -1;
  403. }
  404. v = mtk_image__tga_save(f, image, width, height, type);
  405. fclose(f);
  406. return v;
  407. }