Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Coder.h

Go to the documentation of this file.
00001 #include "CSource.h"
00002 /****************************************************************************
00003  *  This file is part of PPMd project                                       *
00004  *  Contents: 'Carryless rangecoder' by Dmitry Subbotin                     *
00005  *  Comments: this implementation is claimed to be a public domain          *
00006  ****************************************************************************/
00007 /**********************  Original text  *************************************
00009 
00010 typedef unsigned int  uint;
00011 typedef unsigned char uc;
00012 
00013 #define  DO(n)     for (int _=0; _<n; _++)
00014 #define  TOP       (1<<24)
00015 #define  BOT       (1<<16)
00016 
00017 
00018 class RangeCoder
00019 {
00020  uint  low, code, range, passed;
00021  FILE  *f;
00022 
00023  void OutByte (uc c)           { passed++; fputc(c,f); }
00024  uc   InByte ()                { passed++; return fgetc(f); }
00025 
00026 public:
00027 
00028  uint GetPassed ()             { return passed; }
00029  void StartEncode (FILE *F)    { f=F; passed=low=0;  range= (uint) -1; }
00030  void FinishEncode ()          { DO(4)  OutByte(low>>24), low<<=8; }
00031  void StartDecode (FILE *F)    { passed=low=code=0;  range= (uint) -1;
00032                                  f=F; DO(4) code= code<<8 | InByte();
00033                                }
00034 
00035  void Encode (uint cumFreq, uint freq, uint totFreq) {
00036     assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
00037     low  += cumFreq * (range/= totFreq);
00038     range*= freq;
00039     while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
00040        OutByte(low>>24), range<<=8, low<<=8;
00041  }
00042 
00043  uint GetFreq (uint totFreq) {
00044    uint tmp= (code-low) / (range/= totFreq);
00045    if (tmp >= totFreq)  throw ("Input data corrupt"); // or force it to return
00046    return tmp;                                         // a valid value :)
00047  }
00048 
00049  void Decode (uint cumFreq, uint freq, uint totFreq) {
00050     assert(cumFreq+freq<totFreq && freq && totFreq<=BOT);
00051     low  += cumFreq*range;
00052     range*= freq;
00053     while ((low ^ low+range)<TOP || range<BOT && ((range= -low & BOT-1),1))
00054        code= code<<8 | InByte(), range<<=8, low<<=8;
00055  }
00056 };
00057 *****************************************************************************/
00058 
00059 static struct SUBRANGE {
00060     DWORD LowCount, HighCount, scale;
00061 } SubRange;
00062 enum { TOP=1 << 24, BOT=1 << 15 };
00063 static DWORD low, code, range;
00064 
00065 inline void ariInitEncoder()
00066 {
00067     low=0;                                  range=DWORD(-1);
00068 }
00069 #define ARI_ENC_NORMALIZE(stream) {                                         \
00070     while ((low ^ (low+range)) < TOP || range < BOT &&                      \
00071             ((range= -low & (BOT-1)),1)) {                                  \
00072         _PPMD_E_PUTC(low >> 24,stream);                                     \
00073         range <<= 8;                        low <<= 8;                      \
00074     }                                                                       \
00075 }
00076 inline void ariEncodeSymbol()
00077 {
00078     low += SubRange.LowCount*(range /= SubRange.scale);
00079     range *= SubRange.HighCount-SubRange.LowCount;
00080 }
00081 inline void ariShiftEncodeSymbol(UINT SHIFT)
00082 {
00083     low += SubRange.LowCount*(range >>= SHIFT);
00084     range *= SubRange.HighCount-SubRange.LowCount;
00085 }
00086 #define ARI_FLUSH_ENCODER(stream) {                                         \
00087     for (UINT i=0;i < 4;i++) {                                              \
00088         _PPMD_E_PUTC(low >> 24,stream);                 low <<= 8;          \
00089     }                                                                       \
00090 }
00091 #define ARI_INIT_DECODER(stream) {                                          \
00092     low=code=0;                             range=DWORD(-1);                \
00093     for (UINT i=0;i < 4;i++)                                                \
00094             code=(code << 8) | _PPMD_D_GETC(stream);                        \
00095 }
00096 #define ARI_DEC_NORMALIZE(stream) {                                         \
00097     while ((low ^ (low+range)) < TOP || range < BOT &&                      \
00098             ((range= -low & (BOT-1)),1)) {                                  \
00099         code=(code << 8) | _PPMD_D_GETC(stream);                            \
00100         range <<= 8;                        low <<= 8;                      \
00101     }                                                                       \
00102 }
00103 inline UINT ariGetCurrentCount() {
00104     return (code-low)/(range /= SubRange.scale);
00105 }
00106 inline UINT ariGetCurrentShiftCount(UINT SHIFT) {
00107     return (code-low)/(range >>= SHIFT);
00108 }
00109 inline void ariRemoveSubrange()
00110 {
00111     low += range*SubRange.LowCount;
00112     range *= SubRange.HighCount-SubRange.LowCount;
00113 }

Generated on Sat Nov 5 16:16:54 2005 for OPIE by  doxygen 1.4.2