.TH RICE local "07 November 1995" .SH NAME .B rice, unrice \- compress/uncompress a 16-bit integer FITS 2-D image file .SH SYNOPSIS .B rice file [optimize] [noise=N] [unsigned] .SH SYNOPSIS .B unrice compressed_file [unsigned] .SH DESCRIPTION .LP This pair of programs compresses or uncompresses a simple 2-D 16-bit integer FITS file. The FITS header is left in ASCII form, so that one can use .B more or one's favorite pager to examine the header. The original FITS image (compressed image) is not deleted after the program finishes creating a compressed (uncompressed) version. .B rice gives its output file the same name as the input file, but with an extension of .I ".ftz". Thus, .B rice m67.fit yields output file .I m67.ftz, and .B rice bigimage yields output file .I bigimage.ftz. .B unrice replaces the extension of its input file with .I .fts. Thus, .B unrice m67.ftz produces an output file .I m67.fts. .LP The .B noise=N option allows the user to set the number of "noise bits" used in the compression. See the section on .B ALGORITHM below for an explanation of the "noise bits". If the user does not supply a value, a default of 5 is used. .LP If the user specifies .B optimize, the program loops through values of 1,2,..,8 for "noise bits", calculating the degree of compression in each case. It prints a line to stdout for each value. If all values cause the output file to exceed the input file in size, the program prints a message to that effect and quits. Otherwise, it chooses the value which yields the smallest output file and initiates compression. .LP When .B rice is run, it inserts a line into the FITS header with keyword .B COMPRESS and value .B 'riceXX', where XX is a 2-digit, zero-padded integer which is the number of "noise bits" used in the compression. When one uncompresses the file, this keyword is kept in the header, but its value is set to .B 'none'. .SH EXAMPLES .IP rice m67 .LP Compressed file "m67", producing new compressed file .I m67.ftz. .IP rice high_23.fit unsigned .LP Treats file "high_23.fit" as a pseudo-FITS image with unsigned 16-bit integers and SIMPLE=F in its header. Compresses the image, producing a compressed file .I high_23.ftz. .IP unrice high_23.ftz unsigned .LP Uncompresses the file "high_23.ftz", producing a pseudo-FITS image with SIMPLE=F in the header. .IP rice m51 noise=3 .LP Compress the image "m51", treating the 3 lowest-order bits in each pixel as "noise". Produce an output file called .I m51.ftz. .IP rice bigimage.fts optimize .LP Step through all the possible values of "noise bits", from 1 to 8, and choose the best one. Then compress the image "bigimage.fts" with that value, producing an output file .I bigimage.ftz. If all values for "noise bits" yield files bigger than the original, produce no output file. .SH ALGORITHM .LP A variant of "Rice-compression" is used by these programs. The basic idea is to separate each pixel value into two pieces: the low-order bits, which vary strongly from pixel-to-pixel (and hence are called "noise bits"), and the high-order bits, which don't change much at all, at least in a typical astronomical image which is filled with blank sky. The "noise bits" can't be compressed much, so one writes them out verbatim; but the high-order bits DO compress, and so one can encode them into a small number of bits before writing them out. .LP There are a couple of extra ideas tacked on to this framework. First, one can measure the .B difference between each pixel and its neighbor (delta-encoding) and use that, rather than the raw pixel value. In (most) images which are not very undersampled, the differences between adjacent pixel values are smaller than their absolute values, and so can be encoded in fewer bits. Second, when one pixel really is VERY different from its neighbors (due to a cosmic ray, for example), the Rice-encoding algorithm doesn't work well -- it produces a very long string of zeroes. These programs therefore set a maximum value of the difference between adjacent pixels, and if any delta exceeds this difference, the offending pixel value is written out in its original, 16-bit integer form. .LP Now, a detailed look at the algorithm. .IP 0. Calculate the maximum number of zeroes allowed in an encoded value. This is max_zeroes = MAXDELT / (2^(noise_bits - 1)). .IP 1. Calculate delta = current pixel - previous pixel. .IP 2a. If abs(delta) >= MAXDELT, write out .br max_zeroes 0-bits .br one more 0-bit .br one 1-bit .br the pixel value, in a 16-bit integer form .IP 2b. If abs(delta) < MAXDELT, then encode the delta into an unsigned 16-bit integer "val", as follows: .br if (delta >= 0), let val = 2*delta .br if (delta < 0), let val = 2*(0 - delta) - 1. .br Now, consider the top 16-noise_bits bits in "val". If one shifts them rightwards by "noise_bits" bits, they form what is (usually) a small integer. .br Write this many 0-bits to the output. .br If this integer is 0, then write no 0-bits to the output. .br Write a single 1-bit to the output. .br Write the "noise_bits" lowest-order bits in "val" .br to the output, just as they are. .IP 3. Move to next pixel and go to Step 1. .LP To read a compressed file, .B unrice looks at the number of 0-bits present at the start of each number; the number of 0-bits tells it what sort of encoding has been done to the pixel value, and it then reads the encoded value and de-codes it appropriately. Note that the single 1-bit must always be inserted, since it is possible to write no 0-bits for an encoded pixel value. .SH BUGS .LP Can probably be speeded up quite a bit by carefully examining the code in bit-I/O routines, especially "bwrite_number" and "bread_number".