shithub: patch

ref: 801c6e1167653f01779b5643a3e3870e2de56dee
dir: patch/png-trns-unfinished

View raw version
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;