xref: /plan9/sys/src/cmd/jpg/ppm.c (revision 9863c128e160e47d0bf3a33658496e0e3d0bd48e)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <bio.h>
47dd7cddfSDavid du Colombier #include <draw.h>
57dd7cddfSDavid du Colombier #include <event.h>
67dd7cddfSDavid du Colombier #include "imagefile.h"
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier int		cflag = 0;
97dd7cddfSDavid du Colombier int		dflag = 0;
107dd7cddfSDavid du Colombier int		eflag = 0;
117dd7cddfSDavid du Colombier int		nineflag = 0;
127dd7cddfSDavid du Colombier int		threeflag = 0;
137dd7cddfSDavid du Colombier int		output = 0;
147dd7cddfSDavid du Colombier ulong	outchan = CMAP8;
157dd7cddfSDavid du Colombier int		defaultcolor = 1;
167dd7cddfSDavid du Colombier Image	*image;
177dd7cddfSDavid du Colombier 
187dd7cddfSDavid du Colombier enum{
197dd7cddfSDavid du Colombier 	Border	= 2,
207dd7cddfSDavid du Colombier 	Edge		= 5
217dd7cddfSDavid du Colombier };
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier char	*show(int, char*);
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier void
eresized(int new)267dd7cddfSDavid du Colombier eresized(int new)
277dd7cddfSDavid du Colombier {
287dd7cddfSDavid du Colombier 	Rectangle r;
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier 	if(new && getwindow(display, Refnone) < 0){
317dd7cddfSDavid du Colombier 		fprint(2, "ppm: can't reattach to window\n");
327dd7cddfSDavid du Colombier 		exits("resize");
337dd7cddfSDavid du Colombier 	}
347dd7cddfSDavid du Colombier 	if(image == nil)
357dd7cddfSDavid du Colombier 		return;
367dd7cddfSDavid du Colombier 	r = insetrect(screen->clipr, Edge+Border);
377dd7cddfSDavid du Colombier 	r.max.x = r.min.x+Dx(image->r);
387dd7cddfSDavid du Colombier 	r.max.y = r.min.y+Dy(image->r);
397dd7cddfSDavid du Colombier 	border(screen, r, -Border, nil, ZP);
40*9863c128SDavid du Colombier 	drawop(screen, r, image, nil, image->r.min, S);
417dd7cddfSDavid du Colombier 	flushimage(display, 1);
427dd7cddfSDavid du Colombier }
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier void
main(int argc,char * argv[])457dd7cddfSDavid du Colombier main(int argc, char *argv[])
467dd7cddfSDavid du Colombier {
477dd7cddfSDavid du Colombier 	int fd, i;
487dd7cddfSDavid du Colombier 	char *err;
497dd7cddfSDavid du Colombier 
507dd7cddfSDavid du Colombier 	ARGBEGIN{
517dd7cddfSDavid du Colombier 	case '3':		/* produce encoded, compressed, three-color bitmap file; no display by default */
527dd7cddfSDavid du Colombier 		threeflag++;
537dd7cddfSDavid du Colombier 		/* fall through */
547dd7cddfSDavid du Colombier 	case 't':		/* produce encoded, compressed, true-color bitmap file; no display by default */
557dd7cddfSDavid du Colombier 		cflag++;
567dd7cddfSDavid du Colombier 		dflag++;
577dd7cddfSDavid du Colombier 		output++;
587dd7cddfSDavid du Colombier 		defaultcolor = 0;
597dd7cddfSDavid du Colombier 		outchan = RGB24;
607dd7cddfSDavid du Colombier 		break;
617dd7cddfSDavid du Colombier 	case 'c':		/* produce encoded, compressed, bitmap file; no display by default */
627dd7cddfSDavid du Colombier 		cflag++;
637dd7cddfSDavid du Colombier 		dflag++;
647dd7cddfSDavid du Colombier 		output++;
657dd7cddfSDavid du Colombier 		if(defaultcolor)
667dd7cddfSDavid du Colombier 			outchan = CMAP8;
677dd7cddfSDavid du Colombier 		break;
687dd7cddfSDavid du Colombier 	case 'd':		/* suppress display of image */
697dd7cddfSDavid du Colombier 		dflag++;
707dd7cddfSDavid du Colombier 		break;
717dd7cddfSDavid du Colombier 	case 'e':		/* disable floyd-steinberg error diffusion */
727dd7cddfSDavid du Colombier 		eflag++;
737dd7cddfSDavid du Colombier 		break;
747dd7cddfSDavid du Colombier 	case 'k':		/* force black and white */
757dd7cddfSDavid du Colombier 		defaultcolor = 0;
767dd7cddfSDavid du Colombier 		outchan = GREY8;
777dd7cddfSDavid du Colombier 		break;
787dd7cddfSDavid du Colombier 	case 'v':		/* force RGBV */
797dd7cddfSDavid du Colombier 		defaultcolor = 0;
807dd7cddfSDavid du Colombier 		outchan = CMAP8;
817dd7cddfSDavid du Colombier 		break;
827dd7cddfSDavid du Colombier 	case '9':		/* produce plan 9, uncompressed, bitmap file; no display by default */
837dd7cddfSDavid du Colombier 		nineflag++;
847dd7cddfSDavid du Colombier 		dflag++;
857dd7cddfSDavid du Colombier 		output++;
867dd7cddfSDavid du Colombier 		if(defaultcolor)
877dd7cddfSDavid du Colombier 			outchan = CMAP8;
887dd7cddfSDavid du Colombier 		break;
897dd7cddfSDavid du Colombier 	default:
907dd7cddfSDavid du Colombier 		fprint(2, "usage: ppm -39cdektv  [file.ppm ...]\n");
917dd7cddfSDavid du Colombier 		exits("usage");
927dd7cddfSDavid du Colombier 	}ARGEND;
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier 	err = nil;
957dd7cddfSDavid du Colombier 	if(argc == 0)
967dd7cddfSDavid du Colombier 		err = show(0, "<stdin>");
977dd7cddfSDavid du Colombier 	else{
987dd7cddfSDavid du Colombier 		for(i=0; i<argc; i++){
997dd7cddfSDavid du Colombier 			fd = open(argv[i], OREAD);
1007dd7cddfSDavid du Colombier 			if(fd < 0){
1017dd7cddfSDavid du Colombier 				fprint(2, "ppm: can't open %s: %r\n", argv[i]);
1027dd7cddfSDavid du Colombier 				err = "open";
1037dd7cddfSDavid du Colombier 			}else{
1047dd7cddfSDavid du Colombier 				err = show(fd, argv[i]);
1057dd7cddfSDavid du Colombier 				close(fd);
1067dd7cddfSDavid du Colombier 			}
1077dd7cddfSDavid du Colombier 			if((nineflag || cflag) && argc>1 && err==nil){
1087dd7cddfSDavid du Colombier 				fprint(2, "ppm: exiting after one file\n");
1097dd7cddfSDavid du Colombier 				break;
1107dd7cddfSDavid du Colombier 			}
1117dd7cddfSDavid du Colombier 		}
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 	exits(err);
1147dd7cddfSDavid du Colombier }
1157dd7cddfSDavid du Colombier 
1167dd7cddfSDavid du Colombier int
init(void)1177dd7cddfSDavid du Colombier init(void)
1187dd7cddfSDavid du Colombier {
1197dd7cddfSDavid du Colombier 	static int inited;
1207dd7cddfSDavid du Colombier 
1217dd7cddfSDavid du Colombier 	if(inited == 0){
1227dd7cddfSDavid du Colombier 		if(initdraw(0, 0, 0) < 0){
1237dd7cddfSDavid du Colombier 			fprint(2, "ppm: initdraw failed: %r");
1247dd7cddfSDavid du Colombier 			return -1;
1257dd7cddfSDavid du Colombier 		}
1267dd7cddfSDavid du Colombier 		einit(Ekeyboard|Emouse);
1277dd7cddfSDavid du Colombier 		inited++;
1287dd7cddfSDavid du Colombier 	}
1297dd7cddfSDavid du Colombier 	return 1;
1307dd7cddfSDavid du Colombier }
1317dd7cddfSDavid du Colombier 
1327dd7cddfSDavid du Colombier char*
show(int fd,char * name)1337dd7cddfSDavid du Colombier show(int fd, char *name)
1347dd7cddfSDavid du Colombier {
1357dd7cddfSDavid du Colombier 	Rawimage **array, *r, *c;
1367dd7cddfSDavid du Colombier 	Image *i;
1377dd7cddfSDavid du Colombier 	int j, ch;
1387dd7cddfSDavid du Colombier 	char buf[32];
1397dd7cddfSDavid du Colombier 
1407dd7cddfSDavid du Colombier 	array = readpixmap(fd, CRGB);
1417dd7cddfSDavid du Colombier 	if(array == nil || array[0]==nil){
1427dd7cddfSDavid du Colombier 		fprint(2, "ppm: decode %s failed: %r\n", name);
1437dd7cddfSDavid du Colombier 		return "decode";
1447dd7cddfSDavid du Colombier 	}
1457dd7cddfSDavid du Colombier 	if(!dflag){
1467dd7cddfSDavid du Colombier 		if(init() < 0)
1477dd7cddfSDavid du Colombier 			return "initdraw";
1487dd7cddfSDavid du Colombier 		if(defaultcolor && screen->depth>8)
1497dd7cddfSDavid du Colombier 			outchan = RGB24;
1507dd7cddfSDavid du Colombier 	}
1517dd7cddfSDavid du Colombier 	r = array[0];
1527dd7cddfSDavid du Colombier 	if(outchan == CMAP8)
1537dd7cddfSDavid du Colombier 		c = torgbv(r, !eflag);
1547dd7cddfSDavid du Colombier 	else{
1557dd7cddfSDavid du Colombier 		if(outchan==GREY8 || (r->chandesc==CY && threeflag==0))
1567dd7cddfSDavid du Colombier 			c = totruecolor(r, CY);
1577dd7cddfSDavid du Colombier 		else
1587dd7cddfSDavid du Colombier 			c = totruecolor(r, CRGB24);
1597dd7cddfSDavid du Colombier 	}
1607dd7cddfSDavid du Colombier 	if(c == nil){
1617dd7cddfSDavid du Colombier 		fprint(2, "ppm: converting %s to local format failed: %r\n", name);
1627dd7cddfSDavid du Colombier 		return "torgbv";
1637dd7cddfSDavid du Colombier 	}
1647dd7cddfSDavid du Colombier 	if(!dflag){
1657dd7cddfSDavid du Colombier 		if(r->chandesc == CY)
166*9863c128SDavid du Colombier 			outchan = GREY8;
1677dd7cddfSDavid du Colombier 		i = allocimage(display, c->r, outchan, 0, 0);
1687dd7cddfSDavid du Colombier 		if(i == nil){
1697dd7cddfSDavid du Colombier 			fprint(2, "ppm: allocimage %s failed: %r\n", name);
1707dd7cddfSDavid du Colombier 			return "allocimage";
1717dd7cddfSDavid du Colombier 		}
1727dd7cddfSDavid du Colombier 		if(loadimage(i, i->r, c->chans[0], c->chanlen) < 0){
1737dd7cddfSDavid du Colombier 			fprint(2, "ppm: loadimage %s failed: %r\n", name);
1747dd7cddfSDavid du Colombier 			return "loadimage";
1757dd7cddfSDavid du Colombier 		}
1767dd7cddfSDavid du Colombier 		image = i;
1777dd7cddfSDavid du Colombier 		eresized(0);
1787dd7cddfSDavid du Colombier 		if((ch=ekbd())=='q' || ch==0x7F || ch==0x04)
1797dd7cddfSDavid du Colombier 			exits(nil);
1807dd7cddfSDavid du Colombier 		draw(screen, screen->clipr, display->white, nil, ZP);
1817dd7cddfSDavid du Colombier 		image = nil;
1827dd7cddfSDavid du Colombier 		freeimage(i);
1837dd7cddfSDavid du Colombier 	}
1847dd7cddfSDavid du Colombier 	if(nineflag){
185*9863c128SDavid du Colombier 		if(r->chandesc == CY)
186*9863c128SDavid du Colombier 			outchan = GREY8;
1877dd7cddfSDavid du Colombier 		chantostr(buf, outchan);
1887dd7cddfSDavid du Colombier 		print("%11s %11d %11d %11d %11d ", buf,
1897dd7cddfSDavid du Colombier 			c->r.min.x, c->r.min.y, c->r.max.x, c->r.max.y);
1907dd7cddfSDavid du Colombier 		if(write(1, c->chans[0], c->chanlen) != c->chanlen){
1917dd7cddfSDavid du Colombier 			fprint(2, "ppm: %s: write error %r\n", name);
1927dd7cddfSDavid du Colombier 			return "write";
1937dd7cddfSDavid du Colombier 		}
1947dd7cddfSDavid du Colombier 	}else if(cflag){
1957dd7cddfSDavid du Colombier 		if(writerawimage(1, c) < 0){
1967dd7cddfSDavid du Colombier 			fprint(2, "ppm: %s: write error: %r\n", name);
1977dd7cddfSDavid du Colombier 			return "write";
1987dd7cddfSDavid du Colombier 		}
1997dd7cddfSDavid du Colombier 	}
2007dd7cddfSDavid du Colombier 	for(j=0; j<r->nchans; j++)
2017dd7cddfSDavid du Colombier 		free(r->chans[j]);
2027dd7cddfSDavid du Colombier 	free(r->cmap);
2037dd7cddfSDavid du Colombier 	free(r);
2047dd7cddfSDavid du Colombier 	free(array);
2057dd7cddfSDavid du Colombier 	if(c){
2067dd7cddfSDavid du Colombier 		free(c->chans[0]);
2077dd7cddfSDavid du Colombier 		free(c);
2087dd7cddfSDavid du Colombier 	}
2097dd7cddfSDavid du Colombier 	return nil;
2107dd7cddfSDavid du Colombier }
211