Browse Source

Plan 9 from Bell Labs 2005-02-20

David du Colombier 19 years ago
parent
commit
6838837d87

+ 17 - 17
dist/replica/_plan9.db

@@ -165,7 +165,7 @@
 386/bin/bitsy/params - 775 sys sys 1104121990 58776
 386/bin/bitsy/pencal - 775 sys sys 1104121991 117190
 386/bin/bitsy/prompter - 775 sys sys 1106799172 285651
-386/bin/bmp - 775 sys sys 1105502893 157210
+386/bin/bmp - 775 sys sys 1108872009 157219
 386/bin/bunzip2 - 775 sys sys 1104121992 97499
 386/bin/bzip2 - 775 sys sys 1104121992 114034
 386/bin/cal - 775 sys sys 1104121993 67886
@@ -303,7 +303,7 @@
 386/bin/ip/traceroute - 775 sys sys 1104122030 73497
 386/bin/ip/udpecho - 775 sys sys 1104122030 43159
 386/bin/join - 775 sys sys 1104122031 116241
-386/bin/jpg - 775 sys sys 1104122031 174137
+386/bin/jpg - 775 sys sys 1108872010 174146
 386/bin/kbmap - 775 sys sys 1106799176 142498
 386/bin/kprof - 775 sys sys 1108008333 99571
 386/bin/ktrace - 775 sys sys 1108008334 113522
@@ -353,8 +353,8 @@
 386/bin/plot - 775 sys sys 1106799178 221135
 386/bin/plumb - 775 sys sys 1104122045 66969
 386/bin/plumber - 775 sys sys 1108354560 169711
-386/bin/png - 775 sys sys 1104122046 161232
-386/bin/ppm - 775 sys sys 1104122046 148999
+386/bin/png - 775 sys sys 1108872011 163787
+386/bin/ppm - 775 sys sys 1108872012 148971
 386/bin/pr - 775 sys sys 1104122046 77408
 386/bin/primes - 775 sys sys 1104122046 38793
 386/bin/prof - 775 sys sys 1108008334 104314
@@ -419,7 +419,7 @@
 386/bin/tlssrv - 775 sys sys 1104122064 198001
 386/bin/togif - 775 sys sys 1104122064 189145
 386/bin/toico - 775 sys sys 1104122065 123524
-386/bin/topng - 775 sys sys 1104122065 137679
+386/bin/topng - 775 sys sys 1108872012 138083
 386/bin/toppm - 775 sys sys 1104122065 164905
 386/bin/touch - 775 sys sys 1104122066 63763
 386/bin/tprof - 775 sys sys 1108008337 255167
@@ -504,7 +504,7 @@
 386/bin/xmr - 775 sys sys 1104122093 40157
 386/bin/xms - 775 sys sys 1104122093 40735
 386/bin/yacc - 775 sys sys 1104122094 101853
-386/bin/yuv - 775 sys sys 1104122094 149499
+386/bin/yuv - 775 sys sys 1108872012 149508
 386/bin/zip - 775 sys sys 1104122094 89990
 386/include - 20000000775 sys sys 953243048 0
 386/include/ape - 20000000775 sys sys 944946041 0
@@ -9562,24 +9562,24 @@ sys/src/cmd/ip/traceroute.c - 664 sys sys 1032060124 9370
 sys/src/cmd/ip/udpecho.c - 664 sys sys 1050714674 855
 sys/src/cmd/join.c - 664 sys sys 944961364 7488
 sys/src/cmd/jpg - 20000000775 sys sys 988249983 0
-sys/src/cmd/jpg/bmp.c - 664 sys sys 1079970078 4217
+sys/src/cmd/jpg/bmp.c - 664 sys sys 1108852826 4222
 sys/src/cmd/jpg/bmp.h - 664 sys sys 1105455271 1034
 sys/src/cmd/jpg/close.c - 664 sys sys 944961292 1930
 sys/src/cmd/jpg/gif.c - 664 sys sys 1045505400 8844
 sys/src/cmd/jpg/ico.c - 664 sys sys 1072107030 8799
 sys/src/cmd/jpg/imagefile.h - 664 sys sys 988225303 2246
 sys/src/cmd/jpg/jpegdump.c - 664 sys sys 1018802871 7161
-sys/src/cmd/jpg/jpg.c - 664 sys sys 1014926432 7389
+sys/src/cmd/jpg/jpg.c - 664 sys sys 1108852825 7394
 sys/src/cmd/jpg/mkfile - 664 sys sys 1079970080 1056
 sys/src/cmd/jpg/multichan.c - 664 sys sys 1039753047 825
 sys/src/cmd/jpg/onechan.c - 664 sys sys 1039753044 3732
-sys/src/cmd/jpg/png.c - 664 sys sys 1014926432 4655
-sys/src/cmd/jpg/ppm.c - 664 sys sys 944961292 4190
+sys/src/cmd/jpg/png.c - 664 sys sys 1108853800 4818
+sys/src/cmd/jpg/ppm.c - 664 sys sys 1108852826 4204
 sys/src/cmd/jpg/readbmp.c - 664 sys sys 1105455271 13691
 sys/src/cmd/jpg/readgif.c - 664 sys sys 1014926433 10306
 sys/src/cmd/jpg/readjpg.c - 664 sys sys 1032060302 33009
-sys/src/cmd/jpg/readpng.c - 664 sys sys 1068773222 6914
-sys/src/cmd/jpg/readppm.c - 664 sys sys 1014926433 3649
+sys/src/cmd/jpg/readpng.c - 664 sys sys 1108852825 10117
+sys/src/cmd/jpg/readppm.c - 664 sys sys 1108851603 3645
 sys/src/cmd/jpg/readyuv.c - 664 sys sys 1067742240 3502
 sys/src/cmd/jpg/rgbrgbv.c - 664 sys sys 984718829 1236
 sys/src/cmd/jpg/rgbycc.c - 664 sys sys 944961292 2486
@@ -9590,10 +9590,10 @@ sys/src/cmd/jpg/toppm.c - 664 sys sys 944961292 1571
 sys/src/cmd/jpg/torgbv.c - 664 sys sys 1067719080 6443
 sys/src/cmd/jpg/totruecolor.c - 664 sys sys 1014926434 3407
 sys/src/cmd/jpg/writegif.c - 664 sys sys 1014926434 10727
-sys/src/cmd/jpg/writepng.c - 664 sys sys 1068658904 4313
+sys/src/cmd/jpg/writepng.c - 664 sys sys 1108851604 4556
 sys/src/cmd/jpg/writeppm.c - 664 sys sys 1014926434 3072
 sys/src/cmd/jpg/writerawimage.c - 664 sys sys 1014926435 4584
-sys/src/cmd/jpg/yuv.c - 664 sys sys 1067719080 4234
+sys/src/cmd/jpg/yuv.c - 664 sys sys 1108852826 4239
 sys/src/cmd/ka - 20000000775 sys sys 944961014 0
 sys/src/cmd/ka/a.h - 664 sys sys 1089299172 2911
 sys/src/cmd/ka/a.y - 664 sys sys 944961013 9900
@@ -10932,12 +10932,12 @@ sys/src/cmd/upas/send/translate.c - 664 sys sys 944961322 804
 sys/src/cmd/upas/send/tryit - 664 sys sys 944961322 584
 sys/src/cmd/upas/smtp - 20000000775 sys sys 988250017 0
 sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1091126808 6470
-sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1067722781 746
+sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1108828019 746
 sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1105114609 6024
 sys/src/cmd/upas/smtp/rfc822.y - 664 sys sys 1064589606 13417
 sys/src/cmd/upas/smtp/rmtdns.c - 664 sys sys 1015013150 1069
-sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1105114610 20113
-sys/src/cmd/upas/smtp/smtp.h - 664 sys sys 1105114610 1111
+sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1108827987 20071
+sys/src/cmd/upas/smtp/smtp.h - 664 sys sys 1108827986 1270
 sys/src/cmd/upas/smtp/smtpd.c - 664 sys sys 1102093207 30350
 sys/src/cmd/upas/smtp/smtpd.h - 664 sys sys 1067722781 1111
 sys/src/cmd/upas/smtp/smtpd.y - 664 sys sys 1061836986 6949

+ 17 - 17
dist/replica/plan9.db

@@ -165,7 +165,7 @@
 386/bin/bitsy/params - 775 sys sys 1104121990 58776
 386/bin/bitsy/pencal - 775 sys sys 1104121991 117190
 386/bin/bitsy/prompter - 775 sys sys 1106799172 285651
-386/bin/bmp - 775 sys sys 1105502893 157210
+386/bin/bmp - 775 sys sys 1108872009 157219
 386/bin/bunzip2 - 775 sys sys 1104121992 97499
 386/bin/bzip2 - 775 sys sys 1104121992 114034
 386/bin/cal - 775 sys sys 1104121993 67886
@@ -303,7 +303,7 @@
 386/bin/ip/traceroute - 775 sys sys 1104122030 73497
 386/bin/ip/udpecho - 775 sys sys 1104122030 43159
 386/bin/join - 775 sys sys 1104122031 116241
-386/bin/jpg - 775 sys sys 1104122031 174137
+386/bin/jpg - 775 sys sys 1108872010 174146
 386/bin/kbmap - 775 sys sys 1106799176 142498
 386/bin/kprof - 775 sys sys 1108008333 99571
 386/bin/ktrace - 775 sys sys 1108008334 113522
@@ -353,8 +353,8 @@
 386/bin/plot - 775 sys sys 1106799178 221135
 386/bin/plumb - 775 sys sys 1104122045 66969
 386/bin/plumber - 775 sys sys 1108354560 169711
-386/bin/png - 775 sys sys 1104122046 161232
-386/bin/ppm - 775 sys sys 1104122046 148999
+386/bin/png - 775 sys sys 1108872011 163787
+386/bin/ppm - 775 sys sys 1108872012 148971
 386/bin/pr - 775 sys sys 1104122046 77408
 386/bin/primes - 775 sys sys 1104122046 38793
 386/bin/prof - 775 sys sys 1108008334 104314
@@ -419,7 +419,7 @@
 386/bin/tlssrv - 775 sys sys 1104122064 198001
 386/bin/togif - 775 sys sys 1104122064 189145
 386/bin/toico - 775 sys sys 1104122065 123524
-386/bin/topng - 775 sys sys 1104122065 137679
+386/bin/topng - 775 sys sys 1108872012 138083
 386/bin/toppm - 775 sys sys 1104122065 164905
 386/bin/touch - 775 sys sys 1104122066 63763
 386/bin/tprof - 775 sys sys 1108008337 255167
@@ -504,7 +504,7 @@
 386/bin/xmr - 775 sys sys 1104122093 40157
 386/bin/xms - 775 sys sys 1104122093 40735
 386/bin/yacc - 775 sys sys 1104122094 101853
-386/bin/yuv - 775 sys sys 1104122094 149499
+386/bin/yuv - 775 sys sys 1108872012 149508
 386/bin/zip - 775 sys sys 1104122094 89990
 386/include - 20000000775 sys sys 953243048 0
 386/include/ape - 20000000775 sys sys 944946041 0
@@ -9562,24 +9562,24 @@ sys/src/cmd/ip/traceroute.c - 664 sys sys 1032060124 9370
 sys/src/cmd/ip/udpecho.c - 664 sys sys 1050714674 855
 sys/src/cmd/join.c - 664 sys sys 944961364 7488
 sys/src/cmd/jpg - 20000000775 sys sys 988249983 0
-sys/src/cmd/jpg/bmp.c - 664 sys sys 1079970078 4217
+sys/src/cmd/jpg/bmp.c - 664 sys sys 1108852826 4222
 sys/src/cmd/jpg/bmp.h - 664 sys sys 1105455271 1034
 sys/src/cmd/jpg/close.c - 664 sys sys 944961292 1930
 sys/src/cmd/jpg/gif.c - 664 sys sys 1045505400 8844
 sys/src/cmd/jpg/ico.c - 664 sys sys 1072107030 8799
 sys/src/cmd/jpg/imagefile.h - 664 sys sys 988225303 2246
 sys/src/cmd/jpg/jpegdump.c - 664 sys sys 1018802871 7161
-sys/src/cmd/jpg/jpg.c - 664 sys sys 1014926432 7389
+sys/src/cmd/jpg/jpg.c - 664 sys sys 1108852825 7394
 sys/src/cmd/jpg/mkfile - 664 sys sys 1079970080 1056
 sys/src/cmd/jpg/multichan.c - 664 sys sys 1039753047 825
 sys/src/cmd/jpg/onechan.c - 664 sys sys 1039753044 3732
-sys/src/cmd/jpg/png.c - 664 sys sys 1014926432 4655
-sys/src/cmd/jpg/ppm.c - 664 sys sys 944961292 4190
+sys/src/cmd/jpg/png.c - 664 sys sys 1108853800 4818
+sys/src/cmd/jpg/ppm.c - 664 sys sys 1108852826 4204
 sys/src/cmd/jpg/readbmp.c - 664 sys sys 1105455271 13691
 sys/src/cmd/jpg/readgif.c - 664 sys sys 1014926433 10306
 sys/src/cmd/jpg/readjpg.c - 664 sys sys 1032060302 33009
-sys/src/cmd/jpg/readpng.c - 664 sys sys 1068773222 6914
-sys/src/cmd/jpg/readppm.c - 664 sys sys 1014926433 3649
+sys/src/cmd/jpg/readpng.c - 664 sys sys 1108852825 10117
+sys/src/cmd/jpg/readppm.c - 664 sys sys 1108851603 3645
 sys/src/cmd/jpg/readyuv.c - 664 sys sys 1067742240 3502
 sys/src/cmd/jpg/rgbrgbv.c - 664 sys sys 984718829 1236
 sys/src/cmd/jpg/rgbycc.c - 664 sys sys 944961292 2486
@@ -9590,10 +9590,10 @@ sys/src/cmd/jpg/toppm.c - 664 sys sys 944961292 1571
 sys/src/cmd/jpg/torgbv.c - 664 sys sys 1067719080 6443
 sys/src/cmd/jpg/totruecolor.c - 664 sys sys 1014926434 3407
 sys/src/cmd/jpg/writegif.c - 664 sys sys 1014926434 10727
-sys/src/cmd/jpg/writepng.c - 664 sys sys 1068658904 4313
+sys/src/cmd/jpg/writepng.c - 664 sys sys 1108851604 4556
 sys/src/cmd/jpg/writeppm.c - 664 sys sys 1014926434 3072
 sys/src/cmd/jpg/writerawimage.c - 664 sys sys 1014926435 4584
-sys/src/cmd/jpg/yuv.c - 664 sys sys 1067719080 4234
+sys/src/cmd/jpg/yuv.c - 664 sys sys 1108852826 4239
 sys/src/cmd/ka - 20000000775 sys sys 944961014 0
 sys/src/cmd/ka/a.h - 664 sys sys 1089299172 2911
 sys/src/cmd/ka/a.y - 664 sys sys 944961013 9900
@@ -10932,12 +10932,12 @@ sys/src/cmd/upas/send/translate.c - 664 sys sys 944961322 804
 sys/src/cmd/upas/send/tryit - 664 sys sys 944961322 584
 sys/src/cmd/upas/smtp - 20000000775 sys sys 988250017 0
 sys/src/cmd/upas/smtp/greylist.c - 664 sys sys 1091126808 6470
-sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1067722781 746
+sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1108828019 746
 sys/src/cmd/upas/smtp/mxdial.c - 664 sys sys 1105114609 6024
 sys/src/cmd/upas/smtp/rfc822.y - 664 sys sys 1064589606 13417
 sys/src/cmd/upas/smtp/rmtdns.c - 664 sys sys 1015013150 1069
-sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1105114610 20113
-sys/src/cmd/upas/smtp/smtp.h - 664 sys sys 1105114610 1111
+sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1108827987 20071
+sys/src/cmd/upas/smtp/smtp.h - 664 sys sys 1108827986 1270
 sys/src/cmd/upas/smtp/smtpd.c - 664 sys sys 1102093207 30350
 sys/src/cmd/upas/smtp/smtpd.h - 664 sys sys 1067722781 1111
 sys/src/cmd/upas/smtp/smtpd.y - 664 sys sys 1061836986 6949

+ 21 - 0
dist/replica/plan9.log

@@ -13687,3 +13687,24 @@
 1108701111 7 c 386/lib/libplumb.a - 664 sys sys 1108699740 18876
 1108701111 8 c 386/lib/libscribble.a - 664 sys sys 1108699740 107280
 1108744322 0 c sys/games/lib/fortunes - 664 sys sys 1108743634 253142
+1108828820 0 c sys/src/cmd/jpg/readpng.c - 664 sys sys 1108828759 9455
+1108828820 1 c sys/src/cmd/upas/smtp/mkfile - 664 sys sys 1108828019 746
+1108828820 2 c sys/src/cmd/upas/smtp/smtp.c - 664 sys sys 1108827987 20071
+1108828820 3 c sys/src/cmd/upas/smtp/smtp.h - 664 sys sys 1108827986 1270
+1108852225 0 c sys/src/cmd/jpg/png.c - 664 sys sys 1108851604 4675
+1108852225 1 c sys/src/cmd/jpg/ppm.c - 664 sys sys 1108851604 4199
+1108852225 2 c sys/src/cmd/jpg/readpng.c - 664 sys sys 1108851604 9791
+1108852225 3 c sys/src/cmd/jpg/readppm.c - 664 sys sys 1108851603 3645
+1108852225 4 c sys/src/cmd/jpg/writepng.c - 664 sys sys 1108851604 4556
+1108854025 0 c sys/src/cmd/jpg/bmp.c - 664 sys sys 1108852826 4222
+1108854025 1 c sys/src/cmd/jpg/jpg.c - 664 sys sys 1108852825 7394
+1108854025 2 c sys/src/cmd/jpg/png.c - 664 sys sys 1108853800 4818
+1108854025 3 c sys/src/cmd/jpg/ppm.c - 664 sys sys 1108852826 4204
+1108854025 4 c sys/src/cmd/jpg/readpng.c - 664 sys sys 1108852825 10117
+1108854025 5 c sys/src/cmd/jpg/yuv.c - 664 sys sys 1108852826 4239
+1108872029 0 c 386/bin/png - 775 sys sys 1108872011 163787
+1108872029 1 c 386/bin/topng - 775 sys sys 1108872012 138083
+1108872029 2 c 386/bin/jpg - 775 sys sys 1108872010 174146
+1108872029 3 c 386/bin/ppm - 775 sys sys 1108872012 148971
+1108872029 4 c 386/bin/bmp - 775 sys sys 1108872009 157219
+1108872029 5 c 386/bin/yuv - 775 sys sys 1108872012 149508

+ 1 - 1
sys/src/cmd/jpg/bmp.c

@@ -39,7 +39,7 @@ eresized(int new)
 	r.max.x = r.min.x+Dx(image->r);
 	r.max.y = r.min.y+Dy(image->r);
 	border(screen, r, -Border, nil, ZP);
-	draw(screen, r, image, nil, image->r.min);
+	drawop(screen, r, image, nil, image->r.min, S);
 	flushimage(display, 1);
 }
 

+ 1 - 1
sys/src/cmd/jpg/jpg.c

@@ -41,7 +41,7 @@ eresized(int new)
 	r.max.x = r.min.x+Dx(image->r);
 	r.max.y = r.min.y+Dy(image->r);
 	border(screen, r, -Border, nil, ZP);
-	draw(screen, r, image, nil, image->r.min);
+	drawop(screen, r, image, nil, image->r.min, S);
 	flushimage(display, 1);
 }
 

+ 21 - 10
sys/src/cmd/jpg/png.c

@@ -138,6 +138,7 @@ show(int fd, char *name, int outc)
 	Rawimage **array, *r, *c;
 	static int inited;
 	Image *i;
+	Image *i2;
 	int j, ch, outchan;
 	Biobuf b;
 	char buf[32];
@@ -166,21 +167,28 @@ show(int fd, char *name, int outc)
 	if(outchan == CMAP8)
 		c = torgbv(r, !eflag);
 	else{
-		if(outchan==GREY8 || (r->chandesc==CY && threeflag==0)){
-			c = totruecolor(r, CY);
+		switch(r->chandesc){
+		case CY:
 			outchan = GREY8;
-		}else
-			c = totruecolor(r, CRGB24);
+			break;
+		case CYA16:
+			outchan = CHAN2(CGrey, 8, CAlpha, 8);
+			break;
+		case CRGB24:
+			outchan = RGB24;
+			break;
+		case CRGBA32:
+			outchan = RGBA32;
+			break;
+		}
+		c = r;
 	}
 	if(c == nil){
 		fprint(2, "png: conversion of %s failed: %r\n", name);
 		return "torgbv";
 	}
 	if(!dflag){
-		if(c->chandesc == CY)
-			i = allocimage(display, c->r, GREY8, 0, 0);
-		else
-			i = allocimage(display, c->r, outchan, 0, 0);
+		i = allocimage(display, c->r, outchan, 0, 0);
 		if(i == nil){
 			fprint(2, "png: allocimage %s failed: %r\n", name);
 			return "allocimage";
@@ -189,7 +197,10 @@ show(int fd, char *name, int outc)
 			fprint(2, "png: loadimage %s failed: %r\n", name);
 			return "loadimage";
 		}
-		image = i;
+		i2 = allocimage(display, c->r, outchan, 0, 0);
+		draw(i2, i2->r, display->white, nil, ZP);
+		draw(i2, i2->r, i, nil, i->r.min);
+		image = i2;
 		eresized(0);
 		if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)
 			exits(nil);
@@ -216,7 +227,7 @@ show(int fd, char *name, int outc)
 	free(r->cmap);
 	free(r);
 	free(array);
-	if(c){
+	if(c && c != r){
 		free(c->chans[0]);
 		free(c);
 	}

+ 5 - 4
sys/src/cmd/jpg/ppm.c

@@ -37,7 +37,7 @@ eresized(int new)
 	r.max.x = r.min.x+Dx(image->r);
 	r.max.y = r.min.y+Dy(image->r);
 	border(screen, r, -Border, nil, ZP);
-	draw(screen, r, image, nil, image->r.min);
+	drawop(screen, r, image, nil, image->r.min, S);
 	flushimage(display, 1);
 }
 
@@ -163,9 +163,8 @@ show(int fd, char *name)
 	}
 	if(!dflag){
 		if(r->chandesc == CY)
-			i = allocimage(display, c->r, GREY8, 0, 0);
-		else
-			i = allocimage(display, c->r, outchan, 0, 0);
+			outchan = GREY8;
+		i = allocimage(display, c->r, outchan, 0, 0);
 		if(i == nil){
 			fprint(2, "ppm: allocimage %s failed: %r\n", name);
 			return "allocimage";
@@ -183,6 +182,8 @@ show(int fd, char *name)
 		freeimage(i);
 	}
 	if(nineflag){
+		if(r->chandesc == CY)
+			outchan = GREY8;
 		chantostr(buf, outchan);
 		print("%11s %11d %11d %11d %11d ", buf,
 			c->r.min.x, c->r.min.y, c->r.max.x, c->r.max.y);

+ 341 - 154
sys/src/cmd/jpg/readpng.c

@@ -1,6 +1,3 @@
-//  work in progress...  this version only good enough to read
-//  non-interleaved, 24bit RGB images
-
 #include <u.h>
 #include <libc.h>
 #include <ctype.h>
@@ -11,38 +8,57 @@
 
 int debug;
 
-enum{  IDATSIZE=1000000,
-	/* filtering algorithms, supposedly increase compression */
+enum
+{
+	IDATSIZE = 1000000,
+
+	/* filtering algorithms */
 	FilterNone =	0,	/* new[x][y] = buf[x][y] */
-	FilterSub	=	1,	/* new[x][y] = buf[x][y] + new[x-1][y] */ 
-	FilterUp	=	2,	/* new[x][y] = buf[x][y] + new[x][y-1] */ 
-	FilterAvg	=	3,	/* new[x][y] = buf[x][y] + (new[x-1][y]+new[x][y-1])/2 */ 
-	FilterPaeth=	4,	/* new[x][y] = buf[x][y] + paeth(new[x-1][y],new[x][y-1],new[x-1][y-1]) */ 
-	FilterLast	=	5,
-	PropertyBit =	1<<5,
+	FilterSub =	1,	/* new[x][y] = buf[x][y] + new[x-1][y] */ 
+	FilterUp =		2,	/* new[x][y] = buf[x][y] + new[x][y-1] */ 
+	FilterAvg =	3,	/* new[x][y] = buf[x][y] + (new[x-1][y]+new[x][y-1])/2 */ 
+	FilterPaeth =	4,	/* new[x][y] = buf[x][y] + paeth(new[x-1][y],new[x][y-1],new[x-1][y-1]) */
+	FilterLast =	5,
+
+	PropertyBit = 1<<5,
+};
+
+typedef struct ZlibR ZlibR;
+typedef struct ZlibW ZlibW;
+
+struct ZlibW
+{
+	uchar *data;		/* Rawimage data */
+	int ndata;
+	int noutchan;
+	int chandesc;
+	int nchan;
+
+	uchar *scan;		/* new scanline */
+	uchar *lastscan;	/* previous scan line */
+	int scanlen;		/* scan line length */
+	int scanpos;		/* scan position */
+
+	int dx;			/* width of image */
+	int dy;			/* height of image */
+	int bpc;			/* bits per channel (per pixel) */
+	int y;				/* current scan line */
+	int pass;			/* adam7 pass#; 0 means no adam7 */
+	uchar palette[3*256];	/* color palette */
+	int palsize;		/* number of palette entries */
 };
 
-typedef struct ZlibR{
-	Biobuf *bi;
-	uchar *buf;
-	uchar *b;	// next byte to decompress
-	uchar *e;	// past end of buf
-} ZlibR;
-
-typedef struct ZlibW{
-	uchar *r, *g, *b; // Rawimage channels
-	int chan;	// next channel to write
-	int col;	// column index of current pixel
-			// -1 = one-byte pseudo-column for filter spec
-	int row;	// row index of current pixel
-	int ncol, nrow;	// image width, height
-	int filter;	// algorithm for current scanline
-} ZlibW;
+struct ZlibR
+{
+	Biobuf *io;		/* input buffer */
+	uchar *buf;		/* malloc'ed staging buffer */
+	uchar *p;			/* next byte to decompress */
+	uchar *e;			/* end of buffer */
+	ZlibW *w;
+};
 
 static ulong *crctab;
-static uchar PNGmagic[] = {137,80,78,71,13,10,26,10};
-static char readerr[] = "ReadPNG: read error: %r";
-static char memerr[] = "ReadPNG: malloc failed: %r";
+static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
 
 static ulong
 get4(uchar *a)
@@ -71,11 +87,9 @@ pngmalloc(ulong n, int clear)
 {
 	void *p;
 
-	p = malloc(n);
+	p = mallocz(n, clear);
 	if(p == nil)
-		sysfatal(memerr);
-	if(clear)
-		memset(p, 0, n);
+		sysfatal("malloc: %r");
 	return p;
 }
 
@@ -113,30 +127,40 @@ zread(void *va)
 	char type[5];
 	int n;
 
-	if(z->b >= z->e){
-refill_buffer:
-		z->b = z->buf;
-		n = getchunk(z->bi, type, z->b, IDATSIZE);
+	if(z->p >= z->e){
+	Again:
+		z->p = z->buf;
+		z->e = z->p;
+		n = getchunk(z->io, type, z->p, IDATSIZE);
 		if(n < 0 || strcmp(type, "IEND") == 0)
 			return -1;
-		z->e = z->b + n;
+		z->e = z->p + n;
+		if(!strcmp(type,"PLTE")){
+			if(n < 3 || n > 3*256 || n%3)
+				sysfatal("invalid PLTE chunk len %d", n);
+			memcpy(z->w->palette, z->p, n);
+			z->w->palsize = 256;
+			goto Again;
+		}
 		if(type[0] & PropertyBit)
-			goto refill_buffer;  /* skip auxiliary chunks for now */
-		if(strcmp(type,"IDAT") != 0)
+			goto Again;  /* skip auxiliary chunks fornow */
+		if(strcmp(type,"IDAT")){
 			sysfatal("unrecognized mandatory chunk %s", type);
+			goto Again;
+		}
 	}
-	return *z->b++;
+	return *z->p++;
 }
 
 static uchar 
 paeth(uchar a, uchar b, uchar c)
 {
 	int p, pa, pb, pc;
-	
-	p = (int)a + (int)b - (int)c;
-	pa = abs(p - (int)a);
-	pb = abs(p - (int)b);
-	pc = abs(p - (int)c);
+
+	p = a + b - c;
+	pa = abs(p - a);
+	pb = abs(p - b);
+	pc = abs(p - c);
 
 	if(pa <= pb && pa <= pc)
 		return a;
@@ -146,100 +170,223 @@ paeth(uchar a, uchar b, uchar c)
 }
 
 static void
-unfilter(int alg, uchar *buf, uchar *ebuf, int up)
+unfilter(int alg, uchar *buf, uchar *up, int len, int bypp)
 {
+	int i;
+
 	switch(alg){
+	case FilterNone:
+		break;
+
 	case FilterSub:
-		while (++buf < ebuf)
-			*buf += buf[-1];
+		for(i = bypp; i < len; ++i)
+			buf[i] += buf[i-bypp];
 		break;
+
 	case FilterUp:
-		if (up != 0)
-			do
-				*buf += buf[up];
-			while (++buf < ebuf);
+		for(i = 0; i < len; ++i)
+			buf[i] += up[i];
 		break;
+
 	case FilterAvg:
-		if (up == 0)
-			while (++buf < ebuf)
-				*buf += buf[-1]/2;
-		else{
-			*buf += buf[up]/2;
-			while (++buf < ebuf)
-				*buf += (buf[-1]+buf[up])/2;
-		}
+		for(i = 0; i < bypp; ++i)
+			buf[i] += (0+up[i])/2;
+		for(; i < len; ++i)
+			buf[i] += (buf[i-bypp]+up[i])/2;
 		break;
+
 	case FilterPaeth:
-		if (up == 0)
-			while (++buf < ebuf)
-				*buf += buf[-1];
-		else{
-			*buf += paeth(0, buf[up], 0);
-			while (++buf < ebuf)
-				*buf += paeth(buf[-1], buf[up], buf[up-1]);
-		}
+		for(i = 0; i < bypp; ++i)
+			buf[i] += paeth(0, up[i], 0);
+		for(; i < len; ++i)
+			buf[i] += paeth(buf[i-bypp], up[i], up[i-bypp]);
 		break;
+
+	default:
+		sysfatal("unknown filtering scheme %d\n", alg);
 	}
 }
 
-static int
-zwrite(void *va, void *vb, int n)
+struct {
+	int x;
+	int y;
+	int dx;
+	int dy;
+} adam7[] = {
+	{0,0,1,1},	/* eve alone */
+	{0,0,8,8},	/* pass 1 */
+	{4,0,8,8},	/* pass 2 */
+	{0,4,4,8},	/* pass 3 */
+	{2,0,4,4},	/* pass 4 */
+	{0,2,2,4},	/* pass 5 */
+	{1,0,2,2},	/* pass 6 */
+	{0,1,1,2},	/* pass 7 */
+};
+
+static void
+scan(int len, ZlibW *z)
 {
-	ZlibW *z = va;
-	uchar *buf = vb;
-	int i, up;
-	for(i=0; i<n; i++){
-		if(z->col == -1){
-			// set filter byte
-			z->filter = *buf++;
-			if (z->filter >= FilterLast)
-				sysfatal("unknown filter algorithm %d for row %d", z->row, z->filter);
-			z->col++;
-			continue;
-		}
-		switch(z->chan){
-		case 0:
-			*z->r++ = *buf++;
-			z->chan = 1;
-			break;
-		case 1:
-			*z->g++ = *buf++;
-			z->chan = 2;
-			break;
-		case 2:
-			*z->b++ = *buf++;
-			z->chan = 0;
-			z->col++;
-			if(z->col == z->ncol){
-				if (z->filter){
-					if(z->row == 0)
-						up = 0;
-					else
-						up = -z->ncol;
-					unfilter(z->filter, z->r - z->col, z->r, up);
-					unfilter(z->filter, z->g - z->col, z->g, up);
-					unfilter(z->filter, z->b - z->col, z->b, up);
+	int chan, i, j, nbit, off, val;
+	uchar pixel[4], *p, *w;
+
+	unfilter(z->scan[0], z->scan+1, z->lastscan+1, len-1, (z->nchan*z->bpc+7)/8);
+
+	/*
+	 * loop over raw bits extracting pixel values and converting to 8-bit
+	 */
+	nbit = 0;
+	chan = 0;
+	val = 0;
+	off = z->y*z->dx + adam7[z->pass].x;
+	w = z->data + z->noutchan*off;
+	p = z->scan+1;	/* skip alg byte */
+	len--;
+	for(i=0; i<len*8; i++){
+		val <<= 1;
+		if(p[i>>3] & (1<<(7-(i&7))))
+			val++;
+		if(++nbit == z->bpc){
+			/* finished the value */
+			pixel[chan++] = (val*255)/((1<<z->bpc)-1);
+			val = 0;
+			nbit = 0;
+			if(chan == z->nchan){
+				/* finished the pixel */
+				if(off < z->dx*z->dy){
+					if(z->nchan < 3 && z->palsize){
+						j = pixel[0];
+						if(z->bpc < 8)
+							j >>= 8-z->bpc;
+						if(j >= z->palsize)
+							sysfatal("index %d >= palette size %d", j, z->palsize);
+						pixel[3] = pixel[1];	/* alpha */
+						pixel[0] = z->palette[3*j];
+						pixel[1] = z->palette[3*j+1];
+						pixel[2] = z->palette[3*j+2];
+					}
+					switch(z->chandesc){
+					case CYA16:
+					//	print("%.2x%.2x ", pixel[0], pixel[1]);
+						*w++ = pixel[1];
+						*w++ += (pixel[0]*pixel[1])/255;
+						break;
+					case CRGBA32:
+					//	print("%.2x%.2x%.2x%.2x ", pixel[0], pixel[1], pixel[2], pixel[3]);
+						*w++ += pixel[3];
+						*w++ += (pixel[2]*pixel[3])/255;
+						*w++ += (pixel[1]*pixel[3])/255;
+						*w++ += (pixel[0]*pixel[3])/255;
+						break;
+					case CRGB24:
+						*w++ = pixel[2];
+						*w++ = pixel[1];
+					case CY:
+						*w++ = pixel[0];
+						break;
+					}
+					w += (adam7[z->pass].dx-1)*z->noutchan;
 				}
-				z->col = -1;
-				z->row++;
-				if((z->row >= z->nrow) && (i < n-1) )
-					sysfatal("header said %d rows; data goes further", z->nrow);
+				off += adam7[z->pass].dx;
+				if(off >= (z->y+1)*z->dx){
+					/* finished the line */
+					return;
+				}
+				chan = 0;
 			}
+		}
+	}
+	sysfatal("scan line too short");
+}
+
+static int
+scanbytes(ZlibW *z)
+{
+	int bits, n, adx, dx;
+
+	if(adam7[z->pass].y >= z->dy || adam7[z->pass].x >= z->dx)
+		return 0;
+	adx = adam7[z->pass].dx;
+	dx = z->dx - adam7[z->pass].x;
+	if(dx <= 0)
+		n = 1;
+	else
+		n = (dx+adx-1)/adx;
+	if(n != 1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx){
+		print("%d/%d != 1+(%d-1)/%d = %d\n",
+			z->dx - adam7[z->pass].x - 1 + adx, adx,
+			z->dx - (adam7[z->pass].x+1), adam7[z->pass].dx,
+			1 + (z->dx - (adam7[z->pass].x+1)) / adam7[z->pass].dx);
+	}
+	bits = n*z->bpc*z->nchan;
+	return 1 + (bits+7)/8;
+}
+
+static int
+nextpass(ZlibW *z)
+{
+	int len;
+
+	memset(z->lastscan, 0, z->scanlen);
+	do{
+		z->pass = (z->pass+1)%8;
+		z->y = adam7[z->pass].y;
+		len = scanbytes(z);
+	}while(len < 2);
+	return len;
+}
+
+static int
+zwrite(void *vz, void *vbuf, int n)
+{
+	int oldn, m, len;
+	uchar *buf, *t;
+	ZlibW *z;
+
+	z = vz;
+	buf = vbuf;
+	oldn = n;
+
+	len = scanbytes(z);
+	if(len < 2)
+		len = nextpass(z);
+
+	while(n > 0){
+		m = len - z->scanpos;
+		if(m > n){
+			/* save final partial line */
+			memmove(z->scan+z->scanpos, buf, n);
+			z->scanpos += n;
 			break;
 		}
+
+		/* fill line */
+		memmove(z->scan+z->scanpos, buf, m);
+		buf += m;
+		n -= m;
+
+		/* process line */
+		scan(len, z);
+		t = z->scan;
+		z->scan = z->lastscan;
+		z->lastscan = t;
+
+		z->scanpos = 0;
+		z->y += adam7[z->pass].dy;
+		if(z->y >= z->dy)
+			len = nextpass(z);
 	}
-	return n;
+	return oldn;
 }
 
 static Rawimage*
 readslave(Biobuf *b)
 {
-	ZlibR zr;
-	ZlibW zw;
-	Rawimage *image;
 	char type[5];
+	int bpc, colorfmt, dx, dy, err, n, nchan, nout, useadam7;
 	uchar *buf, *h;
-	int k, n, nrow, ncol, err;
+	Rawimage *image;
+	ZlibR zr;
+	ZlibW zw;
 
 	buf = pngmalloc(IDATSIZE, 0);
 	Bread(b, buf, sizeof PNGmagic);
@@ -250,63 +397,104 @@ readslave(Biobuf *b)
 	if(n < 13 || strcmp(type,"IHDR") != 0)
 		sysfatal("missing IHDR chunk");
 	h = buf;
-	ncol = get4(h);  h += 4;
-	nrow = get4(h);  h += 4;
-	if(ncol <= 0 || nrow <= 0)
-		sysfatal("impossible image size nrow=%d ncol=%d", nrow, ncol);
+	dx = get4(h);
+	h += 4;
+	dy = get4(h);
+	h += 4;
+	if(dx <= 0 || dy <= 0)
+		sysfatal("impossible image size %dx%d", dx, dy);
 	if(debug)
-		fprint(2, "readpng nrow=%d ncol=%d\n", nrow, ncol);
-	if(*h++ != 8)
-		sysfatal("only 24 bit per pixel supported for now [%d]", h[-1]);
-	if(*h++ != 2)
-		sysfatal("only rgb supported for now [%d]", h[-1]);
+		fprint(2, "readpng %dx%d\n", dx, dy);
+
+	bpc = *h++;
+	colorfmt = *h++;
+	nchan = 0;
 	if(*h++ != 0)
 		sysfatal("only deflate supported for now [%d]", h[-1]);
 	if(*h++ != FilterNone)
 		sysfatal("only FilterNone supported for now [%d]", h[-1]);
-	if(*h != 0)
-		sysfatal("only non-interlaced supported for now [%d]", h[-1]);
+	useadam7 = *h++;
+	USED(h);
 
 	image = pngmalloc(sizeof(Rawimage), 1);
-	image->r = Rect(0, 0, ncol, nrow);
-	image->cmap = nil;
-	image->cmaplen = 0;
-	image->chanlen = ncol*nrow;
-	image->fields = 0;
-	image->gifflags = 0;
-	image->gifdelay = 0;
-	image->giftrindex = 0;
-	image->chandesc = CRGB;
-	image->nchans = 3;
-	for(k=0; k<3; k++)
-		image->chans[k] = pngmalloc(ncol*nrow, 0);
-	zr.bi = b;
+	image->r = Rect(0, 0, dx, dy);
+	nout = 0;
+	switch(colorfmt){
+	case 0:	/* grey */
+		image->nchans = 1;
+		image->chandesc = CY;
+		nout = 1;
+		nchan = 1;
+		break;
+	case 2:	/* rgb */
+		image->nchans = 1;
+		image->chandesc = CRGB24;
+		nout = 3;
+		nchan = 3;
+		break;
+	case 3: /* indexed rgb with PLTE */
+		image->nchans = 1;
+		image->chandesc = CRGB24;
+		nout = 3;
+		nchan = 1;
+		break;
+	case 4:	/* grey+alpha */
+		image->nchans = 1;
+		image->chandesc = CYA16;
+		nout = 2;
+		nchan = 2;
+		break;
+	case 6:	/* rgb+alpha */
+		image->nchans = 1;
+		image->chandesc = CRGBA32;
+		nout = 4;
+		nchan = 4;
+		break;
+	default:
+		sysfatal("unsupported color scheme %d", h[-1]);
+	}
+	image->chanlen = dx*dy*nout;
+	image->chans[0] = pngmalloc(image->chanlen, 0);
+	memset(image->chans[0], 0, image->chanlen);
+
+	memset(&zr, 0, sizeof zr);
+	zr.w = &zw;
+	zr.io = b;
 	zr.buf = buf;
-	zr.b = zr.e = buf + IDATSIZE;
-	zw.r = image->chans[0];
-	zw.g = image->chans[1];
-	zw.b = image->chans[2];
-	zw.chan = 0;
-	zw.col = -1;
-	zw.row = 0;
-	zw.ncol = ncol;
-	zw.nrow = nrow;
+
+	memset(&zw, 0, sizeof zw);
+	if(useadam7)
+		zw.pass = 1;
+	zw.data = image->chans[0];
+	zw.ndata = image->chanlen;
+	zw.chandesc = image->chandesc;
+	zw.noutchan = nout;
+
+	zw.dx = dx;
+	zw.dy = dy;
+	zw.scanlen = (nchan*dx*bpc+7)/8+1;
+	zw.scan = pngmalloc(zw.scanlen, 1);
+	zw.lastscan = pngmalloc(zw.scanlen, 1);
+	zw.nchan = nchan;
+	zw.bpc = bpc;
+
 	err = inflatezlib(&zw, zwrite, &zr, zread);
+
 	if(err)
 		sysfatal("inflatezlib %s\n", flateerr(err));
+
 	free(buf);
+	free(zw.scan);
+	free(zw.lastscan);
 	return image;
 }
 
 Rawimage**
 Breadpng(Biobuf *b, int colorspace)
 {
-	Rawimage *r, **array;
-	char buf[ERRMAX];
+	Rawimage **array, *r;
 
-	buf[0] = '\0';
 	if(colorspace != CRGB){
-		errstr(buf, sizeof buf);	/* throw it away */
 		werrstr("ReadPNG: unknown color space %d", colorspace);
 		return nil;
 	}
@@ -314,7 +502,6 @@ Breadpng(Biobuf *b, int colorspace)
 	array = malloc(2*sizeof(*array));
 	if(array==nil)
 		return nil;
-	errstr(buf, sizeof buf);	/* throw it away */
 	r = readslave(b);
 	array[0] = r;
 	array[1] = nil;
@@ -324,8 +511,8 @@ Breadpng(Biobuf *b, int colorspace)
 Rawimage**
 readpng(int fd, int colorspace)
 {
-	Rawimage** a;
 	Biobuf b;
+	Rawimage **a;
 
 	if(Binit(&b, fd, OREAD) < 0)
 		return nil;

+ 1 - 1
sys/src/cmd/jpg/readppm.c

@@ -74,7 +74,7 @@ Bgetbit(Biobufhdr *b)
 			return -1;
 	}
 	nbit--;
-	return (bitc >> (nbit-1)) & 0x1;
+	return (bitc >> nbit) & 0x1;
 }
 
 static

+ 131 - 84
sys/src/cmd/jpg/writepng.c

@@ -1,8 +1,6 @@
-// based on PNG 1.2 specification, July 1999  (see also rfc2083)
-// Alpha is not supported yet because of lack of industry acceptance and
-// because Plan9 Image uses premultiplied alpha, so png can't be lossless.
-// Only 24bit color supported, because 8bit may as well use GIF.
-
+/*
+ * See PNG 1.2 spec, also RFC 2083.
+ */
 #include <u.h>
 #include <libc.h>
 #include <draw.h>
@@ -12,26 +10,36 @@
 #include <flate.h>
 #include "imagefile.h"
 
-enum{	IDATSIZE = 	20000,
+enum
+{
+	IDATSIZE = 	20000,
 	FilterNone =	0,
 };
 
-typedef struct ZlibR{
+typedef struct ZlibR ZlibR;
+typedef struct ZlibW ZlibW;
+
+struct ZlibR
+{
 	uchar *data;
 	int width;
-	int nrow, ncol;
-	int row, col;	// next pixel to send
-} ZlibR;
+	int dx;
+	int dy;
+	int x;
+	int y;
+	int pixwid;
+};
 
-typedef struct ZlibW{
-	Biobuf *bo;
+struct ZlibW
+{
+	Biobuf *io;
 	uchar *buf;
-	uchar *b;	// next place to write
-	uchar *e;	// past end of buf
-} ZlibW;
+	uchar *b;
+	uchar *e;
+};
 
 static ulong *crctab;
-static uchar PNGmagic[] = {137,80,78,71,13,10,26,10};
+static uchar PNGmagic[] = { 137, 'P', 'N', 'G', '\r', '\n', 26, '\n'};
 
 static void
 put4(uchar *a, ulong v)
@@ -63,35 +71,51 @@ chunk(Biobuf *bo, char *type, uchar *d, int n)
 static int
 zread(void *va, void *buf, int n)
 {
-	ZlibR *z = va;
-	int nrow = z->nrow;
-	int ncol = z->ncol;
-	uchar *b = buf, *e = b+n, *img;
-	int i, pixels;  // number of pixels in row that can be sent now
-
-	while(b+3 <= e){ // loop over image rows
-		if(z->row >= nrow)
+	int a, i, pixels, pixwid;
+	uchar *b, *e, *img;
+	ZlibR *z;
+
+	z = va;
+	pixwid = z->pixwid;
+	b = buf;
+	e = b+n;
+	while(b+pixwid <= e){
+		if(z->y >= z->dy)
 			break;
-		if(z->col==0)
+		if(z->x == 0)
 			*b++ = FilterNone;
-		pixels = (e-b)/3;
-		if(pixels > ncol - z->col)
-			pixels = ncol - z->col;
-		img = z->data + z->width * z->row + 3 * z->col;
-
-		// Plan 9 image format is BGR?!!!
-		// memmove(b, img, 3*pixels);
-		// b += 3*pixels;
-		for(i=0; i<pixels; i++, img += 3){
-			*b++ = img[2];
-			*b++ = img[1];
-			*b++ = img[0];
-		}
+		pixels = (e-b)/pixwid;
+		if(pixels > z->dx - z->x)
+			pixels = z->dx - z->x;
+		img = z->data + z->width*z->y + pixwid*z->x;
+		memmove(b, img, pixwid*pixels);
+		if(pixwid == 4){
+			/*
+			 * Convert to non-premultiplied alpha.
+			 */
+			for(i=0; i<pixels; i++, b+=4){
+				a = b[3];
+				if(a == 0)
+					b[0] = b[1] = b[2] = 0;
+				else if(a != 255){
+					if(b[0] >= a)
+						b[0] = a;
+					b[0] = (b[0]*255)/a;
+					if(b[1] >= a)
+						b[1] = a;
+					b[1] = (b[1]*255)/a;
+					if(b[2] >= a)
+						b[2] = a;
+					b[2] = (b[2]*255)/a;
+				}
+			}
+		}else	
+			b += pixwid*pixels;
 
-		z->col += pixels;
-		if(z->col >= ncol){
-			z->col = 0;
-			z->row++;
+		z->x += pixels;
+		if(z->x >= z->dx){
+			z->x = 0;
+			z->y++;
 		}
 	}
 	return b - (uchar*)buf;
@@ -100,18 +124,22 @@ zread(void *va, void *buf, int n)
 static void
 IDAT(ZlibW *z)
 {
-	chunk(z->bo, "IDAT", z->buf, z->b - z->buf);
+	chunk(z->io, "IDAT", z->buf, z->b - z->buf);
 	z->b = z->buf;
 }
 
 static int
 zwrite(void *va, void *buf, int n)
 {
-	ZlibW *z = va;
-	uchar *b = buf, *e = b+n;
 	int m;
+	uchar *b, *e;
+	ZlibW *z;
 
-	while(b < e){ // loop over IDAT chunks
+	z = va;
+	b = buf;
+	e = b+n;
+
+	while(b < e){
 		m = z->e - z->b;
 		if(m > e - b)
 			m = e - b;
@@ -125,14 +153,25 @@ zwrite(void *va, void *buf, int n)
 }
 
 static Memimage*
-memRGB(Memimage *i)
+memRGBA(Memimage *i)
 {
 	Memimage *ni;
-
-	if(i->chan == RGB24)
+	char buf[32];
+	ulong dst;
+	
+	/*
+	 * [A]BGR because we want R,G,B,[A] in big-endian order.  Sigh.
+	 */
+	chantostr(buf, i->chan);
+	if(strchr(buf, 'a'))
+		dst = ABGR32;
+	else
+		dst = BGR24;
+		
+	if(i->chan == dst)
 		return i;
 
-	ni = allocmemimage(i->r, RGB24);
+	ni = allocmemimage(i->r, dst);
 	if(ni == nil)
 		return ni;
 	memimagedraw(ni, ni->r, i, i->r.min, nil, i->r.min, S);
@@ -140,38 +179,42 @@ memRGB(Memimage *i)
 }
 
 char*
-memwritepng(Biobuf *bo, Memimage *r, ImageInfo *II)
+memwritepng(Biobuf *io, Memimage *m, ImageInfo *II)
 {
+	int err, n;
 	uchar buf[200], *h;
 	ulong vgamma;
-	int err, n;
-	ZlibR zr;
-	ZlibW zw;
-	int nrow = r->r.max.y - r->r.min.y;
-	int ncol = r->r.max.x - r->r.min.x;
 	Tm *tm;
 	Memimage *rgb;
+	ZlibR zr;
+	ZlibW zw;
 
-	rgb = memRGB(r);
-	if(rgb == nil)
-		return "allocmemimage nil";
 	crctab = mkcrctab(0xedb88320);
 	if(crctab == nil)
 		sysfatal("mkcrctab error");
 	deflateinit();
 
-	Bwrite(bo, PNGmagic, sizeof PNGmagic);
-	// IHDR chunk
+	rgb = memRGBA(m);
+	if(rgb == nil)
+		return "allocmemimage nil";
+
+	Bwrite(io, PNGmagic, sizeof PNGmagic);
+
+	/* IHDR chunk */
 	h = buf;
-	put4(h, ncol); h += 4;
-	put4(h, nrow); h += 4;
-	*h++ = 8; // bit depth = 24 bit per pixel
-	*h++ = 2; // color type = rgb
-	*h++ = 0; // compression method = deflate
-	*h++ = 0; // filter method
-	*h++ = 0; // interlace method = no interlace
-	chunk(bo, "IHDR", buf, h-buf);
+	put4(h, Dx(m->r)); h += 4;
+	put4(h, Dy(m->r)); h += 4;
+	*h++ = 8;	/* 8 bits per channel */
+	if(rgb->chan == BGR24)
+		*h++ = 2;		/* RGB */
+	else
+		*h++ = 6;		/* RGBA */
+	*h++ = 0;	/* compression - deflate */
+	*h++ = 0;	/* filter - none */
+	*h++ = 0;	/* interlace - none */
+	chunk(io, "IHDR", buf, h-buf);
 
+	/* time - using now is suspect */
 	tm = gmtime(time(0));
 	h = buf;
 	*h++ = (tm->year + 1900)>>8;
@@ -181,40 +224,44 @@ memwritepng(Biobuf *bo, Memimage *r, ImageInfo *II)
 	*h++ = tm->hour;
 	*h++ = tm->min;
 	*h++ = tm->sec;
-	chunk(bo, "tIME", buf, h-buf);
-	
+	chunk(io, "tIME", buf, h-buf);
+
+	/* gamma */
 	if(II->fields_set & II_GAMMA){
 		vgamma = II->gamma*100000;
 		put4(buf, vgamma);
-		chunk(bo, "gAMA", buf, 4);
+		chunk(io, "gAMA", buf, 4);
 	}
 
+	/* comment */
 	if(II->fields_set & II_COMMENT){
 		strncpy((char*)buf, "Comment", sizeof buf);
 		n = strlen((char*)buf)+1; // leave null between Comment and text
 		strncpy((char*)(buf+n), II->comment, sizeof buf - n);
-		chunk(bo, "tEXt", buf, n+strlen((char*)buf+n));
+		chunk(io, "tEXt", buf, n+strlen((char*)buf+n));
 	}
 
-	// image chunks
-	zr.nrow = nrow;
-	zr.ncol = ncol;
+	/* image data */
+	zr.dx = Dx(m->r);
+	zr.dy = Dy(m->r);
 	zr.width = rgb->width * sizeof(ulong);
 	zr.data = rgb->data->bdata;
-	zr.row = zr.col = 0;
-	zw.bo = bo;
+	zr.x = 0;
+	zr.y = 0;
+	zr.pixwid = chantodepth(rgb->chan)/8;
+	zw.io = io;
 	zw.buf = malloc(IDATSIZE);
+	if(zw.buf == nil)
+		sysfatal("malloc: %r");
 	zw.b = zw.buf;
 	zw.e = zw.b + IDATSIZE;
-	err = deflatezlib(&zw, zwrite, &zr, zread, 6, 0);
+	if((err=deflatezlib(&zw, zwrite, &zr, zread, 6, 0)) < 0)
+		sysfatal("deflatezlib %s", flateerr(err));
 	if(zw.b > zw.buf)
 		IDAT(&zw);
 	free(zw.buf);
-	if(err)
-		sysfatal("deflatezlib %s\n", flateerr(err));
-	chunk(bo, "IEND", nil, 0);
-
-	if(r != rgb)
+	chunk(io, "IEND", nil, 0);
+	if(m != rgb)
 		freememimage(rgb);
 	return nil;
 }

+ 1 - 1
sys/src/cmd/jpg/yuv.c

@@ -39,7 +39,7 @@ eresized(int new)
 	r.max.x = r.min.x+Dx(image->r);
 	r.max.y = r.min.y+Dy(image->r);
 	border(screen, r, -Border, nil, ZP);
-	draw(screen, r, image, nil, image->r.min);
+	drawop(screen, r, image, nil, image->r.min, S);
 	flushimage(display, 1);
 }
 

+ 1 - 2
sys/src/cmd/upas/smtp/mkfile

@@ -22,8 +22,7 @@ UPDATE=\
 </sys/src/cmd/mkmany
 CFLAGS=$CFLAGS -I../common -D'SPOOL="/mail"'
 
-$O.smtpd:	smtpd.tab.$O rmtdns.$O spam.$O rfc822.tab.$O greylist.$O
-
+$O.smtpd:	smtpd.tab.$O rmtdns.$O spam.$O rfc822.tab.$O greylist.$O mxdial.$O
 $O.smtp:	rfc822.tab.$O mxdial.$O
 
 smtpd.$O: 	smtpd.h

+ 38 - 36
sys/src/cmd/upas/smtp/mxdial.c

@@ -1,5 +1,6 @@
 #include "common.h"
 #include <ndb.h>
+#include <smtp.h>	/* to publish dial_string_parse */
 
 enum
 {
@@ -16,16 +17,6 @@ struct Mx
 };
 static Mx mx[Nmx];
 
-typedef struct DS	DS;
-struct DS {
-	/* dist string */
-	char	buf[128];
-	char	*netdir;
-	char	*proto;
-	char	*host;
-	char	*service;
-};
-
 Ndb *db;
 extern int debug;
 
@@ -33,7 +24,7 @@ static int	mxlookup(DS*, char*);
 static int	mxlookup1(DS*, char*);
 static int	compar(void*, void*);
 static int	callmx(DS*, char*, char*);
-static void	dial_string_parse(char*, DS*);
+static void expand_meta(DS *ds);
 extern int	cistrcmp(char*, char*);
 
 int
@@ -234,7 +225,7 @@ compar(void *a, void *b)
 }
 
 /* break up an address to its component parts */
-static void
+void
 dial_string_parse(char *str, DS *ds)
 {
 	char *p, *p2;
@@ -264,48 +255,59 @@ dial_string_parse(char *str, DS *ds)
 	ds->service = strchr(ds->host, '!');
 	if(ds->service)
 		*ds->service++ = 0;
+	if(*ds->host == '$')
+		expand_meta(ds);
 }
 
-char *
-expand_meta(char *addr)
+static void
+expand_meta(DS *ds)
 {
-	DS ds;
+	char buf[128], cs[128], *net, *p;
 	int fd, n;
-	char *p, cs[128];
-	static char buf[1024];
-
-	dial_string_parse(addr, &ds);
 
-	if (*ds.host != '$')
-		return addr;
-	if (! ds.netdir)
-		ds.netdir = "/net";
+	net = ds->netdir;
+	if(!net)
+		net = "/net";
 
-	snprint(cs, sizeof(cs), "%s/cs", ds.netdir);
-	if ((fd = open(cs, ORDWR)) == -1){
-		syslog(0, "smtp", "cannot open cs: %r", cs);
-		return addr;
+	if(debug)
+		fprint(2, "expanding %s!%s\n", net, ds->host);
+	snprint(cs, sizeof(cs), "%s/cs", net);
+	if((fd = open(cs, ORDWR)) == -1){
+		if(debug)
+			fprint(2, "open %s: %r\n", cs);
+		syslog(0, "smtp", "cannot open %s: %r", cs);
+		return;
 	}
 
-	snprint(buf, sizeof(buf), "!ipinfo %s", ds.host+1);	// +1 to skip $
+	snprint(buf, sizeof(buf), "!ipinfo %s", ds->host+1);	// +1 to skip $
 	if(write(fd, buf, strlen(buf)) <= 0){
+		if(debug)
+			fprint(2, "write %s: %r\n", cs);
 		syslog(0, "smtp", "%s to %s - write failed: %r", buf, cs);
 		close(fd);
-		return addr;
+		return;
 	}
 
 	seek(fd, 0, 0);
-	if((n = read(fd, buf, sizeof(buf)-1)) < 0){
+	if((n = read(fd, ds->expand, sizeof(ds->expand)-1)) < 0){
+		if(debug)
+			fprint(2, "read %s: %r\n", cs);
 		syslog(0, "smtp", "%s - read failed: %r", cs);
 		close(fd);
-		return addr;
+		return;
 	}
 	close(fd);
 
-	buf[n] = 0;
-	if((p = strchr(buf, '=')) == nil){
-		syslog(0, "smtp", "%q from %s - bad response: %r", buf, cs);
-		return addr;
+	ds->expand[n] = 0;
+	if((p = strchr(ds->expand, '=')) == nil){
+		if(debug)
+			fprint(2, "response %s: %s\n", cs, ds->expand);
+		syslog(0, "smtp", "%q from %s - bad response: %r", ds->expand, cs);
+		return;
 	}
-	return p+1; 	// +1 to skip =
+	ds->host = p+1;
+
+	/* take only first one returned (quasi-bug) */
+	if((p = strchr(ds->host, ' ')) != nil)
+		*p = 0;
 }

+ 6 - 6
sys/src/cmd/upas/smtp/smtp.c

@@ -372,19 +372,19 @@ dotls(char *me)
 static char *
 doauth(char *methods)
 {
-	char *sys, *buf, *base64;
-	UserPasswd *p;
+	char *buf, *base64;
 	int n;
+	DS ds;
+	UserPasswd *p;
 
-	sys = expand_meta(ddomain);
-	//fprint(2, "expand address %s -> %s\n", ddomain, sys);
+	dial_string_parse(ddomain, &ds);
 
 	if(user != nil)
 		p = auth_getuserpasswd(nil,
-	  	  "proto=pass service=smtp server=%q user=%q", sys, user);
+	  	  "proto=pass service=smtp server=%q user=%q", ds.host, user);
 	else
 		p = auth_getuserpasswd(nil,
-	  	  "proto=pass service=smtp server=%q", sys);
+	  	  "proto=pass service=smtp server=%q", ds.host);
 	if (p == nil)
 		return Giveup;
 

+ 12 - 1
sys/src/cmd/upas/smtp/smtp.h

@@ -19,6 +19,17 @@ struct Field {
 	int	source;
 };
 
+typedef struct DS	DS;
+struct DS {
+	/* dist string */
+	char	buf[128];
+	char	expand[128];
+	char	*netdir;
+	char	*proto;
+	char	*host;
+	char	*service;
+};
+
 extern Field	*firstfield;
 extern Field	*lastfield;
 extern Node	*usender;
@@ -47,4 +58,4 @@ String*	yywhite(void);
 Node*	whiten(Node*);
 void	yycleanup(void);
 int	mxdial(char*, char*, char*);
-char*	expand_meta(char *);
+void	dial_string_parse(char*, DS*);