1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#include "CSource.h"
/****************************************************************************
* This file is part of PPMd project *
* Contents: 'Carryless rangecoder' by Dmitry Subbotin *
* Comments: this implementation is claimed to be a public domain *
****************************************************************************/
/********************** Original text *************************************
//////// Carryless rangecoder (c) 1999 by Dmitry Subbotin ////////
typedef unsigned int uint;
typedef unsigned char uc;
#define DO(n) for (int _=0; _<n; _++)
#define TOP (1<<24)
#define BOT (1<<16)
class RangeCoder
{
uint low, code, range, passed;
FILE *f;
void OutByte (uc c) { passed++; fputc(c,f); }
uc InByte () { passed++; return fgetc(f); }
public:
uint GetPassed () { return passed; }
void StartEncode (FILE *F) { f=F; passed=low=0; range= (uint) -1; }
void FinishEncode () { DO(4) OutByte(low>>24), low<<=8; }
void StartDecode (FILE *F) { passed=low=code=0; range= (uint) -1;
f=F; DO(4) code= code<<8 | InByte();
}
void Encode (uint cumFreq, uint freq, uint totFreq) {
assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
low += cumFreq * (range/= totFreq);
range*= freq;
while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
OutByte(low>>24), range<<=8, low<<=8;
}
uint GetFreq (uint totFreq) {
uint tmp= (code-low) / (range/= totFreq);
if (tmp >= totFreq) throw ("Input data corrupt"); // or force it to return
return tmp; // a valid value :)
}
void Decode (uint cumFreq, uint freq, uint totFreq) {
assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
low += cumFreq*range;
range*= freq;
while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
code= code<<8 | InByte(), range<<=8, low<<=8;
}
};
*****************************************************************************/
static struct SUBRANGE {
DWORD LowCount, HighCount, scale;
} SubRange;
enum { TOP=1 << 24, BOT=1 << 15 };
static DWORD low, code, range;
inline void ariInitEncoder()
{
low=0; range=DWORD(-1);
}
#define ARI_ENC_NORMALIZE(stream) { \
while ((low ^ (low+range)) < TOP || range < BOT && \
((range= -low & (BOT-1)),1)) { \
_PPMD_E_PUTC(low >> 24,stream); \
range <<= 8; low <<= 8; \
} \
}
inline void ariEncodeSymbol()
{
low += SubRange.LowCount*(range /= SubRange.scale);
range *= SubRange.HighCount-SubRange.LowCount;
}
inline void ariShiftEncodeSymbol(UINT SHIFT)
{
low += SubRange.LowCount*(range >>= SHIFT);
range *= SubRange.HighCount-SubRange.LowCount;
}
#define ARI_FLUSH_ENCODER(stream) { \
for (UINT i=0;i < 4;i++) { \
_PPMD_E_PUTC(low >> 24,stream); low <<= 8; \
} \
}
#define ARI_INIT_DECODER(stream) { \
low=code=0; range=DWORD(-1); \
for (UINT i=0;i < 4;i++) \
code=(code << 8) | _PPMD_D_GETC(stream); \
}
#define ARI_DEC_NORMALIZE(stream) { \
while ((low ^ (low+range)) < TOP || range < BOT && \
((range= -low & (BOT-1)),1)) { \
code=(code << 8) | _PPMD_D_GETC(stream); \
range <<= 8; low <<= 8; \
} \
}
inline UINT ariGetCurrentCount() {
return (code-low)/(range /= SubRange.scale);
}
inline UINT ariGetCurrentShiftCount(UINT SHIFT) {
return (code-low)/(range >>= SHIFT);
}
inline void ariRemoveSubrange()
{
low += range*SubRange.LowCount;
range *= SubRange.HighCount-SubRange.LowCount;
}
|