2 libimago - a multi-format image file input/output library.
3 Copyright (C) 2010-2017 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 rdalpha, 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;
113 int rle_mode = 0, rle_pix_left = 0;
118 hdr.idlen = iofgetc(io);
119 hdr.cmap_type = iofgetc(io);
120 hdr.img_type = iofgetc(io);
121 hdr.cmap_first = img_read_int16_le(io);
122 hdr.cmap_len = img_read_int16_le(io);
123 hdr.cmap_entry_sz = iofgetc(io);
124 hdr.img_x = img_read_int16_le(io);
125 hdr.img_y = img_read_int16_le(io);
126 hdr.img_width = img_read_int16_le(io);
127 hdr.img_height = img_read_int16_le(io);
128 hdr.img_bpp = iofgetc(io);
129 if((c = iofgetc(io)) == -1) {
134 if(!IS_RGBA(hdr.img_type)) {
135 fprintf(stderr, "libimago: only true color tga images are supported\n");
139 io->seek(hdr.idlen, SEEK_CUR, io->uptr); /* skip the image ID */
141 /* skip the color map if it exists */
142 if(hdr.cmap_type == 1) {
143 io->seek(hdr.cmap_len * hdr.cmap_entry_sz / 8, SEEK_CUR, io->uptr);
148 rdalpha = hdr.img_desc & 0xf;
149 pixel_bytes = rdalpha ? 4 : 3;
151 if(img_set_pixels(img, x, y, rdalpha ? IMG_FMT_RGBA32 : IMG_FMT_RGB24, 0) == -1) {
159 ptr = (unsigned char*)img->pixels + ((hdr.img_desc & 0x20) ? i : y - (i + 1)) * x * pixel_bytes;
162 /* if the image is raw, then just read the next pixel */
163 if(!IS_RLE(hdr.img_type)) {
164 if(read_pixel(io, rdalpha, ptr) == -1) {
168 /* otherwise, for RLE... */
170 /* if we have pixels left in the packet ... */
172 /* if it's a raw packet, read the next pixel, otherwise keep the same */
174 if(read_pixel(io, rdalpha, ptr) == -1) {
178 for(k=0; k<pixel_bytes; k++) {
179 ptr[k] = ptr[k - pixel_bytes];
184 /* read RLE packet header */
185 unsigned char phdr = iofgetc(io);
186 rle_mode = (phdr & 128); /* last bit shows the mode for this packet (1: rle, 0: raw) */
187 rle_pix_left = (phdr & ~128); /* the rest gives the count of pixels minus one (we also read one here, so no +1) */
188 /* and read the first pixel of the packet */
189 if(read_pixel(io, rdalpha, ptr) == -1) {
202 static int write_tga(struct img_pixmap *img, struct img_io *io)
204 return -1; /* TODO */
207 static int read_pixel(struct img_io *io, int rdalpha, unsigned char *pix)
210 if((b = iofgetc(io)) == -1 || (g = iofgetc(io)) == -1 || (r = iofgetc(io)) == -1) {
219 if((a = iofgetc(io)) == -1) {