2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010-2021 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU Lesser General Public License as published
7 by the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
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 Lesser General Public License for more details.
15 You should have received a copy of the GNU Lesser General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
19 /* -- Targa (tga) module -- */
38 #define IS_RLE(x) ((x) >= IMG_RLE_CMAP)
39 #define IS_RGBA(x) ((x) == IMG_RGBA || (x) == IMG_RLE_RGBA)
43 uint8_t idlen; /* id field length */
44 uint8_t cmap_type; /* color map type (0:no color map, 1:color map present) */
45 uint8_t img_type; /* image type:
47 * 1: uncomp. color-mapped 9: RLE color-mapped
48 * 2: uncomp. true color 10: RLE true color
49 * 3: uncomp. black/white 11: RLE black/white */
50 uint16_t cmap_first; /* color map first entry index */
51 uint16_t cmap_len; /* color map length */
52 uint8_t cmap_entry_sz; /* color map entry size */
53 uint16_t img_x; /* X-origin of the image */
54 uint16_t img_y; /* Y-origin of the image */
55 uint16_t img_width; /* image width */
56 uint16_t img_height; /* image height */
57 uint8_t img_bpp; /* bits per pixel */
58 uint8_t img_desc; /* descriptor:
59 * bits 0 - 3: alpha or overlay bits
60 * bits 5 & 4: origin (0 = bottom/left, 1 = top/right)
61 * bits 7 & 6: data interleaving */
65 uint32_t ext_off; /* extension area offset */
66 uint32_t devdir_off; /* developer directory offset */
67 char sig[18]; /* signature with . and \0 */
71 static int check(struct img_io *io);
72 static int read_tga(struct img_pixmap *img, struct img_io *io);
73 static int write_tga(struct img_pixmap *img, struct img_io *io);
74 static int read_pixel(struct img_io *io, int fmt, unsigned char *pix);
76 int img_register_tga(void)
78 static struct ftype_module mod = {".tga:.targa", check, read_tga, write_tga};
79 return img_register_module(&mod);
83 static int check(struct img_io *io)
85 struct tga_footer foot;
87 long pos = io->seek(0, SEEK_CUR, io->uptr);
88 io->seek(-18, SEEK_END, io->uptr);
90 if(io->read(foot.sig, 17, io->uptr) < 17) {
91 io->seek(pos, SEEK_SET, io->uptr);
95 if(memcmp(foot.sig, "TRUEVISION-XFILE.", 17) == 0) {
98 io->seek(pos, SEEK_SET, io->uptr);
102 static int iofgetc(struct img_io *io)
105 return io->read(&c, 1, io->uptr) < 1 ? -1 : c;
108 static int read_tga(struct img_pixmap *img, struct img_io *io)
110 struct tga_header hdr;
112 int i, idx, c, r, g, b;
113 int rle_mode = 0, rle_pix_left = 0;
116 struct img_colormap cmap;
119 hdr.idlen = iofgetc(io);
120 hdr.cmap_type = iofgetc(io);
121 hdr.img_type = iofgetc(io);
122 hdr.cmap_first = img_read_int16_le(io);
123 hdr.cmap_len = img_read_int16_le(io);
124 hdr.cmap_entry_sz = iofgetc(io);
125 hdr.img_x = img_read_int16_le(io);
126 hdr.img_y = img_read_int16_le(io);
127 hdr.img_width = img_read_int16_le(io);
128 hdr.img_height = img_read_int16_le(io);
129 hdr.img_bpp = iofgetc(io);
130 if((c = iofgetc(io)) == -1) {
135 io->seek(hdr.idlen, SEEK_CUR, io->uptr); /* skip the image ID */
137 /* read the color map if it exists */
138 if(hdr.cmap_type == 1) {
139 cmap.ncolors = hdr.cmap_len;
141 for(i=0; i<(int)hdr.cmap_len; i++) {
142 switch(hdr.cmap_entry_sz) {
144 c = img_read_int16_le(io);
145 r = (c & 0x7c00) >> 7;
146 g = (c & 0x03e0) >> 2;
147 b = (c & 0x001f) << 3;
160 iofgetc(io); /* ignore attribute byte */
163 idx = i + hdr.cmap_first;
165 cmap.color[idx].r = r;
166 cmap.color[idx].g = g;
167 cmap.color[idx].b = b;
168 if(cmap.ncolors <= idx) cmap.ncolors = idx + 1;
176 if(hdr.img_type == IMG_CMAP || hdr.img_type == IMG_RLE_CMAP) {
177 if(hdr.img_bpp != 8) {
178 fprintf(stderr, "read_tga: indexed images with more than 8bpp not supported\n");
184 int alpha = hdr.img_desc & 0xf;
185 pixel_bytes = alpha ? 4 : 3;
186 fmt = alpha ? IMG_FMT_RGBA32 : IMG_FMT_RGB24;
189 if(img_set_pixels(img, x, y, fmt, 0) == -1) {
193 for(i=0; i<(int)y; i++) {
197 ptr = (unsigned char*)img->pixels + ((hdr.img_desc & 0x20) ? i : y - (i + 1)) * x * pixel_bytes;
199 for(j=0; j<(int)x; j++) {
200 /* if the image is raw, then just read the next pixel */
201 if(!IS_RLE(hdr.img_type)) {
202 if(read_pixel(io, fmt, ptr) == -1) {
206 /* otherwise, for RLE... */
208 /* if we have pixels left in the packet ... */
210 /* if it's a raw packet, read the next pixel, otherwise keep the same */
212 if(read_pixel(io, fmt, ptr) == -1) {
216 for(k=0; k<pixel_bytes; k++) {
217 ptr[k] = ptr[k - pixel_bytes];
222 /* read RLE packet header */
223 unsigned char phdr = iofgetc(io);
224 rle_mode = (phdr & 128); /* last bit shows the mode for this packet (1: rle, 0: raw) */
225 rle_pix_left = (phdr & ~128); /* the rest gives the count of pixels minus one (we also read one here, so no +1) */
226 /* and read the first pixel of the packet */
227 if(read_pixel(io, fmt, ptr) == -1) {
237 if(fmt == IMG_FMT_IDX8) {
238 struct img_colormap *dest = img_colormap(img);
245 static int write_tga(struct img_pixmap *img, struct img_io *io)
247 return -1; /* TODO */
250 static int read_pixel(struct img_io *io, int fmt, unsigned char *pix)
254 if(fmt == IMG_FMT_IDX8) {
255 if((b = iofgetc(io)) == -1) {
262 if((b = iofgetc(io)) == -1 || (g = iofgetc(io)) == -1 || (r = iofgetc(io)) == -1) {
270 if(fmt == IMG_FMT_RGBA32) {
271 if((a = iofgetc(io)) == -1) {