Alternative University

Computer Science

Raster Image Storage

Higher Precision Extended Range

XRH File Format 3.0

Zebra Compression

If the Compression Type integer of a Channel Block is 0x5A425200030000 (Zebra), a Zebra Compression Stream immediately follows the Compression Type integer, after which the end-of-channel-block marker follows the Zebra Compression Stream.

Figure 1:  Channel Block (image plane) of an XRH file, with Compression Type set to 0x5A425200030000, stores a Zebra Compression Stream as the Channel Block Data (yellow in this diagram).

Zebra is a simple lossless compression scheme for compressing floating point or integer numbers. It consists of splitting up number samples into bytes, and storing the corresponding bytes of the different samples together: the most significant byte of all the samples are stored together, the next most significant byte of the samples are stored together, etc.

Each such group of bytes is called a Byte Channel.

If the samples are 32-bit numbers (4 bytes per sample), then there are 4 Byte Channels; if the samples are 64-bit numbers (8 bytes per sample), then there are 8 Byte Channels, etc.

Byte Channels are stored in Big Endian format:  most significant Byte Channel first, next most significant Byte Channel next, etc.;  the least significant byte of all the image channel samples are the last Byte Channel, the second least significant byte is the second-to-last Byte Channel, etc.

Zebra Compression Stream

The Zebra Compression Stream begins with a start-of-zebra marker (ASCII string SZB\0),

followed with a 64-bit Size integer that stores the total size (number of bytes) of the entire Zebra Compression Stream (including this Size integer and the start and end markers),

followed with a 64-bit Compression Type integer (0x5A425200030000),

followed with a 32-bit integer that stores the Image Width (must equal the File Header Image Width),

followed with a 32-bit integer that stores the Image Height (same as File Header Image Height),

followed with a 32-bit integer that stores the Sample Type and Stride (must equal the Channel Block Sample Type and Stride),

followed with 32 bytes that are reserved for future use and must store zero,

followed with Byte Channels, one byte channel per byte of Sample Stride (e.g., 4 Byte Channels for 32-bit samples, 8 Byte Channels for 64-bit samples, etc.),

followed with the end-of-zebra marker (ASCII string EZB\0) that marks the end of the Zebra stream.

Figure 2:  Zebra Compression Stream (shown yellow and light brown) as the Data of a Channel Block in an XRH 3.0 file. The Byte Channels are depicted light brown. The byte offset (number of bytes) from the beginning of the Zebra Compression Stream to the beginning of the Byte Channels is 64 bytes.

The Zebra Compression Stream is self-contained and may be used in any file format (not just in an XRH file).

The first four bytes of a Zebra Compression Stream store the value 0x535A4200 (ASCII string SZB\0) which marks the start-of-zebra.

Start of Zebra Stream Marker:  SZB\0

The last 4 bytes of a Zebra Compression Stream store the value 0x455A4200 (ASCII string EZB\0) which marks the end-of-zebra (the last 4 bytes of the Zebra Compression Stream).

End of Zebra Stream Marker:  EZB\0

Sample Type and Stride

Sample Type and Stride is a 4-byte integer storing the type of sample in the upper two bytes (must be 1 for floating point, or 2 for unsigned integer), and storing the byte length (Sample Stride) of each sample in the lower two bytes.

If the Type is floating point (Sample Type 1), then Sample Stride could be 3, 4 or 8 (for Float24, Float32 or Float64 respectively).

If the Type is unsigned integer (Sample Type 2), then Sample Stride could be 1 through 8, for a one-byte integer, two-byte integer, etc., up to 8 bytes per unsigned integer.

Byte Channel

The data bytes of a Byte Channel are compressed using ZST (a lossless compressor, also called “Zstandard”).

Each Byte Channel consists of a start-of-byte-channel marker (ASCII string SBC\0),

followed with a 64-bit integer that specifies the size of the ZST code stream that stores the data bytes of the Byte Channel,

followed with that ZST code stream (the compressed data generated by ZST),

followed with an end-of-byte-channel marker (ASCII string EBC\0).

Figure 3:  Byte Channel.

The first four bytes of a Byte Channel store the value 0x53424300 (ASCII string SBC\0) which marks the start-of-byte-channel.

Start of Byte Channel Marker:  SBC\0

The last 4 bytes of a Byte Channel store the value 0x45424300 (ASCII string EBC\0) which marks the end-of-byte-channel.

End of Byte Channel Marker:  EBC\0

The ZST code stream of each Byte Channel is a compressed byte stream that when uncompressed provides the sample bytes of the Byte Channel in raster order.

For example, to reconstruct the 5th sample of a Channel Block: the 5th data byte of the first Byte Channel becomes the high order byte of the 5th sample of the Channel Block, the 5th data byte of the second Byte Channel becomes the next most significant byte of the 5th sample of the Channel Block, etc.

Default Value

If all of the bytes of a Byte Channel are the same, then a Default Value (one byte) may be stored that specifies the value of all the bytes of the Byte Channel. In that case, one (1) is stored in Size of ZST Code Stream (see Figure 3 above) and the single-byte Default Value is stored in place of the ZST Code Stream (immediately after the Size of ZST Code Stream, without storing a ZST Code Stream), after which the end-of-byte-channel marker immediately follows the single-byte Default Value.

IEEE Floating Point Samples

If the samples of the image channel are IEEE floating point numbers (Float32 or Float64), the samples (numbers) are filtered before splitting up the samples into the Byte Channels that will be compressed, to map the IEEE floating point numbers into quasi-integer sequences for better compressibility.

This filtering is only for IEEE numbers (Float32 and Float64). To split and compress Float32 or Float64 numbers without this filtering, or with your own custom filtering, simply set the Sample Type to unsigned integer (2) instead of floating point (1).

If the samples are Float32 or Float64 (Sample Type and Stride 0x10004 or 0x10008 respectively), each sample is converted from IEEE floating point to unsigned integer, using a mapping that was developed by Lindstrom and Isenburg. To perform this mapping, first copy the floating point bit sequence of each sample directly into integer memory of the same byte length (bitwise bijection), then toggle the leading sign bit if positive, or toggle all bits if negative. The mapped samples (unsigned integers) are then split up into Byte Channels, and each Byte Channel is sent to the ZST encoder.

For data retrieval of Float32 or Float64 samples, after uncompressing the Byte Channels, the Byte Channels are merged (shuffled) back into unsigned integers. The unsigned integers are then inverse mapped (reverse filtered) back to the original IEEE floating point numbers.

New Version Available

Newer XRH version recommended for new applications:

XRH version 4.0

< Previous Page: Channels    
    Next: SZMOD Compression >

XRH 3.0 File Format

Page 1 : 
Page 2 : 
Page 3 : 
Page 4 : 
Page 5 : 
Page 6 : 
Page 7 : 
Page 8 : 
Page 9 : 
Page 10 : 
File Layout & Header
Custom Properties
Channel Names
Zebra Compression (this page)
SZMOD Compression
Color Transformations
Sample Files