2 * TGA is a fairly dead standard, however in the video industry
3 * it is still used a little for test patterns and the like.
5 * Thus we ignore any alpha channels, and colour mapped images.
13 #include "imagefile.h"
20 int idlen; /* length of string after header */
21 int cmaptype; /* 1 => datatype = 1 => colourmapped */
22 int datatype; /* see below */
23 int cmaporigin; /* index of first entry in colour map */
24 int cmaplen; /* length of olour map */
25 int cmapbpp; /* bips per pixel of colour map: 16, 24, or 32 */
26 int xorigin; /* source image origin */
30 int bpp; /* bits per pixel of image: 16, 24, or 32 */
32 uchar *cmap; /* colour map (optional) */
37 * d0-3 = number of attribute bits per pixel
38 * d4 = reserved, always zero
39 * d6-7 = origin: 0=lower left, 1=upper left, 2=lower right, 3=upper right
40 * d8-9 = interleave: 0=progressive, 1=2 way, 3 = 4 way, 4 = reserved.
48 [9] "RLE color-mapped",
50 [11] "Compressed B&W",
51 [32] "Compressed color",
52 [33] "Quadtree compressed color",
60 if((x = Bgetc(bp)) < 0)
62 if((y = Bgetc(bp)) < 0)
73 if((h = malloc(sizeof(Tga))) == nil)
75 if((h->idlen = Bgetc(bp)) == -1)
77 if((h->cmaptype = Bgetc(bp)) == -1)
79 if((h->datatype = Bgetc(bp)) == -1)
81 if((h->cmaporigin = Bgeti(bp)) == -1)
83 if((h->cmaplen = Bgeti(bp)) == -1)
85 if((h->cmapbpp = Bgetc(bp)) == -1)
87 if((h->xorigin = Bgeti(bp)) == -1)
89 if((h->yorigin = Bgeti(bp)) == -1)
91 if((h->width = Bgeti(bp)) == -1)
93 if((h->height = Bgeti(bp)) == -1)
95 if((h->bpp = Bgetc(bp)) == -1)
97 if((h->descriptor = Bgetc(bp)) == -1)
100 /* skip over ID, usually empty anyway */
101 if(Bseek(bp, h->idlen, 1) < 0){
106 if(h->cmaptype == 0){
111 n = (h->cmapbpp/8)*h->cmaplen;
112 if((h->cmap = malloc(n)) == nil){
116 if(Breadn(bp, h->cmap, n) != n){
125 luma(Biobuf *bp, uchar *l, int num)
127 return Breadn(bp, l, num);
131 luma_rle(Biobuf *bp, uchar *l, int num)
136 for(got = 0; got < num; got += len){
137 if(Bread(bp, &len, 1) != 1)
141 len += 1; /* run of zero is meaningless */
142 if(luma(bp, l, 1) != 1)
144 for(i = 0; i < len && got < num; i++)
148 len += 1; /* raw block of zero is meaningless */
149 if(luma(bp, l, len) != len)
159 rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
166 for(i = 0; i < num; i++){
167 if(Breadn(bp, buf, 2) != 2)
172 *g++ = ((y&0x03)<<6) | ((x&0xe0)>>2);
177 for(i = 0; i < num; i++){
178 if(Breadn(bp, buf, 3) != 3)
186 for(i = 0; i < num; i++){
187 if(Breadn(bp, buf, 4) != 4)
202 rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
207 for(got = 0; got < num; got += len){
208 if(Bread(bp, &len, 1) != 1)
212 len += 1; /* run of zero is meaningless */
213 if(rgba(bp, bpp, r, g, b, 1) != 1)
215 for(i = 0; i < len-1 && got < num; i++){
222 len += 1; /* raw block of zero is meaningless */
223 if(rgba(bp, bpp, r, g, b, len) != len)
241 if((t = malloc(w)) == nil){
242 werrstr("ReadTGA: no memory - %r\n");
246 for(c = 0; c < ar->nchans; c++){
248 d = ar->chans[c] + ar->chanlen - w;
249 for(l = 0; l < (h/2); l++){
262 reflect(Rawimage *ar)
265 uchar t, *sol, *eol, *s, *d;
270 for(c = 0; c < ar->nchans; c++){
272 eol = ar->chans[c] +w -1;
273 for(l = 0; l < h; l++){
276 for(p = 0; p < w/2; p++){
297 Rawimage *ar, **array;
299 if((h = rdhdr(bp)) == nil){
300 werrstr("ReadTGA: bad header %r");
305 fprint(2, "idlen=%d\n", h->idlen);
306 fprint(2, "cmaptype=%d\n", h->cmaptype);
307 fprint(2, "datatype=%s\n", datatype[h->datatype]);
308 fprint(2, "cmaporigin=%d\n", h->cmaporigin);
309 fprint(2, "cmaplen=%d\n", h->cmaplen);
310 fprint(2, "cmapbpp=%d\n", h->cmapbpp);
311 fprint(2, "xorigin=%d\n", h->xorigin);
312 fprint(2, "yorigin=%d\n", h->yorigin);
313 fprint(2, "width=%d\n", h->width);
314 fprint(2, "height=%d\n", h->height);
315 fprint(2, "bpp=%d\n", h->bpp);
316 fprint(2, "descriptor=%d\n", h->descriptor);
320 if((ar = calloc(sizeof(Rawimage), 1)) == nil){
321 werrstr("ReadTGA: no memory - %r\n");
325 if((array = calloc(sizeof(Rawimage *), 2)) == nil){
326 werrstr("ReadTGA: no memory - %r\n");
332 if(h->datatype == 3){
341 ar->chanlen = h->width*h->height;
342 ar->r = Rect(0, 0, h->width, h->height);
343 for (c = 0; c < ar->nchans; c++)
344 if ((ar->chans[c] = malloc(h->width*h->height)) == nil){
345 werrstr("ReadTGA: no memory - %r\n");
352 num = h->width*h->height;
355 if(rgba(bp, h->bpp, r, g, b, num) != num){
356 werrstr("ReadTGA: decode fail - %r\n");
361 if(luma(bp, r, num) != num){
362 werrstr("ReadTGA: decode fail - %r\n");
367 if((n = rgba_rle(bp, h->bpp, r, g, b, num)) != num){
368 werrstr("ReadTGA: decode fail (%d!=%d) - %r\n", n, num);
373 if(luma_rle(bp, r, num) != num){
374 werrstr("ReadTGA: decode fail - %r\n");
379 werrstr("ReadTGA: type=%d (%s) unsupported\n", h->datatype, datatype[h->datatype]);
394 for (c = 0; c < ar->nchans; c++)
409 if (Binit(&b, fd, OREAD) < 0)