Blame IlmImf/ImfHuf.cpp

Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
//
Packit 0d464f
// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas
Packit 0d464f
// Digital Ltd. LLC
Packit 0d464f
// 
Packit 0d464f
// All rights reserved.
Packit 0d464f
// 
Packit 0d464f
// Redistribution and use in source and binary forms, with or without
Packit 0d464f
// modification, are permitted provided that the following conditions are
Packit 0d464f
// met:
Packit 0d464f
// *       Redistributions of source code must retain the above copyright
Packit 0d464f
// notice, this list of conditions and the following disclaimer.
Packit 0d464f
// *       Redistributions in binary form must reproduce the above
Packit 0d464f
// copyright notice, this list of conditions and the following disclaimer
Packit 0d464f
// in the documentation and/or other materials provided with the
Packit 0d464f
// distribution.
Packit 0d464f
// *       Neither the name of Industrial Light & Magic nor the names of
Packit 0d464f
// its contributors may be used to endorse or promote products derived
Packit 0d464f
// from this software without specific prior written permission. 
Packit 0d464f
// 
Packit 0d464f
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
Packit 0d464f
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
Packit 0d464f
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
Packit 0d464f
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
Packit 0d464f
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
Packit 0d464f
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit 0d464f
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit 0d464f
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit 0d464f
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
Packit 0d464f
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit 0d464f
//
Packit 0d464f
///////////////////////////////////////////////////////////////////////////
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
//
Packit 0d464f
//	16-bit Huffman compression and decompression.
Packit 0d464f
//
Packit 0d464f
//	The source code in this file is derived from the 8-bit
Packit 0d464f
//	Huffman compression and decompression routines written
Packit 0d464f
//	by Christian Rouet for his PIZ image file format.
Packit 0d464f
//
Packit 0d464f
//-----------------------------------------------------------------------------
Packit 0d464f
Packit 0d464f
#include <ImfHuf.h>
Packit 0d464f
#include <ImfInt64.h>
Packit 0d464f
#include "ImfAutoArray.h"
Packit 0d464f
#include "ImfFastHuf.h"
Packit 0d464f
#include "Iex.h"
Packit 0d464f
#include <cstring>
Packit 0d464f
#include <cassert>
Packit 0d464f
#include <algorithm>
Packit 0d464f
Packit 0d464f
Packit 0d464f
using namespace std;
Packit 0d464f
using namespace IEX_NAMESPACE;
Packit 0d464f
#include "ImfNamespace.h"
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_ENTER
Packit 0d464f
Packit 0d464f
namespace {
Packit 0d464f
Packit 0d464f
Packit 0d464f
const int HUF_ENCBITS = 16;			// literal (value) bit length
Packit 0d464f
const int HUF_DECBITS = 14;			// decoding bit size (>= 8)
Packit 0d464f
Packit 0d464f
const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1;	// encoding table size
Packit 0d464f
const int HUF_DECSIZE =  1 << HUF_DECBITS;	// decoding table size
Packit 0d464f
const int HUF_DECMASK = HUF_DECSIZE - 1;
Packit 0d464f
Packit 0d464f
Packit 0d464f
struct HufDec
Packit 0d464f
{				// short code		long code
Packit 0d464f
				//-------------------------------
Packit 0d464f
    int		len:8;		// code length		0	 
Packit 0d464f
    int		lit:24;		// lit			p size	 
Packit 0d464f
    int	*	p;		// 0			lits	 
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
invalidNBits ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in header for Huffman-encoded data "
Packit 0d464f
		    "(invalid number of bits).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
tooMuchData ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(decoded data are longer than expected).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
notEnoughData ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(decoded data are shorter than expected).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
invalidCode ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(invalid code).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
invalidTableSize ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(invalid code table size).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
unexpectedEndOfTable ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(unexpected end of code table data).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
tableTooLong ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(code table is longer than expected).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
invalidTableEntry ()
Packit 0d464f
{
Packit 0d464f
    throw InputExc ("Error in Huffman-encoded data "
Packit 0d464f
		    "(invalid code table entry).");
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
inline Int64
Packit 0d464f
hufLength (Int64 code)
Packit 0d464f
{
Packit 0d464f
    return code & 63;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
inline Int64
Packit 0d464f
hufCode (Int64 code)
Packit 0d464f
{
Packit 0d464f
    return code >> 6;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
inline void
Packit 0d464f
outputBits (int nBits, Int64 bits, Int64 &c, int &lc, char *&out)
Packit 0d464f
{
Packit 0d464f
    c <<= nBits;
Packit 0d464f
    lc += nBits;
Packit 0d464f
Packit 0d464f
    c |= bits;
Packit 0d464f
Packit 0d464f
    while (lc >= 8)
Packit 0d464f
	*out++ = (c >> (lc -= 8));
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
inline Int64
Packit 0d464f
getBits (int nBits, Int64 &c, int &lc, const char *&in)
Packit 0d464f
{
Packit 0d464f
    while (lc < nBits)
Packit 0d464f
    {
Packit 0d464f
	c = (c << 8) | *(unsigned char *)(in++);
Packit 0d464f
	lc += 8;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    lc -= nBits;
Packit 0d464f
    return (c >> lc) & ((1 << nBits) - 1);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// ENCODING TABLE BUILDING & (UN)PACKING
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Build a "canonical" Huffman code table:
Packit 0d464f
//	- for each (uncompressed) symbol, hcode contains the length
Packit 0d464f
//	  of the corresponding code (in the compressed data)
Packit 0d464f
//	- canonical codes are computed and stored in hcode
Packit 0d464f
//	- the rules for constructing canonical codes are as follows:
Packit 0d464f
//	  * shorter codes (if filled with zeroes to the right)
Packit 0d464f
//	    have a numerically higher value than longer codes
Packit 0d464f
//	  * for codes with the same length, numerical values
Packit 0d464f
//	    increase with numerical symbol values
Packit 0d464f
//	- because the canonical code table can be constructed from
Packit 0d464f
//	  symbol lengths alone, the code table can be transmitted
Packit 0d464f
//	  without sending the actual code values
Packit 0d464f
//	- see http://www.compressconsult.com/huffman/
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE])
Packit 0d464f
{
Packit 0d464f
    Int64 n[59];
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // For each i from 0 through 58, count the
Packit 0d464f
    // number of different codes of length i, and
Packit 0d464f
    // store the count in n[i].
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (int i = 0; i <= 58; ++i)
Packit 0d464f
	n[i] = 0;
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < HUF_ENCSIZE; ++i)
Packit 0d464f
	n[hcode[i]] += 1;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // For each i from 58 through 1, compute the
Packit 0d464f
    // numerically lowest code with length i, and
Packit 0d464f
    // store that code in n[i].
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    Int64 c = 0;
Packit 0d464f
Packit 0d464f
    for (int i = 58; i > 0; --i)
Packit 0d464f
    {
Packit 0d464f
	Int64 nc = ((c + n[i]) >> 1);
Packit 0d464f
	n[i] = c;
Packit 0d464f
	c = nc;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // hcode[i] contains the length, l, of the
Packit 0d464f
    // code for symbol i.  Assign the next available
Packit 0d464f
    // code of length l to the symbol and store both
Packit 0d464f
    // l and the code in hcode[i].
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < HUF_ENCSIZE; ++i)
Packit 0d464f
    {
Packit 0d464f
	int l = hcode[i];
Packit 0d464f
Packit 0d464f
	if (l > 0)
Packit 0d464f
	    hcode[i] = l | (n[l]++ << 6);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Compute Huffman codes (based on frq input) and store them in frq:
Packit 0d464f
//	- code structure is : [63:lsb - 6:msb] | [5-0: bit length];
Packit 0d464f
//	- max code length is 58 bits;
Packit 0d464f
//	- codes outside the range [im-iM] have a null length (unused values);
Packit 0d464f
//	- original frequencies are destroyed;
Packit 0d464f
//	- encoding tables are used by hufEncode() and hufBuildDecTable();
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
Packit 0d464f
struct FHeapCompare
Packit 0d464f
{
Packit 0d464f
    bool operator () (Int64 *a, Int64 *b) {return *a > *b;}
Packit 0d464f
};
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufBuildEncTable
Packit 0d464f
    (Int64*	frq,	// io: input frequencies [HUF_ENCSIZE], output table
Packit 0d464f
     int*	im,	//  o: min frq index
Packit 0d464f
     int*	iM)	//  o: max frq index
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // This function assumes that when it is called, array frq
Packit 0d464f
    // indicates the frequency of all possible symbols in the data
Packit 0d464f
    // that are to be Huffman-encoded.  (frq[i] contains the number
Packit 0d464f
    // of occurrences of symbol i in the data.)
Packit 0d464f
    //
Packit 0d464f
    // The loop below does three things:
Packit 0d464f
    //
Packit 0d464f
    // 1) Finds the minimum and maximum indices that point
Packit 0d464f
    //    to non-zero entries in frq:
Packit 0d464f
    //
Packit 0d464f
    //     frq[im] != 0, and frq[i] == 0 for all i < im
Packit 0d464f
    //     frq[iM] != 0, and frq[i] == 0 for all i > iM
Packit 0d464f
    //
Packit 0d464f
    // 2) Fills array fHeap with pointers to all non-zero
Packit 0d464f
    //    entries in frq.
Packit 0d464f
    //
Packit 0d464f
    // 3) Initializes array hlink such that hlink[i] == i
Packit 0d464f
    //    for all array entries.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    AutoArray <int, HUF_ENCSIZE> hlink;
Packit 0d464f
    AutoArray <Int64 *, HUF_ENCSIZE> fHeap;
Packit 0d464f
Packit 0d464f
    *im = 0;
Packit 0d464f
Packit 0d464f
    while (!frq[*im])
Packit 0d464f
	(*im)++;
Packit 0d464f
Packit 0d464f
    int nf = 0;
Packit 0d464f
Packit 0d464f
    for (int i = *im; i < HUF_ENCSIZE; i++)
Packit 0d464f
    {
Packit 0d464f
	hlink[i] = i;
Packit 0d464f
Packit 0d464f
	if (frq[i])
Packit 0d464f
	{
Packit 0d464f
	    fHeap[nf] = &frq[i];
Packit 0d464f
	    nf++;
Packit 0d464f
	    *iM = i;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Add a pseudo-symbol, with a frequency count of 1, to frq;
Packit 0d464f
    // adjust the fHeap and hlink array accordingly.  Function
Packit 0d464f
    // hufEncode() uses the pseudo-symbol for run-length encoding.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    (*iM)++;
Packit 0d464f
    frq[*iM] = 1;
Packit 0d464f
    fHeap[nf] = &frq[*iM];
Packit 0d464f
    nf++;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Build an array, scode, such that scode[i] contains the number
Packit 0d464f
    // of bits assigned to symbol i.  Conceptually this is done by
Packit 0d464f
    // constructing a tree whose leaves are the symbols with non-zero
Packit 0d464f
    // frequency:
Packit 0d464f
    //
Packit 0d464f
    //     Make a heap that contains all symbols with a non-zero frequency,
Packit 0d464f
    //     with the least frequent symbol on top.
Packit 0d464f
    //
Packit 0d464f
    //     Repeat until only one symbol is left on the heap:
Packit 0d464f
    //
Packit 0d464f
    //         Take the two least frequent symbols off the top of the heap.
Packit 0d464f
    //         Create a new node that has first two nodes as children, and
Packit 0d464f
    //         whose frequency is the sum of the frequencies of the first
Packit 0d464f
    //         two nodes.  Put the new node back into the heap.
Packit 0d464f
    //
Packit 0d464f
    // The last node left on the heap is the root of the tree.  For each
Packit 0d464f
    // leaf node, the distance between the root and the leaf is the length
Packit 0d464f
    // of the code for the corresponding symbol.
Packit 0d464f
    //
Packit 0d464f
    // The loop below doesn't actually build the tree; instead we compute
Packit 0d464f
    // the distances of the leaves from the root on the fly.  When a new
Packit 0d464f
    // node is added to the heap, then that node's descendants are linked
Packit 0d464f
    // into a single linear list that starts at the new node, and the code
Packit 0d464f
    // lengths of the descendants (that is, their distance from the root
Packit 0d464f
    // of the tree) are incremented by one.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    make_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
Packit 0d464f
Packit 0d464f
    AutoArray <Int64, HUF_ENCSIZE> scode;
Packit 0d464f
    memset (scode, 0, sizeof (Int64) * HUF_ENCSIZE);
Packit 0d464f
Packit 0d464f
    while (nf > 1)
Packit 0d464f
    {
Packit 0d464f
	//
Packit 0d464f
	// Find the indices, mm and m, of the two smallest non-zero frq
Packit 0d464f
	// values in fHeap, add the smallest frq to the second-smallest
Packit 0d464f
	// frq, and remove the smallest frq value from fHeap.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	int mm = fHeap[0] - frq;
Packit 0d464f
	pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
Packit 0d464f
	--nf;
Packit 0d464f
Packit 0d464f
	int m = fHeap[0] - frq;
Packit 0d464f
	pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
Packit 0d464f
Packit 0d464f
	frq[m ] += frq[mm];
Packit 0d464f
	push_heap (&fHeap[0], &fHeap[nf], FHeapCompare());
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// The entries in scode are linked into lists with the
Packit 0d464f
	// entries in hlink serving as "next" pointers and with
Packit 0d464f
	// the end of a list marked by hlink[j] == j.
Packit 0d464f
	//
Packit 0d464f
	// Traverse the lists that start at scode[m] and scode[mm].
Packit 0d464f
	// For each element visited, increment the length of the
Packit 0d464f
	// corresponding code by one bit. (If we visit scode[j]
Packit 0d464f
	// during the traversal, then the code for symbol j becomes
Packit 0d464f
	// one bit longer.)
Packit 0d464f
	//
Packit 0d464f
	// Merge the lists that start at scode[m] and scode[mm]
Packit 0d464f
	// into a single list that starts at scode[m].
Packit 0d464f
	//
Packit 0d464f
	
Packit 0d464f
	//
Packit 0d464f
	// Add a bit to all codes in the first list.
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	for (int j = m; true; j = hlink[j])
Packit 0d464f
	{
Packit 0d464f
	    scode[j]++;
Packit 0d464f
Packit 0d464f
	    assert (scode[j] <= 58);
Packit 0d464f
Packit 0d464f
	    if (hlink[j] == j)
Packit 0d464f
	    {
Packit 0d464f
		//
Packit 0d464f
		// Merge the two lists.
Packit 0d464f
		//
Packit 0d464f
Packit 0d464f
		hlink[j] = mm;
Packit 0d464f
		break;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Add a bit to all codes in the second list
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	for (int j = mm; true; j = hlink[j])
Packit 0d464f
	{
Packit 0d464f
	    scode[j]++;
Packit 0d464f
Packit 0d464f
	    assert (scode[j] <= 58);
Packit 0d464f
Packit 0d464f
	    if (hlink[j] == j)
Packit 0d464f
		break;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Build a canonical Huffman code table, replacing the code
Packit 0d464f
    // lengths in scode with (code, code length) pairs.  Copy the
Packit 0d464f
    // code table from scode into frq.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    hufCanonicalCodeTable (scode);
Packit 0d464f
    memcpy (frq, scode, sizeof (Int64) * HUF_ENCSIZE);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Pack an encoding table:
Packit 0d464f
//	- only code lengths, not actual codes, are stored
Packit 0d464f
//	- runs of zeroes are compressed as follows:
Packit 0d464f
//
Packit 0d464f
//	  unpacked		packed
Packit 0d464f
//	  --------------------------------
Packit 0d464f
//	  1 zero		0	(6 bits)
Packit 0d464f
//	  2 zeroes		59
Packit 0d464f
//	  3 zeroes		60
Packit 0d464f
//	  4 zeroes		61
Packit 0d464f
//	  5 zeroes		62
Packit 0d464f
//	  n zeroes (6 or more)	63 n-6	(6 + 8 bits)
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
const int SHORT_ZEROCODE_RUN = 59;
Packit 0d464f
const int LONG_ZEROCODE_RUN  = 63;
Packit 0d464f
const int SHORTEST_LONG_RUN  = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;
Packit 0d464f
const int LONGEST_LONG_RUN   = 255 + SHORTEST_LONG_RUN;
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufPackEncTable
Packit 0d464f
    (const Int64*	hcode,		// i : encoding table [HUF_ENCSIZE]
Packit 0d464f
     int		im,		// i : min hcode index
Packit 0d464f
     int		iM,		// i : max hcode index
Packit 0d464f
     char**		pcode)		//  o: ptr to packed table (updated)
Packit 0d464f
{
Packit 0d464f
    char *p = *pcode;
Packit 0d464f
    Int64 c = 0;
Packit 0d464f
    int lc = 0;
Packit 0d464f
Packit 0d464f
    for (; im <= iM; im++)
Packit 0d464f
    {
Packit 0d464f
	int l = hufLength (hcode[im]);
Packit 0d464f
Packit 0d464f
	if (l == 0)
Packit 0d464f
	{
Packit 0d464f
	    int zerun = 1;
Packit 0d464f
Packit 0d464f
	    while ((im < iM) && (zerun < LONGEST_LONG_RUN))
Packit 0d464f
	    {
Packit 0d464f
		if (hufLength (hcode[im+1]) > 0 )	 
Packit 0d464f
		    break;
Packit 0d464f
		im++;
Packit 0d464f
		zerun++;
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    if (zerun >= 2)
Packit 0d464f
	    {
Packit 0d464f
		if (zerun >= SHORTEST_LONG_RUN)
Packit 0d464f
		{
Packit 0d464f
		    outputBits (6, LONG_ZEROCODE_RUN, c, lc, p);
Packit 0d464f
		    outputBits (8, zerun - SHORTEST_LONG_RUN, c, lc, p);
Packit 0d464f
		}
Packit 0d464f
		else
Packit 0d464f
		{
Packit 0d464f
		    outputBits (6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);
Packit 0d464f
		}
Packit 0d464f
		continue;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	outputBits (6, l, c, lc, p);
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (lc > 0)
Packit 0d464f
	*p++ = (unsigned char) (c << (8 - lc));
Packit 0d464f
Packit 0d464f
    *pcode = p;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Unpack an encoding table packed by hufPackEncTable():
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufUnpackEncTable
Packit 0d464f
    (const char**	pcode,		// io: ptr to packed table (updated)
Packit 0d464f
     int		ni,		// i : input size (in bytes)
Packit 0d464f
     int		im,		// i : min hcode index
Packit 0d464f
     int		iM,		// i : max hcode index
Packit 0d464f
     Int64*		hcode)		//  o: encoding table [HUF_ENCSIZE]
Packit 0d464f
{
Packit 0d464f
    memset (hcode, 0, sizeof (Int64) * HUF_ENCSIZE);
Packit 0d464f
Packit 0d464f
    const char *p = *pcode;
Packit 0d464f
    Int64 c = 0;
Packit 0d464f
    int lc = 0;
Packit 0d464f
Packit 0d464f
    for (; im <= iM; im++)
Packit 0d464f
    {
Packit 0d464f
	if (p - *pcode > ni)
Packit 0d464f
	    unexpectedEndOfTable();
Packit 0d464f
Packit 0d464f
	Int64 l = hcode[im] = getBits (6, c, lc, p); // code length
Packit 0d464f
Packit 0d464f
	if (l == (Int64) LONG_ZEROCODE_RUN)
Packit 0d464f
	{
Packit 0d464f
	    if (p - *pcode > ni)
Packit 0d464f
		unexpectedEndOfTable();
Packit 0d464f
Packit 0d464f
	    int zerun = getBits (8, c, lc, p) + SHORTEST_LONG_RUN;
Packit 0d464f
Packit 0d464f
	    if (im + zerun > iM + 1)
Packit 0d464f
		tableTooLong();
Packit 0d464f
Packit 0d464f
	    while (zerun--)
Packit 0d464f
		hcode[im++] = 0;
Packit 0d464f
Packit 0d464f
	    im--;
Packit 0d464f
	}
Packit 0d464f
	else if (l >= (Int64) SHORT_ZEROCODE_RUN)
Packit 0d464f
	{
Packit 0d464f
	    int zerun = l - SHORT_ZEROCODE_RUN + 2;
Packit 0d464f
Packit 0d464f
	    if (im + zerun > iM + 1)
Packit 0d464f
		tableTooLong();
Packit 0d464f
Packit 0d464f
	    while (zerun--)
Packit 0d464f
		hcode[im++] = 0;
Packit 0d464f
Packit 0d464f
	    im--;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    *pcode = const_cast<char *>(p);
Packit 0d464f
Packit 0d464f
    hufCanonicalCodeTable (hcode);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// DECODING TABLE BUILDING
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Clear a newly allocated decoding table so that it contains only zeroes.
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufClearDecTable
Packit 0d464f
    (HufDec *		hdecod)		// io: (allocated by caller)
Packit 0d464f
     					//     decoding table [HUF_DECSIZE]
Packit 0d464f
{
Packit 0d464f
    memset (hdecod, 0, sizeof (HufDec) * HUF_DECSIZE);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Build a decoding hash table based on the encoding table hcode:
Packit 0d464f
//	- short codes (<= HUF_DECBITS) are resolved with a single table access;
Packit 0d464f
//	- long code entry allocations are not optimized, because long codes are
Packit 0d464f
//	  unfrequent;
Packit 0d464f
//	- decoding tables are used by hufDecode();
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufBuildDecTable
Packit 0d464f
    (const Int64*	hcode,		// i : encoding table
Packit 0d464f
     int		im,		// i : min index in hcode
Packit 0d464f
     int		iM,		// i : max index in hcode
Packit 0d464f
     HufDec *		hdecod)		//  o: (allocated by caller)
Packit 0d464f
     					//     decoding table [HUF_DECSIZE]
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Init hashtable & loop on all codes.
Packit 0d464f
    // Assumes that hufClearDecTable(hdecod) has already been called.
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (; im <= iM; im++)
Packit 0d464f
    {
Packit 0d464f
	Int64 c = hufCode (hcode[im]);
Packit 0d464f
	int l = hufLength (hcode[im]);
Packit 0d464f
Packit 0d464f
	if (c >> l)
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // Error: c is supposed to be an l-bit code,
Packit 0d464f
	    // but c contains a value that is greater
Packit 0d464f
	    // than the largest l-bit number.
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    invalidTableEntry();
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	if (l > HUF_DECBITS)
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // Long code: add a secondary entry
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));
Packit 0d464f
Packit 0d464f
	    if (pl->len)
Packit 0d464f
	    {
Packit 0d464f
		//
Packit 0d464f
		// Error: a short code has already
Packit 0d464f
		// been stored in table entry *pl.
Packit 0d464f
		//
Packit 0d464f
Packit 0d464f
		invalidTableEntry();
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    pl->lit++;
Packit 0d464f
Packit 0d464f
	    if (pl->p)
Packit 0d464f
	    {
Packit 0d464f
		int *p = pl->p;
Packit 0d464f
		pl->p = new int [pl->lit];
Packit 0d464f
Packit 0d464f
		for (int i = 0; i < pl->lit - 1; ++i)
Packit 0d464f
		    pl->p[i] = p[i];
Packit 0d464f
Packit 0d464f
		delete [] p;
Packit 0d464f
	    }
Packit 0d464f
	    else
Packit 0d464f
	    {
Packit 0d464f
		pl->p = new int [1];
Packit 0d464f
	    }
Packit 0d464f
Packit 0d464f
	    pl->p[pl->lit - 1]= im;
Packit 0d464f
	}
Packit 0d464f
	else if (l)
Packit 0d464f
	{
Packit 0d464f
	    //
Packit 0d464f
	    // Short code: init all primary entries
Packit 0d464f
	    //
Packit 0d464f
Packit 0d464f
	    HufDec *pl = hdecod + (c << (HUF_DECBITS - l));
Packit 0d464f
Packit 0d464f
	    for (Int64 i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++)
Packit 0d464f
	    {
Packit 0d464f
		if (pl->len || pl->p)
Packit 0d464f
		{
Packit 0d464f
		    //
Packit 0d464f
		    // Error: a short code or a long code has
Packit 0d464f
		    // already been stored in table entry *pl.
Packit 0d464f
		    //
Packit 0d464f
Packit 0d464f
		    invalidTableEntry();
Packit 0d464f
		}
Packit 0d464f
Packit 0d464f
		pl->len = l;
Packit 0d464f
		pl->lit = im;
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Free the long code entries of a decoding table built by hufBuildDecTable()
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufFreeDecTable (HufDec *hdecod)	// io: Decoding table
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < HUF_DECSIZE; i++)
Packit 0d464f
    {
Packit 0d464f
	if (hdecod[i].p)
Packit 0d464f
	{
Packit 0d464f
	    delete [] hdecod[i].p;
Packit 0d464f
	    hdecod[i].p = 0;
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// ENCODING
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
inline void
Packit 0d464f
outputCode (Int64 code, Int64 &c, int &lc, char *&out)
Packit 0d464f
{
Packit 0d464f
    outputBits (hufLength (code), hufCode (code), c, lc, out);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
inline void
Packit 0d464f
sendCode (Int64 sCode, int runCount, Int64 runCode,
Packit 0d464f
	  Int64 &c, int &lc, char *&out)
Packit 0d464f
{
Packit 0d464f
    //
Packit 0d464f
    // Output a run of runCount instances of the symbol sCount.
Packit 0d464f
    // Output the symbols explicitly, or if that is shorter, output
Packit 0d464f
    // the sCode symbol once followed by a runCode symbol and runCount
Packit 0d464f
    // expressed as an 8-bit number.
Packit 0d464f
    //
Packit 0d464f
    
Packit 0d464f
    if (hufLength (sCode) + hufLength (runCode) + 8 <
Packit 0d464f
        hufLength (sCode) * runCount)
Packit 0d464f
    {
Packit 0d464f
	outputCode (sCode, c, lc, out);
Packit 0d464f
	outputCode (runCode, c, lc, out);
Packit 0d464f
	outputBits (8, runCount, c, lc, out);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
	while (runCount-- >= 0)
Packit 0d464f
	    outputCode (sCode, c, lc, out);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Encode (compress) ni values based on the Huffman encoding table hcode:
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
hufEncode				// return: output size (in bits)
Packit 0d464f
    (const Int64*  	    hcode,	// i : encoding table
Packit 0d464f
     const unsigned short*  in,		// i : uncompressed input buffer
Packit 0d464f
     const int     	    ni,		// i : input buffer size (in bytes)
Packit 0d464f
     int           	    rlc,	// i : rl code
Packit 0d464f
     char*         	    out)	//  o: compressed output buffer
Packit 0d464f
{
Packit 0d464f
    char *outStart = out;
Packit 0d464f
    Int64 c = 0;	// bits not yet written to out
Packit 0d464f
    int lc = 0;		// number of valid bits in c (LSB)
Packit 0d464f
    int s = in[0];
Packit 0d464f
    int cs = 0;
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Loop on input values
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    for (int i = 1; i < ni; i++)
Packit 0d464f
    {
Packit 0d464f
	//
Packit 0d464f
	// Count same values or send code
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	if (s == in[i] && cs < 255)
Packit 0d464f
	{
Packit 0d464f
	    cs++;
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    sendCode (hcode[s], cs, hcode[rlc], c, lc, out);
Packit 0d464f
	    cs=0;
Packit 0d464f
	}
Packit 0d464f
Packit 0d464f
	s = in[i];
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Send remaining code
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    sendCode (hcode[s], cs, hcode[rlc], c, lc, out);
Packit 0d464f
Packit 0d464f
    if (lc)
Packit 0d464f
	*out = (c << (8 - lc)) & 0xff;
Packit 0d464f
Packit 0d464f
    return (out - outStart) * 8 + lc;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// DECODING
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// In order to force the compiler to inline them,
Packit 0d464f
// getChar() and getCode() are implemented as macros
Packit 0d464f
// instead of "inline" functions.
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
#define getChar(c, lc, in)			\
Packit 0d464f
{						\
Packit 0d464f
    c = (c << 8) | *(unsigned char *)(in++);	\
Packit 0d464f
    lc += 8;					\
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
#define getCode(po, rlc, c, lc, in, out, oe)	\
Packit 0d464f
{						\
Packit 0d464f
    if (po == rlc)				\
Packit 0d464f
    {						\
Packit 0d464f
	if (lc < 8)				\
Packit 0d464f
	    getChar(c, lc, in);			\
Packit 0d464f
						\
Packit 0d464f
	lc -= 8;				\
Packit 0d464f
						\
Packit 0d464f
	unsigned char cs = (c >> lc);		\
Packit 0d464f
						\
Packit 0d464f
	if (out + cs > oe)			\
Packit 0d464f
	    tooMuchData();			\
Packit 0d464f
						\
Packit 0d464f
	unsigned short s = out[-1];		\
Packit 0d464f
						\
Packit 0d464f
	while (cs-- > 0)			\
Packit 0d464f
	    *out++ = s;				\
Packit 0d464f
    }						\
Packit 0d464f
    else if (out < oe)				\
Packit 0d464f
    {						\
Packit 0d464f
	*out++ = po;				\
Packit 0d464f
    }						\
Packit 0d464f
    else					\
Packit 0d464f
    {						\
Packit 0d464f
	tooMuchData();				\
Packit 0d464f
    }						\
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// Decode (uncompress) ni bits based on encoding & decoding tables:
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufDecode
Packit 0d464f
    (const Int64 * 	hcode,	// i : encoding table
Packit 0d464f
     const HufDec * 	hdecod,	// i : decoding table
Packit 0d464f
     const char* 	in,	// i : compressed input buffer
Packit 0d464f
     int		ni,	// i : input size (in bits)
Packit 0d464f
     int		rlc,	// i : run-length code
Packit 0d464f
     int		no,	// i : expected output size (in bytes)
Packit 0d464f
     unsigned short*	out)	//  o: uncompressed output buffer
Packit 0d464f
{
Packit 0d464f
    Int64 c = 0;
Packit 0d464f
    int lc = 0;
Packit 0d464f
    unsigned short * outb = out;
Packit 0d464f
    unsigned short * oe = out + no;
Packit 0d464f
    const char * ie = in + (ni + 7) / 8; // input byte size
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Loop on input bytes
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    while (in < ie)
Packit 0d464f
    {
Packit 0d464f
	getChar (c, lc, in);
Packit 0d464f
Packit 0d464f
	//
Packit 0d464f
	// Access decoding table
Packit 0d464f
	//
Packit 0d464f
Packit 0d464f
	while (lc >= HUF_DECBITS)
Packit 0d464f
	{
Packit 0d464f
	    const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK];
Packit 0d464f
Packit 0d464f
	    if (pl.len)
Packit 0d464f
	    {
Packit 0d464f
		//
Packit 0d464f
		// Get short code
Packit 0d464f
		//
Packit 0d464f
Packit 0d464f
		lc -= pl.len;
Packit 0d464f
		getCode (pl.lit, rlc, c, lc, in, out, oe);
Packit 0d464f
	    }
Packit 0d464f
	    else
Packit 0d464f
	    {
Packit 0d464f
		if (!pl.p)
Packit 0d464f
		    invalidCode(); // wrong code
Packit 0d464f
Packit 0d464f
		//
Packit 0d464f
		// Search long code
Packit 0d464f
		//
Packit 0d464f
Packit 0d464f
		int j;
Packit 0d464f
Packit 0d464f
		for (j = 0; j < pl.lit; j++)
Packit 0d464f
		{
Packit 0d464f
		    int	l = hufLength (hcode[pl.p[j]]);
Packit 0d464f
Packit 0d464f
		    while (lc < l && in < ie)	// get more bits
Packit 0d464f
			getChar (c, lc, in);
Packit 0d464f
Packit 0d464f
		    if (lc >= l)
Packit 0d464f
		    {
Packit 0d464f
			if (hufCode (hcode[pl.p[j]]) ==
Packit 0d464f
				((c >> (lc - l)) & ((Int64(1) << l) - 1)))
Packit 0d464f
			{
Packit 0d464f
			    //
Packit 0d464f
			    // Found : get long code
Packit 0d464f
			    //
Packit 0d464f
Packit 0d464f
			    lc -= l;
Packit 0d464f
			    getCode (pl.p[j], rlc, c, lc, in, out, oe);
Packit 0d464f
			    break;
Packit 0d464f
			}
Packit 0d464f
		    }
Packit 0d464f
		}
Packit 0d464f
Packit 0d464f
		if (j == pl.lit)
Packit 0d464f
		    invalidCode(); // Not found
Packit 0d464f
	    }
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    //
Packit 0d464f
    // Get remaining (short) codes
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    int i = (8 - ni) & 7;
Packit 0d464f
    c >>= i;
Packit 0d464f
    lc -= i;
Packit 0d464f
Packit 0d464f
    while (lc > 0)
Packit 0d464f
    {
Packit 0d464f
	const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];
Packit 0d464f
Packit 0d464f
	if (pl.len)
Packit 0d464f
	{
Packit 0d464f
	    lc -= pl.len;
Packit 0d464f
	    getCode (pl.lit, rlc, c, lc, in, out, oe);
Packit 0d464f
	}
Packit 0d464f
	else
Packit 0d464f
	{
Packit 0d464f
	    invalidCode(); // wrong (long) code
Packit 0d464f
	}
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    if (out - outb != no)
Packit 0d464f
	notEnoughData ();
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
countFrequencies (Int64 freq[HUF_ENCSIZE],
Packit 0d464f
		  const unsigned short data[/*n*/],
Packit 0d464f
		  int n)
Packit 0d464f
{
Packit 0d464f
    for (int i = 0; i < HUF_ENCSIZE; ++i)
Packit 0d464f
	freq[i] = 0;
Packit 0d464f
Packit 0d464f
    for (int i = 0; i < n; ++i)
Packit 0d464f
	++freq[data[i]];
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
writeUInt (char buf[4], unsigned int i)
Packit 0d464f
{
Packit 0d464f
    unsigned char *b = (unsigned char *) buf;
Packit 0d464f
Packit 0d464f
    b[0] = i;
Packit 0d464f
    b[1] = i >> 8;
Packit 0d464f
    b[2] = i >> 16;
Packit 0d464f
    b[3] = i >> 24;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
unsigned int
Packit 0d464f
readUInt (const char buf[4])
Packit 0d464f
{
Packit 0d464f
    const unsigned char *b = (const unsigned char *) buf;
Packit 0d464f
Packit 0d464f
    return ( b[0]        & 0x000000ff) |
Packit 0d464f
	   ((b[1] <<  8) & 0x0000ff00) |
Packit 0d464f
	   ((b[2] << 16) & 0x00ff0000) |
Packit 0d464f
	   ((b[3] << 24) & 0xff000000);
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
} // namespace
Packit 0d464f
Packit 0d464f
Packit 0d464f
//
Packit 0d464f
// EXTERNAL INTERFACE
Packit 0d464f
//
Packit 0d464f
Packit 0d464f
Packit 0d464f
int
Packit 0d464f
hufCompress (const unsigned short raw[],
Packit 0d464f
	     int nRaw,
Packit 0d464f
	     char compressed[])
Packit 0d464f
{
Packit 0d464f
    if (nRaw == 0)
Packit 0d464f
	return 0;
Packit 0d464f
Packit 0d464f
    AutoArray <Int64, HUF_ENCSIZE> freq;
Packit 0d464f
Packit 0d464f
    countFrequencies (freq, raw, nRaw);
Packit 0d464f
Packit 0d464f
    int im = 0;
Packit 0d464f
    int iM = 0;
Packit 0d464f
    hufBuildEncTable (freq, &im, &iM;;
Packit 0d464f
Packit 0d464f
    char *tableStart = compressed + 20;
Packit 0d464f
    char *tableEnd   = tableStart;
Packit 0d464f
    hufPackEncTable (freq, im, iM, &tableEnd);
Packit 0d464f
    int tableLength = tableEnd - tableStart;
Packit 0d464f
Packit 0d464f
    char *dataStart = tableEnd;
Packit 0d464f
    int nBits = hufEncode (freq, raw, nRaw, iM, dataStart);
Packit 0d464f
    int dataLength = (nBits + 7) / 8;
Packit 0d464f
Packit 0d464f
    writeUInt (compressed,      im);
Packit 0d464f
    writeUInt (compressed +  4, iM);
Packit 0d464f
    writeUInt (compressed +  8, tableLength);
Packit 0d464f
    writeUInt (compressed + 12, nBits);
Packit 0d464f
    writeUInt (compressed + 16, 0);	// room for future extensions
Packit 0d464f
Packit 0d464f
    return dataStart + dataLength - compressed;
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
void
Packit 0d464f
hufUncompress (const char compressed[],
Packit 0d464f
	       int nCompressed,
Packit 0d464f
	       unsigned short raw[],
Packit 0d464f
	       int nRaw)
Packit 0d464f
{
Packit 0d464f
    if (nCompressed == 0)
Packit 0d464f
    {
Packit 0d464f
	if (nRaw != 0)
Packit 0d464f
	    notEnoughData();
Packit 0d464f
Packit 0d464f
	return;
Packit 0d464f
    }
Packit 0d464f
Packit 0d464f
    int im = readUInt (compressed);
Packit 0d464f
    int iM = readUInt (compressed + 4);
Packit 0d464f
    // int tableLength = readUInt (compressed + 8);
Packit 0d464f
    int nBits = readUInt (compressed + 12);
Packit 0d464f
Packit 0d464f
    if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE)
Packit 0d464f
	invalidTableSize();
Packit 0d464f
Packit 0d464f
    const char *ptr = compressed + 20;
Packit 0d464f
Packit 0d464f
    // 
Packit 0d464f
    // Fast decoder needs at least 2x64-bits of compressed data, and
Packit 0d464f
    // needs to be run-able on this platform. Otherwise, fall back
Packit 0d464f
    // to the original decoder
Packit 0d464f
    //
Packit 0d464f
Packit 0d464f
    if (FastHufDecoder::enabled() && nBits > 128)
Packit 0d464f
    {
Packit 0d464f
        FastHufDecoder fhd (ptr, nCompressed - (ptr - compressed), im, iM, iM);
Packit 0d464f
        fhd.decode ((unsigned char*)ptr, nBits, raw, nRaw);
Packit 0d464f
    }
Packit 0d464f
    else
Packit 0d464f
    {
Packit 0d464f
        AutoArray <Int64, HUF_ENCSIZE> freq;
Packit 0d464f
        AutoArray <HufDec, HUF_DECSIZE> hdec;
Packit 0d464f
Packit 0d464f
        hufClearDecTable (hdec);
Packit 0d464f
Packit 0d464f
        hufUnpackEncTable (&ptr,
Packit 0d464f
                           nCompressed - (ptr - compressed),
Packit 0d464f
                           im,
Packit 0d464f
                           iM,
Packit 0d464f
                           freq);
Packit 0d464f
Packit 0d464f
        try
Packit 0d464f
        {
Packit 0d464f
            if (nBits > 8 * (nCompressed - (ptr - compressed)))
Packit 0d464f
                invalidNBits();
Packit 0d464f
Packit 0d464f
            hufBuildDecTable (freq, im, iM, hdec);
Packit 0d464f
            hufDecode (freq, hdec, ptr, nBits, iM, nRaw, raw);
Packit 0d464f
        }
Packit 0d464f
        catch (...)
Packit 0d464f
        {
Packit 0d464f
            hufFreeDecTable (hdec);
Packit 0d464f
            throw;
Packit 0d464f
        }
Packit 0d464f
Packit 0d464f
        hufFreeDecTable (hdec);
Packit 0d464f
    }
Packit 0d464f
}
Packit 0d464f
Packit 0d464f
Packit 0d464f
OPENEXR_IMF_INTERNAL_NAMESPACE_SOURCE_EXIT