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.
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 colour map */
25 int cmapbpp; /* bits 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",
51 [32] "Compressed color",
52 [33] "Quadtree compressed color",
60 if((x = Bgetc(bp)) < 0)
62 if((y = Bgetc(bp)) < 0)
68 fixcmap(uchar *cmap, int *cmapbpp, int cmaplen)
77 for(i = 0; i < cmaplen; i++){
79 cmap[4*i+0] = cmap[4*i+2];
85 for(i = 0; i < cmaplen; i++){
87 cmap[3*i+0] = cmap[3*i+2];
93 /* convert to 24-bit colormap */
94 if((cmap = realloc(cmap, 3*cmaplen)) == nil)
96 for(i = cmaplen-1; i >= 0; i--){
97 x = (cmap[2*i+1]<<8) | cmap[2*i+0];
99 cmap[3*i+2] = (tmp<<3) | (tmp>>2);
101 cmap[3*i+1] = (tmp<<3) | (tmp>>2);
103 cmap[3*i+0] = (tmp<<3) | (tmp>>2);
120 if((h = malloc(sizeof(Tga))) == nil)
122 if((h->idlen = Bgetc(bp)) == -1)
124 if((h->cmaptype = Bgetc(bp)) == -1)
126 if((h->datatype = Bgetc(bp)) == -1)
128 if((h->cmaporigin = Bgeti(bp)) == -1)
130 if((h->cmaplen = Bgeti(bp)) == -1)
132 if((h->cmapbpp = Bgetc(bp)) == -1)
134 if((h->xorigin = Bgeti(bp)) == -1)
136 if((h->yorigin = Bgeti(bp)) == -1)
138 if((h->width = Bgeti(bp)) == -1)
140 if((h->height = Bgeti(bp)) == -1)
142 if((h->bpp = Bgetc(bp)) == -1)
144 if((h->descriptor = Bgetc(bp)) == -1)
147 /* skip over ID, usually empty anyway */
148 if(Bseek(bp, h->idlen, 1) < 0){
153 if(h->cmaptype == 0){
158 /* skip over unused color map data */
159 n = (h->cmapbpp/8)*h->cmaporigin;
160 if(Bseek(bp, n, 1) < 0){
164 h->cmaplen -= h->cmaporigin;
166 n = (h->cmapbpp/8)*h->cmaplen;
167 if((h->cmap = malloc(n)) == nil){
171 if(Bread(bp, h->cmap, n) != n){
176 if(fixcmap(h->cmap, &h->cmapbpp, h->cmaplen) != 0){
185 cmap(Biobuf *bp, uchar *l, int num)
187 return Bread(bp, l, num);
191 luma(Biobuf *bp, int bpp, uchar *l, int num)
197 got = Bread(bp, l, num);
200 for(got = 0; got < num; got++){
201 if(Bread(bp, tmp, 2) != 2)
210 luma_rle(Biobuf *bp, int bpp, uchar *l, int num)
215 for(got = 0; got < num;){
216 if(Bread(bp, &len, 1) != 1)
220 if(luma(bp, bpp, &p, 1) != 1)
222 for(len++; len > 0 && got < num; len--, got++)
226 for(len++; len > 0 && got < num; len--, got++)
227 if(luma(bp, bpp, l++, 1) != 1)
235 cmap_rle(Biobuf *bp, uchar *l, int num)
237 return luma_rle(bp, 8, l, num);
241 rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
250 for(i = 0; i < num; i++){
251 if(Bread(bp, buf, 2) != 2)
253 x = (buf[1]<<8) | buf[0];
255 *b++ = (tmp<<3) | (tmp>>2);
257 *g++ = (tmp<<3) | (tmp>>2);
259 *r++ = (tmp<<3) | (tmp>>2);
263 for(i = 0; i < num; i++){
264 if(Bread(bp, buf, 3) != 3)
272 for(i = 0; i < num; i++){
273 if(Bread(bp, buf, 4) != 4)
288 rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
293 for(got = 0; got < num; got += len){
294 if(Bread(bp, &len, 1) != 1)
298 len += 1; /* run of zero is meaningless */
299 if(rgba(bp, bpp, r, g, b, 1) != 1)
301 for(i = 1; i < len && got+i < num; i++){
309 len += 1; /* raw block of zero is meaningless */
310 if(rgba(bp, bpp, r, g, b, len) != len)
328 if((t = malloc(w)) == nil){
329 werrstr("ReadTGA: no memory - %r\n");
333 for(c = 0; c < ar->nchans; c++){
335 d = ar->chans[c] + ar->chanlen - w;
336 for(l = 0; l < (h/2); l++){
349 reflect(Rawimage *ar)
352 uchar t, *sol, *eol, *s, *d;
357 for(c = 0; c < ar->nchans; c++){
359 eol = ar->chans[c] +w -1;
360 for(l = 0; l < h; l++){
363 for(p = 0; p < w/2; p++){
384 Rawimage *ar, **array;
386 if((h = rdhdr(bp)) == nil){
387 werrstr("ReadTGA: bad header %r");
392 fprint(2, "idlen=%d\n", h->idlen);
393 fprint(2, "cmaptype=%d\n", h->cmaptype);
394 fprint(2, "datatype=%s\n", datatype[h->datatype]);
395 fprint(2, "cmaporigin=%d\n", h->cmaporigin);
396 fprint(2, "cmaplen=%d\n", h->cmaplen);
397 fprint(2, "cmapbpp=%d\n", h->cmapbpp);
398 fprint(2, "xorigin=%d\n", h->xorigin);
399 fprint(2, "yorigin=%d\n", h->yorigin);
400 fprint(2, "width=%d\n", h->width);
401 fprint(2, "height=%d\n", h->height);
402 fprint(2, "bpp=%d\n", h->bpp);
403 fprint(2, "descriptor=%d\n", h->descriptor);
407 if((ar = calloc(sizeof(Rawimage), 1)) == nil){
408 werrstr("ReadTGA: no memory - %r\n");
412 if((array = calloc(sizeof(Rawimage *), 2)) == nil){
413 werrstr("ReadTGA: no memory - %r\n");
419 if(h->datatype == 3 || h->datatype == 11){
423 else if(h->datatype == 1){
425 ar->chandesc = CRGB1;
427 else if(h->datatype == 9){
429 ar->chandesc = (h->cmapbpp == 32) ? CRGBV : CRGB1;
437 ar->cmaplen = (h->cmapbpp/8)*h->cmaplen;
438 ar->chanlen = h->width*h->height;
439 ar->r = Rect(0, 0, h->width, h->height);
440 for(c = 0; c < ar->nchans; c++)
441 if((ar->chans[c] = malloc(h->width*h->height)) == nil){
442 werrstr("ReadTGA: no memory - %r\n");
449 num = h->width*h->height;
452 n = cmap(bp, r, num);
455 n = rgba(bp, h->bpp, r, g, b, num);
458 n = luma(bp, h->bpp, r, num);
461 n = cmap_rle(bp, r, num);
464 n = rgba_rle(bp, h->bpp, r, g, b, num);
467 n = luma_rle(bp, h->bpp, r, num);
470 werrstr("ReadTGA: type=%d (%s) unsupported\n", h->datatype, datatype[h->datatype]);
475 werrstr("ReadTGA: decode fail (%d!=%d) - %r\n", n, num);
478 if((h->descriptor&(1<<4)) != 0)
480 if((h->descriptor&(1<<5)) == 0)
488 for (c = 0; c < ar->nchans; c++)
503 if(Binit(&b, fd, OREAD) < 0)