/tags/jet3d_dev_msvc2003/source/Engine/JetEngine/Bitmap/Compression/huffman2.c
C | 1880 lines | 1309 code | 253 blank | 318 comment | 243 complexity | 76f8590de9253f61631b8f2d5c8f5540 MD5 | raw file
- /****************************************************************************************/
- /* HUFFMAN2.C */
- /* */
- /* Author: */
- /* Description: */
- /* */
- /* The contents of this file are subject to the Jet3D Public License */
- /* Version 1.02 (the "License"); you may not use this file except in */
- /* compliance with the License. You may obtain a copy of the License at */
- /* http://www.jet3d.com */
- /* */
- /* Software distributed under the License is distributed on an "AS IS" */
- /* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See */
- /* the License for the specific language governing rights and limitations */
- /* under the License. */
- /* */
- /* The Original Code is Jet3D, released December 12, 1999. */
- /* Copyright (C) 1996-1999 Eclipse Entertainment, L.L.C. All Rights Reserved */
- /* */
- /****************************************************************************************/
- /******
- problem :
- encoding/decoding when GotNumSymbols == 1 needs to be handled as
- a special case.
- I think encoding is Ok, but DecodeBuildTree needs to set NodeBase->Char
- to be the one char to code
- --
- Macros need to be updated to handle this case
- *********/
- /*
- * notez : there's kind of a bug in FastDecode :
- * if the last code in decodes to more than one char, you might
- * skip more bits than were written
- *
- * this can mess you up in merge-bit-stream cases
- *
- *
- * note: this is handled properly by FastDecodeArray
- *
- */
- /*
- * notez : you must PackCodeLens BEFORE BuildEncodeTable
- * in order to set Min & Max CodeLen
- * if you don't PackCodeLens, call SetMinMaxCodeLen
- */
- /*
- *
- * Huffman2 : 7-5-96
- *
- * not a general purpose Huffman utility
- * does not generate Huffman codes. Codes have same lengths, but
- * values are ordered thus:
- * for each code length, values are ordered by alphabetic order
- *
- * ---
- *
- * Encode BuildTree time is nearly identical to old Huffman
- * Decode BuildTree time is MUCH shorter!
- * EncodeC time is identical
- * DecodeC time is shorter
- *
- * ---
- *
- * 7-6-95 :
- * FastDecode ! uses table lookup for multi-symbol-at-a-time operation!
- *
- * 7-7-95
- * I just peeked the IJG JPEG source & discovered that they use
- * this method with MaxNumMadeChars = 1
- *
- */
- //#define DEBUG
- /* DEBUG toggles some tests which
- garauntee proper operation, but take some time to do */
- //#define DO_MEMCLEARS
- /* DO_MEMCLEARS toggles some unnecessary memclears
- probably a good idea to turn it on for debug purposes */
- #define PACKCODES_TOPSYM
- /* if this is on, then in PackCodeLens, the value of the highest
- non-zero-count symbol is written, and codes are only written up
- to that symbol ; this helps compression a good deal in most cases */
- /*
- *
- * Modularized Static Huffman encoding
- *
- * Notes: works on a LBitIOInfo structure
- * this structure must be independently allocated and destroyd
- *
- * Uses the O(n) Huffman algorithm with QuickSort, RadixSort, or NoSort
- * NOTEZ: RadixSort assumes counts are bounded in the range [0,MaxCharCount]
- * if AlphaSize > 64 or so, use the RadixSort
- *
- * You are responsible for calling
- * LBitIO_FlushWrite(HI->BII);
- * yourself. It is no longer done in EncodeCDone
- *
- * You must also call
- * LBitIO_InitRead(HI->BII);
- * yourself before doing any reads. It is no longer done in DecodeCInit
- *
- * 7-4-95 new stuff:
- * 1. charcounts are now packed as codelengths only (much better packing)
- * 2. this creates a problem : two chars with different counts but the
- * same code length are no longer distinguishable by the decoder,
- * but they were distinguished by the encoder!
- * 3. result : Huffman2 : uses manual code assignment
- *
- *
- */
- #include <limits.h>
- #include "Utility.h"
- #include "MemPool.h"
- #include "lbitio.h"
- #include "IntMath.h"
- #pragma warning(disable : 4244)
- #ifdef DEBUG
- #include <stdio.h>
- #endif
- #include "huffman2.h"
- #define memclearFast(m,s) memclear(m,s*4)
- #define FreeMem(m,s) destroy(m)
- //protos:
- struct Huff2Info * Huff2_Init(long NumSymbols,struct LBitIOInfo * BII,long SortType);
- void Huff2_CleanUp(struct Huff2Info *HI);
- void Huff2_GetMaxCharCount(struct Huff2Info *HI,long * CharCounts);
- void Huff2_ScaleCounts(struct Huff2Info *HI,long * CharCounts,long MaxVal);
- jeBoolean Huff2_BuildCodeLens(struct Huff2Info *HI,long *CharCounts);
- jeBoolean Huff2_BuildEncodeTable(struct Huff2Info *HI);
- jeBoolean Huff2_BuildDecodeTable(struct Huff2Info *HI);
- jeBoolean Huff2_BuildFastDecodeTable(struct Huff2Info *HI);
- void Huff2_EncodeC(struct Huff2Info *HI,uint16 C);
- uint16 Huff2_DecodeC(struct Huff2Info *HI);
- uint16 Huff2_FastDecodeC(struct Huff2Info *HI);
- jeBoolean Huff2_FastDecodeArray(struct Huff2Info *HI,uint8 * Array,long ArrayLen);
- jeBoolean Huff2_FindDecodeOne(struct Huff2Info *HI);
- void Huff2_SetMinMaxCodeLen(struct Huff2Info *HI);
- void Huff2_PackCodeLens(struct Huff2Info *HI);
- void Huff2_UnPackCodeLens(struct Huff2Info *HI);
- void Huff2_PackCodeLens_Delta(struct Huff2Info *HI,long * LastCodeLens);
- void Huff2_UnPackCodeLens_Delta(struct Huff2Info *HI,long * LastCodeLens);
- //sort protos:
- jeBoolean Huff2RadixSort(struct Huff2CodeNode ** BucketArray,
- long MaxCharCount,struct Huff2CodeNode ** Array,long ArraySize);
- void Huff2QuickSort(long Left,long Right);
- struct Huff2CodeNode ** Huff2QuickSortArray; //global for recursion non-stacking
- //functions:
- /*
- */
- struct Huff2Info * Huff2_Init(long NumSymbols,struct LBitIOInfo * BII,long SortType)
- {
- struct Huff2Info * HI;
- if ( (HI = (struct Huff2Info *)jeRam_AllocateClear(sizeof(struct Huff2Info))) == NULL )
- return(NULL);
- HI->GotNumSymbols = 0;
- HI->NumSymbols = NumSymbols;
- HI->MaxCharCount = LONG_MAX;
- HI->BII = BII;
- HI->SortType = SortType;
- HI->CodeNodeHunkI = 0;
- if ( (HI->CodeLenTable = (long *)jeRam_AllocateClear(HI->NumSymbols*sizeof(long))) == NULL )
- {
- Huff2_CleanUp(HI);
- return(NULL);
- }
- if ( (HI->NumCodesOfLen = (long *)jeRam_AllocateClear(32*sizeof(long))) == NULL )
- {
- Huff2_CleanUp(HI);
- return(NULL);
- }
- if ( (HI->CodePrefixByLen = (uint32 *)jeRam_AllocateClear(32*sizeof(uint32))) == NULL )
- {
- Huff2_CleanUp(HI);
- return(NULL);
- }
- return(HI);
- }
- /*
- */
- void Huff2_CleanUp(struct Huff2Info * HI)
- {
- FreeMem(HI->NodeWork,sizeofpointer*HI->NumSymbols);
- FreeMem(HI->MadeNodeWork,sizeofpointer*HI->NumSymbols*2);
- FreeMem(HI->CodeLenTable,HI->NumSymbols*sizeof(long));
- FreeMem(HI->NumCodesOfLen,32*sizeof(long));
- FreeMem(HI->CodePrefixByLen,32*sizeof(uint32));
- FreeMem(HI->CodeNodeHunk,sizeof(struct Huff2CodeNode)*2*HI->NumSymbols);
- FreeMem(HI->StackArray,2*(HI->NumSymbols)*sizeof(uint32));
- FreeMem(HI->EnDe_codeTable,HI->EnDe_codeTableLen);
- if ( HI->SortType == HUFF2_SORT_RADIX )
- {
- FreeMem(HI->SortWork,sizeofpointer*(HI->MaxCharCount + 1));
- }
- FreeMem(HI,sizeof(struct Huff2Info));
- }
- /*
- * Compute the codelens into Huff2Info from the CharCounts array
- *
- NOTEZ: MadeNodeWork is large enough, but you may have the problem of looping
- i.e. ( (MadeNodeWorkIn - MadeNodeWorkOut) < NumSymbols ) is just fine,
- the problem is ( MadeNodeWorkIn < NumSymbols ) isn't JE_TRUE
- thus all made-array lookups are done: [MadeNodeWorkIn % NumSymbols]
- 10-15-95 : alloced MadeNodeWork to double length so as to eliminate this.
- */
- /*
- *
- * return values :
- * 1 = all ok
- * 0 = error
- *
- */
- jeBoolean Huff2_BuildCodeLens(struct Huff2Info *HI,long *CharCounts)
- {
- register struct Huff2CodeNode * CurNode;
- register struct Huff2CodeNode ** NodeWork;
- register long i,NumSymbols,GotNumSymbols;
- /*long swapchar;*/
- if ( !HI->CodeNodeHunk || !HI->NodeWork || !HI->MadeNodeWork )
- {
- if ( HI->CodeNodeHunk || HI->NodeWork || HI->MadeNodeWork )
- {
- return(0);
- }
- HI->NodeWork = (struct Huff2CodeNode **)jeRam_Allocate(sizeofpointer*HI->NumSymbols);
- HI->MadeNodeWork = (struct Huff2CodeNode **)jeRam_Allocate(sizeofpointer*2*HI->NumSymbols);
- HI->CodeNodeHunk = (struct Huff2CodeNode *)jeRam_Allocate(sizeof(struct Huff2CodeNode)*2*HI->NumSymbols);
- if ( !HI->CodeNodeHunk || !HI->NodeWork || !HI->MadeNodeWork )
- {
- return(0);
- }
- }
- /* reset, if this is an already-used Huff2Info */
- if ( HI->NodeBase )
- {
- HI->NodeBase = NULL;
- HI->CodeNodeHunkI = 0;
- HI->GotNumSymbols = 0;
- HI->MaxCharCount = LONG_MAX;
- HI->CodeNodeHunkI = 0;
- HI->MinCodeLen = HI->MaxCodeLen = 0;
- #ifdef DO_MEMCLEARS
- memclearFast((long *)HI->CodeNodeHunk,sizeof(struct Huff2CodeNode)*HI->NumSymbols);
- memclearFast((long *)HI->NodeWork,HI->NumSymbols);
- memclearFast((long *)HI->MadeNodeWork,HI->NumSymbols);
- #endif // DO_MEMCLEARS
- memclearFast((long *)HI->CodeLenTable,HI->NumSymbols);
- memclearFast((long *)HI->NumCodesOfLen,32);
- memclearFast((long *)HI->CodePrefixByLen,32);
- }
- NodeWork = HI->NodeWork;
- NumSymbols = HI->NumSymbols;
- /*
- * Read the chars into NodeWork
- * packing out the NULLs
- *
- */
- GotNumSymbols=0;
- for(i=0;i<NumSymbols;i++) /* $ 12% !! */
- {
- if ( CharCounts[i] > 0 )
- {
- NodeWork[GotNumSymbols] = HI->CodeNodeHunk + HI->CodeNodeHunkI; HI->CodeNodeHunkI++;
- NodeWork[GotNumSymbols]->Char = i;
- NodeWork[GotNumSymbols]->Count = CharCounts[i];
- NodeWork[GotNumSymbols]->Up = NodeWork[GotNumSymbols]->Down = NULL;
- GotNumSymbols++;
- }
- }
- /* !!!! you should not do any huffman coding if this ever happens ! */
- /* NOTEZ: BuildEncodeTable WILL fail ! */
- /* PackCodeLens & UnPackCodeLens will work */
- HI->GotNumSymbols = GotNumSymbols;
- if ( GotNumSymbols < 2 )
- {
- if ( GotNumSymbols == 0 )
- {
- return(1);
- }
- else
- {
- HI->NodeBase = NodeWork[0];
- HI->NodeBase->Up = NULL;
- HI->NodeBase->Down = NULL;
- HI->CodeLenTable[HI->NodeBase->Char] = 1;
- HI->NumCodesOfLen[1] = 1;
- /* call PackCodeLens anyway, so the decoder knows which char to copy */
- return(1);
- }
- }
- /*
- * sort NodeWork in order of ascending counts
- *
- */
- switch(HI->SortType)
- {
- case HUFF2_SORT_NONE:
- break;
- case HUFF2_SORT_RADIX:
- if ( ! HI->SortWork )
- {
- if ( HI->MaxCharCount == LONG_MAX )
- {
- return(0);
- }
- if ( (HI->SortWork = jeRam_Allocate(sizeofpointer*(HI->MaxCharCount + 1))) == NULL )
- {
- return(0);
- }
- }
- if ( ! Huff2RadixSort((struct Huff2CodeNode **)HI->SortWork,
- HI->MaxCharCount,NodeWork,GotNumSymbols) ) return(0);
- break;
- case HUFF2_SORT_QSORT:
- Huff2QuickSortArray = NodeWork;
- Huff2QuickSort(0,GotNumSymbols-1);
- break;
- default:
- return(0);
- break;
- }
- /* sort puts lowest value of ->Count first */
- /* register the tree-building variables */
- {
- register long MadeNodeWorkIn,MadeNodeWorkOut,NodeWorkOut;
- register struct Huff2CodeNode ** MadeNodeWork;
- MadeNodeWork = HI->MadeNodeWork;
- NodeWorkOut=0;
- MadeNodeWorkIn = 0;
- MadeNodeWorkOut = 0;
- /*
- * Build the tree while there are more leaf-nodes to go
- *
- */
- while( NodeWorkOut < (GotNumSymbols-1) ) /* $ 38 % */
- {
- CurNode = HI->CodeNodeHunk + HI->CodeNodeHunkI; HI->CodeNodeHunkI++;
- CurNode->Char = HUFF2_CODE_BRANCH;
- #ifdef DEBUG
- if ( HI->CodeNodeHunkI >= (NumSymbols*2) )
- {
- BrandoError(" HI->CodeNodeHunkI >= (NumSymbols*2) !");
- exit(1);
- }
- #endif // DEBUG
- /*
- * get the lowest two
- * if counts are equal, use a madenode before a leafnode
- *
- */
- if ( MadeNodeWorkOut < MadeNodeWorkIn )
- {
- if ( NodeWork[NodeWorkOut]->Count < MadeNodeWork[MadeNodeWorkOut]->Count )
- {
- CurNode->Down = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- else
- {
- CurNode->Down = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- }
- if ( MadeNodeWorkOut < MadeNodeWorkIn )
- {
- if ( NodeWork[NodeWorkOut]->Count < MadeNodeWork[MadeNodeWorkOut]->Count )
- {
- CurNode->Up = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- else
- {
- CurNode->Up = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- }
- }
- else
- {
- CurNode->Up = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- }
- else
- {
- CurNode->Down = NodeWork[NodeWorkOut]; NodeWorkOut++;
- CurNode->Up = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- /* ->Down gets the lower valued count & the lower valued character */
- /* make sure lower char is on the Down pointer */
- /* notez: this is only needed in encode ! */
- /* don't bother swapping the counts, they're not needed anymore */
- /*
- if ( CurNode->Down->Char != HUFF2_CODE_BRANCH &&
- CurNode->Up->Char != HUFF2_CODE_BRANCH )
- {
- if ( CurNode->Down->Char > CurNode->Up->Char )
- {
- swapchar = CurNode->Down->Char;
- CurNode->Down->Char = CurNode->Up->Char;
- CurNode->Up->Char = swapchar;
- }
- }
- */
- /*
- * put them into a MadeNode
- *
- */
- MadeNodeWork[MadeNodeWorkIn] = CurNode; MadeNodeWorkIn++;
- CurNode->Count = CurNode->Down->Count + CurNode->Up->Count;
- }
- /*
- * we stop the prior loop when there are less than 2 nodework symbols left
- * if there is only one left, this loops until it is eaten off
- *
- */
- while ( NodeWorkOut < GotNumSymbols && MadeNodeWorkOut < MadeNodeWorkIn )
- {
- CurNode = HI->CodeNodeHunk + HI->CodeNodeHunkI; HI->CodeNodeHunkI++;
- CurNode->Char = HUFF2_CODE_BRANCH;
- #ifdef DEBUG
- if ( HI->CodeNodeHunkI >= (NumSymbols*2) )
- {
- BrandoError(" HI->CodeNodeHunkI >= (NumSymbols*2) !");
- exit(1);
- }
- #endif // DEBUG
- if ( NodeWork[NodeWorkOut]->Count < MadeNodeWork[MadeNodeWorkOut]->Count )
- {
- CurNode->Down = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- else
- {
- CurNode->Down = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- }
- if ( MadeNodeWorkOut < MadeNodeWorkIn )
- {
- if ( NodeWorkOut < GotNumSymbols )
- {
- if ( NodeWork[NodeWorkOut]->Count < MadeNodeWork[MadeNodeWorkOut]->Count )
- {
- CurNode->Up = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- else
- {
- CurNode->Up = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- }
- }
- else
- {
- CurNode->Up = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- }
- }
- else
- {
- CurNode->Up = NodeWork[NodeWorkOut]; NodeWorkOut++;
- }
- MadeNodeWork[MadeNodeWorkIn] = CurNode; MadeNodeWorkIn++;
- CurNode->Count = CurNode->Down->Count + CurNode->Up->Count;
- }
- /*
- * there may still be extras in MadeNodeWork
- *
- */
- while ( MadeNodeWorkOut < (MadeNodeWorkIn-1) )
- {
- CurNode = HI->CodeNodeHunk + HI->CodeNodeHunkI; HI->CodeNodeHunkI++;
- CurNode->Char = HUFF2_CODE_BRANCH;
- CurNode->Down = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- CurNode->Up = MadeNodeWork[MadeNodeWorkOut]; MadeNodeWorkOut++;
- #ifdef DEBUG
- if ( HI->CodeNodeHunkI >= (NumSymbols*2) )
- {
- BrandoError(" HI->CodeNodeHunkI >= (NumSymbols*2) !");
- exit(1);
- }
- #endif // DEBUG
- MadeNodeWork[MadeNodeWorkIn] = CurNode; MadeNodeWorkIn++;
- CurNode->Count = CurNode->Down->Count + CurNode->Up->Count;
- }
- /*
- * grab the base node out
- *
- */
- HI->NodeBase = MadeNodeWork[(MadeNodeWorkIn-1)];
- if ( HI->NodeBase == NULL )
- {
- return(0); /* debugger catch point */
- }
- }
- /* end tree-building registered variables */
- /* now read out the codelens into an array */
- {
- long * CodeLenTable;
- long * NumCodesOfLen;
- register struct Huff2CodeNode * CurNode;
- register uint32 CurCodeLen;
- register uint32 GotC;
- register uint32 * StackArray;
- register long StackI;
-
- if ( ! HI->StackArray )
- {
- if ( (HI->StackArray = (uint32 *)jeRam_Allocate(2*(HI->NumSymbols)*sizeof(uint32))) == NULL )
- return(0);
- }
-
- NumCodesOfLen = HI->NumCodesOfLen;
- CodeLenTable = HI->CodeLenTable;
- StackArray = HI->StackArray;
-
- StackArray[0] = (uint32) HI->NodeBase;
- StackArray[1] = 0;
- StackI = 2;
- while ( StackI > 0 ) /* $ 15% */
- {
- StackI--;
- CurCodeLen = StackArray[StackI];
- StackI--;
- CurNode = (struct Huff2CodeNode *) StackArray[StackI];
-
- /* traverse all Up branches w/o Stack bumping
- remember the Down branches as you go
- once you reach the end of an Up, go back and get the
- most recent Down & traverse it
- */
-
- while ( CurNode )
- {
- GotC = CurNode->Char;
- if ( GotC == HUFF2_CODE_BRANCH )
- {
- CurCodeLen++;
- #ifdef DEBUG
- if ( CurCodeLen > 31 )
- {
- fprintf(stderr,"CodeLen > 31 !");
- return(0);
- }
- #endif
- if ( CurNode->Down )
- {
- GotC = CurNode->Down->Char;
- if ( GotC == HUFF2_CODE_BRANCH )
- {
- StackArray[StackI++] = (uint32) CurNode->Down;
- StackArray[StackI++] = CurCodeLen;
-
- #ifdef DEBUG
- if ( StackI >= (HI->NumSymbols * 2) )
- {
- BrandoError("Stack usage higher than expected!");
- exit(10);
- }
- #endif
-
- }
- else
- {
- CodeLenTable[GotC] = CurCodeLen;
- NumCodesOfLen[CurCodeLen] ++;
- }
- }
-
- CurNode = CurNode->Up;
- }
- else
- {
- CodeLenTable[GotC] = CurCodeLen;
- NumCodesOfLen[CurCodeLen] ++;
- CurNode = NULL;
- }
- }
-
- }
-
- }
- /* end codelen-retrieval registered variables */
- return(1);
- }
- /*
- * at this point CodeLenTable & NumCodesOfLen are filled out
- *
- */
- jeBoolean Huff2_BuildEncodeTable(struct Huff2Info *HI)
- {
- uint32 LastCodePrefix;
- uint32 * CodePrefixByLen;
- uint32 * CharToCodeTable;
- long * CodeLenTable;
- long * NumCodesOfLen;
- long NumSymbols;
- long i;
- long CurCodeLen;
- uint32 CurCode;
- if ( HI->GotNumSymbols < 2 ) return(1);
- NumSymbols = HI->NumSymbols;
- if ( HI->MaxCodeLen == 0 )
- return(0);
- if ( HI->MaxCodeLen > 30 )
- return(0);
- if ( HI->EnDe_codeTable )
- {
- CharToCodeTable = (uint32 *) HI->EnDe_codeTable;
- memclear((long *)CharToCodeTable,HI->EnDe_codeTableLen);
- }
- else
- {
- if ( (CharToCodeTable = (uint32 *)jeRam_AllocateClear(NumSymbols*sizeof(uint32))) == NULL )
- return(0);
- HI->EnDe_codeTable = (void *) CharToCodeTable;
- HI->EnDe_codeTableLen = NumSymbols*sizeof(uint32);
- }
- CodePrefixByLen = HI->CodePrefixByLen;
- CodeLenTable = HI->CodeLenTable;
- NumCodesOfLen = HI->NumCodesOfLen;
- LastCodePrefix = 0;
- CodePrefixByLen[HI->MinCodeLen] = 0;
- for(i=(HI->MinCodeLen);i<(HI->MaxCodeLen);)
- {
- LastCodePrefix = (LastCodePrefix + NumCodesOfLen[i]) << 1;
- i++;
- CodePrefixByLen[i] = LastCodePrefix;
- }
- for(i=0;i<NumSymbols;i++)
- {
- CurCodeLen = CodeLenTable[i];
- if ( CurCodeLen > 0 )
- {
- CurCode = CodePrefixByLen[CurCodeLen]++;
- CharToCodeTable[i] = CurCode;
- }
- }
- return(1);
- }
- /*
- * at this point CodeLenTable & NumCodesOfLen are filled out
- *
- */
- jeBoolean Huff2_BuildDecodeTable(struct Huff2Info *HI)
- {
- uint32 BaseCodeByLen[32]; /* I'm lazy! So sue me! */
- uint32 LastCodePrefix;
- uint32 * CodePrefixByLen;
- uint16 * DecodeTable;
- long * CodeLenTable;
- long * NumCodesOfLen;
- long NumSymbols;
- long i,CurCodeLen;
- uint32 CurCode,PackedCode;
- long NumCodesOfLowerLen;
- if ( HI->GotNumSymbols < 2 ) return( Huff2_FindDecodeOne(HI) );
- NumSymbols = HI->NumSymbols;
- if ( HI->MaxCodeLen == 0 )
- return(0);
- if ( HI->MaxCodeLen > 30 )
- return(0);
- if ( HI->EnDe_codeTable )
- {
- DecodeTable = (uint16 *) HI->EnDe_codeTable;
- memclear((long *)DecodeTable,HI->EnDe_codeTableLen);
- }
- else
- {
- HI->EnDe_codeTableLen = 2*NumSymbols*sizeof(uint16);
- if ( (DecodeTable = (uint16 *)jeRam_AllocateClear(HI->EnDe_codeTableLen)) == NULL )
- return(0);
- HI->EnDe_codeTable = (void *) DecodeTable;
- }
- CodePrefixByLen = HI->CodePrefixByLen;
- CodeLenTable = HI->CodeLenTable;
- NumCodesOfLen = HI->NumCodesOfLen;
- LastCodePrefix = 0;
- NumCodesOfLowerLen = 0;
- CodePrefixByLen[HI->MinCodeLen] = 0;
- BaseCodeByLen[HI->MinCodeLen] = 0;
- for(i=(HI->MinCodeLen);i<(HI->MaxCodeLen);)
- {
- LastCodePrefix = (LastCodePrefix + NumCodesOfLen[i]) << 1;
- NumCodesOfLowerLen += NumCodesOfLen[i];
- i++;
- CodePrefixByLen[i] = LastCodePrefix;
- BaseCodeByLen[i] = LastCodePrefix - NumCodesOfLowerLen;
- }
- for(i=0;i<NumSymbols;i++)
- {
- CurCodeLen = CodeLenTable[i];
- if ( CurCodeLen > 0 )
- {
- CurCode = CodePrefixByLen[CurCodeLen]++;
- PackedCode = CurCode - BaseCodeByLen[CurCodeLen];
- DecodeTable[PackedCode] = CurCodeLen;
- DecodeTable[PackedCode+NumSymbols] = i;
- }
- }
- for(i=(HI->MinCodeLen);i<=(HI->MaxCodeLen);i++)
- {
- CodePrefixByLen[i] = BaseCodeByLen[i];
- }
- return(1);
- }
- /*
- * The FastDecodeTable is a raw 8 bit table (256 entries)
- * it is indexed by the next 8 bits of the input bitstream
- * and the value of the table is :
- * number of bits used (max of 8) = 3 bits -> 1byte
- * number of chars made (max of 4) = 2 bits -> 1 byte
- * values of chars made (max of 4) = 8 bytes
- * total size = 256*10 = 2560 bytes (not bad!)
- * ( note that this could be as low as 256*5 = 1280 bytes )
- *
- * note that you must also keep the old decodetable around,
- * in case the code is longer than 8 bits ( numberofcharsmade == 0 )
- *
- * <> todo: make this routine take the number of bits of the table
- * as a parameter
- *
- */
- jeBoolean Huff2_BuildFastDecodeTable(struct Huff2Info *HI)
- {
- struct FastDecodeItem * FastDecodeTable;
- uint16 * DecodeTable;
- long NumSymbols;
- long Huff2CodeLen;
- uint32 CurCode,StartCode,Huff2Code,CheckCode,ReadCodeMask,PackedCode;
- long DecodeTableLen,FastDecodeTableLen;
- long MinCodeLen,NumBitsUsed;
- uint16 GotChar;
- uint32 * CodePrefixByLen;
- if ( HI->GotNumSymbols < 2 ) return( Huff2_FindDecodeOne(HI) );
- CodePrefixByLen = HI->CodePrefixByLen;
- NumSymbols = HI->NumSymbols;
- MinCodeLen = HI->MinCodeLen;
- if ( HI->MaxCodeLen == 0 )
- return(0);
- if ( HI->MaxCodeLen > 30 )
- return(0);
- DecodeTableLen = 2*NumSymbols*sizeof(uint16);
- FastDecodeTableLen = 256*sizeof(struct FastDecodeItem);
- if ( HI->EnDe_codeTable )
- {
- DecodeTable = (uint16 *)HI->EnDe_codeTable;
- FastDecodeTable = (struct FastDecodeItem *) ( (char *)HI->EnDe_codeTable + DecodeTableLen );
- memclear((long *)DecodeTable,DecodeTableLen);
- memclear((long *)FastDecodeTable,FastDecodeTableLen);
- }
- else
- {
- HI->EnDe_codeTableLen = DecodeTableLen + FastDecodeTableLen;
- if ( (HI->EnDe_codeTable = jeRam_AllocateClear(HI->EnDe_codeTableLen)) == NULL )
- return(0);
- DecodeTable = (uint16 *)HI->EnDe_codeTable;
- FastDecodeTable = (struct FastDecodeItem *) ( ((char *)HI->EnDe_codeTable) + DecodeTableLen );
- }
- /* build the old style table */
- if ( ! Huff2_BuildDecodeTable(HI) )
- return(0);
- /* now DecodeTable is filled out */
- /* step through all the codes & find what chars correspond to them
- when you find a char for a code, propagate it through all codes which
- have that as a prefix
- keep going until NumBitsFree < Huff2CodeLen for all entries */
- for(StartCode=0;StartCode<255;StartCode++)
- {
- NumBitsUsed = FastDecodeTable[StartCode].NumBitsUsed;
- while ( (8-NumBitsUsed) >= MinCodeLen && FastDecodeTable[StartCode].NumCharsMade < FD_MAXCHARSMADE )
- {
- CurCode = StartCode ;
- /* find char that encodes to curcode */
- Huff2CodeLen = MinCodeLen;
- Huff2Code = ( CurCode >> (8 - NumBitsUsed - Huff2CodeLen) ) & ( (1<<Huff2CodeLen) - 1 ) ;
- ReadCodeMask = 1 << ( 7 - NumBitsUsed - Huff2CodeLen ) ;
- PackedCode = Huff2Code;
- while( DecodeTable[PackedCode] != Huff2CodeLen )
- {
- Huff2Code += Huff2Code;
- if ( CurCode & ReadCodeMask ) Huff2Code++;
- ReadCodeMask >>= 1;
- Huff2CodeLen++;
- if ( ReadCodeMask == 0 )
- goto DoneWithCurCode;
- PackedCode = Huff2Code - CodePrefixByLen[Huff2CodeLen];
- }
- if ( Huff2CodeLen > (8 - NumBitsUsed) )
- goto DoneWithCurCode;
- GotChar = DecodeTable[PackedCode+NumSymbols];
- /* step through while Huff2Code is the next code
- all occurances of Huff2Code will be contiguous */
- do
- {
- if ( FastDecodeTable[CurCode].NumCharsMade < FD_MAXCHARSMADE )
- {
- FastDecodeTable[CurCode].CharsMade[FastDecodeTable[CurCode].NumCharsMade] = GotChar;
- FastDecodeTable[CurCode].NumCharsMade++;
- FastDecodeTable[CurCode].NumBitsUsed = NumBitsUsed + Huff2CodeLen;
- }
- CurCode ++;
- NumBitsUsed = FastDecodeTable[CurCode].NumBitsUsed;
- if ( Huff2CodeLen > (8-NumBitsUsed) ) break;
- CheckCode = ( CurCode >> (8 - NumBitsUsed - Huff2CodeLen) ) & ( (1<<Huff2CodeLen) - 1 ) ;
- } while ( CheckCode == Huff2Code );
- NumBitsUsed = FastDecodeTable[StartCode].NumBitsUsed;
- }
- DoneWithCurCode: /* see Knuth : "Structured use of Goto" :^> */
- continue;
- }
- HI->NumCharsWaiting = 0;
- return(1);
- }
- void Huff2_EncodeC(struct Huff2Info *HI,uint16 Symbol)
- {
- register uint32 CurCode;
- register long CurCodeLen;
- register struct LBitIOInfo * BII;
- if ( HI->GotNumSymbols < 2 ) return;
- CurCode = ((uint32 *)HI->EnDe_codeTable)[Symbol];
- CurCodeLen = HI->CodeLenTable[Symbol];
- BII = HI->BII;
- #ifdef DEBUG
- if ( CurCodeLen == 0 )
- {
- BrandoError("Got EncodeC for CodeLen == 0 symbol!");
- exit(10);
- }
- #endif
- LBitIO_WriteBits(BII,CurCode,CurCodeLen);
- }
- #define FASTDECODE_PAD 6
- jeBoolean Huff2_FastDecodeArray(struct Huff2Info *HI,uint8 * Array,long ArrayLen)
- {
- register uint32 PeekedCode;
- register struct FastDecodeItem * FastDecodeTable;
- long NumCharsMade;
- uint16 * CharsMade;
- long NumSymbols;
- uint16 * DecodeTable;
- uint32 * CodePrefixByLen;
- uint32 CurCode,PackedCode;
- long CurCodeLen;
- jeBoolean bit;
- uint8 *CurArrayPtr,*ArrayPtrDone;
- LocalLBitIO_Variables();
- if ( HI->GotNumSymbols < 2 )
- {
- if ( HI->GotNumSymbols == 0 ) return(0);
- else
- {
- while(ArrayLen--) *Array++ = HI->OneChar;
- }
- return(1);
- }
- LocalLBitIO_GetState(HI->BII);
- NumSymbols = HI->NumSymbols;
- FastDecodeTable = (struct FastDecodeItem *) ( ((char *)HI->EnDe_codeTable) + 2*NumSymbols*sizeof(uint16) );
- DecodeTable = (uint16 *)HI->EnDe_codeTable;
- CodePrefixByLen = HI->CodePrefixByLen;
- CurArrayPtr = Array;
- ArrayPtrDone = Array + ArrayLen - FASTDECODE_PAD;
- while ( CurArrayPtr < ArrayPtrDone )
- {
- LocalLBitIO_PeekBits(PeekedCode,8);
-
- NumCharsMade = FastDecodeTable[PeekedCode].NumCharsMade;
- if ( NumCharsMade > 0 )
- {
- CurCodeLen = FastDecodeTable[PeekedCode].NumBitsUsed;
- LocalLBitIO_SkipBits(CurCodeLen);
- switch ( NumCharsMade )
- {
- case 1:
- *CurArrayPtr++ = *(FastDecodeTable[PeekedCode].CharsMade);
- break;
- case 2:
- CharsMade = FastDecodeTable[PeekedCode].CharsMade;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade;
- break;
- case 3:
- CharsMade = FastDecodeTable[PeekedCode].CharsMade;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade;
- break;
- case 4:
- CharsMade = FastDecodeTable[PeekedCode].CharsMade;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade++;
- *CurArrayPtr++ = *CharsMade;
- break;
- }
- }
- else /* use old decode method, can read 9 bits automatically */
- {
- CurCodeLen = 8;
- CurCode = PeekedCode;
- LocalLBitIO_SkipBits(8);
- PackedCode = CurCode - CodePrefixByLen[CurCodeLen];
-
- /* could read another bit here, but who cares? */
- while( DecodeTable[PackedCode] != CurCodeLen )
- {
- CurCode += CurCode;
- LocalLBitIO_ReadBit(bit);
- CurCode += bit;
- CurCodeLen++;
-
- PackedCode = CurCode - CodePrefixByLen[CurCodeLen];
- }
-
- *CurArrayPtr++ = DecodeTable[PackedCode+NumSymbols];
- }
- }
- LocalLBitIO_PutState(HI->BII);
- /* do normal decode for last several to make sure we don't go too far */
- ArrayPtrDone += FASTDECODE_PAD;
- while ( CurArrayPtr < ArrayPtrDone )
- {
- *CurArrayPtr++ = Huff2_DecodeC(HI);
- }
- return(1);
- }
- jeBoolean Huff2_FindDecodeOne(struct Huff2Info *HI)
- {
- uint16 i;
- for(i=0;i<HI->NumSymbols;i++)
- {
- if ( HI->CodeLenTable[i] > 0 )
- {
- HI->OneChar = i;
- return(1);
- }
- }
- return(0);
- }
- uint16 Huff2_FastDecodeC(struct Huff2Info *HI)
- {
- if ( HI->GotNumSymbols < 2 ) return(HI->OneChar);
- #if FD_MAXCHARSMADE_SUBONE > 0
- if ( HI->NumCharsWaiting > 0 )
- {
- HI->NumCharsWaiting--;
- return(HI->CharsWaiting[HI->NumCharsWaiting]);
- }
- #endif // FD_MAXCHARSMADE_SUBONE == 0
- /* variables not init-ed if there are chars waiting */
- {
- struct FastDecodeItem * FastDecodeTable;
- uint32 PeekedCode;
- struct LBitIOInfo * BII;
- long NumSymbols;
- NumSymbols = HI->NumSymbols;
- FastDecodeTable = (struct FastDecodeItem *) ( ((char *)HI->EnDe_codeTable) + 2*NumSymbols*sizeof(uint16) );
- BII = HI->BII;
- LBitIO_PeekBits(BII,PeekedCode,8);
- if ( FastDecodeTable[PeekedCode].NumCharsMade > 0 )
- {
- LBitIO_SkipBits(BII,FastDecodeTable[PeekedCode].NumBitsUsed);
- #if FD_MAXCHARSMADE_SUBONE > 0
- HI->NumCharsWaiting = FastDecodeTable[PeekedCode].NumCharsMade - 1;
- switch ( HI->NumCharsWaiting ) /* !<>! */
- {
- case 0:
- break;
- case 1:
- HI->CharsWaiting[0] = FastDecodeTable[PeekedCode].CharsMade[1];
- break;
- case 2:
- HI->CharsWaiting[1] = FastDecodeTable[PeekedCode].CharsMade[1];
- HI->CharsWaiting[0] = FastDecodeTable[PeekedCode].CharsMade[2];
- break;
- case 3:
- HI->CharsWaiting[2] = FastDecodeTable[PeekedCode].CharsMade[1];
- HI->CharsWaiting[1] = FastDecodeTable[PeekedCode].CharsMade[2];
- HI->CharsWaiting[0] = FastDecodeTable[PeekedCode].CharsMade[3];
- break;
- }
- #endif // FD_MAXCHARSMADE_SUBONE == 0
- return( FastDecodeTable[PeekedCode].CharsMade[0] );
- }
- else /* use old decode method, can read 9 bits automatically */
- {
- uint16 * DecodeTable;
- uint32 * CodePrefixByLen;
- uint32 CurCode,PackedCode;
- long CurCodeLen;
- jeBoolean bit;
-
- DecodeTable = (uint16 *)HI->EnDe_codeTable;
- CodePrefixByLen = HI->CodePrefixByLen;
-
- CurCodeLen = 8;
- CurCode = PeekedCode;
- LBitIO_SkipBits(BII,8);
- PackedCode = CurCode - CodePrefixByLen[CurCodeLen];
- /* could read another bit here, but who cares? */
- while( DecodeTable[PackedCode] != CurCodeLen )
- {
- CurCode += CurCode;
- LBitIO_ReadBit(BII,bit);
- CurCode += bit;
- CurCodeLen++;
-
- PackedCode = CurCode - CodePrefixByLen[CurCodeLen];
- }
-
- #ifdef DEBUG
- if ( CurCodeLen > HI->MaxCodeLen )
- {
- BrandoError("Got code longer than MaxCodeLen!");
- exit(10);
- }
- #endif
-
- return(DecodeTable[PackedCode+NumSymbols]);
- }
- }
- /* end variable-space */
- }
- uint16 Huff2_DecodeC(struct Huff2Info *HI)
- {
- uint16 * DecodeTable;
- long NumSymbols;
- uint32 * CodePrefixByLen;
- uint32 CurCode,PackedCode;
- long CurCodeLen;
- struct LBitIOInfo * BII;
- jeBoolean bit;
- if ( HI->GotNumSymbols < 2 ) return(HI->OneChar);
- NumSymbols = HI->NumSymbols;
- DecodeTable = (uint16 *) HI->EnDe_codeTable;
- CodePrefixByLen = HI->CodePrefixByLen;
- BII = HI->BII;
- CurCodeLen = HI->MinCodeLen;
- LBitIO_ReadBits(BII,CurCode,CurCodeLen);
- PackedCode = CurCode;
- while( DecodeTable[PackedCode] != CurCodeLen )
- {
- CurCode += CurCode;
- LBitIO_ReadBit(BII,bit);
- CurCode += bit;
- CurCodeLen++;
- PackedCode = CurCode - CodePrefixByLen[CurCodeLen];
- }
- #ifdef DEBUG
- if ( CurCodeLen > HI->MaxCodeLen )
- {
- BrandoError("Got code longer than MaxCodeLen!");
- exit(10);
- }
- #endif
- return(DecodeTable[PackedCode+NumSymbols]);
- }
- /*
- * Scale Counts to [0,MaxVal]
- * (brackets indicate the range is "inclusive")
- *
- * a count which was > 0 will not be scaled to 0
- *
- */
- void Huff2_ScaleCounts(struct Huff2Info *HI,long * CharCounts,long MaxVal)
- {
- long MaxCharCount;
- long NumSymbols,i;
- long OutCharCount;
- NumSymbols = HI->NumSymbols;
- //get maxcharcount
- MaxCharCount = 0;
- for(i=0;i<NumSymbols;i++)
- {
- if ( CharCounts[i] > MaxCharCount ) MaxCharCount = CharCounts[i];
- }
- //scale counts
- if ( MaxCharCount > MaxVal )
- {
- for(i=0;i<NumSymbols;i++)
- {
- OutCharCount = ( (long)CharCounts[i] * MaxVal ) / MaxCharCount;
- if ( OutCharCount > MaxVal ) OutCharCount = MaxVal;
- else if ( CharCounts[i] && ! OutCharCount ) OutCharCount = 1;
- CharCounts[i] = OutCharCount;
- }
- }
- if ( HI->MaxCharCount != MaxVal && HI->SortType == HUFF2_SORT_RADIX &&
- HI->SortWork != NULL )
- {
- FreeMem(HI->SortWork,sizeofpointer*(HI->MaxCharCount+1));
- HI->SortWork = NULL;
- }
- HI->MaxCharCount = min(MaxCharCount,MaxVal);
- }
- /*
- * Sets ->MaxCharCount in HI
- *
- */
- void Huff2_GetMaxCharCount(struct Huff2Info *HI,long * CharCounts)
- {
- long MaxCharCount;
- long NumSymbols,i;
- NumSymbols = HI->NumSymbols;
- //get maxcharcount
- MaxCharCount = 0;
- for(i=0;i<NumSymbols;i++)
- {
- if ( CharCounts[i] > MaxCharCount ) MaxCharCount = CharCounts[i];
- }
- if ( HI->MaxCharCount != MaxCharCount && HI->SortType == HUFF2_SORT_RADIX &&
- HI->SortWork != NULL )
- {
- FreeMem(HI->SortWork,sizeofpointer*(HI->MaxCharCount+1));
- HI->SortWork = NULL;
- }
- HI->MaxCharCount = MaxCharCount;
- }
- /*
- * sets MinCodeLen & MaxCodeLen which must be set
- * for BuildEncodeTable
- *
- */
- void Huff2_SetMinMaxCodeLen(struct Huff2Info *HI)
- {
- long MinCodeLen,MaxCodeLen;
- if ( HI->GotNumSymbols < 2 )
- { HI->MinCodeLen = HI->MaxCodeLen = 1; return; }
- MinCodeLen = 1;
- while ( HI->NumCodesOfLen[MinCodeLen] == 0 ) MinCodeLen++;
- MaxCodeLen = 31;
- while ( HI->NumCodesOfLen[MaxCodeLen] == 0 ) MaxCodeLen--;
- HI->MaxCodeLen = MaxCodeLen;
- HI->MinCodeLen = MinCodeLen;
- }
- /*
- * Writes codelens out to the BII
- *
- * also sets MinCodeLen & MaxCodeLen which must be set
- * for BuildEncodeTable
- *
- */
- void Huff2_PackCodeLens(struct Huff2Info *HI)
- {
- long MinCodeLen,MaxCodeLen;
- long i,j,GotNumSymbols;
- uint8 RunData[32];
- long RunLen;
- long CurCodeLen;
- struct LBitIOInfo * BII;
- BII = HI->BII;
- #ifdef PACKCODES_TOPSYM
- GotNumSymbols = HI->NumSymbols;
- while ( HI->CodeLenTable[GotNumSymbols-1] == 0 ) GotNumSymbols--;
- if ( (HI->NumSymbols - GotNumSymbols) < 32 )
- {
- LBitIO_WriteBit(BII,0);
- GotNumSymbols = HI->NumSymbols;
- }
- else
- {
- LBitIO_WriteBit(BII,1);
- CurCodeLen = intlog2(HI->NumSymbols);
- LBitIO_WriteBits(BII,GotNumSymbols,CurCodeLen);
- }
- #else
- GotNumSymbols = HI->NumSymbols;
- #endif // PACKCODES_TOPSYM
- MinCodeLen = 1;
- while ( HI->NumCodesOfLen[MinCodeLen] == 0 ) MinCodeLen++;
- MaxCodeLen = 31;
- while ( HI->NumCodesOfLen[MaxCodeLen] == 0 ) MaxCodeLen--;
- HI->MaxCodeLen = MaxCodeLen;
- HI->MinCodeLen = MinCodeLen;
- if ( MaxCodeLen >= 0xF ) {
- LBitIO_WriteBits(BII,0xF,4);
- LBitIO_WriteBits(BII,MaxCodeLen-0xF,4);
- } else {
- LBitIO_WriteBits(BII,MaxCodeLen,4);
- }
- for(i=0;i<GotNumSymbols;) {
- RunLen = 0;
- while ( HI->CodeLenTable[i] == 0 && RunLen < 32 && i<GotNumSymbols ) {
- RunLen++;
- i++;
- }
- if ( RunLen > 0 ) {
- LBitIO_WriteBit(BII,0);
- LBitIO_WriteBits(BII,(RunLen-1),5);
- }
- RunLen = 0;
- while ( ( HI->CodeLenTable[i] != 0 || HI->CodeLenTable[i+1] != 0 ) && RunLen < 32 && i<GotNumSymbols )
- {
- RunData[RunLen] = HI->CodeLenTable[i];
- RunLen++; i++;
- }
- if ( RunLen > 0 )
- {
- LBitIO_WriteBit(BII,1);
- LBitIO_WriteBits(BII,(RunLen-1),5);
- for(j=0;j<RunLen;j++)
- {
- CurCodeLen = MaxCodeLen - RunData[j];
- while ( CurCodeLen >= 0x7 )
- {
- LBitIO_WriteBits(BII,0x7,3);
- CurCodeLen -= 0x7;
- }
- LBitIO_WriteBits(BII,CurCodeLen,3);
- }
- }
- }
- }
- /*
- * reads packed codelens to CodeLenTable
- *
- * also sets NumCodesOfLen
- *
- */
- void Huff2_UnPackCodeLens(struct Huff2Info *HI)
- {
- long i,j,GotNumSymbols;
- long MinCodeLen,MaxCodeLen,CurCodeLen;
- long RunLen,CurCode;
- struct LBitIOInfo * BII;
- jeBoolean bit;
- HI->GotNumSymbols = 0;
- memclearFast(HI->CodeLenTable,HI->NumSymbols);
- memclearFast(HI->NumCodesOfLen,32);
- HI->MinCodeLen = HI->MaxCodeLen = 0;
- BII = HI->BII;
- #ifdef PACKCODES_TOPSYM
- LBitIO_ReadBit(BII,bit);
- if ( bit )
- {
- CurCodeLen = intlog2(HI->NumSymbols);
- LBitIO_ReadBits(BII,GotNumSymbols,CurCodeLen);
- }
- else
- {
- GotNumSymbols = HI->NumSymbols;
- }
- #else
- GotNumSymbols = HI->NumSymbols;
- #endif // PACKCODES_TOPSYM
- LBitIO_ReadBits(BII,CurCode,4);
- if ( CurCode == 0xF )
- {
- LBitIO_ReadBits(BII,CurCode,4);
- MaxCodeLen = CurCode + 0xF;
- }
- else
- {
- MaxCodeLen = CurCode;
- }
- HI->MaxCodeLen = MaxCodeLen;
- MinCodeLen = MaxCodeLen;
- for(i=0;i<GotNumSymbols; )
- {
- LBitIO_ReadBit(BII,bit);
- LBitIO_ReadBits(BII,RunLen,5);
- RunLen++;
- if ( bit == 0 )
- {
- for(j=0;j<RunLen;j++)
- {
- HI->CodeLenTable[i++] = 0;
- }
- }
- else
- {
- HI->GotNumSymbols += RunLen;
- for(j=0;j<RunLen;j++)
- {
- CurCodeLen = 0;
- LBitIO_ReadBits(BII,CurCode,3);
- while( CurCode == 0x7 )
- {
- CurCodeLen += 0x7;
- LBitIO_ReadBits(BII,CurCode,3);
- }
- CurCodeLen += CurCode;
- CurCodeLen = MaxCodeLen - CurCodeLen;
- HI->CodeLenTable[i++] = CurCodeLen;
- if ( CurCodeLen > 0 ) HI->NumCodesOfLen[CurCodeLen] ++;
- if ( CurCodeLen < MinCodeLen && CurCodeLen > 0 ) MinCodeLen = CurCodeLen;
- }
- }
- }
- HI->MinCodeLen = MinCodeLen;
- }
- /*
- * Writes codelens out to the BII
- *
- * compresses differences for an earlier huff build
- * you must allocate lastcodelens, & set to 0 initially
- *
- * also sets MinCodeLen & MaxCodeLen which must be set
- * for BuildEncodeTable
- *
- */
- void Huff2_PackCodeLens_Delta(struct Huff2Info *HI,long * LastCodeLens)
- {
- long MinCodeLen,MaxCodeLen;
- long i,j,GotNumSymbols;
- uint8 RunData[512],RunDataLast[512];
- long RunLen;
- long CurCodeLen;
- struct LBitIOInfo * BII;
- BII = HI->BII;
- #ifdef PACKCODES_TOPSYM
- GotNumSymbols = HI->NumSymbols;
- while ( HI->CodeLenTable[GotNumSymbols-1] == 0 ) GotNumSymbols--;
- if ( (HI->NumSymbols - GotNumSymbols) < 32 )
- {
- LBitIO_WriteBit(BII,0);
- GotNumSymbols = HI->NumSymbols;
- }
- else
- {
- LBitIO_WriteBit(BII,1);
- CurCodeLen = intlog2(HI->NumSymbols);
- LBitIO_WriteBits(BII,GotNumSymbols,CurCodeLen);
- }
- #else
- GotNumSymbols = HI->NumSymbols;
- #endif // PACKCODES_TOPSYM
- MinCodeLen = 1;
- while ( HI->NumCodesOfLen[MinCodeLen] == 0 ) MinCodeLen++;
- MaxCodeLen = 31;
- while ( HI->NumCodesOfLen[MaxCodeLen] == 0 ) MaxCodeLen--;
- HI->MaxCodeLen = MaxCodeLen;
- HI->MinCodeLen = MinCodeLen;
- if ( MaxCodeLen >= 0xF )
- {
- LBitIO_WriteBits(BII,0xF,4);
- LBitIO_WriteBits(BII,MaxCodeLen-0xF,4);
- }
- else
- {
- LBitIO_WriteBits(BII,MaxCodeLen,4);
- }
- for(i=0;i<GotNumSymbols;)
- {
- RunLen = 0;
- while ( ( HI->CodeLenTable[i] - LastCodeLens[i] ) == 0 && i<GotNumSymbols )
- {
- RunLen++;
- i++;
- }
- if ( RunLen >= 0x03 )
- {
- LBitIO_WriteBits(BII,0x03,2);
- RunLen -= 0x3;
- if ( RunLen >= 0x07 )
- {
- long Thresh,Bits;
- LBitIO_WriteBits(BII,0x07,3);
- RunLen -= 0x7;
- Thresh = 0xF; Bits = 4;
- while ( RunLen >= Thresh )
- {
- LBitIO_WriteBits(BII,Thresh,Bits);
- RunLen -= Thresh;
- Thresh += Thresh + 1; Bits++;
- }
- LBitIO_WriteBits(BII,RunLen,Bits);
- }
- else
- {
- LBitIO_WriteBits(BII,RunLen,3);
- }
- }
- else
- {
- LBitIO_WriteBits(BII,RunLen,2);
- }
- if ( i == GotNumSymbols ) break;
- RunLen = 0;
- while ( ( ( HI->CodeLenTable[i] - LastCodeLens[i] ) != 0 ) && i<GotNumSymbols )
- {
- RunData[RunLen] = HI->CodeLenTable[i];
- RunDataLast[RunLen] = LastCodeLens[i];
- RunLen++; i++;
- if ( RunLen == 512 ) return; /* BAD ! */
- }
- if ( RunLen >= 0x03 )
- {
- j = RunLen;
- LBitIO_WriteBits(BII,0x03,2);
- RunLen -= 0x3;
- if ( RunLen >= 0x07 )
- {
- long Thresh,Bits;
- LBitIO_WriteBits(BII,0x07,3);
- RunLen -= 0x7;
- Thresh = 0xF; Bits = 4;
- while ( RunLen >= Thresh )
- {
- LBitIO_WriteBits(BII,Thresh,Bits);
- RunLen -= Thresh;
- Thresh += Thresh + 1; Bits++;
- }
- LBitIO_WriteBits(BII,RunLen,Bits);
- }
- else
- {
- LBitIO_WriteBits(BII,RunLen,3);
- }
- RunLen = j;
- }
- else
- {
- LBitIO_WriteBits(BII,RunLen,2);
- }
- if ( RunLen > 0 )
- {
- for(j=0;j<RunLen;j++)
- {
- if ( RunDataLast[j] == 0 )
- {
- CurCodeLen = MaxCodeLen - RunData[j];
- while ( CurCodeLen >= 0x7 )
- {
- LBitIO_WriteBits(BII,0x7,3);
- CurCodeLen -= 0x7;
- }
- LBitIO_WriteBits(BII,CurCodeLen,3);
- }
- else
- {
- CurCodeLen = RunData[j] - RunDataLast[j];
- if ( CurCodeLen < 0 )
- {
- LBitIO_WriteBit(BII,0);
- CurCodeLen = - (CurCodeLen + 1);
- }
- else
- {
- LBitIO_WriteBit(BII,1);
- CurCodeLen--;
- }
- while ( CurCodeLen > 0 )
- {
- LBitIO_WriteBit(BII,0);
- CurCodeLen --;
- }
- LBitIO_WriteBit(BII,1);
- }
- }
- }
- }
- for(i=0;i<HI->NumSymbols;i++)
- {
- LastCodeLens[i] = HI->CodeLenTable[i];
- }
- }
- /*
- * reads packed codelens to CodeLenTable
- *
- * also sets NumCodesOfLen
- *
- * <> doesn't decode new style of runlen yet
- *
- */
- void Huff2_UnPackCodeLens_Delta(struct Huff2Info *HI,long * LastCodeLens)
- {
- long i,j,GotNumSymbols;
- long MinCodeLen,MaxCodeLen,CurCodeLen;
- long RunLen,CurCode;
- struct LBitIOInfo * BII;
- jeBoolean bit;
- long sign;
- BII = HI->BII;
- memclear((long *)HI->NumCodesOfLen,32*sizeof(long));
- #ifdef PACKCODES_TOPSYM
- LBitIO_ReadBit(BII,bit);
- if ( bit )
- {
- CurCodeLen = intlog2(HI->NumSymbols);
- LBitIO_ReadBits(BII,GotNumSymbols,CurCodeLen);
- }
- else
- {
- GotNumSymbols = HI->NumSymbols;
- }
- #else
- GotNumSymbols = HI->NumSymbols;
- #endif // PACKCODES_TOPSYM
- LBitIO_ReadBits(BII,CurCode,4);
- if ( CurCode == 0xF )
- {
- LBitIO_ReadBits(BII,CurCode,4);
- MaxCodeLen = CurCode + 0xF;
- }
- else
- {
- MaxCodeLen = CurCode;
- }
- HI->MaxCodeLen = MaxCodeLen;
- MinCodeLen = MaxCodeLen;
- for(i=0;i<GotNumSymbols; )
- {
- LBitIO_ReadBit(BII,bit);
- LBitIO_ReadBits(BII,RunLen,5);
- RunLen++;
- if ( bit == 0 )
- {
- for(j=0;j<RunLen;j++)
- {
- HI->CodeLenTable[i] = LastCodeLens[i]; i++;
- }
- }
- else
- {
- for(j=0;j<RunLen;j++)
- {
- if ( LastCodeLens[i] > 0 )
- {
- LBitIO_ReadBit(BII,bit);
- if ( bit ) sign = -1;
- else sign = 1;
- LBitIO_ReadBit(BII,bit);
- CurCodeLen = 1;
- while( bit == 0 )
- {
- CurCodeLen++;
- LBitIO_ReadBit(BII,bit);
- }
- CurCodeLen = CurCodeLen * sign + LastCodeLens[i];
- }
- else
- {
- CurCodeLen = 0;
- LBitIO_ReadBits(BII,CurCode,3);
- while( CurCode == 0x7 )
- {
- CurCodeLen += 0x7;
- LBitIO_ReadBits(BII,CurCode,3);
- }
- CurCodeLen += CurCode;
-
- CurCodeLen = MaxCodeLen - CurCodeLen;
- }
- HI->CodeLenTable[i++] = CurCodeLen;
- if ( CurCodeLen > 0 ) HI->NumCodesOfLen[CurCodeLen] ++;
- if ( CurCodeLen < MinCodeLen && CurCodeLen > 0 ) MinCodeLen = CurCodeLen;
- }
- }
- }
- for(i=0;i<HI->NumSymbols;i++)
- {
- LastCodeLens[i] = HI->CodeLenTable[i];
- }
- HI->MinCodeLen = MinCodeLen;
- }
- /*
- * QuickSort on the NodeWork array
- * set Huff2QuickSortArray
- *
- */
- void Huff2QuickSort(long Left,long Right)
- {
- if ( (Right - Left) > 1 )
- {
- long i;
- {
- long j;
- long pivot;
- struct Huff2CodeNode *swapper;
- register struct Huff2CodeNode ** Array;
- Array = Huff2QuickSortArray;
- pivot = Array[Right]->Count;
- i = Left-1;
- j = Right;
- for(;;)
- {
- /* could remove i < Right && j > Left checking by putting
- dummy array slots in [-1] and [GotNumSymbols] w/ Counts 0 and LONG_MAX */
- do ++i; while(Array[i]->Count < pivot && i < Right);
- do --j; while(Array[j]->Count > pivot && j > Left);
- if (i >= j) break;
- swapper = Array[i];
- Array[i] = Array[j];
- Array[j] = swapper;
- }
- swapper = Array[i];
- Array[i] = Array[Right];
- Array[Right] = swapper;
- }
- Huff2QuickSort(Left,i-1);
- Huff2QuickSort(i+1,Right);
- }
- else
- {
- if ( Right > Left )
- {
- if ( Huff2QuickSortArray[Right]->Count < Huff2QuickSortArray[Left]->Count )
- {
- struct Huff2CodeNode *swapper;
- swapper = Huff2QuickSortArray[Left];
- Huff2QuickSortArray[Left] = Huff2QuickSortArray[Right];
- Huff2QuickSortArray[Right] = swapper;
- }
- }
- }
- }
- /*
- * Radix sort on the NodeWork
- * counts must be bounded by [0,MaxCharCount]
- * this is much faster than QuickSort for large NumSymbols
- *
- * I think NumSymbols as small as 256 is still faster here
- * Radix = O(256 + 2*NumSymbols)
- * QuickSort = O(NumSymbols*log2(NumSymbols))
- * bigOs are equal for NumSymbols == 64
- *
- * NOTEZ: uses the ->Up in the codenode structure
- * resets ->Up to NULL when its done
- *
- */
- jeBoolean Huff2RadixSort(struct Huff2CodeNode ** BucketArray,
- long MaxCharCount,struct Huff2CodeNode ** Array,long ArraySize)
- {
- register struct Huff2CodeNode * CurNode;
- register long i,j;
- memclear((long *)BucketArray,sizeofpointer*(MaxCharCount+1));
- /* go backwards so that alphabetic order is preserved */
- for(i=(ArraySize-1);i>=0;i--)
- {
- Array[i]->Up = BucketArray[Array[i]->Count];
- BucketArray[Array[i]->Count] = Array[i];
- }
- j=0;
- for(i=0;i<=MaxCharCount;i++)
- {
- CurNode = BucketArray[i];
- while(CurNode) /* $ 15% */
- {
- Array[j] = CurNode;
- CurNode = CurNode->Up;
- Array[j]->Up = NULL;
- j++;
- }
- }
- if ( j != ArraySize )
- {
- return(0);
- }
- return(1);
- }