added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / image_tga.c
1 /*
2 This is a small image library.
3
4 Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
5
6 This library is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this library; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19 */
20
21 /* targa support
22  * 
23  * author: John Tsiombikas 2004
24  * modified: John Tsiombikas 2005
25  */
26
27 #include "3dengfx_config.h"
28 #include "image.h"
29 #include <stdio.h>
30
31 #ifdef IMGLIB_USE_TGA
32
33 #include <stdlib.h>
34 #include <string.h>
35 #include "color_bits.h"
36 #include "common/byteorder.h"
37
38 struct tga_header {
39         uint8_t idlen;                  /* id field length */
40         uint8_t cmap_type;              /* color map type (0:no color map, 1:color map present) */
41         uint8_t img_type;               /* image type: 
42                                                          * 0: no image data
43                                                          *      1: uncomp. color-mapped          9: RLE color-mapped
44                                                          *      2: uncomp. true color           10: RLE true color
45                                                          *      3: uncomp. black/white          11: RLE black/white */  
46         uint16_t cmap_first;    /* color map first entry index */
47         uint16_t cmap_len;              /* color map length */
48         uint8_t cmap_entry_sz;  /* color map entry size */
49         uint16_t img_x;                 /* X-origin of the image */
50         uint16_t img_y;                 /* Y-origin of the image */
51         uint16_t img_width;             /* image width */
52         uint16_t img_height;    /* image height */
53         uint8_t img_bpp;                /* bits per pixel */
54         uint8_t img_desc;               /* descriptor: 
55                                                          * bits 0 - 3: alpha or overlay bits
56                                                          * bits 5 & 4: origin (0 = bottom/left, 1 = top/right)
57                                                          * bits 7 & 6: data interleaving */     
58 };
59
60 struct tga_footer {
61         uint32_t ext_off;               /* extension area offset */
62         uint32_t devdir_off;    /* developer directory offset */
63         char sig[18];                           /* signature with . and \0 */
64 };
65
66 /*static void print_tga_info(struct tga_header *hdr);*/
67
68 int check_tga(FILE *fp) {
69         struct tga_footer foot;
70         
71         fseek(fp, -18, SEEK_END);
72         fread(foot.sig, 1, 18, fp);
73
74         foot.sig[17] = 0;
75         return strcmp(foot.sig, "TRUEVISION-XFILE.") == 0 ? 1 : 0;
76 }
77
78 void *load_tga(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
79         struct tga_header hdr;
80         unsigned long x, y, sz;
81         int i;
82         uint32_t *pix;
83
84         /* read header */
85         fseek(fp, 0, SEEK_SET);
86         hdr.idlen = fgetc(fp);
87         hdr.cmap_type = fgetc(fp);
88         hdr.img_type = fgetc(fp);
89         hdr.cmap_first = read_int16_le(fp);
90         hdr.cmap_len = read_int16_le(fp);
91         hdr.cmap_entry_sz = fgetc(fp);
92         hdr.img_x = read_int16_le(fp);
93         hdr.img_y = read_int16_le(fp);
94         hdr.img_width = read_int16_le(fp);
95         hdr.img_height = read_int16_le(fp);
96         hdr.img_bpp = fgetc(fp);
97         hdr.img_desc = fgetc(fp);
98
99         if(feof(fp)) {
100                 fclose(fp);
101                 return 0;
102         }
103         
104         /* only read true color images */
105         if(hdr.img_type != 2) {
106                 fclose(fp);
107                 fprintf(stderr, "only true color tga images supported\n");
108                 return 0;
109         }
110
111         fseek(fp, hdr.idlen, SEEK_CUR); /* skip the image ID */
112
113         /* skip the color map if it exists */
114         if(hdr.cmap_type == 1) {
115                 fseek(fp, hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR);
116         }
117
118         x = hdr.img_width;
119         y = hdr.img_height;
120         sz = x * y;
121         if(!(pix = malloc(sz * 4))) {
122                 fclose(fp);
123                 return 0;
124         }
125
126         for(i=0; i<y; i++) {
127                 uint32_t *ptr;
128                 int j;
129
130                 ptr = pix + ((hdr.img_desc & 0x20) ? i : y-(i+1)) * x;
131
132                 for(j=0; j<x; j++) {
133                         unsigned char r, g, b, a;
134                         r = fgetc(fp);
135                         g = fgetc(fp);
136                         b = fgetc(fp);
137                         a = (hdr.img_desc & 0xf) ? fgetc(fp) : 255;
138                 
139                         *ptr++ = PACK_COLOR32(a, r, g, b);
140                         
141                         if(feof(fp)) break;
142                 }
143         }
144
145         fclose(fp);
146         *xsz = x;
147         *ysz = y;
148         return pix;
149 }
150
151 int save_tga(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
152         struct tga_header hdr;
153         struct tga_footer ftr;
154         unsigned long pix_count = xsz * ysz;
155         uint32_t *pptr = pixels;
156         unsigned long save_flags;
157         int i;
158
159         save_flags = get_image_save_flags();
160
161         memset(&hdr, 0, sizeof hdr);
162         hdr.img_type = 2;
163         hdr.img_width = xsz;
164         hdr.img_height = ysz;
165
166         if(save_flags & IMG_SAVE_ALPHA) {
167                 hdr.img_bpp = 32;
168                 hdr.img_desc = 8 | 0x20;        /* 8 alpha bits, origin top-left */
169         } else {
170                 hdr.img_bpp = 24;
171                 hdr.img_desc = 0x20;            /* no alpha bits, origin top-left */
172         }
173
174         if(save_flags & IMG_SAVE_INVERT) {
175                 hdr.img_desc ^= 0x20;
176         }
177
178         ftr.ext_off = 0;
179         ftr.devdir_off = 0;
180         strcpy(ftr.sig, "TRUEVISION-XFILE.");
181
182         /* write the header */
183         
184         fwrite(&hdr.idlen, 1, 1, fp);
185         fwrite(&hdr.cmap_type, 1, 1, fp);
186         fwrite(&hdr.img_type, 1, 1, fp);
187         write_int16_le(fp, hdr.cmap_first);
188         write_int16_le(fp, hdr.cmap_len);
189         fwrite(&hdr.cmap_entry_sz, 1, 1, fp);
190         write_int16_le(fp, hdr.img_x);
191         write_int16_le(fp, hdr.img_y);
192         write_int16_le(fp, hdr.img_width);
193         write_int16_le(fp, hdr.img_height);
194         fwrite(&hdr.img_bpp, 1, 1, fp);
195         fwrite(&hdr.img_desc, 1, 1, fp);
196
197         /* write the pixels */
198         for(i=0; i<pix_count; i++) {
199                 fputc((*pptr >> BLUE_SHIFT32) & 0xff, fp);
200                 fputc((*pptr >> GREEN_SHIFT32) & 0xff, fp);
201                 fputc((*pptr >> RED_SHIFT32) & 0xff, fp);
202                 
203                 if(save_flags & IMG_SAVE_ALPHA) {
204                         fputc((*pptr >> ALPHA_SHIFT32) & 0xff, fp);
205                 }
206                 
207                 pptr++;
208         }
209
210         /* write the footer */
211         write_int32_le(fp, ftr.ext_off);
212         write_int32_le(fp, ftr.devdir_off);
213         fputs(ftr.sig, fp);
214         fputc(0, fp);
215
216         fclose(fp);
217         return 0;
218 }
219
220 /*
221 static void print_tga_info(struct tga_header *hdr) {
222         static const char *img_type_str[] = {
223                 "no image data",
224                 "uncompressed color-mapped",
225                 "uncompressed true color",
226                 "uncompressed black & white",
227                 "", "", "", "", "",
228                 "RLE color-mapped",
229                 "RLE true color",
230                 "RLE black & white"
231         };
232         
233         printf("id field length: %d\n", (int)hdr->idlen);
234         printf("color map present: %s\n", hdr->cmap_type ? "yes" : "no");
235         printf("image type: %s\n", img_type_str[hdr->img_type]);
236         printf("color-map start: %d\n", (int)hdr->cmap_first);
237         printf("color-map length: %d\n", (int)hdr->cmap_len);
238         printf("color-map entry size: %d\n", (int)hdr->cmap_entry_sz);
239         printf("image origin: %d, %d\n", (int)hdr->img_x, (int)hdr->img_y);
240         printf("image size: %d, %d\n", (int)hdr->img_width, (int)hdr->img_height);
241         printf("bpp: %d\n", (int)hdr->img_bpp);
242         printf("attribute bits (alpha/overlay): %d\n", (int)(hdr->img_desc & 0xf));
243         printf("origin: %s-", (hdr->img_desc & 0x20) ? "top" : "bottom");
244         printf("%s\n", (hdr->img_desc & 0x10) ? "right" : "left");
245 }
246 */
247
248 #endif  /* IMGLIB_USE_TGA */