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

  1. /* ppmtouil.c - read a portable pixmap and produce a Motif UIL icon file
  2. **
  3. ** Converted by Jef Poskanzer from ppmtoxpm.c, which is
  4. ** Copyright (C) 1990 by Mark W. Snitily.
  5. **
  6. ** Permission to use, copy, modify, and distribute this software and its
  7. ** documentation for any purpose and without fee is hereby granted, provided
  8. ** that the above copyright notice appear in all copies and that both that
  9. ** copyright notice and this permission notice appear in supporting
  10. ** documentation.  This software is provided "as is" without express or
  11. ** implied warranty.
  12. */
  13.  
  14. #include <ctype.h>
  15. #include "ppm.h"
  16. #include "ppmcmap.h"
  17.  
  18. /* Max number of colors allowed in ppm input. */
  19. #define MAXCOLORS 256
  20.  
  21. /* Lower bound and upper bound of character-pixels printed in UIL output. */
  22. #define LOW_CHAR '`'
  23. #define HIGH_CHAR '~'
  24.  
  25. typedef struct {    /* character-pixel mapping */
  26.     char* cixel;    /* character string printed for pixel */
  27.     char* rgbname;    /* ascii rgb color, either mnemonic or #rgb value */
  28.     char* barname;    /* ascii rgb color with spaces replaced by underbars */
  29.     } cixel_map;
  30.  
  31. static char* gen_numstr ARGS(( int i, int base, char low_char, int digits ));
  32. static void gen_cmap ARGS(( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP ));
  33.  
  34. int
  35. main( argc, argv )
  36.     int argc;
  37.     char* argv[];
  38.     {
  39.     FILE* ifp;
  40.     pixel** pixels;
  41.     register pixel* pP;
  42.     int argn, rows, cols, ncolors, row, col, i;
  43.     pixval maxval;
  44.     colorhash_table cht;
  45.     colorhist_vector chv;
  46.     cixel_map cmap[MAXCOLORS];
  47.     int charspp;
  48.     char out_name[100];
  49.     char* cp;
  50.     int printed_one;
  51.     char* usage = "[-name <uilname>] [ppmfile]";
  52.  
  53.  
  54.     ppm_init( &argc, argv );
  55.     out_name[0] = '\0';
  56.  
  57.     argn = 1;
  58.  
  59.     /* Check for command line options. */
  60.     while ( argn < argc && argv[argn][0] == '-' && argv[argn][1] != '\0' )
  61.     {
  62.     if ( pm_keymatch( argv[argn], "-name", 2 ) )
  63.         {
  64.         ++argn;
  65.         if ( argn == argc )
  66.         pm_usage( usage );
  67.         (void) strcpy( out_name, argv[argn] );
  68.         }
  69.     else
  70.         pm_usage( usage );
  71.     ++argn;
  72.     }
  73.  
  74.     if ( argn != argc )
  75.     {
  76.     /* Open the input file. */
  77.     ifp = pm_openr( argv[argn] );
  78.  
  79.     /* If output filename not specified, use input filename as default. */
  80.     if ( out_name[0] == '\0' )
  81.         {
  82.         (void) strcpy( out_name, argv[argn] );
  83.         cp = index( out_name, '.' );
  84.         if ( cp != 0 )
  85.         *cp = '\0';    /* remove extension */
  86.         if ( strcmp( out_name, "-" ) == 0 )
  87.         (void) strcpy( out_name, "noname" );
  88.         /* Remove trailing _icon in name. */
  89.         cp = rindex( out_name, '_' );
  90.         if ( cp != (char*) 0 &&
  91.          cp[1] == 'i' && cp[2] == 'c' && cp[3] == 'o' &&
  92.          cp[4] == 'n' && cp[5] == '\0' )
  93.         *cp = '\0';
  94.         }
  95.     ++argn;
  96.     }
  97.     else
  98.     {
  99.     /* No input file specified. */
  100.     ifp = stdin;
  101.     if ( out_name[0] == '\0' )
  102.         (void) strcpy( out_name, "noname" );
  103.     }
  104.  
  105.     if ( argn != argc )
  106.     pm_usage( usage );
  107.  
  108.     /* Read in the ppm file. */
  109.     pixels = ppm_readppm( ifp, &cols, &rows, &maxval );
  110.     pm_close( ifp );
  111.  
  112.     /* Figure out the colormap. */
  113.     pm_message( "computing colormap..." );
  114.     chv = ppm_computecolorhist( pixels, cols, rows, MAXCOLORS, &ncolors );
  115.     if ( chv == (colorhist_vector) 0 )
  116.     pm_error(
  117.         "too many colors - try doing a 'ppmquant %d'", MAXCOLORS );
  118.     pm_message( "%d colors found", ncolors );
  119.  
  120.     /* Make a hash table for fast color lookup. */
  121.     cht = ppm_colorhisttocolorhash( chv, ncolors );
  122.  
  123.     /* Now generate the character-pixel colormap table. */
  124.     gen_cmap( chv, ncolors, maxval, cmap, &charspp );
  125.  
  126.     /* Write out the UIL header. */
  127.     printf( "module %s\n", out_name );
  128.     printf( "version = 'V1.0'\n" );
  129.     printf( "names = case_sensitive\n" );
  130.     printf( "include file 'XmAppl.uil';\n" );
  131.  
  132.     /* Write out the colors. */
  133.     printf( "\n" );
  134.     printf( "value\n" );
  135.     for ( i = 0; i < ncolors; ++i )
  136.     if ( cmap[i].barname != (char*) 0 )
  137.         printf(
  138.         "    %s : color( '%s' );\n", cmap[i].barname, cmap[i].rgbname );
  139.  
  140.     /* Write out the ascii colormap. */
  141.     printf( "\n" );
  142.     printf( "value\n" );
  143.     printf( "  %s_rgb : color_table (\n", out_name );
  144.     printed_one = 0;
  145.     for ( i = 0; i < ncolors; ++i )
  146.     if ( cmap[i].barname != (char*) 0 )
  147.         {
  148.         if ( printed_one )
  149.         printf( ",\n" );
  150.         printf( "    %s = '%s'", cmap[i].barname, cmap[i].cixel );
  151.         printed_one = 1;
  152.         }     
  153.     printf( "\n    );\n" );
  154.  
  155.     /* Write out the ascii character-pixel image. */
  156.     printf( "\n" );
  157.     printf(
  158.     "%s_icon : exported icon( color_table = %s_rgb,\n",
  159.     out_name, out_name );
  160.     for ( row = 0; row < rows; ++row )
  161.     {
  162.     printf( "    '" );
  163.     for ( col = 0, pP = pixels[row]; col < cols; ++col, ++pP )
  164.         {
  165.         if ( ( col * charspp ) % 70 == 0 && col > 0 )
  166.         printf( "\\\n" );        /* line continuation */
  167.         printf( "%s", cmap[ppm_lookupcolor(cht, pP)].cixel );
  168.         }
  169.     if ( row != rows - 1 )
  170.         printf( "',\n" );
  171.     else
  172.         printf( "'\n") ; 
  173.     }
  174.     printf( ");\n" );
  175.     printf( "\n" );
  176.     printf( "end module;\n" );
  177.  
  178.     exit( 0 );
  179.     }
  180.  
  181. /* Given a number and a base, this routine prints the number into a
  182. ** malloc'ed string and returns it.  The length of the string is
  183. ** specified by "digits".  The ascii characters of the printed
  184. ** number range from low_char to low_char + base.  The string is
  185. ** low_char filled.
  186. */
  187.  
  188. #if __STDC__
  189. static char*
  190. gen_numstr( int i, int base, char low_char, int digits )
  191. #else /*__STDC__*/
  192. static char*
  193. gen_numstr( i, base, low_char, digits )
  194.     int i, base, digits;
  195.     char low_char;
  196. #endif /*__STDC__*/
  197.     {
  198.     char* str;
  199.     char* p;
  200.     int d;
  201.  
  202.     /* Allocate memory for printed number.  Abort if error. */
  203.     str = (char*) malloc( digits + 1 );
  204.     if ( str == 0 )
  205.     pm_error( "out of memory allocating number string" );
  206.  
  207.     /* Generate characters starting with least significant digit. */
  208.     p = str + digits;
  209.     *p-- = '\0';    /* nul terminate string */
  210.     while ( p >= str )
  211.     {
  212.     d = i % base;
  213.     i /= base;
  214.     *p-- = low_char + d;
  215.     }
  216.  
  217.     return str;
  218.     }
  219.  
  220. #if __STDC__
  221. static void
  222. gen_cmap( colorhist_vector chv, int ncolors, pixval maxval, cixel_map cmap[MAXCOLORS], int* charsppP )
  223. #else /*__STDC__*/
  224. static void
  225. gen_cmap( chv, ncolors, maxval, cmap, charsppP )
  226.     colorhist_vector chv;
  227.     int ncolors;
  228.     pixval maxval;
  229.     cixel_map cmap[MAXCOLORS];
  230.     int* charsppP;
  231. #endif /*__STDC__*/
  232.     {
  233.     int i, j, base;
  234.     char* colorname;
  235.     char* cp1;
  236.     char* cp2;
  237.  
  238.     /* Figure out how many characters per pixel we'll be using.  Don't want
  239.     ** to be forced to link with libm.a, so using a division loop rather than
  240.     ** a log function.
  241.     */
  242.     base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
  243.     for ( *charsppP = 0, i = ncolors; i > 0; ++(*charsppP) )
  244.     i /= base;
  245.  
  246.     /* Generate the character-pixel string and the rgb name for each colormap
  247.     ** entry.
  248.     */
  249.     for ( i = 0; i < ncolors; ++i )
  250.     {
  251.     /* Generate color name string. */
  252.     colorname = ppm_colorname( &(chv[i].color), maxval, 0 );
  253.  
  254.     /* Check whether we've already assigned a character to this name,
  255.     ** via the closest-match code.
  256.     */
  257.     for ( j = 0; j < i; ++j )
  258.         {
  259.         if ( cmap[j].rgbname != (char*) 0 &&
  260.          strcmp( colorname, cmap[j].rgbname ) == 0 )
  261.         {
  262.         cmap[i].cixel = cmap[j].cixel;
  263.         cmap[i].rgbname = (char*) 0;
  264.         cmap[i].barname = (char*) 0;
  265.         goto nexti;
  266.         }
  267.         }
  268.  
  269.     /* Copy it. */
  270.     cmap[i].rgbname = (char*) malloc( strlen( colorname ) + 1 );
  271.     if ( cmap[i].rgbname == 0 )
  272.         pm_error( "out of memory allocating color name" );
  273.     (void) strcpy( cmap[i].rgbname, colorname );
  274.  
  275.     /* Copy it again and replace the blanks with underbars. */
  276.     cmap[i].barname = malloc( strlen( colorname ) + 1 );
  277.     if ( cmap[i].barname == 0 )
  278.         pm_error( "out of memory allocating color name", 0,0,0,0,0 );
  279.     cp1 = colorname;
  280.     cp2 = cmap[i].barname;
  281.     for ( ; ; )
  282.         {
  283.         if ( *cp1 == ' ' )
  284.         *cp2 = '_';
  285.         else
  286.         *cp2 = *cp1;
  287.         if ( *cp1 == '\0' )
  288.         break;
  289.         ++cp1;
  290.         ++cp2;
  291.         }
  292.  
  293.     /* Generate color value characters. */
  294.     cmap[i].cixel = gen_numstr( i, base, LOW_CHAR, *charsppP );
  295.  
  296.     nexti: ;
  297.     }
  298.     }
  299.