jpg/tga: decode TGA32 images into RGBA32 ones

This commit is contained in:
rodri 2024-09-12 19:09:40 +00:00
parent ce97bb4998
commit 9482f887f9
4 changed files with 37 additions and 13 deletions

View file

@ -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,

View file

@ -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);

View file

@ -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);
}

View file

@ -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; j<i->chanlen; j++){
r = *bp++;
@ -116,6 +121,15 @@ totruecolor(Rawimage *i, int chandesc)
}
}else
for(j=0; j<i->chanlen; 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++;