diff options
author | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
---|---|---|
committer | giraffedata <giraffedata@9d0c8265-081b-0410-96cb-a4ca84ce46f8> | 2006-08-19 03:12:28 +0000 |
commit | 1fd361a1ea06e44286c213ca1f814f49306fdc43 (patch) | |
tree | 64c8c96cf54d8718847339a403e5e67b922e8c3f /converter/ppm/ppmtoicr.c | |
download | netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.gz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.tar.xz netpbm-mirror-1fd361a1ea06e44286c213ca1f814f49306fdc43.zip |
Create Subversion repository
git-svn-id: http://svn.code.sf.net/p/netpbm/code/trunk@1 9d0c8265-081b-0410-96cb-a4ca84ce46f8
Diffstat (limited to 'converter/ppm/ppmtoicr.c')
-rw-r--r-- | converter/ppm/ppmtoicr.c | 320 |
1 files changed, 320 insertions, 0 deletions
diff --git a/converter/ppm/ppmtoicr.c b/converter/ppm/ppmtoicr.c new file mode 100644 index 00000000..feca0c18 --- /dev/null +++ b/converter/ppm/ppmtoicr.c @@ -0,0 +1,320 @@ +/* ppmtoicr.c - convert a portable pixmap to NCSA ICR protocol +** +** Copyright (C) 1990 by Kanthan Pillay (svpillay@Princeton.EDU) +** +** 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 "ppm.h" + +#define MAXCOLORS 256 +#define CLUTCOLORS 768 + +static int colorstobpp ARGS(( int colors )); +static int GetPixel ARGS(( int x, int y )); +static int rleit ARGS(( char* buf, char* bufto, int len )); + +static pixel** pixels; +static colorhash_table cht; +static char* testimage; + +int +main(argc, argv) +int argc; +char* argv[]; +{ + FILE* ifp; + int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize; + pixval maxval; + colorhist_vector chv; + char rgb[CLUTCOLORS]; + const char* windowname; + char* thischar; + char* thisline; + char* space; + register unsigned char c; + register char* p; + int display, expand; + int rleflag, winflag; + const char* const usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]"; + + + ppm_init( &argc, argv ); + + argn = 1; + windowname = "untitled"; + winflag = 0; + expand = 1; + display = 0; + rleflag = 0; + + while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' ) + { + if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc ) + { + ++argn; + windowname = argv[argn]; + winflag = 1; + } + else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc ) + { + ++argn; + if ( sscanf( argv[argn], "%d",&expand ) != 1 ) + pm_usage( usage ); + } + else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc ) + { + ++argn; + if ( sscanf( argv[argn], "%d",&display ) != 1 ) + pm_usage( usage ); + } + else if ( pm_keymatch(argv[argn],"-rle",2) ) + rleflag = 1; + else if ( pm_keymatch(argv[argn],"-norle",2) ) + rleflag = 0; + else + pm_usage( usage ); + } + + if ( argn < argc ) + { + ifp = pm_openr( argv[argn] ); + if ( ! winflag ) + windowname = argv[argn]; + ++argn; + } + else + ifp = stdin; + + if ( argn != argc ) + pm_usage( usage ); + + pixels = ppm_readppm( ifp, &cols, &rows, &maxval ); + + pm_close( ifp ); + + for (i = 0; i < CLUTCOLORS; i++) + rgb[i] = 0; + + /* Figure out the colormap. */ + pm_message("computing colormap..." ); + chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors); + if (chv == (colorhist_vector) 0) + pm_error( "too many colors - try doing a 'pnmquant %d'", MAXCOLORS ); + pm_message("%d colors found", colors ); + + /* Turn the ppm colormap into an ICR colormap. */ + if (maxval > 255) + pm_message( + "maxval is not 255 - automatically rescaling colors" ); + 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. */ + 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" */ + + pm_message("creating window %s ...", windowname ); + (void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname); + fflush(stdout); + + + /****************** Download the colormap. ********************/ + pm_message("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); + + /**************** send out picture *************************/ + /* Protocol's RLE scheme is quicker but buggy */ + + if (rleflag) { + pm_message("sending run-length encoded picture data ..." ); + testimage = (char*) malloc(rows*cols); + p = testimage; + for (i=0; i<rows; i++) + for (j=0; j<cols; j++) + *p++ = GetPixel(j,i); + space = (char*) 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); + exit(0); + } + + /* Otherwise, send out uncompressed pixel data via the slow method */ + + else { + pm_message("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); + exit(0); + } + } + +static int +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" ); + return bpp; + } + +static int +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 */ + +static int +rleit(buf,bufto,len) + char* buf; + char* bufto; + int len; + { + register char* p; + register char* q; + register char* cfoll; + register char* 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 = (p - begp); + else + clead--; + + return((int) (clead-bufto)); /*how many stored as encoded */ +} |