⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 imfhuf.cpp

📁 image converter source code
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/////////////////////////////////////////////////////////////////////////////// Copyright (c) 2002, Industrial Light & Magic, a division of Lucas// Digital Ltd. LLC// // All rights reserved.// // Redistribution and use in source and binary forms, with or without// modification, are permitted provided that the following conditions are// met:// *       Redistributions of source code must retain the above copyright// notice, this list of conditions and the following disclaimer.// *       Redistributions in binary form must reproduce the above// copyright notice, this list of conditions and the following disclaimer// in the documentation and/or other materials provided with the// distribution.// *       Neither the name of Industrial Light & Magic nor the names of// its contributors may be used to endorse or promote products derived// from this software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.///////////////////////////////////////////////////////////////////////////////-----------------------------------------------------------------------------////	16-bit Huffman compression and decompression.////	The source code in this file is derived from the 8-bit//	Huffman compression and decompression routines written//	by Christian Rouet for his PIZ image file format.////-----------------------------------------------------------------------------#include <ImfHuf.h>#include <ImfInt64.h>#include <ImfAutoArray.h>#include "Iex.h"#include <string.h>#include <assert.h>#include <algorithm>using namespace std;using namespace Iex;namespace Imf {namespace {const int HUF_ENCBITS = 16;			// literal (value) bit lengthconst int HUF_DECBITS = 14;			// decoding bit size (>= 8)const int HUF_ENCSIZE = (1 << HUF_ENCBITS) + 1;	// encoding table sizeconst int HUF_DECSIZE =  1 << HUF_DECBITS;	// decoding table sizeconst int HUF_DECMASK = HUF_DECSIZE - 1;struct HufDec{				// short code		long code				//-------------------------------    int		len:8;		// code length		0	     int		lit:24;		// lit			p size	     int	*	p;		// 0			lits	 };voidinvalidNBits (){    throw InputExc ("Error in header for Huffman-encoded data "		    "(invalid number of bits).");}voidtooMuchData (){    throw InputExc ("Error in Huffman-encoded data "		    "(decoded data are longer than expected).");}voidnotEnoughData (){    throw InputExc ("Error in Huffman-encoded data "		    "(decoded data are shorter than expected).");}voidinvalidCode (){    throw InputExc ("Error in Huffman-encoded data "		    "(invalid code).");}voidinvalidTableSize (){    throw InputExc ("Error in Huffman-encoded data "		    "(invalid code table size).");}voidunexpectedEndOfTable (){    throw InputExc ("Error in Huffman-encoded data "		    "(unexpected end of code table data).");}voidtableTooLong (){    throw InputExc ("Error in Huffman-encoded data "		    "(code table is longer than expected).");}voidinvalidTableEntry (){    throw InputExc ("Error in Huffman-encoded data "		    "(invalid code table entry).");}inline Int64hufLength (Int64 code){    return code & 63;}inline Int64hufCode (Int64 code){    return code >> 6;}inline voidoutputBits (int nBits, Int64 bits, Int64 &c, int &lc, char *&out){    c <<= nBits;    lc += nBits;    c |= bits;    while (lc >= 8)	*out++ = (c >> (lc -= 8));}inline Int64getBits (int nBits, Int64 &c, int &lc, const char *&in){    while (lc < nBits)    {	c = (c << 8) | *(unsigned char *)(in++);	lc += 8;    }    lc -= nBits;    return (c >> lc) & ((1 << nBits) - 1);}//// ENCODING TABLE BUILDING & (UN)PACKING////// Build a "canonical" Huffman code table://	- for each (uncompressed) symbol, hcode contains the length//	  of the corresponding code (in the compressed data)//	- canonical codes are computed and stored in hcode//	- the rules for constructing canonical codes are as follows://	  * shorter codes (if filled with zeroes to the right)//	    have a numerically higher value than longer codes//	  * for codes with the same length, numerical values//	    increase with numerical symbol values//	- because the canonical code table can be constructed from//	  symbol lengths alone, the code table can be transmitted//	  without sending the actual code values//	- see http://www.compressconsult.com/huffman///voidhufCanonicalCodeTable (Int64 hcode[HUF_ENCSIZE]){    Int64 n[59];    //    // For each i from 0 through 58, count the    // number of different codes of length i, and    // store the count in n[i].    //    for (int i = 0; i <= 58; ++i)	n[i] = 0;    for (int i = 0; i < HUF_ENCSIZE; ++i)	n[hcode[i]] += 1;    //    // For each i from 58 through 1, compute the    // numerically lowest code with length i, and    // store that code in n[i].    //    Int64 c = 0;    for (int i = 58; i > 0; --i)    {	Int64 nc = ((c + n[i]) >> 1);	n[i] = c;	c = nc;    }    //    // hcode[i] contains the length, l, of the    // code for symbol i.  Assign the next available    // code of length l to the symbol and store both    // l and the code in hcode[i].    //    for (int i = 0; i < HUF_ENCSIZE; ++i)    {	int l = hcode[i];	if (l > 0)	    hcode[i] = l | (n[l]++ << 6);    }}//// Compute Huffman codes (based on frq input) and store them in frq://	- code structure is : [63:lsb - 6:msb] | [5-0: bit length];//	- max code length is 58 bits;//	- codes outside the range [im-iM] have a null length (unused values);//	- original frequencies are destroyed;//	- encoding tables are used by hufEncode() and hufBuildDecTable();//struct FHeapCompare{    bool operator () (Int64 *a, Int64 *b) {return *a > *b;}};voidhufBuildEncTable    (Int64*	frq,	// io: input frequencies [HUF_ENCSIZE], output table     int*	im,	//  o: min frq index     int*	iM)	//  o: max frq index{    //    // This function assumes that when it is called, array frq    // indicates the frequency of all possible symbols in the data    // that are to be Huffman-encoded.  (frq[i] contains the number    // of occurrences of symbol i in the data.)    //    // The loop below does three things:    //    // 1) Finds the minimum and maximum indices that point    //    to non-zero entries in frq:    //    //     frq[im] != 0, and frq[i] == 0 for all i < im    //     frq[iM] != 0, and frq[i] == 0 for all i > iM    //    // 2) Fills array fHeap with pointers to all non-zero    //    entries in frq.    //    // 3) Initializes array hlink such that hlink[i] == i    //    for all array entries.    //    AutoArray <int, HUF_ENCSIZE> hlink;    AutoArray <Int64 *, HUF_ENCSIZE> fHeap;    *im = 0;    while (!frq[*im])	(*im)++;    int nf = 0;    for (int i = *im; i < HUF_ENCSIZE; i++)    {	hlink[i] = i;	if (frq[i])	{	    fHeap[nf] = &frq[i];	    nf++;	    *iM = i;	}    }    //    // Add a pseudo-symbol, with a frequency count of 1, to frq;    // adjust the fHeap and hlink array accordingly.  Function    // hufEncode() uses the pseudo-symbol for run-length encoding.    //    (*iM)++;    frq[*iM] = 1;    fHeap[nf] = &frq[*iM];    nf++;    //    // Build an array, scode, such that scode[i] contains the number    // of bits assigned to symbol i.  Conceptually this is done by    // constructing a tree whose leaves are the symbols with non-zero    // frequency:    //    //     Make a heap that contains all symbols with a non-zero frequency,    //     with the least frequent symbol on top.    //    //     Repeat until only one symbol is left on the heap:    //    //         Take the two least frequent symbols off the top of the heap.    //         Create a new node that has first two nodes as children, and    //         whose frequency is the sum of the frequencies of the first    //         two nodes.  Put the new node back into the heap.    //    // The last node left on the heap is the root of the tree.  For each    // leaf node, the distance between the root and the leaf is the length    // of the code for the corresponding symbol.    //    // The loop below doesn't actually build the tree; instead we compute    // the distances of the leaves from the root on the fly.  When a new    // node is added to the heap, then that node's descendants are linked    // into a single linear list that starts at the new node, and the code    // lengths of the descendants (that is, their distance from the root    // of the tree) are incremented by one.    //    make_heap (&fHeap[0], &fHeap[nf], FHeapCompare());    AutoArray <Int64, HUF_ENCSIZE> scode;    memset (scode, 0, sizeof (Int64) * HUF_ENCSIZE);    while (nf > 1)    {	//	// Find the indices, mm and m, of the two smallest non-zero frq	// values in fHeap, add the smallest frq to the second-smallest	// frq, and remove the smallest frq value from fHeap.	//	int mm = fHeap[0] - frq;	pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());	--nf;	int m = fHeap[0] - frq;	pop_heap (&fHeap[0], &fHeap[nf], FHeapCompare());	frq[m ] += frq[mm];	push_heap (&fHeap[0], &fHeap[nf], FHeapCompare());	//	// The entries in scode are linked into lists with the	// entries in hlink serving as "next" pointers and with	// the end of a list marked by hlink[j] == j.	//	// Traverse the lists that start at scode[m] and scode[mm].	// For each element visited, increment the length of the	// corresponding code by one bit. (If we visit scode[j]	// during the traversal, then the code for symbol j becomes	// one bit longer.)	//	// Merge the lists that start at scode[m] and scode[mm]	// into a single list that starts at scode[m].	//		//	// Add a bit to all codes in the first list.	//	for (int j = m; true; j = hlink[j])	{	    scode[j]++;	    assert (scode[j] <= 58);	    if (hlink[j] == j)	    {		//		// Merge the two lists.		//		hlink[j] = mm;		break;	    }	}	//	// Add a bit to all codes in the second list	//	for (int j = mm; true; j = hlink[j])	{	    scode[j]++;	    assert (scode[j] <= 58);	    if (hlink[j] == j)		break;	}    }    //    // Build a canonical Huffman code table, replacing the code    // lengths in scode with (code, code length) pairs.  Copy the    // code table from scode into frq.    //    hufCanonicalCodeTable (scode);    memcpy (frq, scode, sizeof (Int64) * HUF_ENCSIZE);}//// Pack an encoding table://	- only code lengths, not actual codes, are stored//	- runs of zeroes are compressed as follows:////	  unpacked		packed//	  --------------------------------//	  1 zero		0	(6 bits)//	  2 zeroes		59//	  3 zeroes		60//	  4 zeroes		61//	  5 zeroes		62//	  n zeroes (6 or more)	63 n-6	(6 + 8 bits)//const int SHORT_ZEROCODE_RUN = 59;const int LONG_ZEROCODE_RUN  = 63;const int SHORTEST_LONG_RUN  = 2 + LONG_ZEROCODE_RUN - SHORT_ZEROCODE_RUN;const int LONGEST_LONG_RUN   = 255 + SHORTEST_LONG_RUN;voidhufPackEncTable    (const Int64*	hcode,		// i : encoding table [HUF_ENCSIZE]     int		im,		// i : min hcode index     int		iM,		// i : max hcode index     char**		pcode)		//  o: ptr to packed table (updated){    char *p = *pcode;    Int64 c = 0;    int lc = 0;    for (; im <= iM; im++)    {	int l = hufLength (hcode[im]);	if (l == 0)	{	    int zerun = 1;	    while ((im < iM) && (zerun < LONGEST_LONG_RUN))	    {		if (hufLength (hcode[im+1]) > 0 )	 		    break;		im++;		zerun++;	    }	    if (zerun >= 2)	    {		if (zerun >= SHORTEST_LONG_RUN)		{		    outputBits (6, LONG_ZEROCODE_RUN, c, lc, p);		    outputBits (8, zerun - SHORTEST_LONG_RUN, c, lc, p);		}		else		{		    outputBits (6, SHORT_ZEROCODE_RUN + zerun - 2, c, lc, p);		}		continue;	    }	}	outputBits (6, l, c, lc, p);    }    if (lc > 0)	*p++ = (unsigned char) (c << (8 - lc));    *pcode = p;}//// Unpack an encoding table packed by hufPackEncTable()://voidhufUnpackEncTable    (const char**	pcode,		// io: ptr to packed table (updated)     int		ni,		// i : input size (in bytes)     int		im,		// i : min hcode index     int		iM,		// i : max hcode index     Int64*		hcode)		//  o: encoding table [HUF_ENCSIZE]{    memset (hcode, 0, sizeof (Int64) * HUF_ENCSIZE);    const char *p = *pcode;    Int64 c = 0;    int lc = 0;    for (; im <= iM; im++)    {	if (p - *pcode > ni)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -