ref: 03e776bc3cb3be7a0dede3de0fb6af99f43b357f
dir: /png-trns-unfinished/
png: read mTRS chunks for indexed rgb24 images FIXME: UNFINISHED, surely breaks with other formats, and code is crap - then, don't check against apalsize (which should not exist) but channel/nout/... settings - implement support for other modes, if we can find test pictures diff -r 321912cfedf3 sys/src/cmd/jpg/readpng.c --- a/sys/src/cmd/jpg/readpng.c Sun Jun 25 22:57:47 2017 +0200 +++ b/sys/src/cmd/jpg/readpng.c Mon Jun 26 23:29:03 2017 +0200 @@ -46,6 +46,8 @@ int pass; /* adam7 pass#; 0 means no adam7 */ uchar palette[3*256]; /* color palette */ int palsize; /* number of palette entries */ + uchar apalette[256]; /* optional alpha values for palette */ + int hasapal; }; struct ZlibR @@ -142,8 +144,18 @@ z->w->palsize = 256; goto Again; } - if(type[0] & PropertyBit) - goto Again; /* skip auxiliary chunks fornow */ + if(type[0] & PropertyBit){ + /* FIXME: non-3 formats are unhandled */ + if(strcmp(type,"tRNS")) + goto Again; /* skip auxiliary chunks fornow */ + if(z->w->chandesc != CRGBA32 || z->w->nchan != 1) + goto Again; /* unimplemented */ + if(n > z->w->palsize) + sysfatal("invalid tRNS chunk len %d", n); + memcpy(z->w->apalette, z->p, n); + z->w->hasapal = 1; + goto Again; + } if(strcmp(type,"IDAT")){ sysfatal("unrecognized mandatory chunk %s", type); goto Again; @@ -258,7 +270,7 @@ j >>= 8-z->bpc; if(j >= z->palsize) sysfatal("index %d >= palette size %d", j, z->palsize); - pixel[3] = pixel[1]; /* alpha */ + pixel[3] = z->hasapal ? z->apalette[j] : pixel[1]; /* alpha */ pixel[0] = z->palette[3*j]; pixel[1] = z->palette[3*j+1]; pixel[2] = z->palette[3*j+2]; @@ -272,6 +284,12 @@ case CRGBA32: // print("%.2x%.2x%.2x%.2x ", pixel[0], pixel[1], pixel[2], pixel[3]); *w++ += pixel[3]; + if(z->hasapal){ + *w++ = pixel[2]; + *w++ = pixel[1]; + *w++ = pixel[0]; + break; + } *w++ += (pixel[2]*pixel[3])/255; *w++ += (pixel[1]*pixel[3])/255; *w++ += (pixel[0]*pixel[3])/255; @@ -438,9 +456,14 @@ case 3: /* indexed rgb with PLTE */ if(bpc != 1 && bpc != 2 && bpc != 4 && bpc != 8) sysfatal("invalid indexed rgb bpc %d", bpc); + /* FIXME: conditially set CRGBA32? maybe pngmalloc directly to zw buffer, resize it + * as needed, and set it before returning? or perhaps alloc maximal size, + * and if there's no valid tRNS chunk, shrink it before returning image; + * so, alloc max, but use minimal params before inflating... */ + /* FIXME: support other formats */ image->nchans = 1; - image->chandesc = CRGB24; - nout = 3; + image->chandesc = CRGBA32; + nout = 4; nchan = 1; break; case 4: /* grey+alpha */ @@ -478,6 +501,7 @@ zw.ndata = image->chanlen; zw.chandesc = image->chandesc; zw.noutchan = nout; + memset(zw.apalette, 0xff, sizeof zw.apalette); zw.dx = dx; zw.dy = dy;