PackBits is a fast, simple
lossless compression
Lossless compression is a class of data compression that allows the original data to be perfectly reconstructed from the compressed data with no loss of information. Lossless compression is possible because most real-world data exhibits statistic ...
scheme for
run-length encoding
Run-length encoding (RLE) is a form of lossless data compression in which ''runs'' of data (sequences in which the same data value occurs in many consecutive data elements) are stored as a single data value and count, rather than as the original ...
of data.
Apple
An apple is an edible fruit produced by an apple tree (''Malus domestica''). Apple fruit tree, trees are agriculture, cultivated worldwide and are the most widely grown species in the genus ''Malus''. The tree originated in Central Asia, wh ...
introduced the PackBits format with the release of
MacPaint
MacPaint is a raster graphics editor developed by Apple Computer and released with the original Macintosh personal computer on January 24, 1984. It was sold separately for US$195 with its word processing counterpart, MacWrite. MacPaint was nota ...
on the
Macintosh
The Mac (known as Macintosh until 1999) is a family of personal computers designed and marketed by Apple Inc., Apple Inc. Macs are known for their ease of use and minimalist designs, and are popular among students, creative professionals, and ...
computer. This compression scheme can be used in
TIFF
Tag Image File Format, abbreviated TIFF or TIF, is an image file format for storing raster graphics images, popular among graphic artists, the publishing industry, and photographers. TIFF is widely supported by scanning, faxing, word processin ...
files.
TGA files also use this RLE compression scheme, but treats data stream as pixels instead of bytes.
A PackBits data stream consists of packets with a one-byte header followed by data. The header is a signed byte; the data can be signed, unsigned, or packed (such as MacPaint pixels).
In the following table, ''n'' is the value of the header byte as a signed integer.
Note that interpreting 0 as positive or negative makes no difference in the output. Runs of two bytes adjacent to non-runs are typically written as literal data. There is no way based on the PackBits data to determine the end of the data stream; that is to say, one must already know the size of the compressed or uncompressed data before reading a PackBits data stream to know where it ends.
Apple Computer (see the external link) provides this short example of packed data:
FE AA 02 80 00 2A FD AA 03 80 00 2A 22 F7 AA
The following code, written in
Microsoft VBA, unpacks the data:
Sub UnpackBitsDemo()
Dim File As Variant
Dim MyOutput As String
Dim Count As Long
Dim i As Long, j As Long
File = "FE AA 02 80 00 2A FD AA 03 80 00 2A 22 F7 AA"
File = Split(File, " ")
For i = LBound(File) To UBound(File)
Count = Application.WorksheetFunction.Hex2Dec(File(i))
Select Case Count
Case Is >= 128
Count = 256 - Count 'Two's Complement
For j = 0 To Count 'zero-based
MyOutput = MyOutput & File(i + 1) & " "
Next j
i = i + 1 'Adjust the pointer
Case Else
For j = 0 To Count 'zero-based
MyOutput = MyOutput & File(i + j + 1) & " "
Next j
i = i + j 'Adjust the pointer
End Select
Next i
Debug.Print MyOutput
'AA AA AA 80 00 2A AA AA AA AA 80 00 2A 22 AA AA AA AA AA AA AA AA AA AA
End Sub
The same implementation in
JavaScript
JavaScript (), often abbreviated as JS, is a programming language that is one of the core technologies of the World Wide Web, alongside HTML and CSS. As of 2022, 98% of Website, websites use JavaScript on the Client (computing), client side ...
:
/**
* Helper functions to create readable input and output
*
* Also, see this fiddle for interactive PackBits decoder:
* https://jsfiddle.net/y13xkh65/3/
*/
function str2hex (str)
function hex2str (hex)
/**
* PackBits unpack function
*
* @param data
* @return
*/
function unpackBits (data) {
var output = '',
i = 0;
while (i < data.length) {
var hex = data.charCodeAt(i);
if (hex 128) {
// Do nothing, nop
}
else if (hex > 128) {
// This is a repeated byte
hex = 256 - hex;
for (var j = 0; j <= hex; ++j) {
output += data.charAt(i + 1);
}
++i;
}
else {
// These are literal bytes
for (var j = 0; j <= hex; ++j) {
output += data.charAt(i + j + 1);
}
i += j;
}
++i;
}
return output;
}
var original = 'FE AA 02 80 00 2A FD AA 03 80 00 2A 22 F7 AA',
data = unpackBits(hex2str(original));
// Output is: AA AA AA 80 00 2A AA AA AA AA 80 00 2A 22 AA AA AA AA AA AA AA AA AA AA
console.log(str2hex(data));
External links
Apple webpage describing the PackBits formattaken from the https://www.fileformat.info site with permission from Corion.net
the article on site https://www.universal-document-converter.com also describes the algorithm.
Lossless compression algorithms