
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 1 (of 1)."
# Contents:  XPM.README ppmtoxpm.1 ppmtoxpm.c
# Wrapped by mark@zok on Sun Feb 18 15:57:59 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'XPM.README' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'XPM.README'\"
else
echo shar: Extracting \"'XPM.README'\" \(4438 characters\)
sed "s/^X//" >'XPM.README' <<'END_OF_FILE'
XMost of you are familiar with Jef Poskanzer's pbmplus utilities.
XFor those of you who are not, they are a wonderful collection of
Xroutines which transform images from one format to another.  This
Xpackage is distributed on the X11R4 contrib tape and can be found
Xon many archive sites.
X
XA relatively new format is XPM whose origins can be traced back to the
Xpeople at Groupe Bull -- the same wonderful folks who brought you the
Xgwm window manager.
X
XThis article contains the source and man page for a "ppmtoxpm" tool
Xwhich transforms an image from the ppm (portable pixmap) format, found
Xin the pbmplus utilities, to the XPM format.
X
XXPM is an ASCII based *color* pixmap format.  It's similar to the XBM
Xformat in that it can be #include'd in C source code, or read from a file
Xat run time.  An example is probably worth a thousand words; the X11
Xbitmap file ".../include/X11/bitmaps/dot" looks like:
X
X#define dot_width 16
X#define dot_height 16
Xstatic char dot_bits[] = {
X   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0xf0, 0x0f, 0xf0, 0x0f,
X   0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf8, 0x1f, 0xf0, 0x0f, 0xf0, 0x0f,
X   0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
X
XThe same file in XPM format would be:
X
X#define dot_format 1
X#define dot_width  16
X#define dot_height 16
X#define dot_ncolors 2
X#define dot_chars_per_pixel 1
Xstatic char *dot_colors[] = {
X   "`", "black",
X   "a", "white"
X};
Xstatic char *dot_pixels[] = {
X"aaaaaaaaaaaaaaaa",
X"aaaaaaaaaaaaaaaa",
X"aaaaaaaaaaaaaaaa",
X"aaaaaa````aaaaaa",
X"aaaa````````aaaa",
X"aaaa````````aaaa",
X"aaa``````````aaa",
X"aaa``````````aaa",
X"aaa``````````aaa",
X"aaa``````````aaa",
X"aaaa````````aaaa",
X"aaaa````````aaaa",
X"aaaaaa````aaaaaa",
X"aaaaaaaaaaaaaaaa",
X"aaaaaaaaaaaaaaaa",
X"aaaaaaaaaaaaaaaa"
X};
X
XAlthough the above example only uses two colors, XPM files can have an
Xarbitrary number of colors.  Colors can be specified by using either the
Xcolor name mnemonics found in the X11 server's RGB database (e.g. "black"),
Xor the X11 hexadecimal #RGB, ..., #RRRRGGGGBBBB convention.
X
XA good example of a program that understands XPM format is "xloadimage"
X(a.k.a. "xview" and "xsetbg") by Jim Frost (jimf@saber.com).  This program
Xis on the X11R4 contrib tape and has also been posted on comp.sources.x.
X"xloadimage" requires patchlevel 3 to correctly understand the XPM format.
XThis patchlevel should be posted on comp.sources.x in the near future.  In
Xthe mean while, you can obtain a patchlevel 3 version of "xloadimage" via
Xftp from expo.lcs.mit.edu (18.30.0.212) [/contrib/xloadimage.1.03.tar.Z],
Xor via uucp from zok [/usrX/contrib/xldim103.tar.Z].  (BTW, "xloadimage"
Xhas also been tested on unusual X11 servers, those that only have 2 or
X4 bitplanes.)
X
XAfter you unshar the ppmtoxpm.c and ppmtoxpm.1 files, place them into your
X.../pbmplus/ppm directory.  The .../pbmplus/ppm/Imakefile can be updated
Xby applying the following patch:
X
X*** Imakefile.org	Tue Nov 21 22:24:43 1989
X--- Imakefile	Sun Feb 18 14:34:59 1990
X***************
X*** 28,34 ****
X  PORTBINARIES =	giftoppm ilbmtoppm imgtoppm mtvtoppm ppmarith ppmconvol \
X  		ppmcscale ppmhist ppmquant ppmscale ppmtogif ppmtoilbm \
X  		ppmtopgm ppmtops ppmtorast ppmtoxwd qrttoppm rasttoppm \
X! 		tgatoppm xwdtoppm
X  MATHBINARIES =	ppmpat ppmrotate ppmshear
X  BINARIES =	$(PORTBINARIES) $(MATHBINARIES)
X  
X--- 28,34 ----
X  PORTBINARIES =	giftoppm ilbmtoppm imgtoppm mtvtoppm ppmarith ppmconvol \
X  		ppmcscale ppmhist ppmquant ppmscale ppmtogif ppmtoilbm \
X  		ppmtopgm ppmtops ppmtorast ppmtoxwd qrttoppm rasttoppm \
X! 		tgatoppm xwdtoppm ppmtoxpm
X  MATHBINARIES =	ppmpat ppmrotate ppmshear
X  BINARIES =	$(PORTBINARIES) $(MATHBINARIES)
X  
X***************
X*** 36,42 ****
X  		ppmconvol.1 ppmcscale.1 ppmhist.1 ppmpat.1 ppmquant.1 \
X  		ppmrotate.1 ppmscale.1 ppmshear.1 ppmtogif.1 ppmtoilbm.1 \
X  		ppmtopgm.1 ppmtops.1 ppmtorast.1 ppmtoxwd.1 qrttoppm.1 \
X! 		rasttoppm.1 tgatoppm.1 xwdtoppm.1
X  MANUALS3 =	libppm.3
X  MANUALS5 =	ppm.5
X  
X--- 36,42 ----
X  		ppmconvol.1 ppmcscale.1 ppmhist.1 ppmpat.1 ppmquant.1 \
X  		ppmrotate.1 ppmscale.1 ppmshear.1 ppmtogif.1 ppmtoilbm.1 \
X  		ppmtopgm.1 ppmtops.1 ppmtorast.1 ppmtoxwd.1 qrttoppm.1 \
X! 		rasttoppm.1 tgatoppm.1 xwdtoppm.1 ppmtoxpm.1
X  MANUALS3 =	libppm.3
X  MANUALS5 =	ppm.5
X
X  
XEnjoy.
X
X-- Mark
X
XMark W. Snitily                 Consulting Services:
X894 Brookgrove Lane             Graphics, Operating Systems, Compilers
XCupertino, CA 95014             (408) 252-0456
Xmark@zok.uucp
END_OF_FILE
if test 4438 -ne `wc -c <'XPM.README'`; then
    echo shar: \"'XPM.README'\" unpacked with wrong size!
fi
# end of 'XPM.README'
fi
if test -f 'ppmtoxpm.1' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ppmtoxpm.1'\"
else
echo shar: Extracting \"'ppmtoxpm.1'\" \(2447 characters\)
sed "s/^X//" >'ppmtoxpm.1' <<'END_OF_FILE'
X.TH ppmtoxpm 1 "13 February 1990"
X.SH NAME
Xppmtoxpm - convert a portable pixmap into an X11 pixmap
X.SH SYNOPSIS
Xppmtoxpm [-name <xpmname>] [-rgb <rgb-textfile>] [<ppmfile>]
X.SH DESCRIPTION
XReads a portable pixmap as input.
XProduces X11 pixmap (XPM) as output.
X.PP
XThe -name option allows one to specify the prefix string which is printed
Xin the resulting XPM output.  If not specified, will default to the
Xfilename (without extension) of the <ppmfile> argument.
XIf -name is not specified and <ppmfile>
Xis not specified (i.e. piped input), the prefix string will default to
Xthe string "noname".
X.PP
XThe -rgb option allows one to specify an X11 rgb text file for the
Xlookup of color name mnemonics.  This rgb text file is typically the
X/usr/lib/X11/rgb.txt of the MIT X11 distribution, but any file using the
Xsame format may be used.  When specified and
Xa RGB value from the ppm input matches a RGB value from the <rgb-textfile>,
Xthen the corresponding color name mnemonic is printed in the XPM's colormap.
XIf -rgb is not specified, or if the RGB values don't match, then the color
Xwill be printed with the #RGB, #RRGGBB, #RRRGGGBBB, or #RRRRGGGGBBBB
Xhexadecimal format.
X.PP
XAll flags can be abbreviated to their shortest unique prefix.
X.PP
XFor example, to convert the file "dot" (found in /usr/include/X11/bitmaps),
Xfrom xbm to xpm one could specify
X.IP
Xxbmtopbm dot | ppmtoxpm -name dot
X.PP
Xor, with a rgb text file (in the local directory)
X.IP
Xxbmtopbm dot | ppmtoxpm -name dot -rgb rgb.txt
X.SH BUGS
XAn option to match the closest (rather than exact) color name mnemonic
Xfrom the rgb text would be a desirable enhancement.
X.PP
XTruncation of the least significant bits of a RGB value may result in
Xnonexact matches when performing color name mnemonic lookups.
X.SH "SEE ALSO"
Xppm(5), xloadimage(1) patchlevel 3 by Jim Frost, jimf@saber.com
X.SH AUTHOR
XCopyright (C) 1990 by Mark W. Snitily.
X
XPermission to use, copy, modify, and distribute this software and its
Xdocumentation for any purpose and without fee is hereby granted, provided
Xthat the above copyright notice appear in all copies and that both that
Xcopyright notice and this permission notice appear in supporting
Xdocumentation.  This software is provided "as is" without express or
Ximplied warranty.
X
XThis tool was developed for Schlumberger Technologies, ATE Division, and
Xwith their permission is being made available to the public with the above
Xcopyright notice and permission notice.
END_OF_FILE
if test 2447 -ne `wc -c <'ppmtoxpm.1'`; then
    echo shar: \"'ppmtoxpm.1'\" unpacked with wrong size!
fi
# end of 'ppmtoxpm.1'
fi
if test -f 'ppmtoxpm.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'ppmtoxpm.c'\"
else
echo shar: Extracting \"'ppmtoxpm.c'\" \(14877 characters\)
sed "s/^X//" >'ppmtoxpm.c' <<'END_OF_FILE'
X/* ppmtoxpm.c - read a portable pixmap and produce a X11 pixmap
X**
X** Copyright (C) 1990 by Mark W. Snitily
X**
X** Permission to use, copy, modify, and distribute this software and its
X** documentation for any purpose and without fee is hereby granted, provided
X** that the above copyright notice appear in all copies and that both that
X** copyright notice and this permission notice appear in supporting
X** documentation.  This software is provided "as is" without express or
X** implied warranty.
X**
X** This tool was developed for Schlumberger Technologies, ATE Division, and
X** with their permission is being made available to the public with the above
X** copyright notice and permission notice.
X**
X*/
X
X#include <stdio.h>
X#include <ctype.h>
X#include "ppm.h"
X#include "ppmcmap.h"
X
X#ifdef SYSV
X#include <string.h>
X#define index strchr
X#else /*SYSV*/
X#include <strings.h>
X#endif /*SYSV*/
X
X/* Max number of colors allowed in ppm input. */
X#define MAXCOLORS    256
X
X/* Max number of rgb mnemonics allowed in rgb text file. */
X#define MAX_RGBNAMES 1024
X
X/* Lower bound and upper bound of character-pixels printed in XPM output.
X   Be careful, don't want the character '"' in this range. */
X/*#define LOW_CHAR  '#'  <-- minimum ascii character allowed */
X/*#define HIGH_CHAR '~'  <-- maximum ascii character allowed */
X#define LOW_CHAR  '`'
X#define HIGH_CHAR 'z'
X
X#define max(a,b) ((a) > (b) ? (a) : (b))
X
Xvoid read_rgb_names();  /* forward reference */
Xvoid gen_cmap();        /* forward reference */
X
Xtypedef struct {  /* rgb values and ascii names (from rgb text file) */
X   int  r, g, b;  /* rgb values, range of 0 -> 65535 */
X   char *name;    /* color mnemonic of rgb value */
X} rgb_names;
X
Xtypedef struct {  /* character-pixel mapping */
X   char *cixel;   /* character string printed for pixel */
X   char *rgbname; /* ascii rgb color, either color mnemonic or #rgb value */
X} cixel_map;
X
Xpixel **pixels;
X
Xmain(argc, argv)
Xint argc;
Xchar *argv[];
X{
X   FILE *ifd;
X   register pixel *pP;
X   int argn, rows, cols, ncolors, row, col, i;
X   pixval maxval;  /* pixval == unsigned char or unsigned short */
X   colorhash_table  cht;
X   colorhist_vector chv;
X
X   /* Used for rgb value -> rgb mnemonic mapping */
X   int map_rgb_names = 0;
X   rgb_names rgbn[MAX_RGBNAMES];
X   int rgbn_max;
X
X   /* Used for rgb value -> character-pixel string mapping */
X   cixel_map cmap[MAXCOLORS];
X   int charspp; /* chars per pixel */
X
X   char out_name[100], rgb_fname[100], *cp;
X   char *usage = "[-name <xpm-name>] [-rgb <rgb-textfile>] [ppmfile]";
X
X   pm_progname = argv[0];
X   out_name[0] = rgb_fname[0] = '\0';
X
X   argn = 1;
X
X   /* Check for command line options. */
X   while (argn < argc && argv[argn][0] == '-') {
X
X      /* Case "-", use stdin for input. */
X      if (argv[argn][1] == '\0') break;
X
X      /* Case "-name <xpm-filename>", get output filename. */
X      if (strncmp(argv[argn], "-name", max(strlen(argv[argn]),2)) == 0) {
X         argn++;
X         if (argn == argc || sscanf(argv[argn], "%s", out_name) != 1)
X            pm_usage(usage);
X      }
X
X      /* Case "-rgb <rgb-filename>", get rgb mnemonics filename. */
X      else if (strncmp(argv[argn], "-rgb", max(strlen(argv[argn]),2)) == 0) {
X         argn++;
X         if (argn == argc || sscanf(argv[argn], "%s", rgb_fname) != 1)
X            pm_usage(usage);
X         map_rgb_names = 1;
X      }
X
X      /* Nothing else allowed... */
X      else
X         pm_usage(usage);
X
X      argn++;
X   }
X
X   /* Input file specified, open it and set output filename if necessary. */
X   if (argn < argc) {
X
X      /* Open the input file. */
X      ifd = pm_openr(argv[argn]);
X
X      /* If output filename not specified, use input filename as default. */
X      if (out_name[0] == '\0') {
X         strcpy(out_name, argv[argn]);
X         if (cp = index(out_name, '.')) *cp = '\0'; /* remove extension */
X      }
X
X      /* If (1) input file was specified as "-" we're using stdin, or
X            (2) output filename was specified as "-",
X         set output filename to the default. */
X      if (!strcmp(out_name, "-" )) strcpy(out_name, "noname");
X
X      argn++;
X   }
X
X   /* No input file specified.  Using stdin so set default output filename. */
X   else {
X      ifd = stdin;
X      if (out_name[0] == '\0') strcpy(out_name, "noname");
X   }
X
X   /* Only 0 or 1 input files allowed. */
X   if (argn != argc) pm_usage(usage);
X
X   /* "maxval" is the largest value that can be be found in the ppm file.
X      All pixel components are relative to this value. */
X   pixels = ppm_readppm(ifd, &cols, &rows, &maxval);
X   pm_close(ifd);
X
X   /* Figure out the colormap. */
X   fprintf(stderr, "(Computing colormap...");  fflush(stderr);
X   chv = ppm_computecolorhist(pixels, cols, rows, MAXCOLORS, &ncolors);
X   if (chv == (colorhist_vector) 0)
X      pm_error(
X         "too many colors - try running the pixmap through 'ppmquant 256'",
X          0, 0, 0, 0, 0);
X   fprintf(stderr, "  Done.  %d colors found.)\n", ncolors);
X
X   /* Make a hash table for fast color lookup. */
X   cht = ppm_colorhisttocolorhash(chv, ncolors);
X
X   /* If a rgb text file was specified, read in the rgb mnemonics.
X      Does not return if fatal error occurs. */
X   if (map_rgb_names) read_rgb_names(rgb_fname, rgbn, &rgbn_max);
X
X   /* Now generate the character-pixel colormap table. */
X   gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
X            cmap, &charspp);
X
X   /* Write out the XPM header. */
X   printf("#define %s_format %d\n",          out_name, 1);
X   printf("#define %s_width  %d\n",          out_name, cols);
X   printf("#define %s_height %d\n",          out_name, rows);
X   printf("#define %s_ncolors %d\n",         out_name, ncolors);
X   printf("#define %s_chars_per_pixel %d\n", out_name, charspp);
X
X   /* Write out the ascii colormap. */
X   printf("static char *%s_colors[] = {\n", out_name);
X   for (i=0; i<ncolors; i++) {
X      printf("   \"%s\", \"%s\"", cmap[i].cixel, cmap[i].rgbname);
X      if (i != (ncolors - 1)) printf(",\n");
X      else                    printf("\n"); 
X   }     
X   printf("};\n");
X
X   /* Write out the ascii character-pixel image. */
X   printf("static char *%s_pixels[] = {\n", out_name);
X   for (row=0;  row<rows;  row++) {
X      printf("\"");
X      for (col=0, pP=pixels[row];  col<cols;  col++, pP++)
X         printf("%s", cmap[ppm_lookupcolor(cht, *pP)].cixel);
X      if (row != (rows - 1)) printf("\",\n");
X      else                   printf("\"\n"); 
X   }
X   printf("};\n");
X
X   exit(0);
X
X} /* main */
X
X/*---------------------------------------------------------------------------*/
X/* This routine reads a rgb text file.  It stores the rgb values (0->65535)
X   and the rgb mnemonics (malloc'ed) into the "rgbn" array.  Returns the
X   number of entries stored in "rgbn_max". */
Xvoid read_rgb_names(rgb_fname, rgbn, rgbn_max)
Xchar *rgb_fname;
Xrgb_names rgbn[MAX_RGBNAMES];
Xint *rgbn_max;
X{
X   FILE *rgbf;
X   int i, items, red, green, blue;
X   char line[512], name[512], *rgbname, *n, *m;
X
X   /* Open the rgb text file.  Abort if error. */
X   if ((rgbf = fopen(rgb_fname, "r")) == NULL)
X      pm_error("error opening rgb text file \"%s\"", rgb_fname, 0, 0, 0, 0);
X
X   /* Loop reading each line in the file. */
X   for (i=0;  fgets(line, sizeof(line), rgbf);  i++) {
X
X       /* Quit if rgb text file is too large. */
X       if (i == MAX_RGBNAMES) {
X          fprintf(stderr,
X             "Too many entries in rgb text file, truncated to %d entries.\n",
X             MAX_RGBNAMES);
X          fflush(stderr);
X          break;
X       }
X
X       /* Read the line.  Skip if bad. */
X       items = sscanf(line, "%d %d %d %[^\n]\n", &red, &green, &blue, name);
X       if (items != 4) {
X          fprintf(stderr, "rgb text file syntax error on line %d\n", i+1);
X          fflush(stderr);
X          i--;
X          continue;
X       }
X
X       /* Make sure rgb values are within 0->255 range.  Skip if bad. */
X       if (red   < 0 || red   > 0xFF ||
X           green < 0 || green > 0xFF ||
X           blue  < 0 || blue  > 0xFF) {
X          fprintf(stderr, "rgb value for \"%s\" out of range, ignoring it\n",
X                  name);
X          fflush(stderr);
X          i--;
X          continue;
X       }
X
X       /* Allocate memory for ascii name.  Abort if error. */
X       if (!(rgbname = (char *) malloc(strlen(name)+1)))
X          pm_error("out of memory allocating rgb name", 0, 0, 0, 0, 0);
X
X       /* Copy string to ascii name and lowercase it. */
X       for (n=name, m=rgbname; *n; n++)
X          *m++ = isupper(*n) ? tolower(*n) : *n;
X       *m = '\0';
X
X       /* Save the rgb values and ascii name in the array. */
X       rgbn[i].r = red   << 8;
X       rgbn[i].g = green << 8;
X       rgbn[i].b = blue  << 8;
X       rgbn[i].name = rgbname;
X   }
X
X   /* Return the max number of rgb names. */
X   *rgbn_max = i-1;
X
X   fclose(rgbf);
X
X} /* read_rgb_names */
X
X/*---------------------------------------------------------------------------*/
X/* Given a number and a base, (base == HIGH_CHAR-LOW_CHAR+1), this routine
X   prints the number into a malloc'ed string and returns it.  The length of
X   the string is specified by "digits".  The ascii characters of the printed
X   number range from LOW_CHAR to HIGH_CHAR.  The string is LOW_CHAR filled,
X   (e.g. if LOW_CHAR==0, HIGH_CHAR==1, digits==5, i=3, routine would return
X   the malloc'ed string "00011"). */
Xchar *gen_numstr(i, base, digits)
Xint i, base, digits;
X{
X   char *str, *p;
X   int d;
X
X   /* Allocate memory for printed number.  Abort if error. */
X   if (!(str = (char *) malloc(digits+1)))
X      pm_error("out of memory", 0, 0, 0, 0, 0);
X
X   /* Generate characters starting with least significant digit. */
X   p = str + digits;
X   *p-- = '\0'; /* nul terminate string */
X   while (p >= str) {
X      d = i % base;
X      i /= base;
X      *p-- = (char) ((int) LOW_CHAR + d);
X   }
X
X   return str;
X
X} /* gen_numstr */
X
X/*---------------------------------------------------------------------------*/
X/* This routine generates the character-pixel colormap table. */
Xvoid gen_cmap(chv, ncolors, maxval, map_rgb_names, rgbn, rgbn_max,
X              cmap, charspp)
X/* input: */
Xcolorhist_vector chv;         /* contains rgb values for colormap */
Xint       ncolors;            /* number of entries in colormap */
Xpixval    maxval;             /* largest color value, all rgb values relative
X                                 to this, (pixval == unsigned short) */
Xint       map_rgb_names;      /* == 1 if mapping rgb values to rgb mnemonics */
Xrgb_names rgbn[MAX_RGBNAMES]; /* rgb mnemonics from rgb text file */
Xint       rgbn_max;           /* number of rgb mnemonics in table */
X/* output: */
Xcixel_map cmap[MAXCOLORS];    /* pixel strings and ascii rgb colors */
Xint       *charspp;           /* characters per pixel */
X{
X   int i, j, base, cpp, mval, red, green, blue, r, g, b, matched;
X   char *str;
X
X   /* Figure out how many characters per pixel we'll be using.  Don't want
X      to be forced to link with libm.a, so using a division loop rather than
X      a log function. */
X   base = (int) HIGH_CHAR - (int) LOW_CHAR + 1;
X   for (cpp=0, j=ncolors;  j;  cpp++) j /= base;
X   *charspp = cpp;
X
X   /* Determine how many hex digits we'll be normalizing to if the rgb value
X      doesn't match a color mnemonic. */
X   mval = (int) maxval;
X   if      (mval <= 0x000F) mval = 0x000F;
X   else if (mval <= 0x00FF) mval = 0x00FF;
X   else if (mval <= 0x0FFF) mval = 0x0FFF;
X   else                     mval = 0xFFFF;
X
X   /* Generate the character-pixel string and the rgb name for each colormap
X      entry. */
X   for (i=0; i<ncolors; i++) {
X
X      /* The character-pixel string is simply a printed number in base "base"
X         where the digits of the number range from LOW_CHAR to HIGH_CHAR and
X         the printed length of the number is "cpp". */
X      cmap[i].cixel = gen_numstr(i, base, cpp);
X
X      /* Fetch the rgb value of the current colormap entry. */
X      red   = PPM_GETR(chv[i].color);
X      green = PPM_GETG(chv[i].color);
X      blue  = PPM_GETB(chv[i].color);
X
X      /* If the ppm color components are not relative to 15, 255, 4095, 65535,
X         normalize the color components here. */
X      if (mval != (int) maxval) {
X         red   = (red   * mval) / (int) maxval;
X         green = (green * mval) / (int) maxval;
X         blue  = (blue  * mval) / (int) maxval;
X      }
X
X      /* If the "-rgb <rgbfile>" option was specified, attempt to map the
X         rgb value to a color mnemonic. */
X      if (map_rgb_names) {
X
X         /* The rgb values of the color mnemonics are normalized relative
X            to 255 << 8, (i.e. 0xFF00).  [That's how the original MIT code
X            did it, really should have been "v * 65535 / 255" instead of
X            "v << 8", but have to use the same scheme here or else colors
X            won't match...]  So, if our rgb values aren't already 16-bit
X            values, need to shift left. */ 
X         if      (mval==0x000F) { r=red << 12;  g=green << 12;  b=blue << 12;
X                                  /* Special case hack for "white". */
X                                  if (0xF000 == r && r == g && g == b)
X                                     r = g = b = 0xFF00;
X                                                                             }
X         else if (mval==0x00FF) { r=red <<  8;  g=green <<  8;  b=blue <<  8;}
X         else if (mval==0x0FFF) { r=red <<  4;  g=green <<  4;  b=blue <<  4;}
X         else                   { r=red;        g=green;        b=blue;      }
X
X         /* Just perform a dumb linear search over the rgb values of the color
X            mnemonics.  One could speed things up by sorting the rgb values
X            and using a binary search, or building a hash table, etc... */
X         for (matched = 0, j=0; j <= rgbn_max; j++)
X             if (r == rgbn[j].r && g == rgbn[j].g && b == rgbn[j].b) {
X
X                /* Matched.  Allocate string, copy mnemonic, and exit. */
X                if (!(str = (char *) malloc(strlen(rgbn[i].name)+1)))
X                   pm_error("out of memory", 0, 0, 0, 0, 0);
X                strcpy(str, rgbn[j].name);
X                cmap[i].rgbname = str;
X                matched = 1;
X                break;
X             }
X         if (matched) continue;
X      }
X
X      /* Either not mapping to color mnemonics, or didn't find a match.
X         Generate an absolute #RGB value string instead. */
X      if (!(str = (char *) malloc(mval == 0x000F ?  5 :
X                                  mval == 0x00FF ?  8 :
X                                  mval == 0x0FFF ? 11 :
X                                                   14)))
X         pm_error("out of memory", 0, 0, 0, 0, 0);
X
X      sprintf(str, mval == 0x000F ? "#%X%X%X"       :
X                   mval == 0x00FF ? "#%02X%02X%02X" :
X                   mval == 0x0FFF ? "#%03X%03X%03X" :
X                                    "#%04X%04X%04X", red, green, blue);
X      cmap[i].rgbname = str;
X   }
X
X} /* gen_cmap */
END_OF_FILE
if test 14877 -ne `wc -c <'ppmtoxpm.c'`; then
    echo shar: \"'ppmtoxpm.c'\" unpacked with wrong size!
fi
# end of 'ppmtoxpm.c'
fi
echo shar: End of archive 1 \(of 1\).
cp /dev/null ark1isdone
MISSING=""
for I in 1 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have the archive.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0


