147 lines
3.3 KiB
C
147 lines
3.3 KiB
C
|
/* Compress/HuffmanEncode.c */
|
||
|
|
||
|
#include "HuffmanEncode.h"
|
||
|
#include "../../Sort.h"
|
||
|
|
||
|
#define kMaxLen 16
|
||
|
#define NUM_BITS 10
|
||
|
#define MASK ((1 << NUM_BITS) - 1)
|
||
|
|
||
|
#define NUM_COUNTERS 64
|
||
|
|
||
|
/* use BLOCK_SORT_EXTERNAL_FLAGS if blockSize > 1M */
|
||
|
#define HUFFMAN_SPEED_OPT
|
||
|
|
||
|
void Huffman_Generate(const UInt32 *freqs, UInt32 *p, Byte *lens, UInt32 numSymbols, UInt32 maxLen)
|
||
|
{
|
||
|
UInt32 num = 0;
|
||
|
/* if (maxLen > 10) maxLen = 10; */
|
||
|
{
|
||
|
UInt32 i;
|
||
|
|
||
|
#ifdef HUFFMAN_SPEED_OPT
|
||
|
|
||
|
UInt32 counters[NUM_COUNTERS];
|
||
|
for (i = 0; i < NUM_COUNTERS; i++)
|
||
|
counters[i] = 0;
|
||
|
for (i = 0; i < numSymbols; i++)
|
||
|
{
|
||
|
UInt32 freq = freqs[i];
|
||
|
counters[(freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1]++;
|
||
|
}
|
||
|
|
||
|
for (i = 1; i < NUM_COUNTERS; i++)
|
||
|
{
|
||
|
UInt32 temp = counters[i];
|
||
|
counters[i] = num;
|
||
|
num += temp;
|
||
|
}
|
||
|
|
||
|
for (i = 0; i < numSymbols; i++)
|
||
|
{
|
||
|
UInt32 freq = freqs[i];
|
||
|
if (freq == 0)
|
||
|
lens[i] = 0;
|
||
|
else
|
||
|
p[counters[((freq < NUM_COUNTERS - 1) ? freq : NUM_COUNTERS - 1)]++] = i | (freq << NUM_BITS);
|
||
|
}
|
||
|
counters[0] = 0;
|
||
|
HeapSort(p + counters[NUM_COUNTERS - 2], counters[NUM_COUNTERS - 1] - counters[NUM_COUNTERS - 2]);
|
||
|
|
||
|
#else
|
||
|
|
||
|
for (i = 0; i < numSymbols; i++)
|
||
|
{
|
||
|
UInt32 freq = freqs[i];
|
||
|
if (freq == 0)
|
||
|
lens[i] = 0;
|
||
|
else
|
||
|
p[num++] = i | (freq << NUM_BITS);
|
||
|
}
|
||
|
HeapSort(p, num);
|
||
|
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (num < 2)
|
||
|
{
|
||
|
int minCode = 0;
|
||
|
int maxCode = 1;
|
||
|
if (num == 1)
|
||
|
{
|
||
|
maxCode = p[0] & MASK;
|
||
|
if (maxCode == 0)
|
||
|
maxCode++;
|
||
|
}
|
||
|
p[minCode] = 0;
|
||
|
p[maxCode] = 1;
|
||
|
lens[minCode] = lens[maxCode] = 1;
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 b, e, i;
|
||
|
|
||
|
i = b = e = 0;
|
||
|
do
|
||
|
{
|
||
|
UInt32 n, m, freq;
|
||
|
n = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
||
|
freq = (p[n] & ~MASK);
|
||
|
p[n] = (p[n] & MASK) | (e << NUM_BITS);
|
||
|
m = (i != num && (b == e || (p[i] >> NUM_BITS) <= (p[b] >> NUM_BITS))) ? i++ : b++;
|
||
|
freq += (p[m] & ~MASK);
|
||
|
p[m] = (p[m] & MASK) | (e << NUM_BITS);
|
||
|
p[e] = (p[e] & MASK) | freq;
|
||
|
e++;
|
||
|
}
|
||
|
while (num - e > 1);
|
||
|
|
||
|
{
|
||
|
UInt32 lenCounters[kMaxLen + 1];
|
||
|
for (i = 0; i <= kMaxLen; i++)
|
||
|
lenCounters[i] = 0;
|
||
|
|
||
|
p[--e] &= MASK;
|
||
|
lenCounters[1] = 2;
|
||
|
while (e > 0)
|
||
|
{
|
||
|
UInt32 len = (p[p[--e] >> NUM_BITS] >> NUM_BITS) + 1;
|
||
|
p[e] = (p[e] & MASK) | (len << NUM_BITS);
|
||
|
if (len >= maxLen)
|
||
|
for (len = maxLen - 1; lenCounters[len] == 0; len--);
|
||
|
lenCounters[len]--;
|
||
|
lenCounters[len + 1] += 2;
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 len;
|
||
|
i = 0;
|
||
|
for (len = maxLen; len != 0; len--)
|
||
|
{
|
||
|
UInt32 num;
|
||
|
for (num = lenCounters[len]; num != 0; num--)
|
||
|
lens[p[i++] & MASK] = (Byte)len;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
{
|
||
|
UInt32 nextCodes[kMaxLen + 1];
|
||
|
{
|
||
|
UInt32 code = 0;
|
||
|
UInt32 len;
|
||
|
for (len = 1; len <= kMaxLen; len++)
|
||
|
nextCodes[len] = code = (code + lenCounters[len - 1]) << 1;
|
||
|
}
|
||
|
/* if (code + lenCounters[kMaxLen] - 1 != (1 << kMaxLen) - 1) throw 1; */
|
||
|
|
||
|
{
|
||
|
UInt32 i;
|
||
|
for (i = 0; i < numSymbols; i++)
|
||
|
p[i] = nextCodes[lens[i]]++;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|