imfhuf.cpp

来自「image converter source code」· C++ 代码 · 共 1,073 行 · 第 1/2 页

CPP
1,073
字号
	    unexpectedEndOfTable();	Int64 l = hcode[im] = getBits (6, c, lc, p); // code length	if (l == (Int64) LONG_ZEROCODE_RUN)	{	    if (p - *pcode > ni)		unexpectedEndOfTable();	    int zerun = getBits (8, c, lc, p) + SHORTEST_LONG_RUN;	    if (im + zerun > iM + 1)		tableTooLong();	    while (zerun--)		hcode[im++] = 0;	    im--;	}	else if (l >= (Int64) SHORT_ZEROCODE_RUN)	{	    int zerun = l - SHORT_ZEROCODE_RUN + 2;	    if (im + zerun > iM + 1)		tableTooLong();	    while (zerun--)		hcode[im++] = 0;	    im--;	}    }    *pcode = (char *) p;    hufCanonicalCodeTable (hcode);}//// DECODING TABLE BUILDING////// Build a decoding hash table based on the encoding table hcode://	- short codes (<= HUF_DECBITS) are resolved with a single table access;//	- long code entry allocations are not optimized, because long codes are//	  unfrequent;//	- decoding tables are used by hufDecode();//voidhufBuildDecTable    (const Int64*	hcode,		// i : encoding table     int		im,		// i : min index in hcode     int		iM,		// i : max index in hcode     HufDec *		hdecod)		//  o: (allocated by caller)     					//     decoding table [HUF_DECSIZE]{    //    // Init hashtable & loop on all codes    //    memset (hdecod, 0, sizeof (HufDec) * HUF_DECSIZE);    for (; im <= iM; im++)    {	Int64 c = hufCode (hcode[im]);	int l = hufLength (hcode[im]);	if (c >> l)	{	    //	    // Error: c is supposed to be an l-bit code,	    // but c contains a value that is greater	    // than the largest l-bit number.	    //	    invalidTableEntry();	}	if (l > HUF_DECBITS)	{	    //	    // Long code: add a secondary entry	    //	    HufDec *pl = hdecod + (c >> (l - HUF_DECBITS));	    if (pl->len)	    {		//		// Error: a short code has already		// been stored in table entry *pl.		//		invalidTableEntry();	    }	    pl->lit++;	    if (pl->p)	    {		int *p = pl->p;		pl->p = new int [pl->lit];		for (int i = 0; i < pl->lit - 1; ++i)		    pl->p[i] = p[i];		delete [] p;	    }	    else	    {		pl->p = new int [1];	    }	    pl->p[pl->lit - 1]= im;	}	else if (l)	{	    //	    // Short code: init all primary entries	    //	    HufDec *pl = hdecod + (c << (HUF_DECBITS - l));	    for (Int64 i = 1 << (HUF_DECBITS - l); i > 0; i--, pl++)	    {		if (pl->len || pl->p)		{		    //		    // Error: a short code or a long code has		    // already been stored in table entry *pl.		    //		    invalidTableEntry();		}		pl->len = l;		pl->lit = im;	    }	}    }}//// Free the long code entries of a decoding table built by hufBuildDecTable()//voidhufFreeDecTable (HufDec *hdecod)	// io: Decoding table{    for (int i = 0; i < HUF_DECSIZE; i++)    {	if (hdecod[i].p)	{	    delete [] hdecod[i].p;	    hdecod[i].p = 0;	}    }}//// ENCODING//inline voidoutputCode (Int64 code, Int64 &c, int &lc, char *&out){    outputBits (hufLength (code), hufCode (code), c, lc, out);}inline voidsendCode (Int64 sCode, int runCount, Int64 runCode,	  Int64 &c, int &lc, char *&out){    static const int RLMIN = 32; // min count to activate run-length coding    if (runCount > RLMIN)    {	outputCode (sCode, c, lc, out);	outputCode (runCode, c, lc, out);	outputBits (8, runCount, c, lc, out);    }    else    {	while (runCount-- >= 0)	    outputCode (sCode, c, lc, out);    }}//// Encode (compress) ni values based on the Huffman encoding table hcode://inthufEncode				// return: output size (in bits)    (const Int64*  	    hcode,	// i : encoding table     const unsigned short*  in,		// i : uncompressed input buffer     const int     	    ni,		// i : input buffer size (in bytes)     int           	    rlc,	// i : rl code     char*         	    out)	//  o: compressed output buffer{    char *outStart = out;    Int64 c = 0;	// bits not yet written to out    int lc = 0;		// number of valid bits in c (LSB)    int s = in[0];    int cs = 0;    //    // Loop on input values    //    for (int i = 1; i < ni; i++)    {	//	// Count same values or send code	//	if (s == in[i] && cs < 255)	{	    cs++;	}	else	{	    sendCode (hcode[s], cs, hcode[rlc], c, lc, out);	    cs=0;	}	s = in[i];    }    //    // Send remaining code    //    sendCode (hcode[s], cs, hcode[rlc], c, lc, out);    if (lc)	*out = (c << (8 - lc)) & 0xff;    return (out - outStart) * 8 + lc;}//// DECODING////// In order to force the compiler to inline them,// getChar() and getCode() are implemented as macros// instead of "inline" functions.//#define getChar(c, lc, in)			\{						\    c = (c << 8) | *(unsigned char *)(in++);	\    lc += 8;					\}#define getCode(po, rlc, c, lc, in, out, oe)	\{						\    if (po == rlc)				\    {						\	if (lc < 8)				\	    getChar(c, lc, in);			\						\	lc -= 8;				\						\	unsigned char cs = (c >> lc);		\						\	if (out + cs > oe)			\	    tooMuchData();			\						\	unsigned short s = out[-1];		\						\	while (cs-- > 0)			\	    *out++ = s;				\    }						\    else if (out < oe)				\    {						\	*out++ = po;				\    }						\    else					\    {						\	tooMuchData();				\    }						\}//// Decode (uncompress) ni bits based on encoding & decoding tables://voidhufDecode    (const Int64 * 	hcode,	// i : encoding table     const HufDec * 	hdecod,	// i : decoding table     const char* 	in,	// i : compressed input buffer     int		ni,	// i : input size (in bits)     int		rlc,	// i : run-length code     int		no,	// i : expected output size (in bytes)     unsigned short*	out)	//  o: uncompressed output buffer{    Int64 c = 0;    int lc = 0;    unsigned short * outb = out;    unsigned short * oe = out + no;    const char * ie = in + (ni + 7) / 8; // input byte size    //    // Loop on input bytes    //    while (in < ie)    {	getChar (c, lc, in);	//	// Access decoding table	//	while (lc >= HUF_DECBITS)	{	    const HufDec pl = hdecod[(c >> (lc-HUF_DECBITS)) & HUF_DECMASK];	    if (pl.len)	    {		//		// Get short code		//		lc -= pl.len;		getCode (pl.lit, rlc, c, lc, in, out, oe);	    }	    else	    {		if (!pl.p)		    invalidCode(); // wrong code		//		// Search long code		//		int j;		for (j = 0; j < pl.lit; j++)		{		    int	l = hufLength (hcode[pl.p[j]]);		    while (lc < l && in < ie)	// get more bits			getChar (c, lc, in);		    if (lc >= l)		    {			if (hufCode (hcode[pl.p[j]]) ==				((c >> (lc - l)) & ((Int64(1) << l) - 1)))			{			    //			    // Found : get long code			    //			    lc -= l;			    getCode (pl.p[j], rlc, c, lc, in, out, oe);			    break;			}		    }		}		if (j == pl.lit)		    invalidCode(); // Not found	    }	}    }    //    // Get remaining (short) codes    //    int i = (8 - ni) & 7;    c >>= i;    lc -= i;    while (lc > 0)    {	const HufDec pl = hdecod[(c << (HUF_DECBITS - lc)) & HUF_DECMASK];	if (pl.len)	{	    lc -= pl.len;	    getCode (pl.lit, rlc, c, lc, in, out, oe);	}	else	{	    invalidCode(); // wrong (long) code	}    }    if (out - outb != no)	notEnoughData ();}voidcountFrequencies (Int64 freq[HUF_ENCSIZE],		  const unsigned short data[/*n*/],		  int n){    for (int i = 0; i < HUF_ENCSIZE; ++i)	freq[i] = 0;    for (int i = 0; i < n; ++i)	++freq[data[i]];}voidwriteUInt (char buf[4], unsigned int i){    unsigned char *b = (unsigned char *) buf;    b[0] = i;    b[1] = i >> 8;    b[2] = i >> 16;    b[3] = i >> 24;}unsigned intreadUInt (const char buf[4]){    const unsigned char *b = (const unsigned char *) buf;    return ( b[0]        & 0x000000ff) |	   ((b[1] <<  8) & 0x0000ff00) |	   ((b[2] << 16) & 0x00ff0000) |	   ((b[3] << 24) & 0xff000000);}} // namespace//// EXTERNAL INTERFACE//inthufCompress (const unsigned short raw[],	     int nRaw,	     char compressed[]){    if (nRaw == 0)	return 0;    AutoArray <Int64, HUF_ENCSIZE> freq;    countFrequencies (freq, raw, nRaw);    int im, iM;    hufBuildEncTable (freq, &im, &iM);    char *tableStart = compressed + 20;    char *tableEnd   = tableStart;    hufPackEncTable (freq, im, iM, &tableEnd);    int tableLength = tableEnd - tableStart;    char *dataStart = tableEnd;    int nBits = hufEncode (freq, raw, nRaw, iM, dataStart);    int dataLength = (nBits + 7) / 8;    writeUInt (compressed,      im);    writeUInt (compressed +  4, iM);    writeUInt (compressed +  8, tableLength);    writeUInt (compressed + 12, nBits);    writeUInt (compressed + 16, 0);	// room for future extensions    return dataStart + dataLength - compressed;}voidhufUncompress (const char compressed[],	       int nCompressed,	       unsigned short raw[],	       int nRaw){    if (nCompressed == 0)    {	if (nRaw != 0)	    notEnoughData();	return;    }    int im = readUInt (compressed);    int iM = readUInt (compressed + 4);    // int tableLength = readUInt (compressed + 8);    int nBits = readUInt (compressed + 12);    if (im < 0 || im >= HUF_ENCSIZE || iM < 0 || iM >= HUF_ENCSIZE)	invalidTableSize();    const char *ptr = compressed + 20;    AutoArray <Int64, HUF_ENCSIZE> freq;    AutoArray <HufDec, HUF_DECSIZE> hdec;    hufUnpackEncTable (&ptr, nCompressed - (ptr - compressed), im, iM, freq);    try    {	if (nBits > 8 * (nCompressed - (ptr - compressed)))	    invalidNBits();	hufBuildDecTable (freq, im, iM, hdec);	hufDecode (freq, hdec, ptr, nBits, iM, nRaw, raw);    }    catch (...)    {	hufFreeDecTable (hdec);	throw;    }    hufFreeDecTable (hdec);}} // namespace Imf

⌨️ 快捷键说明

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