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