1*7cb50cffSDavid du Colombier /*
2*7cb50cffSDavid du Colombier * TGA is a fairly dead standard, however in the video industry
3*7cb50cffSDavid du Colombier * it is still used a little for test patterns and the like.
4*7cb50cffSDavid du Colombier *
5*7cb50cffSDavid du Colombier * Thus we ignore any alpha channels, and colour mapped images.
6*7cb50cffSDavid du Colombier */
7*7cb50cffSDavid du Colombier
8*7cb50cffSDavid du Colombier #include <u.h>
9*7cb50cffSDavid du Colombier #include <libc.h>
10*7cb50cffSDavid du Colombier #include <bio.h>
11*7cb50cffSDavid du Colombier #include <draw.h>
12*7cb50cffSDavid du Colombier #include <ctype.h>
13*7cb50cffSDavid du Colombier #include "imagefile.h"
14*7cb50cffSDavid du Colombier
15*7cb50cffSDavid du Colombier enum {
16*7cb50cffSDavid du Colombier HdrLen = 18,
17*7cb50cffSDavid du Colombier };
18*7cb50cffSDavid du Colombier
19*7cb50cffSDavid du Colombier typedef struct {
20*7cb50cffSDavid du Colombier int idlen; /* length of string after header */
21*7cb50cffSDavid du Colombier int cmaptype; /* 1 => datatype = 1 => colourmapped */
22*7cb50cffSDavid du Colombier int datatype; /* see below */
23*7cb50cffSDavid du Colombier int cmaporigin; /* index of first entry in colour map */
24*7cb50cffSDavid du Colombier int cmaplen; /* length of olour map */
25*7cb50cffSDavid du Colombier int cmapbpp; /* bips per pixel of colour map: 16, 24, or 32 */
26*7cb50cffSDavid du Colombier int xorigin; /* source image origin */
27*7cb50cffSDavid du Colombier int yorigin;
28*7cb50cffSDavid du Colombier int width;
29*7cb50cffSDavid du Colombier int height;
30*7cb50cffSDavid du Colombier int bpp; /* bits per pixel of image: 16, 24, or 32 */
31*7cb50cffSDavid du Colombier int descriptor;
32*7cb50cffSDavid du Colombier uchar *cmap; /* colour map (optional) */
33*7cb50cffSDavid du Colombier } Tga;
34*7cb50cffSDavid du Colombier
35*7cb50cffSDavid du Colombier /*
36*7cb50cffSDavid du Colombier * descriptor:
37*7cb50cffSDavid du Colombier * d0-3 = number of attribute bits per pixel
38*7cb50cffSDavid du Colombier * d4 = reserved, always zero
39*7cb50cffSDavid du Colombier * d6-7 = origin: 0=lower left, 1=upper left, 2=lower right, 3=upper right
40*7cb50cffSDavid du Colombier * d8-9 = interleave: 0=progressive, 1=2 way, 3 = 4 way, 4 = reserved.
41*7cb50cffSDavid du Colombier */
42*7cb50cffSDavid du Colombier
43*7cb50cffSDavid du Colombier char *datatype[] = {
44*7cb50cffSDavid du Colombier [0] "No image data",
45*7cb50cffSDavid du Colombier [1] "color mapped",
46*7cb50cffSDavid du Colombier [2] "RGB",
47*7cb50cffSDavid du Colombier [3] "B&W",
48*7cb50cffSDavid du Colombier [9] "RLE color-mapped",
49*7cb50cffSDavid du Colombier [10] "RLE RGB",
50*7cb50cffSDavid du Colombier [11] "Compressed B&W",
51*7cb50cffSDavid du Colombier [32] "Compressed color",
52*7cb50cffSDavid du Colombier [33] "Quadtree compressed color",
53*7cb50cffSDavid du Colombier };
54*7cb50cffSDavid du Colombier
55*7cb50cffSDavid du Colombier static int
Bgeti(Biobuf * bp)56*7cb50cffSDavid du Colombier Bgeti(Biobuf *bp)
57*7cb50cffSDavid du Colombier {
58*7cb50cffSDavid du Colombier int x, y;
59*7cb50cffSDavid du Colombier
60*7cb50cffSDavid du Colombier if((x = Bgetc(bp)) < 0)
61*7cb50cffSDavid du Colombier return -1;
62*7cb50cffSDavid du Colombier if((y = Bgetc(bp)) < 0)
63*7cb50cffSDavid du Colombier return -1;
64*7cb50cffSDavid du Colombier return (y<<8)|x;
65*7cb50cffSDavid du Colombier }
66*7cb50cffSDavid du Colombier
67*7cb50cffSDavid du Colombier static Tga *
rdhdr(Biobuf * bp)68*7cb50cffSDavid du Colombier rdhdr(Biobuf *bp)
69*7cb50cffSDavid du Colombier {
70*7cb50cffSDavid du Colombier int n;
71*7cb50cffSDavid du Colombier Tga *h;
72*7cb50cffSDavid du Colombier
73*7cb50cffSDavid du Colombier if((h = malloc(sizeof(Tga))) == nil)
74*7cb50cffSDavid du Colombier return nil;
75*7cb50cffSDavid du Colombier if((h->idlen = Bgetc(bp)) == -1)
76*7cb50cffSDavid du Colombier return nil;
77*7cb50cffSDavid du Colombier if((h->cmaptype = Bgetc(bp)) == -1)
78*7cb50cffSDavid du Colombier return nil;
79*7cb50cffSDavid du Colombier if((h->datatype = Bgetc(bp)) == -1)
80*7cb50cffSDavid du Colombier return nil;
81*7cb50cffSDavid du Colombier if((h->cmaporigin = Bgeti(bp)) == -1)
82*7cb50cffSDavid du Colombier return nil;
83*7cb50cffSDavid du Colombier if((h->cmaplen = Bgeti(bp)) == -1)
84*7cb50cffSDavid du Colombier return nil;
85*7cb50cffSDavid du Colombier if((h->cmapbpp = Bgetc(bp)) == -1)
86*7cb50cffSDavid du Colombier return nil;
87*7cb50cffSDavid du Colombier if((h->xorigin = Bgeti(bp)) == -1)
88*7cb50cffSDavid du Colombier return nil;
89*7cb50cffSDavid du Colombier if((h->yorigin = Bgeti(bp)) == -1)
90*7cb50cffSDavid du Colombier return nil;
91*7cb50cffSDavid du Colombier if((h->width = Bgeti(bp)) == -1)
92*7cb50cffSDavid du Colombier return nil;
93*7cb50cffSDavid du Colombier if((h->height = Bgeti(bp)) == -1)
94*7cb50cffSDavid du Colombier return nil;
95*7cb50cffSDavid du Colombier if((h->bpp = Bgetc(bp)) == -1)
96*7cb50cffSDavid du Colombier return nil;
97*7cb50cffSDavid du Colombier if((h->descriptor = Bgetc(bp)) == -1)
98*7cb50cffSDavid du Colombier return nil;
99*7cb50cffSDavid du Colombier
100*7cb50cffSDavid du Colombier /* skip over ID, usually empty anyway */
101*7cb50cffSDavid du Colombier if(Bseek(bp, h->idlen, 1) < 0){
102*7cb50cffSDavid du Colombier free(h);
103*7cb50cffSDavid du Colombier return nil;
104*7cb50cffSDavid du Colombier }
105*7cb50cffSDavid du Colombier
106*7cb50cffSDavid du Colombier if(h->cmaptype == 0){
107*7cb50cffSDavid du Colombier h->cmap = 0;
108*7cb50cffSDavid du Colombier return h;
109*7cb50cffSDavid du Colombier }
110*7cb50cffSDavid du Colombier
111*7cb50cffSDavid du Colombier n = (h->cmapbpp/8)*h->cmaplen;
112*7cb50cffSDavid du Colombier if((h->cmap = malloc(n)) == nil){
113*7cb50cffSDavid du Colombier free(h);
114*7cb50cffSDavid du Colombier return nil;
115*7cb50cffSDavid du Colombier }
116*7cb50cffSDavid du Colombier if(Bread(bp, h->cmap, n) != n){
117*7cb50cffSDavid du Colombier free(h);
118*7cb50cffSDavid du Colombier free(h->cmap);
119*7cb50cffSDavid du Colombier return nil;
120*7cb50cffSDavid du Colombier }
121*7cb50cffSDavid du Colombier return h;
122*7cb50cffSDavid du Colombier }
123*7cb50cffSDavid du Colombier
124*7cb50cffSDavid du Colombier static int
luma(Biobuf * bp,uchar * l,int num)125*7cb50cffSDavid du Colombier luma(Biobuf *bp, uchar *l, int num)
126*7cb50cffSDavid du Colombier {
127*7cb50cffSDavid du Colombier return Bread(bp, l, num);
128*7cb50cffSDavid du Colombier }
129*7cb50cffSDavid du Colombier
130*7cb50cffSDavid du Colombier static int
luma_rle(Biobuf * bp,uchar * l,int num)131*7cb50cffSDavid du Colombier luma_rle(Biobuf *bp, uchar *l, int num)
132*7cb50cffSDavid du Colombier {
133*7cb50cffSDavid du Colombier uchar len;
134*7cb50cffSDavid du Colombier int i, got;
135*7cb50cffSDavid du Colombier
136*7cb50cffSDavid du Colombier for(got = 0; got < num; got += len){
137*7cb50cffSDavid du Colombier if(Bread(bp, &len, 1) != 1)
138*7cb50cffSDavid du Colombier break;
139*7cb50cffSDavid du Colombier if(len & 0x80){
140*7cb50cffSDavid du Colombier len &= 0x7f;
141*7cb50cffSDavid du Colombier len += 1; /* run of zero is meaningless */
142*7cb50cffSDavid du Colombier if(luma(bp, l, 1) != 1)
143*7cb50cffSDavid du Colombier break;
144*7cb50cffSDavid du Colombier for(i = 0; i < len && got < num; i++)
145*7cb50cffSDavid du Colombier l[i+1] = *l;
146*7cb50cffSDavid du Colombier }
147*7cb50cffSDavid du Colombier else{
148*7cb50cffSDavid du Colombier len += 1; /* raw block of zero is meaningless */
149*7cb50cffSDavid du Colombier if(luma(bp, l, len) != len)
150*7cb50cffSDavid du Colombier break;
151*7cb50cffSDavid du Colombier }
152*7cb50cffSDavid du Colombier l += len;
153*7cb50cffSDavid du Colombier }
154*7cb50cffSDavid du Colombier return got;
155*7cb50cffSDavid du Colombier }
156*7cb50cffSDavid du Colombier
157*7cb50cffSDavid du Colombier
158*7cb50cffSDavid du Colombier static int
rgba(Biobuf * bp,int bpp,uchar * r,uchar * g,uchar * b,int num)159*7cb50cffSDavid du Colombier rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
160*7cb50cffSDavid du Colombier {
161*7cb50cffSDavid du Colombier int i;
162*7cb50cffSDavid du Colombier uchar x, y, buf[4];
163*7cb50cffSDavid du Colombier
164*7cb50cffSDavid du Colombier switch(bpp){
165*7cb50cffSDavid du Colombier case 16:
166*7cb50cffSDavid du Colombier for(i = 0; i < num; i++){
167*7cb50cffSDavid du Colombier if(Bread(bp, buf, 2) != 2)
168*7cb50cffSDavid du Colombier break;
169*7cb50cffSDavid du Colombier x = buf[0];
170*7cb50cffSDavid du Colombier y = buf[1];
171*7cb50cffSDavid du Colombier *b++ = (x&0x1f)<<3;
172*7cb50cffSDavid du Colombier *g++ = ((y&0x03)<<6) | ((x&0xe0)>>2);
173*7cb50cffSDavid du Colombier *r++ = (y&0x1f)<<3;
174*7cb50cffSDavid du Colombier }
175*7cb50cffSDavid du Colombier break;
176*7cb50cffSDavid du Colombier case 24:
177*7cb50cffSDavid du Colombier for(i = 0; i < num; i++){
178*7cb50cffSDavid du Colombier if(Bread(bp, buf, 3) != 3)
179*7cb50cffSDavid du Colombier break;
180*7cb50cffSDavid du Colombier *b++ = buf[0];
181*7cb50cffSDavid du Colombier *g++ = buf[1];
182*7cb50cffSDavid du Colombier *r++ = buf[2];
183*7cb50cffSDavid du Colombier }
184*7cb50cffSDavid du Colombier break;
185*7cb50cffSDavid du Colombier case 32:
186*7cb50cffSDavid du Colombier for(i = 0; i < num; i++){
187*7cb50cffSDavid du Colombier if(Bread(bp, buf, 4) != 4)
188*7cb50cffSDavid du Colombier break;
189*7cb50cffSDavid du Colombier *b++ = buf[0];
190*7cb50cffSDavid du Colombier *g++ = buf[1];
191*7cb50cffSDavid du Colombier *r++ = buf[2];
192*7cb50cffSDavid du Colombier }
193*7cb50cffSDavid du Colombier break;
194*7cb50cffSDavid du Colombier default:
195*7cb50cffSDavid du Colombier i = 0;
196*7cb50cffSDavid du Colombier break;
197*7cb50cffSDavid du Colombier }
198*7cb50cffSDavid du Colombier return i;
199*7cb50cffSDavid du Colombier }
200*7cb50cffSDavid du Colombier
201*7cb50cffSDavid du Colombier static int
rgba_rle(Biobuf * bp,int bpp,uchar * r,uchar * g,uchar * b,int num)202*7cb50cffSDavid du Colombier rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num)
203*7cb50cffSDavid du Colombier {
204*7cb50cffSDavid du Colombier uchar len;
205*7cb50cffSDavid du Colombier int i, got;
206*7cb50cffSDavid du Colombier
207*7cb50cffSDavid du Colombier for(got = 0; got < num; got += len){
208*7cb50cffSDavid du Colombier if(Bread(bp, &len, 1) != 1)
209*7cb50cffSDavid du Colombier break;
210*7cb50cffSDavid du Colombier if(len & 0x80){
211*7cb50cffSDavid du Colombier len &= 0x7f;
212*7cb50cffSDavid du Colombier len += 1; /* run of zero is meaningless */
213*7cb50cffSDavid du Colombier if(rgba(bp, bpp, r, g, b, 1) != 1)
214*7cb50cffSDavid du Colombier break;
215*7cb50cffSDavid du Colombier for(i = 0; i < len-1 && got < num; i++){
216*7cb50cffSDavid du Colombier r[i+1] = *r;
217*7cb50cffSDavid du Colombier g[i+1] = *g;
218*7cb50cffSDavid du Colombier b[i+1] = *b;
219*7cb50cffSDavid du Colombier }
220*7cb50cffSDavid du Colombier }
221*7cb50cffSDavid du Colombier else{
222*7cb50cffSDavid du Colombier len += 1; /* raw block of zero is meaningless */
223*7cb50cffSDavid du Colombier if(rgba(bp, bpp, r, g, b, len) != len)
224*7cb50cffSDavid du Colombier break;
225*7cb50cffSDavid du Colombier }
226*7cb50cffSDavid du Colombier r += len;
227*7cb50cffSDavid du Colombier g += len;
228*7cb50cffSDavid du Colombier b += len;
229*7cb50cffSDavid du Colombier }
230*7cb50cffSDavid du Colombier return got;
231*7cb50cffSDavid du Colombier }
232*7cb50cffSDavid du Colombier
233*7cb50cffSDavid du Colombier int
flip(Rawimage * ar)234*7cb50cffSDavid du Colombier flip(Rawimage *ar)
235*7cb50cffSDavid du Colombier {
236*7cb50cffSDavid du Colombier int w, h, c, l;
237*7cb50cffSDavid du Colombier uchar *t, *s, *d;
238*7cb50cffSDavid du Colombier
239*7cb50cffSDavid du Colombier w = Dx(ar->r);
240*7cb50cffSDavid du Colombier h = Dy(ar->r);
241*7cb50cffSDavid du Colombier if((t = malloc(w)) == nil){
242*7cb50cffSDavid du Colombier werrstr("ReadTGA: no memory - %r\n");
243*7cb50cffSDavid du Colombier return -1;
244*7cb50cffSDavid du Colombier }
245*7cb50cffSDavid du Colombier
246*7cb50cffSDavid du Colombier for(c = 0; c < ar->nchans; c++){
247*7cb50cffSDavid du Colombier s = ar->chans[c];
248*7cb50cffSDavid du Colombier d = ar->chans[c] + ar->chanlen - w;
249*7cb50cffSDavid du Colombier for(l = 0; l < (h/2); l++){
250*7cb50cffSDavid du Colombier memcpy(t, s, w);
251*7cb50cffSDavid du Colombier memcpy(s, d, w);
252*7cb50cffSDavid du Colombier memcpy(d, t, w);
253*7cb50cffSDavid du Colombier s += w;
254*7cb50cffSDavid du Colombier d -= w;
255*7cb50cffSDavid du Colombier }
256*7cb50cffSDavid du Colombier }
257*7cb50cffSDavid du Colombier free(t);
258*7cb50cffSDavid du Colombier return 0;
259*7cb50cffSDavid du Colombier }
260*7cb50cffSDavid du Colombier
261*7cb50cffSDavid du Colombier int
reflect(Rawimage * ar)262*7cb50cffSDavid du Colombier reflect(Rawimage *ar)
263*7cb50cffSDavid du Colombier {
264*7cb50cffSDavid du Colombier int w, h, c, l, p;
265*7cb50cffSDavid du Colombier uchar t, *sol, *eol, *s, *d;
266*7cb50cffSDavid du Colombier
267*7cb50cffSDavid du Colombier w = Dx(ar->r);
268*7cb50cffSDavid du Colombier h = Dy(ar->r);
269*7cb50cffSDavid du Colombier
270*7cb50cffSDavid du Colombier for(c = 0; c < ar->nchans; c++){
271*7cb50cffSDavid du Colombier sol = ar->chans[c];
272*7cb50cffSDavid du Colombier eol = ar->chans[c] +w -1;
273*7cb50cffSDavid du Colombier for(l = 0; l < h; l++){
274*7cb50cffSDavid du Colombier s = sol;
275*7cb50cffSDavid du Colombier d = eol;
276*7cb50cffSDavid du Colombier for(p = 0; p < w/2; p++){
277*7cb50cffSDavid du Colombier t = *s;
278*7cb50cffSDavid du Colombier *s = *d;
279*7cb50cffSDavid du Colombier *d = t;
280*7cb50cffSDavid du Colombier s++;
281*7cb50cffSDavid du Colombier d--;
282*7cb50cffSDavid du Colombier }
283*7cb50cffSDavid du Colombier sol += w;
284*7cb50cffSDavid du Colombier eol += w;
285*7cb50cffSDavid du Colombier }
286*7cb50cffSDavid du Colombier }
287*7cb50cffSDavid du Colombier return 0;
288*7cb50cffSDavid du Colombier }
289*7cb50cffSDavid du Colombier
290*7cb50cffSDavid du Colombier
291*7cb50cffSDavid du Colombier Rawimage**
Breadtga(Biobuf * bp)292*7cb50cffSDavid du Colombier Breadtga(Biobuf *bp)
293*7cb50cffSDavid du Colombier {
294*7cb50cffSDavid du Colombier Tga *h;
295*7cb50cffSDavid du Colombier int n, c, num;
296*7cb50cffSDavid du Colombier uchar *r, *g, *b;
297*7cb50cffSDavid du Colombier Rawimage *ar, **array;
298*7cb50cffSDavid du Colombier
299*7cb50cffSDavid du Colombier if((h = rdhdr(bp)) == nil){
300*7cb50cffSDavid du Colombier werrstr("ReadTGA: bad header %r");
301*7cb50cffSDavid du Colombier return nil;
302*7cb50cffSDavid du Colombier }
303*7cb50cffSDavid du Colombier
304*7cb50cffSDavid du Colombier if(0){
305*7cb50cffSDavid du Colombier fprint(2, "idlen=%d\n", h->idlen);
306*7cb50cffSDavid du Colombier fprint(2, "cmaptype=%d\n", h->cmaptype);
307*7cb50cffSDavid du Colombier fprint(2, "datatype=%s\n", datatype[h->datatype]);
308*7cb50cffSDavid du Colombier fprint(2, "cmaporigin=%d\n", h->cmaporigin);
309*7cb50cffSDavid du Colombier fprint(2, "cmaplen=%d\n", h->cmaplen);
310*7cb50cffSDavid du Colombier fprint(2, "cmapbpp=%d\n", h->cmapbpp);
311*7cb50cffSDavid du Colombier fprint(2, "xorigin=%d\n", h->xorigin);
312*7cb50cffSDavid du Colombier fprint(2, "yorigin=%d\n", h->yorigin);
313*7cb50cffSDavid du Colombier fprint(2, "width=%d\n", h->width);
314*7cb50cffSDavid du Colombier fprint(2, "height=%d\n", h->height);
315*7cb50cffSDavid du Colombier fprint(2, "bpp=%d\n", h->bpp);
316*7cb50cffSDavid du Colombier fprint(2, "descriptor=%d\n", h->descriptor);
317*7cb50cffSDavid du Colombier }
318*7cb50cffSDavid du Colombier
319*7cb50cffSDavid du Colombier array = nil;
320*7cb50cffSDavid du Colombier if((ar = calloc(sizeof(Rawimage), 1)) == nil){
321*7cb50cffSDavid du Colombier werrstr("ReadTGA: no memory - %r\n");
322*7cb50cffSDavid du Colombier goto Error;
323*7cb50cffSDavid du Colombier }
324*7cb50cffSDavid du Colombier
325*7cb50cffSDavid du Colombier if((array = calloc(sizeof(Rawimage *), 2)) == nil){
326*7cb50cffSDavid du Colombier werrstr("ReadTGA: no memory - %r\n");
327*7cb50cffSDavid du Colombier goto Error;
328*7cb50cffSDavid du Colombier }
329*7cb50cffSDavid du Colombier array[0] = ar;
330*7cb50cffSDavid du Colombier array[1] = nil;
331*7cb50cffSDavid du Colombier
332*7cb50cffSDavid du Colombier if(h->datatype == 3){
333*7cb50cffSDavid du Colombier ar->nchans = 1;
334*7cb50cffSDavid du Colombier ar->chandesc = CY;
335*7cb50cffSDavid du Colombier }
336*7cb50cffSDavid du Colombier else{
337*7cb50cffSDavid du Colombier ar->nchans = 3;
338*7cb50cffSDavid du Colombier ar->chandesc = CRGB;
339*7cb50cffSDavid du Colombier }
340*7cb50cffSDavid du Colombier
341*7cb50cffSDavid du Colombier ar->chanlen = h->width*h->height;
342*7cb50cffSDavid du Colombier ar->r = Rect(0, 0, h->width, h->height);
343*7cb50cffSDavid du Colombier for (c = 0; c < ar->nchans; c++)
344*7cb50cffSDavid du Colombier if ((ar->chans[c] = malloc(h->width*h->height)) == nil){
345*7cb50cffSDavid du Colombier werrstr("ReadTGA: no memory - %r\n");
346*7cb50cffSDavid du Colombier goto Error;
347*7cb50cffSDavid du Colombier }
348*7cb50cffSDavid du Colombier r = ar->chans[0];
349*7cb50cffSDavid du Colombier g = ar->chans[1];
350*7cb50cffSDavid du Colombier b = ar->chans[2];
351*7cb50cffSDavid du Colombier
352*7cb50cffSDavid du Colombier num = h->width*h->height;
353*7cb50cffSDavid du Colombier switch(h->datatype){
354*7cb50cffSDavid du Colombier case 2:
355*7cb50cffSDavid du Colombier if(rgba(bp, h->bpp, r, g, b, num) != num){
356*7cb50cffSDavid du Colombier werrstr("ReadTGA: decode fail - %r\n");
357*7cb50cffSDavid du Colombier goto Error;
358*7cb50cffSDavid du Colombier }
359*7cb50cffSDavid du Colombier break;
360*7cb50cffSDavid du Colombier case 3:
361*7cb50cffSDavid du Colombier if(luma(bp, r, num) != num){
362*7cb50cffSDavid du Colombier werrstr("ReadTGA: decode fail - %r\n");
363*7cb50cffSDavid du Colombier goto Error;
364*7cb50cffSDavid du Colombier }
365*7cb50cffSDavid du Colombier break;
366*7cb50cffSDavid du Colombier case 10:
367*7cb50cffSDavid du Colombier if((n = rgba_rle(bp, h->bpp, r, g, b, num)) != num){
368*7cb50cffSDavid du Colombier werrstr("ReadTGA: decode fail (%d!=%d) - %r\n", n, num);
369*7cb50cffSDavid du Colombier goto Error;
370*7cb50cffSDavid du Colombier }
371*7cb50cffSDavid du Colombier break;
372*7cb50cffSDavid du Colombier case 11:
373*7cb50cffSDavid du Colombier if(luma_rle(bp, r, num) != num){
374*7cb50cffSDavid du Colombier werrstr("ReadTGA: decode fail - %r\n");
375*7cb50cffSDavid du Colombier goto Error;
376*7cb50cffSDavid du Colombier }
377*7cb50cffSDavid du Colombier break;
378*7cb50cffSDavid du Colombier default:
379*7cb50cffSDavid du Colombier werrstr("ReadTGA: type=%d (%s) unsupported\n", h->datatype, datatype[h->datatype]);
380*7cb50cffSDavid du Colombier goto Error;
381*7cb50cffSDavid du Colombier }
382*7cb50cffSDavid du Colombier
383*7cb50cffSDavid du Colombier if(h->xorigin != 0)
384*7cb50cffSDavid du Colombier reflect(ar);
385*7cb50cffSDavid du Colombier if(h->yorigin == 0)
386*7cb50cffSDavid du Colombier flip(ar);
387*7cb50cffSDavid du Colombier
388*7cb50cffSDavid du Colombier free(h->cmap);
389*7cb50cffSDavid du Colombier free(h);
390*7cb50cffSDavid du Colombier return array;
391*7cb50cffSDavid du Colombier Error:
392*7cb50cffSDavid du Colombier
393*7cb50cffSDavid du Colombier if(ar)
394*7cb50cffSDavid du Colombier for (c = 0; c < ar->nchans; c++)
395*7cb50cffSDavid du Colombier free(ar->chans[c]);
396*7cb50cffSDavid du Colombier free(ar);
397*7cb50cffSDavid du Colombier free(array);
398*7cb50cffSDavid du Colombier free(h->cmap);
399*7cb50cffSDavid du Colombier free(h);
400*7cb50cffSDavid du Colombier return nil;
401*7cb50cffSDavid du Colombier }
402*7cb50cffSDavid du Colombier
403*7cb50cffSDavid du Colombier Rawimage**
readtga(int fd)404*7cb50cffSDavid du Colombier readtga(int fd)
405*7cb50cffSDavid du Colombier {
406*7cb50cffSDavid du Colombier Rawimage * *a;
407*7cb50cffSDavid du Colombier Biobuf b;
408*7cb50cffSDavid du Colombier
409*7cb50cffSDavid du Colombier if (Binit(&b, fd, OREAD) < 0)
410*7cb50cffSDavid du Colombier return nil;
411*7cb50cffSDavid du Colombier a = Breadtga(&b);
412*7cb50cffSDavid du Colombier Bterm(&b);
413*7cb50cffSDavid du Colombier return a;
414*7cb50cffSDavid du Colombier }
415*7cb50cffSDavid du Colombier
416*7cb50cffSDavid du Colombier
417