svpillay@narnia.Princeton.EDU (Kanthan Pillay) (08/01/90)
ppmtoicr reads a ppm file and outputs a number of commands using NCSA's Interactive Color Raster (ICR) protocol. This means that if you run ppmtoicr on a terminal that understands ICR (for example, a Macintosh with Color Quickdraw running NCSA Telnet 2.3), ppmtoicr will create a window, download a colormap, and display the picture. (See the man page for more details.) You need the PBMPLUS libraries to compile ppmtoicr. ppmtoicr is copyrighted but may be freely distributed (a la PBMPLUS). Kanthan. #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # ppmtoicr # This archive created: Mon Jul 30 20:04:49 1990 export PATH; PATH=/bin:$PATH if test ! -d 'ppmtoicr' then mkdir 'ppmtoicr' fi cd 'ppmtoicr' if test -f 'ppmtoicr.c' then echo shar: will not over-write existing file "'ppmtoicr.c'" else cat << \SHAR_EOF > 'ppmtoicr.c' /* ppmtoicr.c - convert a portable pixmap to NCSA ICR protocol ** ** Copyright (C) 1990 by Kanthan Pillay (svpillay@Princeton.EDU) ** Portions Copyright (C) 1989 by Jef Poskanzer. ** ** Permission to use, copy, modify, and distribute this software and its ** documentation for any purpose and without fee is hereby granted, provided ** that the above copyright notice appear in all copies and that both that ** copyright notice and this permission notice appear in supporting ** documentation. This software is provided "as is" without express or ** implied warranty. */ #include <stdio.h> #include "ppm.h" #include "ppmcmap.h" #define MAXCOLORS 256 #define CLUTCOLORS 768 pixel **pixels; colorhash_table cht; char *malloc(), *testimage; main(argc, argv) int argc; char *argv[]; { FILE *ifd; int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize; pixval maxval; colorhist_vector chv; int Red[MAXCOLORS], Green[MAXCOLORS], Blue[MAXCOLORS]; char rgb[CLUTCOLORS]; int GetPixel(); char *usage = "[-r] [-w windowname] [-d display] [-e expand] [ppmfile]"; char *windowname, *thischar, *thisline, *space; register unsigned char c; register char *p; int ci, icolors; int display = 0, expand = 1; int rflag = 0, wflag = 0, errflg = 0; int q, z; extern int optind, opterr; extern char *optarg; /* I use getopt(3) for parsing options. If you don't have it, there's a public domain version available from comp.sources.misc */ pm_progname = argv[0]; windowname = "untitled"; opterr = 0; while ((q = getopt(argc, argv, "rw:d:e:")) != EOF) switch (q) { case 'r': rflag++; break; case 'w': windowname=optarg; wflag++; break; case 'd': z = (sscanf(optarg,"%d",&display)); if ((z == EOF) || (z == 0)) errflg++; break; case 'e': z = (sscanf(optarg,"%d",&expand)); if ((z == EOF) || (z == 0)) errflg++; break; case '?': errflg++; } if (errflg) { pm_usage(usage); exit(2); } if (optind < argc) { ifd = pm_openr(argv[optind]); if (!wflag) windowname = argv[optind]; optind++; } else { ifd = stdin; } if (optind != argc) pm_usage(usage); pixels = ppm_readppm(ifd, &cols, &rows, &maxval); pm_close(ifd); for (i = 0; i < CLUTCOLORS; i++) rgb[i] = 0; /* Figure out the colormap. This is Jeff's code from ppmtogif.c */ fprintf(stderr, "(Computing colormap..." ); fflush(stderr); chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); if (chv == (colorhist_vector) 0) pm_error( "too many colors - try running the pixmap through 'ppmquant 256'", 0,0,0,0,0 ); fprintf(stderr, "Done. %d colors found.)\n", colors); /* Turn the ppm colormap into an ICR colormap. */ if (maxval > 255) fprintf( stderr, "(Maxval is not 255 -- automatically rescaling colors.)\n"); for (i = 0; i < colors; i++) { j = (3 * i); if (maxval == 255) { rgb[j] = PPM_GETR(chv[i].color) ; j++; rgb[j] = PPM_GETG(chv[i].color) ; j++; rgb[j] = PPM_GETB(chv[i].color) ; } else { rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval; j++; rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval; j++; rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval; } } BitsPerPixel = colorstobpp(colors); /* And make a hash table for fast lookup. Jeff's code again. */ cht = ppm_colorhisttocolorhash(chv, colors); ppm_freecolorhist(chv); /************** Create a new window using ICR protocol *********/ /* Format is "ESC^W;left;top;width;height;display;windowname" */ fprintf(stderr, "(Creating window %s ...",windowname); (void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname); fflush(stdout); fprintf(stderr, "Done ...)\n"); /****************** Download the colormap. ********************/ fprintf(stderr, "(Downloading colormap for %s ...",windowname); (void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname); thischar = rgb; for (j=0; j<CLUTCOLORS; j++) { c = *thischar++; if (c > 31 && c < 123 ) { /* printable ASCII */ putchar(c); } else { putchar((c>>6)+123); /* non-printable, so encode it */ putchar((c & 0x3f) + 32); } } fflush(stdout); fprintf(stderr, "Done ...)\n"); /**************** send out picture *************************/ /* Protocol's RLE scheme is quicker but buggy */ if (rflag) { fprintf(stderr, "(Sending run-length encoded picture data ..."); testimage = malloc(rows*cols); p = testimage; for (i=0; i<rows; i++) for (j=0; j<cols; j++) *p++ = GetPixel(j,i); space = malloc(rows*3); thisline = testimage; for (i = 0; i < rows; i++) { newxsize = rleit(thisline,space,cols); thisline += cols; /* increment to next line */ (void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname); thischar = space; for (j=0; j< newxsize; j++) { c= *thischar++; /*get byte to send */ if (c>31 && c <123) { putchar(c); } else { putchar((c>>6) + 123); putchar((c & 0x3f) + 32); } } fflush(stdout); } free(space); fprintf(stderr, "Done ...)\n"); exit(0); } /* Otherwise, send out uncompressed pixel data via the slow method */ else { fprintf(stderr, "(Sending picture data ..."); for (i = 0; i < rows; i++) { (void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname); for (j = 0; j < cols; j++) { c = GetPixel(j,i); if (c > 31 && c < 123) { putchar(c); } else { putchar((c>>6)+123); putchar((c & 0x3f) + 32); } } } fflush(stdout); fprintf(stderr, "Done)\n"); exit(0); } } /* Jeff's code */ colorstobpp(colors) int colors; { int bpp; if (colors <= 2) bpp = 1; else if (colors <= 4) bpp = 2; else if (colors <= 8) bpp = 3; else if (colors <= 16) bpp = 4; else if (colors <= 32) bpp = 5; else if (colors <= 64) bpp = 6; else if (colors <= 128) bpp = 7; else if (colors <= 256) bpp = 8; else pm_error("can't happen", 0,0,0,0,0); return bpp; } GetPixel(x, y) int x, y; { int color; color = ppm_lookupcolor(cht, pixels[y][x]); return color; } /* rleit compress with run length encoding as per NCSA's documentation */ rleit(buf,bufto,len) int len; char *buf,*bufto; { register char *p,*q,*cfoll,*clead; char *begp; int i; p = buf; cfoll = bufto; clead = cfoll + 1; begp = p; while (len > 0 ) { /* encode until gone */ q = p + 1; i = len-1; while (*p == *q && i+120 > len && i) { q++; i--; } if (q > p +2) { /* three in a row */ if (p > begp) { *cfoll = p - begp; cfoll = clead; } *cfoll++ = 128 | (q-p); /*len of seq*/ *cfoll++ = *p; /* char of seq */ len -= q-p; /* subtract len of seq */ p = q; clead = cfoll+1; begp = p; } else { *clead++ = *p++; /* copy one char */ len--; if (p>begp + 120) { *cfoll = p - begp; cfoll = clead++; begp = p; } } } /* fillin last bytecount */ if (p>begp) *cfoll = 128 | (p-begp); else clead--; return((int) (clead-bufto)); /*how many stored as encoded */ } /* End */ SHAR_EOF fi # end of overwriting check if test -f 'ppmtoicr.1' then echo shar: will not over-write existing file "'ppmtoicr.1'" else cat << \SHAR_EOF > 'ppmtoicr.1' .TH PPMTOICR 1 "30 July 1990" .SH NAME ppmtoicr \- convert a portable pixmap into NCSA ICR format .SH SYNOPSIS .B ppmtoicr [ .B \-w .I windowname ] [ .B \-e .I expand ] [ .B \-d .I display ] [ .B \-r ] .I ppmfile .SH DESCRIPTION .LP Reads a portable pixmap file as input. Produces an NCSA Telnet Interactive Color Raster graphic file as output. If .I ppmfile is not supplied, .B ppmtoicr will read from standard input. .PP Interactive Color Raster (ICR) is a protocol for displaying raster graphics on workstation screens. The protocol is implemented in NCSA Telnet for the Macintosh version 2.3. The ICR protocol shares characteristics of the Tektronix graphics terminal emulation protocol. For example, escape sequences are used to control the display. .PP .B ppmtoicr will output the appropriate sequences to create a window of the dimensions of the input .B ppm(5) file, create a colormap of up to 256 colors on the display, then load the picture data into the window. .SH OPTIONS .TP 14 .BI "\-w" " windowname" Output will be displayed in .I windowname (Default is to use .I ppmfile or "untitled" if standard input is read.) .TP .BI "\-e" " expand" Output will be expanded on display by factor .I expand (For example, a value of 2 will cause four pixels to be displayed for every input pixel.) .TP .BI "\-d" " display" Output will be displayed on screen numbered .I display .TP .B "\-r" Use run-length encoded format for display. (This will nearly always result in a quicker display, but may skew the colormap.) .SH EXAMPLES To display a .B ppm(5) file using the protocol: .LP .RS .nf .BI ppmtoicr " ppmfile " .RE .fi .LP This will create a window named .I ppmfile on the display with the correct dimensions for .IR "ppmfile" , create and download a colormap of up to 256 colors, and download the picture into the window. The same effect may be achieved by the following sequence: .LP .RS .nf .BI ppmtoicr " ppmfile " > " filename" .BI cat " filename " .RE .fi .LP To display a .B GIF file using the protocol in a window titled after the input file, zoom the displayed image by a factor of 2, and run-length encode the data: .LP .RS .nf .BI "giftoppm " "giffile " "| ppmtoicr -w " "giffile " "-r -e " "2" .RE .fi .LP .B ppmtoicr will also read .B pbm(5) and .B pgm(5) files. The full range of pbm manipulation routines may be applied to graphics for display using .BR "ppmtoicr" "." Thus, a monochrome Sun raster file may be viewed in 5 color grayscale by the following sequence: .LP .RS .nf .BI "pbmtorast " "rasterfile " "| ppmscale .5 | ppmtoicr" .RE .fi .LP .SH BUGS Outputting run-length encoded data to the ICR display using the .B \-r option sometimes results in blurring of the picture on the right edge. .PP The protocol uses frequent .BR fflush(3) calls to speed up display. If the output is saved to a file for later display via .BR "cat" "(1)," drawing will be much slower. In either case, increasing the Blocksize limit on the display will speed up transmission substantially. .PP On displays not equipped with the protocol, garbage will be printed on screen. .PP Note that there is currently no .B icrtoppm tool. This is because files generated by .B ppmtoicr are simply strings of escape sequences that generate appropriate responses on a suitably equipped display. These files are inefficient for long-term storage of images. .SH SEE ALSO .BR giftoppm(1), .BR ilbmtoppm(1), .BR imgtoppm(1), .BR mtvtoppm(1), .BR qrttoppm(1), .BR rasttoppm(1), .BR tgatoppm(1), .BR xwdtoppm(1), .BR ppmarith(1), .BR ppmconvol(1), .BR ppmcscale(1), .BR ppmhist(1), .BR ppmquant(1), .BR ppmrotate(1), .BR ppmscale(1), .BR ppmshear(1), .BR ppm(5), .BR pnm(5), .BR pgm(5), .BR pbm(5), .BR cat(1), .LP .IR "NCSA Telnet for the Macintosh", University of Illinois at Urbana-Champaign (1989) .SH AUTHOR Kanthan Pillay, Princeton University Computing and Information Technology. .SH COPYRIGHT Copyright (C) 1990 by Kanthan Pillay .LP Portions Copyright (C) 1989 by Jef Poskanzer. .PP Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation. This software is provided "as is" without express or implied warranty. SHAR_EOF fi # end of overwriting check if test -f 'README' then echo shar: will not over-write existing file "'README'" else cat << \SHAR_EOF > 'README' ppmtoicr is meant to be installed as part of Jeff Poskanzer's PBMPLUS package and requires its libraries. Please do NOT ask me to send you copies of the package. The package may be obtained from the comp.sources.misc archive at uunet.uu.net and is recommended for anyone who doesn't want to reinvent the wheel for image processing, and the price is right! If you find any more bugs than what I've documented in the man page, I'd like to hear about it. Kanthan Pillay --- Work: (609) 258-6028 Internet: svpillay@Princeton.EDU Home: (609) 683-8212 Bitnet: SVPILLAY@PUCC Fax: (609) 258-3943 uucp: ...princeton!svpillay P.S. If you're happy with this program and would like to say thanks, stand up for protecting the free flow of information, including the right to use this program to display whatever images you may want to. SHAR_EOF fi # end of overwriting check if test -f 'INSTALLATION' then echo shar: will not over-write existing file "'INSTALLATION'" else cat << \SHAR_EOF > 'INSTALLATION' 1) If you haven't already done so, build and install the PBMPLUS package. 2) Copy ppmtoicr.c to the ppm subdirectory of the pbm files. 3) Edit ppm/Makefile and add ppmtoicr to the list of files under PORTBINARIES. 4) Change to the ppm subdirectory. 5) Type "make". Alternatively, you can simply build it as follows (assuming you have the libraries somewhere). cc -s -o ppmtoicr ppmtoicr.c libppm.a libpgm.a libpbm.a Neither gcc or /bin/cc -O compile the PBM package correctly on Sun 4 (SPARC) systems. The package does compile correctly on a Sun 3 running SunOS 4.0.3 using gcc. SHAR_EOF fi # end of overwriting check cd .. # End of shell archive exit 0 --- Work: (609) 258-6028 Internet: svpillay@Princeton.EDU Home: (609) 683-8212 Bitnet: SVPILLAY@PUCC Fax: (609) 258-3943 uucp: ...rutgers!princeton!svpillay