This articledoes notcite anysources. Please helpimprove this article byadding citations to reliable sources. Unsourced material may be challenged andremoved. Find sources: "PackBits" – news ·newspapers ·books ·scholar ·JSTOR(October 2011) (Learn how and when to remove this message) |
PackBits is a fast, simplelossless compression scheme forrun-length encoding of data.
Apple introduced the PackBits format with the release ofMacPaint on theMacintosh computer. This compression scheme can be used inTIFF files.TGA files also use this RLE compression scheme, but treats data stream as pixels instead of bytes. Packbit compression was also used inILBM files.
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.
| Header byte | Data following the header byte |
|---|---|
| 0 to 127 | (1 +n)literal bytes of data |
| −1 to −127 | One byte of data, repeated (1 −n) times in the decompressed output |
| −128 | No operation (skip and treat next byte as a header byte) |
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 inMicrosoft VBA, unpacks the data:
SubUnpackBitsDemo()DimFileAsVariantDimMyOutputAsStringDimCountAsLongDimiAsLong,jAsLongFile="FE AA 02 80 00 2A FD AA 03 80 00 2A 22 F7 AA"File=Split(File," ")Fori=LBound(File)ToUBound(File)Count=Application.WorksheetFunction.Hex2Dec(File(i))SelectCaseCountCaseIs>=128Count=256-Count'Two's ComplementForj=0ToCount'zero-basedMyOutput=MyOutput&File(i+1)&" "Nextji=i+1'Adjust the pointerCaseElseForj=0ToCount'zero-basedMyOutput=MyOutput&File(i+j+1)&" "Nextji=i+j'Adjust the pointerEndSelectNextiDebug.PrintMyOutput'AA AA AA 80 00 2A AA AA AA AA 80 00 2A 22 AA AA AA AA AA AA AA AA AA AAEndSub
The same implementation inJavaScript:
/** * Helper functions to create readable input and output * * Also, see this fiddle for interactive PackBits decoder: * https://jsfiddle.net/y13xkh65/3/ */functionstr2hex(str){returnstr.split('').map(function(char){varvalue=char.charCodeAt(0);return((value<16?'0':'')+value.toString(16)).toUpperCase();}).join(' ');}functionhex2str(hex){returnhex.split(' ').map(function(string){returnString.fromCharCode(parseInt(string,16));}).join('');}/** * PackBits unpack function * * @param {String} data * @return {String} */functionunpackBits(data){varoutput='',i=0;while(i<data.length){varhex=data.charCodeAt(i);if(hex==128){// Do nothing, nop}elseif(hex>128){// This is a repeated bytehex=256-hex;for(varj=0;j<=hex;++j){output+=data.charAt(i+1);}++i;}else{// These are literal bytesfor(varj=0;j<=hex;++j){output+=data.charAt(i+j+1);}i+=j;}++i;}returnoutput;}varoriginal='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 AAconsole.log(str2hex(data));