This commit is contained in:
Igor Pavlov
2005-05-30 00:00:00 +00:00
committed by Kornel Lesiński
parent 8c1b5c7b7e
commit 3c510ba80b
926 changed files with 40559 additions and 23519 deletions

View File

@@ -1,60 +1,42 @@
// Compress/HuffmanDecoder.h
#pragma once
#ifndef __COMPRESS_HUFFMANDECODER_H
#define __COMPRESS_HUFFMANDECODER_H
#include "../../../Common/Types.h"
namespace NCompress {
namespace NHuffman {
class CDecoderException{};
const UINT32 kValueTableBits = 8;
const UInt32 kValueTableBits = 9;
template <int kNumBitsInLongestCode>
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
class CDecoder
{
UINT32 m_Limitits[kNumBitsInLongestCode + 1]; // m_Limitits[i] = value limit for symbols with length = i
UINT32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UINT32 m_NumSymbols;
UINT32 *m_Symbols; // symbols: at first with len = 1 then 2, ... 15.
BYTE m_Lengths[1 << kValueTableBits];
UInt32 m_Limitits[kNumBitsInLongestCode + 1]; // m_Limitits[i] = value limit for symbols with length = i
UInt32 m_Positions[kNumBitsInLongestCode + 1]; // m_Positions[i] = index in m_Symbols[] of first symbol with length = i
UInt32 m_Symbols[m_NumSymbols]; // symbols: at first with len = 1 then 2, ... 15.
Byte m_Lengths[1 << kValueTableBits];
public:
CDecoder(UINT32 numSymbols):
m_NumSymbols(numSymbols)
{ m_Symbols = new UINT32[m_NumSymbols]; }
~CDecoder()
{ delete []m_Symbols; }
void SetNumSymbols(UINT32 numSymbols)
{ m_NumSymbols = numSymbols; }
void SetCodeLengths(const BYTE *codeLengths);
void SetNumSymbols(UInt32 numSymbols) { m_NumSymbols = numSymbols; }
void SetCodeLengths(const Byte *codeLengths);
template <class TBitDecoder>
UINT32 DecodeSymbol(TBitDecoder *bitStream)
UInt32 DecodeSymbol(TBitDecoder *bitStream)
{
UINT32 numBits;
UInt32 numBits;
UINT32 value = bitStream->GetValue(kNumBitsInLongestCode);
UInt32 value = bitStream->GetValue(kNumBitsInLongestCode);
if (value < m_Limitits[kValueTableBits])
numBits = m_Lengths[value >> (kNumBitsInLongestCode - kValueTableBits)];
else if (value < m_Limitits[10])
if (value < m_Limitits[9])
numBits = 9;
else
numBits = 10;
else if (value < m_Limitits[11])
numBits = 11;
else if (value < m_Limitits[12])
numBits = 12;
else
for (numBits = 13; numBits < kNumBitsInLongestCode; numBits++)
for (numBits = kValueTableBits + 1; numBits < kNumBitsInLongestCode; numBits++)
if (value < m_Limitits[numBits])
break;
bitStream->MovePos(numBits);
UINT32 index = m_Positions[numBits] +
UInt32 index = m_Positions[numBits] +
((value - m_Limitits[numBits - 1]) >> (kNumBitsInLongestCode - numBits));
if (index >= m_NumSymbols)
throw CDecoderException(); // test it
@@ -62,27 +44,26 @@ public:
}
};
template <int kNumBitsInLongestCode>
void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
template <int kNumBitsInLongestCode, UInt32 m_NumSymbols>
void CDecoder<kNumBitsInLongestCode, m_NumSymbols>::SetCodeLengths(const Byte *codeLengths)
{
int lenCounts[kNumBitsInLongestCode + 1], tmpPositions[kNumBitsInLongestCode + 1];
int i;
for(i = 1; i <= kNumBitsInLongestCode; i++)
lenCounts[i] = 0;
UINT32 symbol;
UInt32 symbol;
for (symbol = 0; symbol < m_NumSymbols; symbol++)
{
BYTE codeLength = codeLengths[symbol];
Byte codeLength = codeLengths[symbol];
if (codeLength > kNumBitsInLongestCode)
throw CDecoderException();
lenCounts[codeLength]++;
}
lenCounts[0] = 0;
tmpPositions[0] = m_Positions[0] = m_Limitits[0] = 0;
UINT32 startPos = 0;
UINT32 index = 0;
const UINT32 kMaxValue = (1 << kNumBitsInLongestCode);
UInt32 startPos = 0;
UInt32 index = 0;
const UInt32 kMaxValue = (1 << kNumBitsInLongestCode);
for (i = 1; i <= kNumBitsInLongestCode; i++)
{
startPos += lenCounts[i] << (kNumBitsInLongestCode - i);
@@ -94,8 +75,8 @@ void CDecoder<kNumBitsInLongestCode>::SetCodeLengths(const BYTE *codeLengths)
if(i <= kValueTableBits)
{
UINT32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
memset(m_Lengths + index, BYTE(i), limit - index);
UInt32 limit = (m_Limitits[i] >> (kNumBitsInLongestCode - kValueTableBits)); // change it
memset(m_Lengths + index, Byte(i), limit - index);
index = limit;
}
}

View File

@@ -4,41 +4,63 @@
#include "HuffmanEncoder.h"
#include "Common/Defs.h"
#include "Common/Alloc.h"
namespace NCompression {
namespace NHuffman {
static const char *kIncorrectBitLenCountsMessage = "Incorrect bit len counts";
CEncoder::CEncoder(UINT32 numSymbols,
const BYTE *extraBits, UINT32 extraBase, UINT32 maxLength):
m_NumSymbols(numSymbols),
m_ExtraBits(extraBits),
m_ExtraBase(extraBase),
m_MaxLength(maxLength),
m_HeapSize(numSymbols * 2+ 1)
CEncoder::CEncoder():
m_Items(0),
m_Heap(0),
m_Depth(0)
{}
void CEncoder::Free()
{
m_Items = new CItem[m_HeapSize];
m_Heap = new UINT32[m_HeapSize];
m_Depth = new BYTE[m_HeapSize];
MyFree(m_Items);
MyFree(m_Heap);
MyFree(m_Depth);
m_Items = 0;
m_Heap = 0;
m_Depth = 0;
}
bool CEncoder::Create(UInt32 numSymbols,
const Byte *extraBits, UInt32 extraBase, UInt32 maxLength)
{
m_NumSymbols = numSymbols;
m_ExtraBits = extraBits;
m_ExtraBase = extraBase;
m_MaxLength = maxLength;
m_HeapSize = numSymbols * 2 + 1;
Free();
m_Items = (CItem *)MyAlloc(m_HeapSize * sizeof(CItem));
m_Heap = (UInt32 *)MyAlloc(m_HeapSize * sizeof(UInt32));
m_Depth = (Byte *)MyAlloc(m_HeapSize * sizeof(Byte));
if (m_Items == 0 || m_Heap == 0 || m_Depth == 0)
{
Free();
return false;
}
return true;
}
CEncoder::~CEncoder()
{
delete []m_Depth;
delete []m_Heap;
delete []m_Items;
Free();
}
void CEncoder::StartNewBlock()
{
for (UINT32 i = 0; i < m_NumSymbols; i++)
for (UInt32 i = 0; i < m_NumSymbols; i++)
m_Items[i].Freq = 0;
}
void CEncoder::SetFreqs(const UINT32 *freqs)
void CEncoder::SetFreqs(const UInt32 *freqs)
{
for (UINT32 i = 0; i < m_NumSymbols; i++)
for (UInt32 i = 0; i < m_NumSymbols; i++)
m_Items[i].Freq = freqs[i];
}
@@ -48,9 +70,9 @@ static const int kSmallest = 1;
// Remove the smallest element from the heap and recreate the heap with
// one less element. Updates heap and m_HeapLength.
UINT32 CEncoder::RemoveSmallest()
UInt32 CEncoder::RemoveSmallest()
{
UINT32 top = m_Heap[kSmallest];
UInt32 top = m_Heap[kSmallest];
m_Heap[kSmallest] = m_Heap[m_HeapLength--];
DownHeap(kSmallest);
return top;
@@ -72,15 +94,15 @@ bool CEncoder::Smaller(int n, int m)
// when the m_Heap property is re-established (each father CompareFreqs than its
// two sons).
void CEncoder::DownHeap(UINT32 k)
void CEncoder::DownHeap(UInt32 k)
{
UINT32 symbol = m_Heap[k];
for (UINT32 j = k << 1; j <= m_HeapLength;) // j: left son of k
UInt32 symbol = m_Heap[k];
for (UInt32 j = k << 1; j <= m_HeapLength;) // j: left son of k
{
// Set j to the smallest of the two sons:
if (j < m_HeapLength && Smaller(m_Heap[j+1], m_Heap[j]))
j++;
UINT32 htemp = m_Heap[j]; // htemp required because of bug in SASC compiler
UInt32 htemp = m_Heap[j]; // htemp required because of bug in SASC compiler
if (Smaller(symbol, htemp)) // Exit if v is smaller than both sons
break;
m_Heap[k] = htemp; // Exchange v with the smallest son
@@ -100,22 +122,22 @@ void CEncoder::DownHeap(UINT32 k)
// The length m_BlockBitLength is updated; static_len is also updated if stree is
// not null.
void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
void CEncoder::GenerateBitLen(UInt32 maxCode, UInt32 heapMax)
{
int overflow = 0; // number of elements with bit length too large
for (UINT32 i = 0; i <= kNumBitsInLongestCode; i++)
for (UInt32 i = 0; i <= kNumBitsInLongestCode; i++)
m_BitLenCounters[i] = 0;
/* In a first pass, compute the optimal bit lengths (which may
* overflow in the case of the bit length tree).
*/
m_Items[m_Heap[heapMax]].Len = 0; /* root of the heap */
UINT32 h; /* heap index */
UInt32 h; /* heap index */
for (h = heapMax+1; h < m_HeapSize; h++)
{
UINT32 symbol = m_Heap[h];
UINT32 len = m_Items[m_Items[symbol].Dad].Len + 1;
UInt32 symbol = m_Heap[h];
UInt32 len = m_Items[m_Items[symbol].Dad].Len + 1;
if (len > m_MaxLength)
{
len = m_MaxLength;
@@ -125,7 +147,7 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
if (symbol > maxCode)
continue; // not a leaf node
m_BitLenCounters[len]++;
UINT32 extraBits;
UInt32 extraBits;
if (m_ExtraBits != 0 && symbol >= m_ExtraBase)
extraBits = m_ExtraBits[symbol - m_ExtraBase];
else
@@ -139,7 +161,7 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// Find the first bit length which could increase:
do
{
UINT32 bits = m_MaxLength-1;
UInt32 bits = m_MaxLength-1;
while (m_BitLenCounters[bits] == 0)
bits--;
m_BitLenCounters[bits]--; // move one leaf down the m_Items
@@ -155,12 +177,12 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// h is still equal to HEAP_SIZE. (It is simpler to reconstruct all
// lengths instead of fixing only the wrong ones. This idea is taken
// from 'ar' written by Haruhiko Okumura.)
for (UINT32 bits = m_MaxLength; bits != 0; bits--)
for (UInt32 bits = m_MaxLength; bits != 0; bits--)
{
UINT32 numNodes = m_BitLenCounters[bits];
UInt32 numNodes = m_BitLenCounters[bits];
while (numNodes != 0)
{
UINT32 m = m_Heap[--h];
UInt32 m = m_Heap[--h];
if (m > maxCode)
continue;
if (m_Items[m].Len != (unsigned) bits)
@@ -182,22 +204,22 @@ void CEncoder::GenerateBitLen(UINT32 maxCode, UINT32 heapMax)
// OUT assertion: the field code is set for all tree elements of non
// zero code length.
// UINT32 maxCode = largest code with non zero frequency
// UInt32 maxCode = largest code with non zero frequency
void CEncoder::GenerateCodes(UINT32 maxCode)
void CEncoder::GenerateCodes(UInt32 maxCode)
{
UINT32 nextCodes[kNumBitsInLongestCode + 1]; // next code value for each bit length
UINT32 code = 0; // running code value
UInt32 nextCodes[kNumBitsInLongestCode + 1]; // next code value for each bit length
UInt32 code = 0; // running code value
// The distribution counts are first used to generate the code values
// without bit reversal.
for (UINT32 bits = 1; bits <= kNumBitsInLongestCode; bits++)
for (UInt32 bits = 1; bits <= kNumBitsInLongestCode; bits++)
nextCodes[bits] = code = (code + m_BitLenCounters[bits - 1]) << 1;
// Check that the bit counts in m_BitLenCounters are consistent. The last code
// must be all ones.
if (code + m_BitLenCounters[kNumBitsInLongestCode] - 1 != (1 << kNumBitsInLongestCode) - 1)
throw kIncorrectBitLenCountsMessage;
for (UINT32 n = 0; n <= maxCode; n++)
for (UInt32 n = 0; n <= maxCode; n++)
{
int len = m_Items[n].Len;
if (len == 0)
@@ -215,7 +237,7 @@ void CEncoder::GenerateCodes(UINT32 maxCode)
// and corresponding code. The length m_BlockBitLength is updated; static_len is
// also updated if stree is not null. The field max_code is set.
void CEncoder::BuildTree(BYTE *levels)
void CEncoder::BuildTree(Byte *levels)
{
m_BlockBitLength = 0;
int maxCode = -1; // WAS = -1; largest code with non zero frequency */
@@ -226,7 +248,7 @@ void CEncoder::BuildTree(BYTE *levels)
//
m_HeapLength = 0;
UINT32 n; // iterate over m_Heap elements
UInt32 n; // iterate over m_Heap elements
for (n = 0; n < m_NumSymbols; n++)
{
if (m_Items[n].Freq != 0)
@@ -260,18 +282,18 @@ void CEncoder::BuildTree(BYTE *levels)
// Construct the Huffman tree by repeatedly combining the least two
// frequent nodes.
int node = m_NumSymbols; // next internal node of the tree
UINT32 heapMax = m_NumSymbols * 2+ 1;
UInt32 heapMax = m_NumSymbols * 2+ 1;
do
{
n = RemoveSmallest(); /* n = node of least frequency */
UINT32 m = m_Heap[kSmallest]; /* m = node of next least frequency */
UInt32 m = m_Heap[kSmallest]; /* m = node of next least frequency */
m_Heap[--heapMax] = n; /* keep the nodes sorted by frequency */
m_Heap[--heapMax] = m;
// Create a new node father of n and m
m_Items[node].Freq = m_Items[n].Freq + m_Items[m].Freq;
m_Depth[node] = (BYTE) (MyMax(m_Depth[n], m_Depth[m]) + 1);
m_Depth[node] = (Byte) (MyMax(m_Depth[n], m_Depth[m]) + 1);
m_Items[n].Dad = m_Items[m].Dad = node;
// and insert the new node in the m_Heap
m_Heap[kSmallest] = node++;
@@ -290,7 +312,7 @@ void CEncoder::BuildTree(BYTE *levels)
GenerateCodes (maxCode);
for (n = 0; n < m_NumSymbols; n++)
levels[n] = BYTE(m_Items[n].Len);
levels[n] = Byte(m_Items[n].Len);
}
}}

View File

@@ -1,7 +1,5 @@
// Compression/HuffmanEncoder.h
#pragma once
#ifndef __COMPRESSION_HUFFMANENCODER_H
#define __COMPRESSION_HUFFMANENCODER_H
@@ -10,54 +8,58 @@
namespace NCompression {
namespace NHuffman {
const int kNumBitsInLongestCode = 15;
const int kNumBitsInLongestCode = 20;
struct CItem
{
UINT32 Freq;
UINT32 Code;
UINT32 Dad;
UINT32 Len;
UInt32 Freq;
UInt32 Code;
UInt32 Dad;
UInt32 Len;
};
class CEncoder
{
UINT32 m_NumSymbols; // number of symbols in adwSymbol
public:
UInt32 m_NumSymbols; // number of symbols in adwSymbol
CItem *m_Items;
UINT32 *m_Heap;
UINT32 m_HeapSize;
BYTE *m_Depth;
const BYTE *m_ExtraBits;
UINT32 m_ExtraBase;
UINT32 m_MaxLength;
UInt32 *m_Heap;
UInt32 m_HeapSize;
Byte *m_Depth;
const Byte *m_ExtraBits;
UInt32 m_ExtraBase;
UInt32 m_MaxLength;
UINT32 m_HeapLength;
UINT32 m_BitLenCounters[kNumBitsInLongestCode + 1];
UInt32 m_HeapLength;
UInt32 m_BitLenCounters[kNumBitsInLongestCode + 1];
UINT32 RemoveSmallest();
UInt32 RemoveSmallest();
bool Smaller(int n, int m);
void DownHeap(UINT32 k);
void GenerateBitLen(UINT32 maxCode, UINT32 heapMax);
void GenerateCodes(UINT32 maxCode);
void DownHeap(UInt32 k);
void GenerateBitLen(UInt32 maxCode, UInt32 heapMax);
void GenerateCodes(UInt32 maxCode);
UINT32 m_BlockBitLength;
UInt32 m_BlockBitLength;
void Free();
public:
CEncoder(UINT32 numSymbols, const BYTE *extraBits,
UINT32 extraBase, UINT32 maxLength);
CEncoder();
~CEncoder();
bool Create(UInt32 numSymbols, const Byte *extraBits,
UInt32 extraBase, UInt32 maxLength);
void StartNewBlock();
void AddSymbol(UINT32 symbol)
{ m_Items[symbol].Freq++; }
void AddSymbol(UInt32 symbol) { m_Items[symbol].Freq++; }
void SetFreqs(const UINT32 *freqs);
void BuildTree(BYTE *levels);
UINT32 GetBlockBitLength() const { return m_BlockBitLength; }
void SetFreqs(const UInt32 *freqs);
void BuildTree(Byte *levels);
UInt32 GetBlockBitLength() const { return m_BlockBitLength; }
template <class TBitEncoder>
void CodeOneValue(TBitEncoder *bitEncoder, UINT32 symbol)
void CodeOneValue(TBitEncoder *bitEncoder, UInt32 symbol)
{ bitEncoder->WriteBits(m_Items[symbol].Code, m_Items[symbol].Len); }
};

View File

@@ -1,6 +1,6 @@
// stdafx.h
// StdAfx.h
#ifndef __STDAFX_H
#define __STDAFX_H
#endif
#endif