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
|
/****************************************************************************
* 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;
}
};
*****************************************************************************/
enum { TOP=1 << 24, BOT=1 << 15 };
static _THREAD1 struct SUBRANGE { DWORD low, high, scale; } _THREAD Range;
static _THREAD1 DWORD _THREAD low, _THREAD code, _THREAD range;
inline void rcInitEncoder() { low=0; range=DWORD(-1); }
#define RC_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 rcEncodeSymbol()
{
low += Range.low*(range/=Range.scale); range *= Range.high-Range.low;
}
inline void rcFlushEncoder(FILE* stream)
{
for (UINT i=0;i < 4;i++) {
_PPMD_E_PUTC(low >> 24,stream); low <<= 8;
}
}
inline void rcInitDecoder(FILE* stream)
{
low=code=0; range=DWORD(-1);
for (UINT i=0;i < 4;i++)
code=(code << 8) | _PPMD_D_GETC(stream);
}
#define RC_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 rcGetCurrentCount() { return (code-low)/(range /= Range.scale); }
inline void rcRemoveSubrange()
{
low += range*Range.low; range *= Range.high-Range.low;
}
inline UINT rcBinStart(UINT f0,UINT Shift) { return f0*(range >>= Shift); }
inline UINT rcBinDecode (UINT tmp) { return (code-low >= tmp); }
inline void rcBinCorrect0(UINT tmp) { range=tmp; }
inline void rcBinCorrect1(UINT tmp,UINT f1) { low += tmp; range *= f1; }
|