      SUBROUTINE DECOMPRESS (IBUF, OBUF, NIN, NOUT)
C**********************************************************************
C_TITLE DECOMPRESS - Decompresses image lines stored in a compressed 
C                    format. (alternate fortran souce code which will
C                    run on a SUN workstation)
C
C_ARGS
      INTEGER*4       NIN             
C                                       Input - number of bytes in
C                                       the compressed buffer.
      INTEGER*4       NOUT            
C                                       Input - known number of bytes
C                                       in decompressed output line
      CHARACTER       IBUF(1)         
C                                       Input - line of data to 
C                                       decompress. The first byte is 
C                                       the actual pixel value, the 
C                                       rest of the array is the bit 
C                                       stream of coded "first
C                                       difference" values.
      CHARACTER       OBUF(1)         
C                                       Output - decompressed line of 
C                                       data. The routine assumes 
C                                       original image composed of 8 
C                                       bit pixels.  This is the 
C                                       restored image line - 
C                                       compression and first 
C                                       differences undone - of the 
C                                       line passed in ibuf.
C
C_DESC  This routine decompresses Huffman encoded compressed data.  
C       (Huffman compression encoding can be found in any standard 
C       data compression reference.  One such book is: "Data 
C       Compression, Techniques and Applications, Hardware and 
C       Software Considerations" by Gilbert Held, John Wiley & Sons, 
C       publishers.)  Huffman coding uses variable number of bits to 
C       encode different values of the original data.  The compression 
C       results because the most frequently occurring values have
C       the smaller number of bits for their codes.
C
C       The routine, used in conjuction with DECMPINIT,  provides 
C       a common data base from which to call the processing
C       subroutines. DECMPINIT builds the Huffman tree from the first-
C       difference histogram and is called only once per image.  
C       DECOMPRESS processes one compressed input line per call and 
C       returns it completely restored.
C
C_CALLS This routine calls two subroutines DCMPRS and HUFFTREE.
C
C
C_LIMS  The fortran code found in the DECOMPS.FOR file was adapted
C       to run on a SUN work station using fortran version 3.4
C
C_HIST  DEC87, DMcMacken, ISD, USGS, Flagstaff, Original version
C
C_END
C***********************************************************************
      INTEGER*2       TREE(5,1024)    
C                                       Huffman tree
      INTEGER*2       VALUE
      INTEGER*2       RIGHT
      INTEGER*2       LEFT
      INTEGER*2       PARENT
      INTEGER*2       BRANCH
      PARAMETER       (VALUE=1, RIGHT=2, LEFT=3, PARENT=4, BRANCH=5)
      COMMON /DECOM/ TREE
C***********************************************************************
C Decompress an input line
C***********************************************************************
      CALL DCMPRS(IBUF, OBUF, NIN, NOUT, TREE)
      RETURN
      END
      SUBROUTINE DECMPINIT(HIST)
C***********************************************************************
C_TITLE DECMPINIT - initialize the decompression TREE from the first
C                   difference histogram
C_ARGS
      INTEGER*4       HIST(512)       
C                                       Input, difference histogram 
C                                       table. The histogram of the 
C                                       whole image after first 
C                                       difference has been run on 
C                                       each line.  In a "first 
C                                       difference" line the first pixel
C                                       retains its actual value; all 
C                                       other pixels are obtained by 
C                                       subtracting the actual value of 
C                                       the pixel from the actual value 
C                                       of the preceding pixel and 
C                                       adding 256 to provide a 
C                                       positive number.  The i-th 
C                                       element of the array HIST 
C                                       should be the number of pixels 
C                                       in the image with value i.
C
C Some computer hardware systems may need to swap the byte order
C of the 32-bit words which make up the first-difference historgram.  
C The histogram  is configured on the CDROM in "least significant byte 
C first" order. This is the order for integer values used by VAX and 
C IBM PC computer systems. Users of other computer architectures
C (IBM Mainframes, MacIntosh, SUN, and Apollo) will need to swap
C byte pairs 1 and 4, and 2 and 3 before passing the histogram to
C the DECMPINIT subroutine.
C                                     
C
C_DESC This routine initializes the Huffman tree using the first
C      difference histogram passed by the calling program. This 
C      subroutine must be called before the DECOMPRESS subroutine
C      can be utilized.
C
C_HIST DEC87, DMcMacken, ISD, USGS, Flagstaff, Original Version
C
C_END
C***********************************************************************
      INTEGER*2       TREE(5,1024)    
      COMMON /DECOM/ TREE

      DO 10 I = 1,1024
      DO 20 J = 1,5
      TREE(J,I) = 0
   20 CONTINUE
   10 CONTINUE
      CALL HUFFTREE (HIST, TREE)
      RETURN
      END
      SUBROUTINE HUFFTREE(HIST, TREE)
C**********************************************************************
C_TITLE HUFFTREE creates a Huffman code tree from input histogram
C
C_ARGS
      INTEGER*4       HIST(512)               
C                                       In - image histogram
      INTEGER*2       TREE(5,1024)            
C                                       Out - Huffman code tree
C
C_DESC  This routine creates a Huffman code tree from the input first
C       difference histogram of an image.  It starts by making all valid
C       (non-zero) densities for the image leaf nodes.  These are sorted
C       in increasing order by histogram frequency.  The two nodes with
C       smallest frequencies are connected by branches to a new node 
C       which is given a frequency equal to the sum of the two 
C       combining nodes. The new node takes the place of the two nodes 
C       and the frequency list is resorted.  The process is repeated 
C       until the frequency set is reduced to one node.  The tree 
C       consists of a double dimensioned array whose first dimension 
C       gives five parameters for each node. The first parameter gives 
C       a value to the node.  This is a density value for leaf nodes 
C       and a -1 for all others.  The second parameter is a pointer to 
C       the next node on the right branch from this node. The third 
C       points to the node on the left branch.  The fourth points
C       to the parent node from which this node branches.  The fifth
C       parameter notes whether this node is on the right or left 
C       branch of the parent node.
C
C_CALLS This routine calls the specially provided sort routine
C               SORTFREQ.
C
C_HIST  Fall86, DMcMacken, ISD, USGS, Flagstaff, Original version
C
C_END
C**********************************************************************
      INTEGER*4       FREQLIST(512)          
C                                       Histogramm frequency list
      INTEGER*2       NODELIST(512)          
C                                       Tree node list
      INTEGER*2       VALUE
      INTEGER*2       RIGHT
      INTEGER*2       LEFT
      INTEGER*2       PARENT
      INTEGER*2       BRANCH
      PARAMETER       (VALUE=1,RIGHT=2,LEFT=3,PARENT=4,BRANCH=5)
      INTEGER*4       NUMNODES               
C                                       Node counter
      INTEGER*4       I                       
C                                       Do loop index
      INTEGER*4       PTR                     
C                                       Current node pointer
      INTEGER*4       NUMFREQ                
C                                       # non-zero frequencies
      INTEGER*4       INDEX                   
C                                       Frequency list pointer
C**********************************************************************
C Create leaf nodes, and pointer tables
C**********************************************************************
      NUMNODES = 0
      DO 10 I = 1, 512
         FREQLIST(I) = HIST(I)
         NUMNODES = NUMNODES + 1
         PTR = NUMNODES
         NODELIST(I) = PTR
         TREE(VALUE, PTR) = I
         TREE(PARENT, PTR) = 0
   10 CONTINUE
C**********************************************************************
C Make sure the last element is always 0. For the first difference
C histogram, there can only be 511 values.
C**********************************************************************
      FREQLIST(512) = 0
C**********************************************************************
C Sort freqlist in increasing order; skip over zero frequencies
C**********************************************************************
      NUMFREQ = 512
      CALL SORTFREQ (FREQLIST, NODELIST, NUMFREQ)
      INDEX = 1
   20 IF (FREQLIST(INDEX) .EQ. 0) THEN
         INDEX = INDEX + 1
         GOTO 20
      ENDIF

      NUMFREQ = NUMFREQ - INDEX + 1
   30 IF (NUMFREQ .GT. 1) THEN
         NUMNODES = NUMNODES + 1
         PTR = NUMNODES
         TREE(RIGHT, PTR) = NODELIST(INDEX)
         TREE(LEFT, PTR) = NODELIST(INDEX+1)
         TREE(PARENT, TREE(RIGHT, PTR)) = PTR
         TREE(BRANCH, TREE(RIGHT, PTR)) = RIGHT
         TREE(PARENT, TREE(LEFT, PTR)) = PTR
         TREE(BRANCH, TREE(LEFT, PTR)) = LEFT
         TREE(VALUE, PTR) = -1

         FREQLIST(INDEX + 1) = FREQLIST(INDEX)
     1   + FREQLIST(INDEX + 1)
         NODELIST(INDEX + 1) = PTR
         FREQLIST(INDEX) = 0
         INDEX = INDEX + 1
         NUMFREQ = NUMFREQ - 1
         CALL SORTFREQ (FREQLIST(INDEX), NODELIST(INDEX),
     1   NUMFREQ)
         GOTO 30
      ENDIF
      TREE(VALUE, 1024) = NUMNODES
      RETURN
      END
      SUBROUTINE SORTFREQ(FREQLIST, NODELIST, NUMFREQ)
C**********************************************************************
C_TITLE SORTFREQ sorts frequency and node lists in increasing freq. 
C       order.
C
C_ARGS
      INTEGER*4       FREQLIST(512)          
C                                       input - frequency list
      INTEGER*2       NODELIST(512)          
C                                       input - node list
      INTEGER*4       NUMFREQ                
C                                       input - # values in freq list
C
C_DESC  This routine uses an insertion sort to reorder a frequency list
C       in order of increasing frequency.  The corresponding elements
C       of the node list are reordered to maintain correspondence.
C
C_HIST  Fall86, DMcMacken, ISD, USGS, Flagstaff, Original version
C
C_END
C***********************************************************************
      INTEGER*4       I                       
C                                       Do loop index
      INTEGER*4       J                       
C                                       List position pointer
      INTEGER*4       TEMP1                   
C                                       Temporary storage - freq.
      INTEGER*4       TEMP2                   
C                                       Temporary storage - node
C***********************************************************************
C Save current element - starting with second - in temporary
C storage.  Compare with all elements in first part of list -
C moving each up one element - until  element is larger.
C Insert current element at this point in list
C***********************************************************************
      DO 20 I = 2, NUMFREQ
         TEMP1 = FREQLIST(I)
         TEMP2 = NODELIST(I)
         J = I
   10    IF (FREQLIST(J-1) .GT. TEMP1) THEN
            FREQLIST(J) = FREQLIST(J-1)
            NODELIST(J) = NODELIST(J-1)
            J = J - 1
            IF (J .GT. 1) GOTO 10
         ENDIF
         FREQLIST(J) = TEMP1
         NODELIST(J) = TEMP2
   20 CONTINUE
      RETURN
      END
      SUBROUTINE DCMPRS(IBUF, OBUF, NIN, NOUT, TREE)
C***********************************************************************
C_TITLE DCMPRS decompresses Huffman coded compressed image lines
C       (Remove this subroutine from the source code if you are
C       planning to use the VAX/VMS DCMPRS.MAR macro routine in
C       place of this fortran code. The DCMPRS macro version is more 
C       than twice as fast as the fortran version)
C
C_ARGS
      INTEGER*4       NIN             
C                                       Input, # bytes in input buffer
      INTEGER*4       NOUT            
C                                       Input, # bytes in output line
      INTEGER*2       TREE(5,1024)    
C                                       Input, Huffman code tree
      CHARACTER       IBUF(1)         
C                                       Input, compressed data buffer
      CHARACTER       OBUF(1)         
C                                       Output, decompressed line
C
C_DESC  This subroutine follows a path from the root of the Huffman tree
C       to one of its leaves.  The choice at each branch is decided by
C       the successive bits of the compressed input stream, left for 1,
C       right for 0.  Only leaf nodes have a value other than -1.  The
C       routine traces a path through the tree until it finds a node 
C       with a value not equal to -1 (a leaf node).  The value at the 
C       leaf node is subtracted from the preceding pixel value plus 256 
C       to restore the the umcompressed pixel.  This algorithm is then 
C       repeated until the entire line has been processed.
C
C_CALLS This routine uses the VAX/VMS implicit function
C       BTEST (VAR, IBIT) to test whether the bit number IBIT is set 
C       in the variable VAR. A fortran version of this routine
C       is available for BTEST.
C
C_HIST  DEC86, DMcMacken, ISD, USGS, Flagstaff, Original version
C
C_END
C**********************************************************************
      INTEGER*4       PTR             
C                                       Pointer to position in tree
      INTEGER*4       K               
C                                       Do loop index
      INTEGER*4       BIT             
C                                       Pointer to current bit in word
      INTEGER*4       NBYTE           
C                                       Counter, # bytes decompressed
      INTEGER*4       TEMP            
C                                       Working variable
      INTEGER*2       VALUE           
C                                       Value index in tree
      INTEGER*2       RIGHT           
C                                       Right branch index in tree
      INTEGER*2       LEFT            
C                                       Left branch index in tree
      INTEGER*2       PARENT          
C                                       Parent pointer index in tree
      INTEGER*2       BRANCH          
C                                       Parent branch index in tree
      PARAMETER       (VALUE=1, RIGHT=2, LEFT=3, PARENT=4, BRANCH=5)
C
      INTEGER*2       DN              
C                                       Current density value
      INTEGER*2       DNL             
C                                       Last density value
      LOGICAL       END             
C                                       End of line flag
      LOGICAL       BTEST
C
C**********************************************************************
C Start at root of tree
C**********************************************************************
      PTR = TREE(1,1024)
C**********************************************************************
C Just copy first byte it is uncompressed.
C**********************************************************************
      OBUF(1) = IBUF(1)
C**********************************************************************
C Count starts here
C**********************************************************************
      NBYTE = 1
C**********************************************************************
C Initialize current and last density values
C**********************************************************************
      DN = ICHAR(IBUF(1))
      IF (DN.LT.0) DN = 256 + DN
      DNL = DN
C**********************************************************************
C Reset end of line flag
C**********************************************************************
      END = .FALSE.
C**********************************************************************
C K points to current input byte loop is done when k exceeds # 
C input bytes.
C**********************************************************************
      K = 2
      IF (K .GT. NIN) END = .TRUE.
C**********************************************************************
C This is the processing loop
C**********************************************************************
   10 IF (.NOT. END) THEN
         TEMP = ICHAR(IBUF(K))
         BIT = 7                         
   20    IF (BIT .GE. 0 .AND. .NOT. END) THEN 
            IF (BTEST(TEMP, BIT)) THEN
               PTR = TREE(LEFT, PTR)
            ELSE
               PTR = TREE(RIGHT, PTR)
            ENDIF
C**********************************************************************
C We are at end leaf when value is not -1
C**********************************************************************
            IF (TREE(VALUE, PTR) .NE. -1) THEN
C**********************************************************************
C Compute value of pixel, reset or increment pointers and counters
C**********************************************************************
               DN = TREE(VALUE, PTR)
               DN = DNL - DN + 256
               DNL = DN
               NBYTE = NBYTE + 1
               OBUF(NBYTE) = CHAR(DN)
               PTR = TREE(1, 1024)
               IF (NBYTE .EQ. NOUT) END = .TRUE.
            ENDIF
C**********************************************************************
C Process next bit in byte
C**********************************************************************
            BIT = BIT - 1
            GOTO 20
         ENDIF
C**********************************************************************
C Set index to next input byte
C**********************************************************************
         K = K + 1
         IF (K .GT. NIN) END = .TRUE.    
         GOTO 10
      ENDIF
C**********************************************************************
C Go back to caller with decompressed line
C**********************************************************************
      RETURN
      END
