home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Voyagers to the Outer Planets 4: Saturn
/
VoyagerstotheOuterPlanetsVol4.cdr
/
software
/
decomp.for
< prev
next >
Wrap
Text File
|
1989-06-08
|
21KB
|
448 lines
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