Note:  This is somewhat obsolete, but may be of interest to any one who
feels like hacking 'xv' 

   --jhb, 8/31/90
------------------------------------------------------------------------------


  general concepts:

  1. main program should do command line parsing, call a LOAD routine of some
     sort, and display the result.  It will sit in a loop parsing keyboard
     commands until a file-changing command is given.

     Keyboard Commands:
       Q:         quit
       CR,SP:     next file
       BS,DEL:    previous file
       ,:         shrink picture 10%
       .:         grow picture 10%
       <:         shrink picture by factor of 2
       >:         grow picture by factor of 2
       N:         home.  (Show picture at normal size)
       M:         max.   (grow picture to size of screen)
       C:         crop picture
       U:         uncrop picture
       I:         info box
       4:         4x3-ify the picture

     Mouse Commands:
       Button1:  lets you draw a cropping rectangle
       Button2:  
       Button3:  

  2. LOAD routines:  given a file name.  They'll do optional suffix-tacking-on
     if they wish to.  They will do whatever needs to be done to the picture
     to get it into an 8-plane image with a colormap.  

     The load routines will return several things (in global variables):
     pWIDE, pHIGH, a pWIDE*pHIGH array of pixels (pic) (one byte per), 0,0 is
     the top-left corner of the image, a colormap (three 256-element arrays
     of bytes, for r,g and b (called 'r', 'g', and 'b', oddly enough)

     load routines will return '0' if successful, a slew of non-zero things if
     not 

  3. A common routine for colormap sort/compression (SortColormap()).
     the colormap will be compressed.  That is, if only 37 colors
     in the 256-element colormap are used, they will be the first 37 entries
     in the colormap.  This way, the display portion of the code won't waste
     resources allocating unused colors.  This routine will also modify the
     PIC array accordingly.  

     This routine calculates 'numcols'.

     Thought:  have the colormap compression algorithm sort the colormap
     so that the most-used color is first, and the other colors are in order
     of decreasing distance from the first color.  (That is, the second color
     will be the 'most unlike' the first color, the third color will be the
     'second most unlike' the first color, and so on.)

     Justification:  Since we allocate colors in the order they're stored
     in the colormap, it'd probably be better to get all the major colors
     first, and then pick up the subtle shade differences if there's any
     colors left.

     Improved sort algorithm.  Slower, but possibly more desirable.
     (besides, the speed of this routine is not likely to be a problem)
     Problem with previous algorithm:  a picture with a blue sky, a green
     ground, and a dark blue car.  The previous algorithm will allocate the
     sky blue (most used), and then try to allocate ALL THE SHADES OF GREEN
     before trying for the dark blue.  Suboptimal.

     Solution, find the most used color, put it first in the cmap.
     find the color the greatest distance from that, put it second in the cmap
     NOW, find the color that is farthest away from BOTH of those colors
     (that is, for each color left in the cmap, compute the min of it's 
     distances from the ones that have been allocated already.  Then, take the
     one that's got the largest min distance and allocate it.  continue)

     Still more modification to sort algorithm: The modified algorithm 
     described above is a good thing, but runs on the order O(3).  Practical
     upshot is that doing it for all 256 colors in a picture takes far too
     long.  New idea: run that algorithm for the first 32 colors (an
     arbitrary smallish number, and plenty fast), then sort the remaining 
     colors in order of decreasing use.

  4. A common routine for 24-bit RGB -> 8 bit colormap conversion.
     Since several different data formats might want to do this, this
     routine will exist for their calling pleasure.  Input will be a wide*high
     * 3 byte array of pixels, 3 bytes per (in order R, G, and B).  The
     procedure will do the 'thing' and store results in all the global
     variables that the load routines are supposed to return.  A load routine
     should be able to just call this routine (once it's built the 24-bit
     image) and return.  

     Input will also be number of colors to use.  That is, while it will still
     produce a 8-bit PIC array, you might want it to only use 16 colors,
     rather than 256.  (Say, if you're on a 4 bit display).  The reason you'd
     want it to do this is that it'll probably do a better job of creating a
     16-color picture than the DISPLAY routine would (if it was handed a 256
     color picture and asked to display it on a 16-color display).
     
     The 24to8 routine (Conv24to8) will be clever, and if it knows you're
     displaying on a monochrome screen (or -mono is set) or that you're
     displaying on a 1-bit display (or -nc 0), it will just return an
     8-bit greyscale version of the picture.  This is because running the
     full 24-bit RGB to 8-bit pseudocolor conversion takes a long time,
     and shouldn't be done if not necessary.

  5. Display routines.  Do whatever is necessary to show PIC on display.
     This includes things like building an Ximage in the correct depth,
     expanding/compressing size of image

     There will be a AllocColors() routine that will take the desired colormap
     and see what it can do, based on the type of display you're using.
     This routine will be called once per picture, before doing Resize()
     (As Resize() calls CreateXImage()...)
     
     if (based on 'theVisual', or '-mono') we appear to be running on a 
     GrayScale or StaticGray display, this algorithm will FIRST run through
     the desired colormap (the 'epic' colormap) and replace the r,g,b values
     for each entry with the corresponding intensity value (I=(.3r+.5g+.2b)/3)
     This way, pictures will be correctly displayed on mono screens.

     Algorithm:  for >1 bit displays (ie, greyscale/color), alloc colors in
     the X colormap in the order that the SortColormap routine returned.
     Colors that couldn't be allocated are matched to the closest colors in
     the global X colormap, or the just the colors allocated (based on the
     value of 'noglob')

     the 'cols[]' array will hold the mapping between 'epic' colors and X
     colors.  (ie, color #37 in epic and the epic colormap will correspond to 
     color # cols[37] in the X image and the X colormap)

     the 'freecols[]' array (and nfcols, the length of it) will hold the X
     pixel values of the colors that were allocated, so that they may be
     later un-allocated.  Also, it will NOT have duplicate entries in it.
     (ie, if allocating (15,15,15) and (16,16,16) both return pixel #2,
     pixel #2 will be in freecols ONCE.)

     More algorithm:  for 1 bit displays there's only going to be two
     colors, 'black' and 'white'.  (What the two colors actually look like
     on the screen (ie, maybe it's blue and white, or black and green), is
     not important.  So what we do here is, rather than try to allocate any
     colors (it'd probably fail anyhow), run the Floyd Steinberg dithering
     algorithm over the picture, and just use 'black' and 'white'

  6. There's several variables that seem to do the same thing.  They don't.
     Here's what they do:

       pic, pWIDE, pHIGH:   This is the 8-bit image ret. by the load routine

       cpic, cWIDE, cHIGH,
       cXOFF, cYOFF:        This is the cropped version of pic.  If there is
                            no cropping going on, it will point to pic.
			    cXOFF and cYOFF specify the offset from 0,0 of 
			    the original pic.  (ie, pixel cXOFF,cYOFF in the
			    original picture will be at 0,0 in the cpic image

       epic, eWIDE, eHIGH:  This is another 8-bit image.  This is an expanded/
                            compressed version of cpic.  Generated in the
			    Resize() function.  When there is no expansion
			    (ie, eWIDE=pWIDE, eHIGH=pHIGH) epic *will* point
			    to 'cpic'.  This way the X conversion routines
			    can simply use epic, eWIDE, and eHIGH.

       theImage:  This is an Ximage version of epic.  It'll be in whatever
                  depth/format is deemed appropriate for the X display.
		  It is generated from epic after epic has been Resize()'d
		  It's generated in the function CreateXImage()

     What happens to a picture from loading to display:
       picture is loaded in some native format  
           (local to LOAD routine)
       picture is converted to 8-bit colortable routine  (pic)
           (in LOAD routine.  native format data is thrown away)
       LOOP
         'pic' is cropped, if desired.  cpic points to picture data
	 'cpic' is expanded, if desired.  epic points to data
	 'epic' is converted to theImage 
             (an X Format in the depth of the screen)
       REPEAT


  7. It should be noted that the several functions break on machines where
     'int' is <32 bits.  These machines are wrong.

  8. added a 'perfect' mode, where it installs it's own colormap

  9. further thoughts...
     add an ability to display multiple iconified-files at once (has to
     be done in 'mono' mode... (contact sheets, Hagan calls them)

 10. color usage.  six colors can be specified via command-line/resource
     database.  They are white,black, foreground,background, and 
     info.foreground,info.background.  white and black are only used in
     the 1-bit dithering routines (FloydDitherize8 and FloydDitherize1)

     foreground,background specify the colors of the window/frame
     info.{fore,back}ground specifies the colors of the info box 
