SUBROUTINE DECOMPRESS (IBUF, OBUF, NIN, NOUT) C********************************************************************** C_TITLE DECOMPRESS - Decompresses image lines stored in a compressed C format. 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 DCMPRS is provided in two versions, one FORTRAN, the other VAX C MACRO. The FORTRAN version is for compatability on non-VAX C systems so that the algorithm might be more easily C understood, while the MACRO version is for speed when running C on a VAX. If you intend to use the macro version of C the DCMPRS routine, then remove the fortran routine C of the same name from the DECOMP source file before building C the system. C C An alternate version of the decompression software can be C found in the DECOMPS.FOR file. DECOMPS.FOR has been adapted C for the SUN fortran compiler version 3.4. C C_LIMS The routines have been tested using version 4.8-276 of C the VAX/VMS fortran compiler and versions V3.31 and V4.01 of C the Microsoft fortran compilers. The hardware used in testing C the software include a VAX-750, an IBM PC/XT and a DEC RAINBOW C PC. Modifications of the code may be required for other C computer systems. See the DECOMPS.FOR file if you have C software which will run on a SUN workstation. 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 buffer CHARACTER TEMPB C Byte working buffer 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) INTEGER*2 DN C Current density value INTEGER*2 DNL C Last density value CHARACTER DNB C Byte addressed density value LOGICAL END C End of line flag LOGICAL BTEST C EQUIVALENCE (DN, DNB), (TEMP, TEMPB) 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 = 0 DNB = IBUF(1) 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 TEMPB = 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) = DNB 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