/[LeafOK_CVS]/pvpgn-1.7.4/src/bniutils/tga.c
ViewVC logotype

Annotation of /pvpgn-1.7.4/src/bniutils/tga.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
CVS Tags: pvpgn_1-7-4-0_MIL
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

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

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1