tga.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:15k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.     Copyright (C) 2000  Marco Ziech (mmz@gmx.net)
  3.     Copyright (C) 2000  Ross Combs (rocombs@cs.nmsu.edu)
  4.     This program is free software; you can redistribute it and/or modify
  5.     it under the terms of the GNU General Public License as published by
  6.     the Free Software Foundation; either version 2 of the License, or
  7.     (at your option) any later version.
  8.     This program is distributed in the hope that it will be useful,
  9.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.     GNU General Public License for more details.
  12.     You should have received a copy of the GNU General Public License
  13.     along with this program; if not, write to the Free Software
  14.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  15. */
  16. #include "common/setup_before.h"
  17. #include <stdio.h>
  18. #ifdef STDC_HEADERS
  19. # include <stdlib.h>
  20. #else
  21. # ifdef HAVE_MALLOC_H
  22. #  include <malloc.h>
  23. # endif
  24. #endif
  25. #ifdef HAVE_STRING_H
  26. # include <string.h>
  27. #else
  28. # ifdef HAVE_STRINGS_H
  29. #  include <strings.h>
  30. # endif
  31. #endif
  32. #include <errno.h>
  33. #include "compat/strerror.h"
  34. #include "fileio.h"
  35. #include "tga.h"
  36. #include "common/setup_after.h"
  37. static int rotate_updown(t_tgaimg *img);
  38. static int rotate_leftright(t_tgaimg *img);
  39. static int RLE_decompress(FILE *f, void *buf, int bufsize, int pixelsize);
  40. static void RLE_write_pkt(FILE *f, t_tgapkttype pkttype, int len, void *data, int pixelsize);
  41. static int RLE_compress(FILE *f, t_tgaimg const *img);
  42. static int rotate_updown(t_tgaimg *img) {
  43. unsigned char *ndata;
  44. int pixelsize;
  45. int y;
  46. if (img == NULL) return -1;
  47. if (img->data == NULL) return -1;
  48. pixelsize = getpixelsize(img);
  49. if (pixelsize == 0) return -1;
  50. ndata = malloc(img->width*img->height*pixelsize);
  51. for (y = 0; y < img->height; y++) {
  52. memcpy(ndata + (y*img->width*pixelsize),
  53.        img->data + ((img->width*img->height*pixelsize)-((y+1)*img->width*pixelsize)),
  54.        img->width*pixelsize);
  55. }
  56. free(img->data);
  57. img->data = ndata;
  58. return 0;
  59. }
  60. static int rotate_leftright(t_tgaimg *img) {
  61.         unsigned char *ndata, *datap;
  62.         int pixelsize;
  63.         int y,x;
  64. fprintf(stderr,"WARNING: rotate_leftright: this function is untested!n");
  65.         if (img == NULL) return -1;
  66.         if (img->data == NULL) return -1;
  67.         pixelsize = getpixelsize(img);
  68.         if (pixelsize == 0) return -1;
  69.         ndata = malloc(img->width*img->height*pixelsize);
  70. datap = img->data;
  71.         for (y = 0; y < img->height; y++) {
  72. unsigned char *linep = (ndata + (((y+1)*img->width*pixelsize)-pixelsize));
  73. for (x = 0; x < img->width; x++) {
  74. memcpy(linep,datap,pixelsize);
  75. linep -= pixelsize;
  76. datap += pixelsize;
  77. }
  78.         }
  79.         free(img->data);
  80.         img->data = ndata;
  81. return 0;
  82. }
  83. extern int getpixelsize(t_tgaimg const *img) {
  84. switch (img->bpp) {
  85. case 8:
  86. return 1;
  87. case 15:
  88. case 16:
  89. return 2;
  90. case 24:
  91. return 3;
  92. case 32:
  93. return 4;
  94. default:
  95. fprintf(stderr,"load_tga: color depth %u is not supported!n",img->bpp);
  96. return 0;
  97. }
  98. }
  99. extern t_tgaimg * new_tgaimg(unsigned int width, unsigned int height, unsigned int bpp, t_tgaimgtype imgtype) {
  100. t_tgaimg *img;
  101. img = malloc(sizeof(t_tgaimg));
  102.         img->idlen = 0;
  103.         img->cmaptype = tgacmap_none;
  104.         img->imgtype = imgtype;
  105.         img->cmapfirst = 0;
  106.         img->cmaplen = 0;
  107.         img->cmapes = 0;
  108.         img->xorigin = 0;
  109.         img->yorigin = 0;
  110.         img->width = width;
  111.         img->height = height;
  112.         img->bpp = bpp;
  113.         img->desc = 0; /* no attribute bits, top, left, and zero reserved */
  114. img->data = NULL;
  115. img->extareaoff = 0;
  116. img->devareaoff = 0;
  117. return img;
  118. }
  119. extern t_tgaimg * load_tgaheader(void) {
  120. t_tgaimg *img;
  121. img = malloc(sizeof(t_tgaimg));
  122.         img->idlen = file_readb();
  123.         img->cmaptype = file_readb();
  124.         img->imgtype = file_readb();
  125.         img->cmapfirst = file_readw_le();
  126.         img->cmaplen = file_readw_le();
  127.         img->cmapes = file_readb();
  128.         img->xorigin = file_readw_le();
  129.         img->yorigin = file_readw_le();
  130.         img->width = file_readw_le();
  131.         img->height = file_readw_le();
  132.         img->bpp = file_readb();
  133.         img->desc = file_readb();
  134. img->data = NULL;
  135. img->extareaoff = 0; /* ignored when reading */
  136. img->devareaoff = 0; /* ignored when reading */
  137. return img;
  138. }
  139. extern t_tgaimg * load_tga(FILE *f) {
  140. t_tgaimg *img;
  141. int pixelsize;
  142. file_rpush(f);
  143. img = load_tgaheader();
  144. /* make sure we understand the header fields */
  145. if (img->cmaptype != tgacmap_none) {
  146. fprintf(stderr,"load_tga: Color-mapped images are not (yet?) supported!n");
  147. free(img);
  148. return NULL;
  149. }
  150. if (img->imgtype!=tgaimgtype_uncompressed_truecolor && img->imgtype!=tgaimgtype_rlecompressed_truecolor) {
  151. fprintf(stderr,"load_tga: imagetype %u is not supported. (only 2 and 10 are supported)n",img->imgtype);
  152. free(img);
  153. return NULL;
  154. }
  155. pixelsize = getpixelsize(img);
  156. if (pixelsize == 0) {
  157. free(img);
  158. return NULL;
  159. }
  160. /* Skip the ID if there is one */
  161. if (img->idlen > 0) {
  162. fprintf(stderr,"load_tga: ID present, skipping %d bytesn",img->idlen);
  163. if (fseek(f,img->idlen,SEEK_CUR)<0)
  164. fprintf(stderr,"load_tga: could not seek %u bytes forward (fseek: %s)n",img->idlen,strerror(errno));
  165. }
  166. /* Now, we can alloc img->data */
  167. img->data = malloc(img->width*img->height*pixelsize);
  168. if (img->imgtype == tgaimgtype_uncompressed_truecolor) {
  169. if (fread(img->data,pixelsize,img->width*img->height,f)<(unsigned)(img->width*img->height)) {
  170. fprintf(stderr,"load_tga: error while reading data!n");
  171. free(img->data);
  172. free(img);
  173. return NULL;
  174. }
  175. }
  176. else { /* == tgaimgtype_rlecompressed_truecolor */
  177. if (RLE_decompress(f,img->data,img->width*img->height*pixelsize,pixelsize) < 0) {
  178. fprintf(stderr,"load_tga: error while decompressing data!n");
  179. free(img->data);
  180. free(img);
  181. return NULL;
  182. }
  183. }
  184. file_rpop();
  185. if ((img->desc & tgadesc_horz) == 1) { /* right, want left */
  186. if (rotate_leftright(img)<0) {
  187. fprintf(stderr,"ERROR: rotate_leftright failed!n");
  188. }
  189. }
  190. if ((img->desc & tgadesc_vert) == 0) { /* bottom, want top */
  191. if (rotate_updown(img)<0) {
  192. fprintf(stderr,"ERROR: rotate_updown failed!n");
  193. }
  194. }
  195. return img;
  196. }
  197. extern int write_tga(FILE *f, t_tgaimg *img) {
  198. if (f == NULL) return -1;
  199. if (img == NULL) return -1;
  200. if (img->data == NULL) return -1;
  201. if (img->idlen!=0) return -1;
  202. if (img->cmaptype!=tgacmap_none) return -1;
  203. if (img->imgtype!=tgaimgtype_uncompressed_truecolor && img->imgtype!=tgaimgtype_rlecompressed_truecolor) return -1;
  204. file_wpush(f);
  205. file_writeb(img->idlen);
  206. file_writeb(img->cmaptype);
  207. file_writeb(img->imgtype);
  208. file_writew_le(img->cmapfirst);
  209. file_writew_le(img->cmaplen);
  210. file_writeb(img->cmapes);
  211. file_writew_le(img->xorigin);
  212. file_writew_le(img->yorigin);
  213. file_writew_le(img->width);
  214. file_writew_le(img->height);
  215. file_writeb(img->bpp);
  216. file_writeb(img->desc);
  217. if ((img->desc&tgadesc_horz)==1) { /* right, want left */
  218.         fprintf(stderr,"write_tga: flipping horizontallyn");
  219. if (rotate_leftright(img)<0) {
  220. fprintf(stderr,"ERROR: rotate_updown failed!n");
  221. }
  222. }
  223. if ((img->desc&tgadesc_vert)==0) { /* bottom, want top */
  224.         fprintf(stderr,"write_tga: flipping verticallyn");
  225. if (rotate_updown(img)<0) {
  226. fprintf(stderr,"ERROR: rotate_updown failed!n");
  227. }
  228. }
  229. if (img->imgtype==tgaimgtype_uncompressed_truecolor) {
  230. int pixelsize;
  231. pixelsize = getpixelsize(img);
  232. if (pixelsize == 0) return -1;
  233. if (fwrite(img->data,pixelsize,img->width*img->height,f)<(unsigned)(img->width*img->height)) {
  234. fprintf(stderr,"write_tga: could not write %d pixels (fwrite: %s)n",img->width*img->height,strerror(errno));
  235. file_wpop();
  236. return -1;
  237. }
  238. } else if (img->imgtype==tgaimgtype_rlecompressed_truecolor) {
  239.         fprintf(stderr,"write_tga: using RLE compressionn");
  240. if (RLE_compress(f,img)<0) {
  241. fprintf(stderr,"write_tga: RLE compression failed.n");
  242. }
  243. }
  244. /* Write the file-footer */
  245. file_writed_le(img->extareaoff);
  246. file_writed_le(img->devareaoff);
  247. if (fwrite(TGAMAGIC,strlen(TGAMAGIC)+1,1,f)<1)
  248. fprintf(stderr,"write_tga: could not write TGA footer magic (fwrite: %s)n",strerror(errno));
  249. /* Ready */
  250. file_wpop();
  251. return 0;
  252. }
  253. static int RLE_decompress(FILE *f, void *buf, int bufsize, int pixelsize) {
  254. unsigned char pt;
  255. unsigned char *bufp;
  256. unsigned char temp[8]; /* MAXPIXELSIZE */
  257. int bufi;
  258. int count;
  259. file_rpush(f);
  260. bufp = buf;
  261. for (bufi=0; bufi<bufsize; ) {
  262. pt = file_readb();
  263. if (feof(f)) {
  264. fprintf(stderr,"RLE_decompress: after final packet only got %d of %d bytesn",bufi,bufsize);
  265. file_rpop();
  266. return -1;
  267. }
  268. count = (pt & 0x7f)+1;
  269. if (bufi+count*pixelsize>bufsize) {
  270. fprintf(stderr,"RLE_decompress: buffer too short for next packet (need %d bytes, have %d)n",bufi+count*pixelsize,bufsize);
  271. file_rpop();
  272. return -1;
  273. }
  274. if ((pt & 0x80) == 0) { /* RAW PACKET */
  275. if (fread(bufp,pixelsize,count,f)<(unsigned)count) {
  276. if (feof(f))
  277. fprintf(stderr,"RLE_decompress: short RAW packet (expected %d bytes) (EOF)n",pixelsize*count);
  278. else
  279. fprintf(stderr,"RLE_decompress: short RAW packet (expected %d bytes) (fread: %s)n",pixelsize*count,strerror(errno));
  280. #if 0
  281. file_rpop();
  282. return -1;
  283. #endif
  284. }
  285. bufp += count*pixelsize;
  286. bufi += count*pixelsize;
  287. } else { /* RLE PACKET */
  288. if (fread(temp,pixelsize,1,f) < 1) {
  289. if (feof(f))
  290. fprintf(stderr,"RLE_decompress: short RLE packet (expected %d bytes) (EOF)n",pixelsize);
  291. else
  292. fprintf(stderr,"RLE_decompress: short RLE packet (expected %d bytes) (fread: %s)n",pixelsize,strerror(errno));
  293. #if 0
  294. file_rpop();
  295. return -1;
  296. #endif
  297. }
  298. if (count<2) {
  299. fprintf(stderr,"RLE_decompress: suspicious RLE repetition count %dn",count);
  300. }
  301. for (;count > 0; count--) {
  302. memcpy(bufp,temp,pixelsize);
  303. bufp += pixelsize;
  304. bufi += pixelsize;
  305. }
  306. }
  307. }
  308. file_rpop();
  309. return 0;
  310. }
  311. static void RLE_write_pkt(FILE *f, t_tgapkttype pkttype, int len, void *data, int pixelsize) {
  312. unsigned char count;
  313. if (len<1 || len>128) {
  314. fprintf(stderr,"RLE_write_pkt: packet has bad length (%d bytes)n",len);
  315. return;
  316. }
  317. if (pkttype==RLE) {
  318. if (len<2) {
  319. fprintf(stderr,"RLE_write_pkt: RLE packet has bad length (%d bytes)n",len);
  320. return;
  321. }
  322. count = (unsigned char)(0x80 | (len-1));
  323. if (fwrite(&count, 1, 1, f)<1)
  324. fprintf(stderr,"RLE_write_pkt: could not write RLE pixel count (fwrite: %s)n",strerror(errno));
  325. if (fwrite(data, pixelsize, 1, f)<1)
  326. fprintf(stderr,"RLE_write_pkt: could not write RLE pixel value (fwrite: %s)n",strerror(errno));
  327. } else {
  328. count = (unsigned char) (len-1);
  329. if (fwrite(&count, 1, 1, f)<1)
  330. fprintf(stderr,"RLE_write_pkt: could not write RAW pixel count (fwrite: %s)n",strerror(errno));
  331. if (fwrite(data,pixelsize,len,f)<(unsigned)len)
  332. fprintf(stderr,"RLE_write_pkt: could not write %d RAW pixels (fwrite: %s)n",len,strerror(errno));
  333. }
  334. }
  335. static int RLE_compress(FILE *f, t_tgaimg const *img) {
  336. int pixelsize;
  337. unsigned char const *datap;
  338. unsigned char *pktdata;
  339. unsigned int pktlen;
  340. t_tgapkttype pkttype;
  341. unsigned char *pktdatap;
  342. unsigned int actual=0,perceived=0;
  343. int i;
  344. pkttype = RAW;
  345. pktdatap = NULL;
  346. if (img == NULL) return -1;
  347. if (img->data == NULL) return -1;
  348. pixelsize = getpixelsize(img);
  349. if (pixelsize == 0) return -1;
  350. datap = img->data;
  351. pktdata = malloc(img->width*img->height*pixelsize);
  352. pktlen = 0;
  353. for (i=0; i<img->width*img->height; ) {
  354. if (pktlen == 0) {
  355. pktdatap = pktdata;
  356. memcpy(pktdatap,datap,pixelsize);
  357. pktlen++;
  358. i++;
  359. pktdatap += pixelsize;
  360. datap += pixelsize;
  361. pkttype = RAW;
  362. continue;
  363. }
  364. if (pktlen == 1) {
  365. if (memcmp(datap-pixelsize,datap,pixelsize)==0) {
  366. pkttype = RLE;
  367. }
  368. }
  369. if (pkttype == RLE) {
  370. if (memcmp(datap-pixelsize,datap,pixelsize)!=0 || pktlen>=128) {
  371. RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize);
  372. actual += 1+pixelsize;
  373. perceived += pixelsize*pktlen;
  374. pktlen = 0;
  375. } else {
  376. pktlen++;
  377. i++;
  378. datap += pixelsize;
  379. }
  380. } else {
  381. if (memcmp(datap-pixelsize,datap,pixelsize)==0 || pktlen>=129) {
  382. datap -= pixelsize; /* push back last pixel */
  383. i--;
  384. if (i<0) fprintf(stderr,"BUG!n");
  385. pktlen--;
  386. RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize);
  387. actual += 1+pixelsize*pktlen;
  388. perceived += pixelsize*pktlen;
  389. pktlen = 0;
  390. } else {
  391. memcpy(pktdatap,datap,pixelsize);
  392. pktlen++;
  393. i++;
  394. pktdatap += pixelsize;
  395. datap += pixelsize;
  396. }
  397. }
  398. }
  399. if (pktlen) {
  400. RLE_write_pkt(f,pkttype,pktlen,pktdata,pixelsize);
  401. if (pkttype==RLE) {
  402. actual += 1+pixelsize;
  403. perceived += pixelsize*pktlen;
  404. } else {
  405. actual += 1+pixelsize*pktlen;
  406. perceived += pixelsize*pktlen;
  407. }
  408. pktlen = 0;
  409. }
  410. fprintf(stderr,"RLE_compress: wrote %u bytes (%u uncompressed)n",actual,perceived);
  411. return 0;
  412. }
  413. extern void destroy_img(t_tgaimg * img) {
  414. if (img == NULL) return;
  415. if (img->data)
  416. free(img->data);
  417. free(img);
  418. }
  419. extern void print_tga_info(t_tgaimg const * img, FILE * fp) {
  420. unsigned int interleave;
  421. unsigned int attrbits;
  422.   char const * typestr;
  423.   char const * cmapstr;
  424. char const * horzstr;
  425. char const * vertstr;
  426. char const * intlstr;
  427. if (!img || !fp)
  428. return;
  429. interleave = ((img->desc&tgadesc_interleave1)!=0)*2+((img->desc&tgadesc_interleave2)!=0);
  430. attrbits = img->desc&(tgadesc_attrbits0|tgadesc_attrbits1|tgadesc_attrbits2|tgadesc_attrbits3);
  431. switch (img->imgtype) {
  432. case tgaimgtype_empty:
  433. typestr = "No Image Data Included";
  434. break;
  435. case tgaimgtype_uncompressed_mapped:
  436. typestr = "Uncompressed, Color-mapped Image";
  437. break;
  438. case tgaimgtype_uncompressed_truecolor:
  439. typestr = "Uncompressed, True-color Image";
  440. break;
  441. case tgaimgtype_uncompressed_monochrome:
  442. typestr = "Uncompressed, Black-and-white image";
  443. break;
  444. case tgaimgtype_rlecompressed_mapped:
  445. typestr = "Run-length encoded, Color-mapped Image";
  446. break;
  447. case tgaimgtype_rlecompressed_truecolor:
  448. typestr = "Run-length encoded, True-color Image";
  449. break;
  450. case tgaimgtype_rlecompressed_monochrome:
  451. typestr = "Run-length encoded, Black-and-white image";
  452. break;
  453. case tgaimgtype_huffman_mapped:
  454. typestr = "Huffman encoded, Color-mapped image";
  455. break;
  456.         case tgaimgtype_huffman_4pass_mapped:
  457. typestr = "Four-pass Huffman encoded, Color-mapped image";
  458. break;
  459. default:
  460. typestr = "unknown";
  461. }
  462. switch (img->cmaptype) {
  463. case tgacmap_none:
  464. cmapstr = "None";
  465. break;
  466. case tgacmap_included:
  467. cmapstr = "Included";
  468. break;
  469. default:
  470. cmapstr = "Unknown";
  471. }
  472. if ((img->desc&tgadesc_horz)==0) {
  473. horzstr = "left";
  474. } else {
  475. horzstr = "right";
  476. }
  477. if ((img->desc&tgadesc_vert)==0) {
  478. vertstr = "bottom";
  479. } else {
  480. vertstr = "top";
  481. }
  482. switch (interleave) {
  483. case 0:
  484. intlstr = "none";
  485. break;
  486. case 2:
  487. intlstr = "two way";
  488. break;
  489. case 3:
  490. intlstr = "four way";
  491. break;
  492. case 4:
  493. default:
  494. intlstr = "unknown";
  495. break;
  496. }
  497. fprintf(fp,"TGAHeader: IDLength=%u ColorMapType=%u(%s)n",img->idlen,img->cmaptype,cmapstr);
  498. fprintf(fp,"TGAHeader: ImageType=%u(%s)n",img->imgtype,typestr);
  499. fprintf(fp,"TGAHeader: ColorMap: FirstEntryIndex=%u ColorMapLength=%un",img->cmapfirst,img->cmaplen);
  500. fprintf(fp,"TGAHeader: ColorMap: ColorMapEntrySize=%ubitsn",img->cmapes);
  501. fprintf(fp,"TGAHeader: X-origin=%u Y-origin=%u Width=%u(0x%x) Height=%u(0x%x)n",img->xorigin,img->yorigin,img->width,img->width,img->height,img->height);
  502. fprintf(fp,"TGAHeader: PixelDepth=%ubits ImageDescriptor=0x%02x(%u attribute bits, origin is %s %s, interleave=%s)n",img->bpp,img->desc,attrbits,vertstr,horzstr,intlstr);
  503. }