added 3dengfx into the repo, probably not the correct version for this
[summerhack] / src / 3dengfx / src / gfx / image_tga.c
diff --git a/src/3dengfx/src/gfx/image_tga.c b/src/3dengfx/src/gfx/image_tga.c
new file mode 100644 (file)
index 0000000..81b27ab
--- /dev/null
@@ -0,0 +1,248 @@
+/*
+This is a small image library.
+
+Copyright (C) 2004, 2005 John Tsiombikas <nuclear@siggraph.org>
+
+This library is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+/* targa support
+ * 
+ * author: John Tsiombikas 2004
+ * modified: John Tsiombikas 2005
+ */
+
+#include "3dengfx_config.h"
+#include "image.h"
+#include <stdio.h>
+
+#ifdef IMGLIB_USE_TGA
+
+#include <stdlib.h>
+#include <string.h>
+#include "color_bits.h"
+#include "common/byteorder.h"
+
+struct tga_header {
+       uint8_t idlen;                  /* id field length */
+       uint8_t cmap_type;              /* color map type (0:no color map, 1:color map present) */
+       uint8_t img_type;               /* image type: 
+                                                        * 0: no image data
+                                                        *      1: uncomp. color-mapped          9: RLE color-mapped
+                                                        *      2: uncomp. true color           10: RLE true color
+                                                        *      3: uncomp. black/white          11: RLE black/white */  
+       uint16_t cmap_first;    /* color map first entry index */
+       uint16_t cmap_len;              /* color map length */
+       uint8_t cmap_entry_sz;  /* color map entry size */
+       uint16_t img_x;                 /* X-origin of the image */
+       uint16_t img_y;                 /* Y-origin of the image */
+       uint16_t img_width;             /* image width */
+       uint16_t img_height;    /* image height */
+       uint8_t img_bpp;                /* bits per pixel */
+       uint8_t img_desc;               /* descriptor: 
+                                                        * bits 0 - 3: alpha or overlay bits
+                                                        * bits 5 & 4: origin (0 = bottom/left, 1 = top/right)
+                                                        * bits 7 & 6: data interleaving */     
+};
+
+struct tga_footer {
+       uint32_t ext_off;               /* extension area offset */
+       uint32_t devdir_off;    /* developer directory offset */
+       char sig[18];                           /* signature with . and \0 */
+};
+
+/*static void print_tga_info(struct tga_header *hdr);*/
+
+int check_tga(FILE *fp) {
+       struct tga_footer foot;
+       
+       fseek(fp, -18, SEEK_END);
+       fread(foot.sig, 1, 18, fp);
+
+       foot.sig[17] = 0;
+       return strcmp(foot.sig, "TRUEVISION-XFILE.") == 0 ? 1 : 0;
+}
+
+void *load_tga(FILE *fp, unsigned long *xsz, unsigned long *ysz) {
+       struct tga_header hdr;
+       unsigned long x, y, sz;
+       int i;
+       uint32_t *pix;
+
+       /* read header */
+       fseek(fp, 0, SEEK_SET);
+       hdr.idlen = fgetc(fp);
+       hdr.cmap_type = fgetc(fp);
+       hdr.img_type = fgetc(fp);
+       hdr.cmap_first = read_int16_le(fp);
+       hdr.cmap_len = read_int16_le(fp);
+       hdr.cmap_entry_sz = fgetc(fp);
+       hdr.img_x = read_int16_le(fp);
+       hdr.img_y = read_int16_le(fp);
+       hdr.img_width = read_int16_le(fp);
+       hdr.img_height = read_int16_le(fp);
+       hdr.img_bpp = fgetc(fp);
+       hdr.img_desc = fgetc(fp);
+
+       if(feof(fp)) {
+               fclose(fp);
+               return 0;
+       }
+       
+       /* only read true color images */
+       if(hdr.img_type != 2) {
+               fclose(fp);
+               fprintf(stderr, "only true color tga images supported\n");
+               return 0;
+       }
+
+       fseek(fp, hdr.idlen, SEEK_CUR); /* skip the image ID */
+
+       /* skip the color map if it exists */
+       if(hdr.cmap_type == 1) {
+               fseek(fp, hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR);
+       }
+
+       x = hdr.img_width;
+       y = hdr.img_height;
+       sz = x * y;
+       if(!(pix = malloc(sz * 4))) {
+               fclose(fp);
+               return 0;
+       }
+
+       for(i=0; i<y; i++) {
+               uint32_t *ptr;
+               int j;
+
+               ptr = pix + ((hdr.img_desc & 0x20) ? i : y-(i+1)) * x;
+
+               for(j=0; j<x; j++) {
+                       unsigned char r, g, b, a;
+                       r = fgetc(fp);
+                       g = fgetc(fp);
+                       b = fgetc(fp);
+                       a = (hdr.img_desc & 0xf) ? fgetc(fp) : 255;
+               
+                       *ptr++ = PACK_COLOR32(a, r, g, b);
+                       
+                       if(feof(fp)) break;
+               }
+       }
+
+       fclose(fp);
+       *xsz = x;
+       *ysz = y;
+       return pix;
+}
+
+int save_tga(FILE *fp, void *pixels, unsigned long xsz, unsigned long ysz) {
+       struct tga_header hdr;
+       struct tga_footer ftr;
+       unsigned long pix_count = xsz * ysz;
+       uint32_t *pptr = pixels;
+       unsigned long save_flags;
+       int i;
+
+       save_flags = get_image_save_flags();
+
+       memset(&hdr, 0, sizeof hdr);
+       hdr.img_type = 2;
+       hdr.img_width = xsz;
+       hdr.img_height = ysz;
+
+       if(save_flags & IMG_SAVE_ALPHA) {
+               hdr.img_bpp = 32;
+               hdr.img_desc = 8 | 0x20;        /* 8 alpha bits, origin top-left */
+       } else {
+               hdr.img_bpp = 24;
+               hdr.img_desc = 0x20;            /* no alpha bits, origin top-left */
+       }
+
+       if(save_flags & IMG_SAVE_INVERT) {
+               hdr.img_desc ^= 0x20;
+       }
+
+       ftr.ext_off = 0;
+       ftr.devdir_off = 0;
+       strcpy(ftr.sig, "TRUEVISION-XFILE.");
+
+       /* write the header */
+       
+       fwrite(&hdr.idlen, 1, 1, fp);
+       fwrite(&hdr.cmap_type, 1, 1, fp);
+       fwrite(&hdr.img_type, 1, 1, fp);
+       write_int16_le(fp, hdr.cmap_first);
+       write_int16_le(fp, hdr.cmap_len);
+       fwrite(&hdr.cmap_entry_sz, 1, 1, fp);
+       write_int16_le(fp, hdr.img_x);
+       write_int16_le(fp, hdr.img_y);
+       write_int16_le(fp, hdr.img_width);
+       write_int16_le(fp, hdr.img_height);
+       fwrite(&hdr.img_bpp, 1, 1, fp);
+       fwrite(&hdr.img_desc, 1, 1, fp);
+
+       /* write the pixels */
+       for(i=0; i<pix_count; i++) {
+               fputc((*pptr >> BLUE_SHIFT32) & 0xff, fp);
+               fputc((*pptr >> GREEN_SHIFT32) & 0xff, fp);
+               fputc((*pptr >> RED_SHIFT32) & 0xff, fp);
+               
+               if(save_flags & IMG_SAVE_ALPHA) {
+                       fputc((*pptr >> ALPHA_SHIFT32) & 0xff, fp);
+               }
+               
+               pptr++;
+       }
+
+       /* write the footer */
+       write_int32_le(fp, ftr.ext_off);
+       write_int32_le(fp, ftr.devdir_off);
+       fputs(ftr.sig, fp);
+       fputc(0, fp);
+
+       fclose(fp);
+       return 0;
+}
+
+/*
+static void print_tga_info(struct tga_header *hdr) {
+       static const char *img_type_str[] = {
+               "no image data",
+               "uncompressed color-mapped",
+               "uncompressed true color",
+               "uncompressed black & white",
+               "", "", "", "", "",
+               "RLE color-mapped",
+               "RLE true color",
+               "RLE black & white"
+       };
+       
+       printf("id field length: %d\n", (int)hdr->idlen);
+       printf("color map present: %s\n", hdr->cmap_type ? "yes" : "no");
+       printf("image type: %s\n", img_type_str[hdr->img_type]);
+       printf("color-map start: %d\n", (int)hdr->cmap_first);
+       printf("color-map length: %d\n", (int)hdr->cmap_len);
+       printf("color-map entry size: %d\n", (int)hdr->cmap_entry_sz);
+       printf("image origin: %d, %d\n", (int)hdr->img_x, (int)hdr->img_y);
+       printf("image size: %d, %d\n", (int)hdr->img_width, (int)hdr->img_height);
+       printf("bpp: %d\n", (int)hdr->img_bpp);
+       printf("attribute bits (alpha/overlay): %d\n", (int)(hdr->img_desc & 0xf));
+       printf("origin: %s-", (hdr->img_desc & 0x20) ? "top" : "bottom");
+       printf("%s\n", (hdr->img_desc & 0x10) ? "right" : "left");
+}
+*/
+
+#endif /* IMGLIB_USE_TGA */