3dphotoshoot

diff libs/imago/file_tga.c @ 14:06dc8b9b4f89

added libimago, libjpeg and libpng
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 07 Jun 2015 17:25:49 +0300
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/libs/imago/file_tga.c	Sun Jun 07 17:25:49 2015 +0300
     1.3 @@ -0,0 +1,250 @@
     1.4 +/*
     1.5 +libimago - a multi-format image file input/output library.
     1.6 +Copyright (C) 2010-2015 John Tsiombikas <nuclear@member.fsf.org>
     1.7 +
     1.8 +This program is free software: you can redistribute it and/or modify
     1.9 +it under the terms of the GNU Lesser General Public License as published
    1.10 +by the Free Software Foundation, either version 3 of the License, or
    1.11 +(at your option) any later version.
    1.12 +
    1.13 +This program is distributed in the hope that it will be useful,
    1.14 +but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.15 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    1.16 +GNU Lesser General Public License for more details.
    1.17 +
    1.18 +You should have received a copy of the GNU Lesser General Public License
    1.19 +along with this program.  If not, see <http://www.gnu.org/licenses/>.
    1.20 +*/
    1.21 +
    1.22 +/* -- Targa (tga) module -- */
    1.23 +
    1.24 +#include <string.h>
    1.25 +#include <stdlib.h>
    1.26 +#include <stdint.h>
    1.27 +#include "imago2.h"
    1.28 +#include "ftype_module.h"
    1.29 +
    1.30 +
    1.31 +#if  defined(__i386__) || defined(__ia64__) || defined(WIN32) || \
    1.32 +    (defined(__alpha__) || defined(__alpha)) || \
    1.33 +     defined(__arm__) || \
    1.34 +    (defined(__mips__) && defined(__MIPSEL__)) || \
    1.35 +     defined(__SYMBIAN32__) || \
    1.36 +     defined(__x86_64__) || \
    1.37 +     defined(__LITTLE_ENDIAN__)
    1.38 +/* little endian */
    1.39 +#define read_int16_le(f)	read_int16(f)
    1.40 +#else
    1.41 +/* big endian */
    1.42 +#define read_int16_le(f)	read_int16_inv(f)
    1.43 +#endif	/* endian check */
    1.44 +
    1.45 +
    1.46 +enum {
    1.47 +	IMG_NONE,
    1.48 +	IMG_CMAP,
    1.49 +	IMG_RGBA,
    1.50 +	IMG_BW,
    1.51 +
    1.52 +	IMG_RLE_CMAP = 9,
    1.53 +	IMG_RLE_RGBA,
    1.54 +	IMG_RLE_BW
    1.55 +};
    1.56 +
    1.57 +#define IS_RLE(x)	((x) >= IMG_RLE_CMAP)
    1.58 +#define IS_RGBA(x)	((x) == IMG_RGBA || (x) == IMG_RLE_RGBA)
    1.59 +
    1.60 +
    1.61 +struct tga_header {
    1.62 +	uint8_t idlen;			/* id field length */
    1.63 +	uint8_t cmap_type;		/* color map type (0:no color map, 1:color map present) */
    1.64 +	uint8_t img_type;		/* image type:
    1.65 +							 * 0: no image data
    1.66 +							 *	1: uncomp. color-mapped		 9: RLE color-mapped
    1.67 +							 *	2: uncomp. true color		10: RLE true color
    1.68 +							 *	3: uncomp. black/white		11: RLE black/white */
    1.69 +	uint16_t cmap_first;	/* color map first entry index */
    1.70 +	uint16_t cmap_len;		/* color map length */
    1.71 +	uint8_t cmap_entry_sz;	/* color map entry size */
    1.72 +	uint16_t img_x;			/* X-origin of the image */
    1.73 +	uint16_t img_y;			/* Y-origin of the image */
    1.74 +	uint16_t img_width;		/* image width */
    1.75 +	uint16_t img_height;	/* image height */
    1.76 +	uint8_t img_bpp;		/* bits per pixel */
    1.77 +	uint8_t img_desc;		/* descriptor:
    1.78 +							 * bits 0 - 3: alpha or overlay bits
    1.79 +							 * bits 5 & 4: origin (0 = bottom/left, 1 = top/right)
    1.80 +							 * bits 7 & 6: data interleaving */
    1.81 +};
    1.82 +
    1.83 +struct tga_footer {
    1.84 +	uint32_t ext_off;		/* extension area offset */
    1.85 +	uint32_t devdir_off;	/* developer directory offset */
    1.86 +	char sig[18];				/* signature with . and \0 */
    1.87 +};
    1.88 +
    1.89 +
    1.90 +static int check(struct img_io *io);
    1.91 +static int read(struct img_pixmap *img, struct img_io *io);
    1.92 +static int write(struct img_pixmap *img, struct img_io *io);
    1.93 +static int read_pixel(struct img_io *io, int rdalpha, uint32_t *pix);
    1.94 +static int16_t read_int16(struct img_io *io);
    1.95 +static int16_t read_int16_inv(struct img_io *io);
    1.96 +
    1.97 +int img_register_tga(void)
    1.98 +{
    1.99 +	static struct ftype_module mod = {".tga", check, read, write};
   1.100 +	return img_register_module(&mod);
   1.101 +}
   1.102 +
   1.103 +
   1.104 +static int check(struct img_io *io)
   1.105 +{
   1.106 +	struct tga_footer foot;
   1.107 +	int res = -1;
   1.108 +	long pos = io->seek(0, SEEK_CUR, io->uptr);
   1.109 +	io->seek(-18, SEEK_END, io->uptr);
   1.110 +
   1.111 +	if(io->read(foot.sig, 17, io->uptr) < 17) {
   1.112 +		io->seek(pos, SEEK_SET, io->uptr);
   1.113 +		return -1;
   1.114 +	}
   1.115 +
   1.116 +	if(memcmp(foot.sig, "TRUEVISION-XFILE.", 17) == 0) {
   1.117 +		res = 0;
   1.118 +	}
   1.119 +	io->seek(pos, SEEK_SET, io->uptr);
   1.120 +	return res;
   1.121 +}
   1.122 +
   1.123 +static int iofgetc(struct img_io *io)
   1.124 +{
   1.125 +	char c;
   1.126 +	return io->read(&c, 1, io->uptr) < 1 ? -1 : c;
   1.127 +}
   1.128 +
   1.129 +static int read(struct img_pixmap *img, struct img_io *io)
   1.130 +{
   1.131 +	struct tga_header hdr;
   1.132 +	unsigned long x, y;
   1.133 +	int i, c;
   1.134 +	uint32_t ppixel = 0;
   1.135 +	int rle_mode = 0, rle_pix_left = 0;
   1.136 +	int rdalpha;
   1.137 +
   1.138 +	/* read header */
   1.139 +	hdr.idlen = iofgetc(io);
   1.140 +	hdr.cmap_type = iofgetc(io);
   1.141 +	hdr.img_type = iofgetc(io);
   1.142 +	hdr.cmap_first = read_int16_le(io);
   1.143 +	hdr.cmap_len = read_int16_le(io);
   1.144 +	hdr.cmap_entry_sz = iofgetc(io);
   1.145 +	hdr.img_x = read_int16_le(io);
   1.146 +	hdr.img_y = read_int16_le(io);
   1.147 +	hdr.img_width = read_int16_le(io);
   1.148 +	hdr.img_height = read_int16_le(io);
   1.149 +	hdr.img_bpp = iofgetc(io);
   1.150 +	if((c = iofgetc(io)) == -1) {
   1.151 +		return -1;
   1.152 +	}
   1.153 +	hdr.img_desc = c;
   1.154 +
   1.155 +	if(!IS_RGBA(hdr.img_type)) {
   1.156 +		fprintf(stderr, "only true color tga images supported\n");
   1.157 +		return -1;
   1.158 +	}
   1.159 +
   1.160 +	io->seek(hdr.idlen, SEEK_CUR, io);	/* skip the image ID */
   1.161 +
   1.162 +	/* skip the color map if it exists */
   1.163 +	if(hdr.cmap_type == 1) {
   1.164 +		io->seek(hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR, io);
   1.165 +	}
   1.166 +
   1.167 +	x = hdr.img_width;
   1.168 +	y = hdr.img_height;
   1.169 +	rdalpha = hdr.img_desc & 0xf;
   1.170 +
   1.171 +	/* TODO make this IMG_FMT_RGB24 if there's no alpha channel */
   1.172 +	if(img_set_pixels(img, x, y, IMG_FMT_RGBA32, 0) == -1) {
   1.173 +		return -1;
   1.174 +	}
   1.175 +
   1.176 +	for(i=0; i<y; i++) {
   1.177 +		uint32_t *ptr;
   1.178 +		int j;
   1.179 +
   1.180 +		ptr = (uint32_t*)img->pixels + ((hdr.img_desc & 0x20) ? i : y - (i + 1)) * x;
   1.181 +
   1.182 +		for(j=0; j<x; j++) {
   1.183 +			/* if the image is raw, then just read the next pixel */
   1.184 +			if(!IS_RLE(hdr.img_type)) {
   1.185 +				if(read_pixel(io, rdalpha, &ppixel) == -1) {
   1.186 +					return -1;
   1.187 +				}
   1.188 +			} else {
   1.189 +				/* otherwise, for RLE... */
   1.190 +
   1.191 +				/* if we have pixels left in the packet ... */
   1.192 +				if(rle_pix_left) {
   1.193 +					/* if it's a raw packet, read the next pixel, otherwise keep the same */
   1.194 +					if(!rle_mode) {
   1.195 +						if(read_pixel(io, rdalpha, &ppixel) == -1) {
   1.196 +							return -1;
   1.197 +						}
   1.198 +					}
   1.199 +					--rle_pix_left;
   1.200 +				} else {
   1.201 +					/* read RLE packet header */
   1.202 +					unsigned char phdr = iofgetc(io);
   1.203 +					rle_mode = (phdr & 128);		/* last bit shows the mode for this packet (1: rle, 0: raw) */
   1.204 +					rle_pix_left = (phdr & ~128);	/* the rest gives the count of pixels minus one (we also read one here, so no +1) */
   1.205 +					/* and read the first pixel of the packet */
   1.206 +					if(read_pixel(io, rdalpha, &ppixel) == -1) {
   1.207 +						return -1;
   1.208 +					}
   1.209 +				}
   1.210 +			}
   1.211 +
   1.212 +			*ptr++ = ppixel;
   1.213 +		}
   1.214 +	}
   1.215 +
   1.216 +	return 0;
   1.217 +}
   1.218 +
   1.219 +static int write(struct img_pixmap *img, struct img_io *io)
   1.220 +{
   1.221 +	return -1;	/* TODO */
   1.222 +}
   1.223 +
   1.224 +#define PACK_COLOR32(r,g,b,a) \
   1.225 +	((((a) & 0xff) << 24) | \
   1.226 +	 (((r) & 0xff) << 0) | \
   1.227 +	 (((g) & 0xff) << 8) | \
   1.228 +	 (((b) & 0xff) << 16))
   1.229 +
   1.230 +static int read_pixel(struct img_io *io, int rdalpha, uint32_t *pix)
   1.231 +{
   1.232 +	int r, g, b, a;
   1.233 +	b = iofgetc(io);
   1.234 +	g = iofgetc(io);
   1.235 +	r = iofgetc(io);
   1.236 +	a = rdalpha ? iofgetc(io) : 0xff;
   1.237 +	*pix = PACK_COLOR32(r, g, b, a);
   1.238 +	return a == -1 || r == -1 ? -1 : 0;
   1.239 +}
   1.240 +
   1.241 +static int16_t read_int16(struct img_io *io)
   1.242 +{
   1.243 +	int16_t v;
   1.244 +	io->read(&v, 2, io);
   1.245 +	return v;
   1.246 +}
   1.247 +
   1.248 +static int16_t read_int16_inv(struct img_io *io)
   1.249 +{
   1.250 +	int16_t v;
   1.251 +	io->read(&v, 2, io);
   1.252 +	return ((v >> 8) & 0xff) | (v << 8);
   1.253 +}