rlm@1
|
1 // Compress/RangeCoder.h
|
rlm@1
|
2
|
rlm@1
|
3 #ifndef __COMPRESS_RANGE_CODER_H
|
rlm@1
|
4 #define __COMPRESS_RANGE_CODER_H
|
rlm@1
|
5
|
rlm@1
|
6 #include "../Common/InBuffer.h"
|
rlm@1
|
7 #include "../Common/OutBuffer.h"
|
rlm@1
|
8
|
rlm@1
|
9 namespace NCompress {
|
rlm@1
|
10 namespace NRangeCoder {
|
rlm@1
|
11
|
rlm@1
|
12 const int kNumTopBits = 24;
|
rlm@1
|
13 const UInt32 kTopValue = (1 << kNumTopBits);
|
rlm@1
|
14
|
rlm@1
|
15 class CEncoder
|
rlm@1
|
16 {
|
rlm@1
|
17 UInt32 _cacheSize;
|
rlm@1
|
18 Byte _cache;
|
rlm@1
|
19 public:
|
rlm@1
|
20 UInt64 Low;
|
rlm@1
|
21 UInt32 Range;
|
rlm@1
|
22 COutBuffer Stream;
|
rlm@1
|
23 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
|
rlm@1
|
24
|
rlm@1
|
25 void SetStream(ISequentialOutStream *stream) { Stream.SetStream(stream); }
|
rlm@1
|
26 void Init()
|
rlm@1
|
27 {
|
rlm@1
|
28 Stream.Init();
|
rlm@1
|
29 Low = 0;
|
rlm@1
|
30 Range = 0xFFFFFFFF;
|
rlm@1
|
31 _cacheSize = 1;
|
rlm@1
|
32 _cache = 0;
|
rlm@1
|
33 }
|
rlm@1
|
34
|
rlm@1
|
35 void FlushData()
|
rlm@1
|
36 {
|
rlm@1
|
37 // Low += 1;
|
rlm@1
|
38 for(int i = 0; i < 5; i++)
|
rlm@1
|
39 ShiftLow();
|
rlm@1
|
40 }
|
rlm@1
|
41
|
rlm@1
|
42 HRESULT FlushStream() { return Stream.Flush(); }
|
rlm@1
|
43
|
rlm@1
|
44 void ReleaseStream() { Stream.ReleaseStream(); }
|
rlm@1
|
45
|
rlm@1
|
46 void Encode(UInt32 start, UInt32 size, UInt32 total)
|
rlm@1
|
47 {
|
rlm@1
|
48 Low += start * (Range /= total);
|
rlm@1
|
49 Range *= size;
|
rlm@1
|
50 while (Range < kTopValue)
|
rlm@1
|
51 {
|
rlm@1
|
52 Range <<= 8;
|
rlm@1
|
53 ShiftLow();
|
rlm@1
|
54 }
|
rlm@1
|
55 }
|
rlm@1
|
56
|
rlm@1
|
57 void ShiftLow()
|
rlm@1
|
58 {
|
rlm@1
|
59 if ((UInt32)Low < (UInt32)0xFF000000 || (int)(Low >> 32) != 0)
|
rlm@1
|
60 {
|
rlm@1
|
61 Byte temp = _cache;
|
rlm@1
|
62 do
|
rlm@1
|
63 {
|
rlm@1
|
64 Stream.WriteByte((Byte)(temp + (Byte)(Low >> 32)));
|
rlm@1
|
65 temp = 0xFF;
|
rlm@1
|
66 }
|
rlm@1
|
67 while(--_cacheSize != 0);
|
rlm@1
|
68 _cache = (Byte)((UInt32)Low >> 24);
|
rlm@1
|
69 }
|
rlm@1
|
70 _cacheSize++;
|
rlm@1
|
71 Low = (UInt32)Low << 8;
|
rlm@1
|
72 }
|
rlm@1
|
73
|
rlm@1
|
74 void EncodeDirectBits(UInt32 value, int numBits)
|
rlm@1
|
75 {
|
rlm@1
|
76 for (numBits--; numBits >= 0; numBits--)
|
rlm@1
|
77 {
|
rlm@1
|
78 Range >>= 1;
|
rlm@1
|
79 Low += Range & (0 - ((value >> numBits) & 1));
|
rlm@1
|
80 if (Range < kTopValue)
|
rlm@1
|
81 {
|
rlm@1
|
82 Range <<= 8;
|
rlm@1
|
83 ShiftLow();
|
rlm@1
|
84 }
|
rlm@1
|
85 }
|
rlm@1
|
86 }
|
rlm@1
|
87
|
rlm@1
|
88 void EncodeBit(UInt32 size0, UInt32 numTotalBits, UInt32 symbol)
|
rlm@1
|
89 {
|
rlm@1
|
90 UInt32 newBound = (Range >> numTotalBits) * size0;
|
rlm@1
|
91 if (symbol == 0)
|
rlm@1
|
92 Range = newBound;
|
rlm@1
|
93 else
|
rlm@1
|
94 {
|
rlm@1
|
95 Low += newBound;
|
rlm@1
|
96 Range -= newBound;
|
rlm@1
|
97 }
|
rlm@1
|
98 while (Range < kTopValue)
|
rlm@1
|
99 {
|
rlm@1
|
100 Range <<= 8;
|
rlm@1
|
101 ShiftLow();
|
rlm@1
|
102 }
|
rlm@1
|
103 }
|
rlm@1
|
104
|
rlm@1
|
105 UInt64 GetProcessedSize() { return Stream.GetProcessedSize() + _cacheSize + 4; }
|
rlm@1
|
106 };
|
rlm@1
|
107
|
rlm@1
|
108 class CDecoder
|
rlm@1
|
109 {
|
rlm@1
|
110 public:
|
rlm@1
|
111 CInBuffer Stream;
|
rlm@1
|
112 UInt32 Range;
|
rlm@1
|
113 UInt32 Code;
|
rlm@1
|
114 bool Create(UInt32 bufferSize) { return Stream.Create(bufferSize); }
|
rlm@1
|
115
|
rlm@1
|
116 void Normalize()
|
rlm@1
|
117 {
|
rlm@1
|
118 while (Range < kTopValue)
|
rlm@1
|
119 {
|
rlm@1
|
120 Code = (Code << 8) | Stream.ReadByte();
|
rlm@1
|
121 Range <<= 8;
|
rlm@1
|
122 }
|
rlm@1
|
123 }
|
rlm@1
|
124
|
rlm@1
|
125 void SetStream(ISequentialInStream *stream) { Stream.SetStream(stream); }
|
rlm@1
|
126 void Init()
|
rlm@1
|
127 {
|
rlm@1
|
128 Stream.Init();
|
rlm@1
|
129 Code = 0;
|
rlm@1
|
130 Range = 0xFFFFFFFF;
|
rlm@1
|
131 for(int i = 0; i < 5; i++)
|
rlm@1
|
132 Code = (Code << 8) | Stream.ReadByte();
|
rlm@1
|
133 }
|
rlm@1
|
134
|
rlm@1
|
135 void ReleaseStream() { Stream.ReleaseStream(); }
|
rlm@1
|
136
|
rlm@1
|
137 UInt32 GetThreshold(UInt32 total)
|
rlm@1
|
138 {
|
rlm@1
|
139 return (Code) / ( Range /= total);
|
rlm@1
|
140 }
|
rlm@1
|
141
|
rlm@1
|
142 void Decode(UInt32 start, UInt32 size)
|
rlm@1
|
143 {
|
rlm@1
|
144 Code -= start * Range;
|
rlm@1
|
145 Range *= size;
|
rlm@1
|
146 Normalize();
|
rlm@1
|
147 }
|
rlm@1
|
148
|
rlm@1
|
149 UInt32 DecodeDirectBits(int numTotalBits)
|
rlm@1
|
150 {
|
rlm@1
|
151 UInt32 range = Range;
|
rlm@1
|
152 UInt32 code = Code;
|
rlm@1
|
153 UInt32 result = 0;
|
rlm@1
|
154 for (int i = numTotalBits; i != 0; i--)
|
rlm@1
|
155 {
|
rlm@1
|
156 range >>= 1;
|
rlm@1
|
157 /*
|
rlm@1
|
158 result <<= 1;
|
rlm@1
|
159 if (code >= range)
|
rlm@1
|
160 {
|
rlm@1
|
161 code -= range;
|
rlm@1
|
162 result |= 1;
|
rlm@1
|
163 }
|
rlm@1
|
164 */
|
rlm@1
|
165 UInt32 t = (code - range) >> 31;
|
rlm@1
|
166 code -= range & (t - 1);
|
rlm@1
|
167 result = (result << 1) | (1 - t);
|
rlm@1
|
168
|
rlm@1
|
169 if (range < kTopValue)
|
rlm@1
|
170 {
|
rlm@1
|
171 code = (code << 8) | Stream.ReadByte();
|
rlm@1
|
172 range <<= 8;
|
rlm@1
|
173 }
|
rlm@1
|
174 }
|
rlm@1
|
175 Range = range;
|
rlm@1
|
176 Code = code;
|
rlm@1
|
177 return result;
|
rlm@1
|
178 }
|
rlm@1
|
179
|
rlm@1
|
180 UInt32 DecodeBit(UInt32 size0, UInt32 numTotalBits)
|
rlm@1
|
181 {
|
rlm@1
|
182 UInt32 newBound = (Range >> numTotalBits) * size0;
|
rlm@1
|
183 UInt32 symbol;
|
rlm@1
|
184 if (Code < newBound)
|
rlm@1
|
185 {
|
rlm@1
|
186 symbol = 0;
|
rlm@1
|
187 Range = newBound;
|
rlm@1
|
188 }
|
rlm@1
|
189 else
|
rlm@1
|
190 {
|
rlm@1
|
191 symbol = 1;
|
rlm@1
|
192 Code -= newBound;
|
rlm@1
|
193 Range -= newBound;
|
rlm@1
|
194 }
|
rlm@1
|
195 Normalize();
|
rlm@1
|
196 return symbol;
|
rlm@1
|
197 }
|
rlm@1
|
198
|
rlm@1
|
199 UInt64 GetProcessedSize() {return Stream.GetProcessedSize(); }
|
rlm@1
|
200 };
|
rlm@1
|
201
|
rlm@1
|
202 }}
|
rlm@1
|
203
|
rlm@1
|
204 #endif
|