home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / netpbma.zip / ppm / ppmtoicr.c < prev    next >
C/C++ Source or Header  |  1993-10-04  |  7KB  |  322 lines

  1. /* ppmtoicr.c - convert a portable pixmap to NCSA ICR protocol
  2. **
  3. ** Copyright (C) 1990 by Kanthan Pillay (svpillay@Princeton.EDU)
  4. **
  5. ** Permission to use, copy, modify, and distribute this software and its
  6. ** documentation for any purpose and without fee is hereby granted, provided
  7. ** that the above copyright notice appear in all copies and that both that
  8. ** copyright notice and this permission notice appear in supporting
  9. ** documentation.  This software is provided "as is" without express or
  10. ** implied warranty.
  11. */
  12.  
  13. #include "ppm.h"
  14. #include "ppmcmap.h"
  15.  
  16. #define MAXCOLORS 256
  17. #define CLUTCOLORS 768
  18.  
  19. static int colorstobpp ARGS(( int colors ));
  20. static int GetPixel ARGS(( int x, int y ));
  21. static int rleit ARGS(( char* buf, char* bufto, int len ));
  22.  
  23. static pixel** pixels;
  24. static colorhash_table cht;
  25. static char* testimage;
  26.  
  27. int
  28. main(argc, argv)
  29. int argc;
  30. char* argv[];
  31. {
  32.     FILE* ifp;
  33.     int argn, rows, cols, colors, i, j, BitsPerPixel, newxsize;
  34.     pixval maxval;
  35.     colorhist_vector chv;
  36.     char rgb[CLUTCOLORS];
  37.     char* windowname;
  38.     char* thischar;
  39.     char* thisline;
  40.     char* space;
  41.     register unsigned char c;
  42.     register char* p;
  43.     int display, expand;
  44.     int rleflag, winflag;
  45.     char* usage = "[-windowname windowname] [-expand expand] [-display display] [-rle] [ppmfile]";
  46.  
  47.  
  48.     ppm_init( &argc, argv );
  49.  
  50.     argn = 1;
  51.     windowname = "untitled";
  52.     winflag = 0;
  53.     expand = 1;
  54.     display = 0;
  55.     rleflag = 0;
  56.  
  57.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  58.         {
  59.         if ( pm_keymatch(argv[argn],"-windowname",2) && argn + 1 < argc )
  60.         {
  61.         ++argn;
  62.         windowname = argv[argn];
  63.         winflag = 1;
  64.         }
  65.         else if ( pm_keymatch(argv[argn],"-expand",2) && argn + 1 < argc )
  66.         {
  67.         ++argn;
  68.         if ( sscanf( argv[argn], "%d",&expand ) != 1 )
  69.             pm_usage( usage );
  70.         }
  71.         else if ( pm_keymatch(argv[argn],"-display",2) && argn + 1 < argc )
  72.         {
  73.         ++argn;
  74.         if ( sscanf( argv[argn], "%d",&display ) != 1 )
  75.             pm_usage( usage );
  76.         }
  77.         else if ( pm_keymatch(argv[argn],"-rle",2) )
  78.         rleflag = 1;
  79.         else if ( pm_keymatch(argv[argn],"-norle",2) )
  80.         rleflag = 0;
  81.         else
  82.         pm_usage( usage );
  83.         }
  84.  
  85.     if ( argn < argc )
  86.         {
  87.         ifp = pm_openr( argv[argn] );
  88.         if ( ! winflag )
  89.         windowname = argv[argn];
  90.         ++argn;
  91.         }
  92.     else
  93.         ifp = stdin;
  94.  
  95.     if ( argn != argc )
  96.         pm_usage( usage );
  97.  
  98.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  99.  
  100.     pm_close( ifp );
  101.  
  102.     for (i = 0; i < CLUTCOLORS; i++)
  103.         rgb[i] = 0;
  104.  
  105.     /* Figure out the colormap. */
  106.     pm_message("computing colormap..." );
  107.     chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &colors);
  108.     if (chv == (colorhist_vector) 0)
  109.     pm_error( "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  110.     pm_message("%d colors found", colors );
  111.  
  112.     /* Turn the ppm colormap into an ICR colormap. */
  113.     if (maxval > 255)
  114.     pm_message(
  115.         "maxval is not 255 - automatically rescaling colors" );
  116.     for (i = 0; i < colors; i++)
  117.     {
  118.     j = (3 * i);
  119.     if (maxval == 255)
  120.         {
  121.         rgb[j] = PPM_GETR(chv[i].color) ;
  122.         j++;
  123.         rgb[j] = PPM_GETG(chv[i].color) ;
  124.         j++;
  125.         rgb[j] = PPM_GETB(chv[i].color) ;
  126.         }
  127.     else
  128.         {
  129.         rgb[j] = (int) PPM_GETR(chv[i].color) * 255 / maxval;
  130.         j++;
  131.         rgb[j] = (int) PPM_GETG(chv[i].color) * 255 / maxval;
  132.         j++;
  133.         rgb[j] = (int) PPM_GETB(chv[i].color) * 255 / maxval;
  134.         }
  135.     }
  136.     BitsPerPixel = colorstobpp(colors);
  137.  
  138.     /* And make a hash table for fast lookup. */
  139.     cht = ppm_colorhisttocolorhash(chv, colors);
  140.     ppm_freecolorhist(chv);
  141.  
  142.  
  143.     /************** Create a new window using ICR protocol *********/
  144.     /* Format is "ESC^W;left;top;width;height;display;windowname"  */
  145.  
  146.     pm_message("creating window %s ...", windowname );
  147.     (void)printf("\033^W;%d;%d;%d;%d;%d;%s^",0,0,cols*expand,rows*expand,display,windowname);
  148.     fflush(stdout);
  149.  
  150.  
  151.     /****************** Download the colormap.  ********************/
  152.     pm_message("downloading colormap for %s ...", windowname );
  153.  
  154.     (void)printf("\033^M;%d;%d;%d;%s^",0,MAXCOLORS,CLUTCOLORS,windowname);
  155.     thischar = rgb;
  156.     for (j=0; j<CLUTCOLORS; j++) {
  157.     c = *thischar++;
  158.         if (c > 31 && c < 123 ) {     /* printable ASCII */
  159.         putchar(c);
  160.         }
  161.         else {
  162.         putchar((c>>6)+123);     /* non-printable, so encode it */
  163.         putchar((c & 0x3f) + 32);
  164.         }
  165.     }
  166.     fflush(stdout);
  167.  
  168.     /**************** send out picture *************************/
  169.     /* Protocol's RLE scheme is quicker but buggy              */
  170.  
  171.     if (rleflag) {    
  172.         pm_message("sending run-length encoded picture data ..." );
  173.         testimage = (char*) malloc(rows*cols);
  174.         p = testimage;
  175.         for (i=0; i<rows; i++)
  176.             for (j=0; j<cols; j++) 
  177.             *p++ = GetPixel(j,i);
  178.         space = (char*) malloc(rows*3);
  179.         thisline = testimage;
  180.         for (i = 0; i < rows; i++) {
  181.             newxsize = rleit(thisline,space,cols);
  182.             thisline += cols;    /* increment to next line */
  183.         (void)printf("\033^R;%d;%d;%d;%d;%s^",0,i*expand,expand,newxsize,windowname);
  184.         thischar = space;
  185.         for (j=0; j< newxsize; j++) {
  186.             c= *thischar++;  /*get byte to send */
  187.             if (c>31 && c <123) {
  188.                 putchar(c);
  189.                 }
  190.             else {
  191.                 putchar((c>>6) + 123);
  192.                 putchar((c & 0x3f) + 32);
  193.                 }
  194.             }
  195.             fflush(stdout);
  196.         }
  197.         free(space);
  198.         exit(0);
  199.         }
  200.  
  201.     /* Otherwise, send out uncompressed pixel data via the slow method */
  202.  
  203.         else {
  204.         pm_message("sending picture data ..." );
  205.         for (i = 0; i < rows; i++) {
  206.             (void)printf("\033^P;%d;%d;%d;%d;%s^",0,i*expand,expand,cols,windowname);
  207.             for (j = 0; j < cols; j++) {
  208.                 c  = GetPixel(j,i);
  209.                 if (c > 31 && c < 123) {
  210.                         putchar(c);
  211.                         }
  212.                 else        {
  213.                         putchar((c>>6)+123);
  214.                         putchar((c & 0x3f) + 32);
  215.                         }
  216.                 }
  217.             }
  218.         fflush(stdout);
  219.         exit(0);
  220.         }
  221.     }
  222.  
  223. static int
  224. colorstobpp(colors)
  225. int colors;
  226.     {
  227.     int bpp;
  228.  
  229.     if (colors <= 2)
  230.     bpp = 1;
  231.     else if (colors <= 4)
  232.     bpp = 2;
  233.     else if (colors <= 8)
  234.     bpp = 3;
  235.     else if (colors <= 16)
  236.     bpp = 4;
  237.     else if (colors <= 32)
  238.     bpp = 5;
  239.     else if (colors <= 64)
  240.     bpp = 6;
  241.     else if (colors <= 128)
  242.     bpp = 7;
  243.     else if (colors <= 256)
  244.     bpp = 8;
  245.     else
  246.     pm_error("can't happen" );
  247.     return bpp;
  248.     }
  249.  
  250. static int
  251. GetPixel(x, y)
  252. int x, y;
  253.     {
  254.     int color;
  255.  
  256.     color = ppm_lookupcolor(cht, &pixels[y][x]);
  257.     return color;
  258.     }
  259.  
  260.  
  261. /* rleit   compress with run length encoding as per NCSA's documentation */
  262.  
  263. static int
  264. rleit(buf,bufto,len)
  265.     char* buf;
  266.     char* bufto;
  267.     int len;
  268.     {
  269.     register char* p;
  270.     register char* q;
  271.     register char* cfoll;
  272.     register char* clead;
  273.     char* begp;
  274.     int i;
  275.  
  276.     p = buf;
  277.     cfoll = bufto;
  278.     clead = cfoll + 1;
  279.  
  280.     begp = p;
  281.     while (len > 0 ) {        /* encode until gone */
  282.         
  283.         q = p + 1;
  284.         i = len-1;
  285.     while (*p == *q && i+120 > len && i) {
  286.         q++;
  287.         i--;
  288.     }
  289.  
  290.     if (q > p +2) {            /* three in a row */
  291.         if (p > begp) {
  292.             *cfoll = p - begp;
  293.             cfoll = clead;
  294.         }
  295.         *cfoll++ = 128 | (q-p);        /*len of seq*/
  296.         *cfoll++ = *p;            /* char of seq */
  297.         len -= q-p;        /* subtract len of seq */
  298.         p = q;
  299.         clead = cfoll+1;
  300.         begp = p;
  301.     }
  302.     else {
  303.         *clead++ = *p++;    /* copy one char */
  304.         len--;
  305.         if (p>begp + 120) {
  306.             *cfoll = p - begp;
  307.             cfoll = clead++;
  308.             begp = p;
  309.         }
  310.     }
  311.     }
  312.  
  313. /* fillin last bytecount */
  314.  
  315.     if (p>begp)
  316.         *cfoll = (p - begp);
  317.     else
  318.         clead--;
  319.  
  320.     return((int) (clead-bufto));    /*how many stored as encoded */
  321. }
  322.