diff --git a/sys/src/cmd/jpg/imagefile.h b/sys/src/cmd/jpg/imagefile.h index 5c808b685..a0e6a8f94 100644 --- a/sys/src/cmd/jpg/imagefile.h +++ b/sys/src/cmd/jpg/imagefile.h @@ -29,6 +29,7 @@ enum CRGBA32 = 6, /* one channel in correct data order for loadimage(RGBA32) */ CYA16 = 7, /* one channel in correct data order for loadimage(Grey8+Alpha8) */ CRGBVA16= 8, /* one channel in correct data order for loadimage(CMAP8+Alpha8) */ + CRGBA = 9, /* four channels, no map */ /* GIF flags */ TRANSP = 1, diff --git a/sys/src/cmd/jpg/readtga.c b/sys/src/cmd/jpg/readtga.c index b0ba260d3..dd4c58979 100644 --- a/sys/src/cmd/jpg/readtga.c +++ b/sys/src/cmd/jpg/readtga.c @@ -238,7 +238,7 @@ cmap_rle(Biobuf *bp, uchar *l, int num) } static int -rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num) +rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, uchar *a, int num) { int i; uchar buf[4], tmp; @@ -275,6 +275,7 @@ rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num) *b++ = buf[0]; *g++ = buf[1]; *r++ = buf[2]; + *a++ = buf[3]; } break; default: @@ -285,7 +286,7 @@ rgba(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num) } static int -rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num) +rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, uchar *a, int num) { uchar len; int i, got; @@ -296,23 +297,27 @@ rgba_rle(Biobuf *bp, int bpp, uchar *r, uchar *g, uchar *b, int num) if(len & 0x80){ len &= 0x7f; len += 1; /* run of zero is meaningless */ - if(rgba(bp, bpp, r, g, b, 1) != 1) + if(rgba(bp, bpp, r, g, b, a, 1) != 1) break; for(i = 1; i < len && got+i < num; i++){ r[i] = *r; g[i] = *g; b[i] = *b; + if(bpp == 32) + a[i] = *a; } len = i; } else{ len += 1; /* raw block of zero is meaningless */ - if(rgba(bp, bpp, r, g, b, len) != len) + if(rgba(bp, bpp, r, g, b, a, len) != len) break; } r += len; g += len; b += len; + if(bpp == 32) + a += len; } return got; } @@ -380,7 +385,7 @@ Breadtga(Biobuf *bp) { Tga *h; int n, c, num; - uchar *r, *g, *b; + uchar *r, *g, *b, *a; Rawimage *ar, **array; if((h = rdhdr(bp)) == nil){ @@ -429,8 +434,8 @@ Breadtga(Biobuf *bp) ar->chandesc = (h->cmapbpp == 32) ? CRGBV : CRGB1; } else{ - ar->nchans = 3; - ar->chandesc = CRGB; + ar->nchans = (h->bpp == 32) ? 4: 3; + ar->chandesc = (h->bpp == 32) ? CRGBA: CRGB; } ar->cmap = h->cmap; @@ -445,6 +450,7 @@ Breadtga(Biobuf *bp) r = ar->chans[0]; g = ar->chans[1]; b = ar->chans[2]; + a = ar->chans[3]; num = h->width*h->height; switch(h->datatype){ @@ -452,7 +458,7 @@ Breadtga(Biobuf *bp) n = cmap(bp, r, num); break; case 2: - n = rgba(bp, h->bpp, r, g, b, num); + n = rgba(bp, h->bpp, r, g, b, a, num); break; case 3: n = luma(bp, h->bpp, r, num); @@ -461,7 +467,7 @@ Breadtga(Biobuf *bp) n = cmap_rle(bp, r, num); break; case 10: - n = rgba_rle(bp, h->bpp, r, g, b, num); + n = rgba_rle(bp, h->bpp, r, g, b, a, num); break; case 11: n = luma_rle(bp, h->bpp, r, num); diff --git a/sys/src/cmd/jpg/tga.c b/sys/src/cmd/jpg/tga.c index 9655f2f5a..f49a0762c 100644 --- a/sys/src/cmd/jpg/tga.c +++ b/sys/src/cmd/jpg/tga.c @@ -166,6 +166,9 @@ show(int fd, char *name) if(outchan==GREY8 || (r->chandesc==CY && threeflag==0)){ c = totruecolor(r, CY); outchan = GREY8; + }else if(r->chandesc==CRGBA){ + c = totruecolor(r, CRGBA32); + outchan = RGBA32; }else c = totruecolor(r, CRGB24); } diff --git a/sys/src/cmd/jpg/totruecolor.c b/sys/src/cmd/jpg/totruecolor.c index 4942a7e5b..901481e9c 100644 --- a/sys/src/cmd/jpg/totruecolor.c +++ b/sys/src/cmd/jpg/totruecolor.c @@ -17,10 +17,11 @@ totruecolor(Rawimage *i, int chandesc) int j, k; Rawimage *im; char err[ERRMAX]; - uchar *rp, *gp, *bp, *cmap, *inp, *outp, cmap1[4*256]; + uchar *rp, *gp, *bp, *ap, *cmap, *inp, *outp, cmap1[4*256]; int r, g, b, Y, Cr, Cb, psize; + double a; - if(chandesc!=CY && chandesc!=CRGB24) + if(chandesc!=CY && chandesc!=CRGB24 && chandesc!=CRGBA32) return _remaperror("remap: can't convert to chandesc %d", chandesc); err[0] = '\0'; @@ -31,8 +32,10 @@ totruecolor(Rawimage *i, int chandesc) memset(im, 0, sizeof(Rawimage)); if(chandesc == CY) im->chanlen = i->chanlen; - else + else if(chandesc == CRGB24) im->chanlen = 3*i->chanlen; + else + im->chanlen = 4*i->chanlen; im->chandesc = chandesc; im->chans[0] = malloc(im->chanlen); if(im->chans[0] == nil){ @@ -101,11 +104,13 @@ totruecolor(Rawimage *i, int chandesc) break; case CRGB: - if(i->nchans != 3) + case CRGBA: + if(i->nchans != 3 && i->nchans != 4) return _remaperror("remap: can't handle nchans %d", i->nchans); rp = i->chans[0]; gp = i->chans[1]; bp = i->chans[2]; + ap = i->chans[3]; if(chandesc == CY){ for(j=0; jchanlen; j++){ r = *bp++; @@ -116,6 +121,15 @@ totruecolor(Rawimage *i, int chandesc) } }else for(j=0; jchanlen; j++){ + if(i->nchans == 4){ + *outp++ = *ap++; + /* pre-multiply alpha */ + a = (double)ap[-1]/0xFF; + *outp++ = *bp++ * a; + *outp++ = *gp++ * a; + *outp++ = *rp++ * a; + continue; + } *outp++ = *bp++; *outp++ = *gp++; *outp++ = *rp++;