/src/assimp/contrib/Open3DGC/o3dgcArithmeticCodec.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | Copyright (c) 2004 Amir Said (said@ieee.org) & William A. Pearlman (pearlw@ecse.rpi.edu) |
3 | | All rights reserved. |
4 | | |
5 | | Redistribution and use in source and binary forms, with or without modification, |
6 | | are permitted provided that the following conditions are met: |
7 | | |
8 | | - Redistributions of source code must retain the above copyright notice, this list |
9 | | of conditions and the following disclaimer. |
10 | | |
11 | | - Redistributions in binary form must reproduce the above copyright notice, this list of |
12 | | conditions and the following disclaimer in the documentation and/or other materials |
13 | | provided with the distribution. |
14 | | |
15 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY |
16 | | EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
17 | | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
18 | | THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
19 | | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
20 | | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; |
21 | | OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER |
22 | | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
23 | | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
24 | | OF SUCH DAMAGE. |
25 | | */ |
26 | | |
27 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
28 | | // - |
29 | | // **************************** - |
30 | | // ARITHMETIC CODING EXAMPLES - |
31 | | // **************************** - |
32 | | // - |
33 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
34 | | // - |
35 | | // Fast arithmetic coding implementation - |
36 | | // -> 32-bit variables, 32-bit product, periodic updates, table decoding - |
37 | | // - |
38 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
39 | | // - |
40 | | // Version 1.00 - April 25, 2004 - |
41 | | // - |
42 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
43 | | // - |
44 | | // WARNING - |
45 | | // ========= - |
46 | | // - |
47 | | // The only purpose of this program is to demonstrate the basic principles - |
48 | | // of arithmetic coding. It is provided as is, without any express or - |
49 | | // implied warranty, without even the warranty of fitness for any particular - |
50 | | // purpose, or that the implementations are correct. - |
51 | | // - |
52 | | // Permission to copy and redistribute this code is hereby granted, provided - |
53 | | // that this warning and copyright notices are not removed or altered. - |
54 | | // - |
55 | | // Copyright (c) 2004 by Amir Said (said@ieee.org) & - |
56 | | // William A. Pearlman (pearlw@ecse.rpi.edu) - |
57 | | // - |
58 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
59 | | // - |
60 | | // A description of the arithmetic coding method used here is available in - |
61 | | // - |
62 | | // Lossless Compression Handbook, ed. K. Sayood - |
63 | | // Chapter 5: Arithmetic Coding (A. Said), pp. 101-152, Academic Press, 2003 - |
64 | | // - |
65 | | // A. Said, Introduction to Arithetic Coding Theory and Practice - |
66 | | // HP Labs report HPL-2004-76 - http://www.hpl.hp.com/techreports/ - |
67 | | // - |
68 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
69 | | |
70 | | |
71 | | // - - Definitions - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
72 | | |
73 | | #ifndef O3DGC_ARITHMETIC_CODEC |
74 | | #define O3DGC_ARITHMETIC_CODEC |
75 | | |
76 | | #include <stdio.h> |
77 | | #include "o3dgcCommon.h" |
78 | | #include <assimp/defs.h> |
79 | | |
80 | | namespace o3dgc |
81 | | { |
82 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
83 | | // - - Class definitions - - - - - - - - - - - - - - - - - - - - - - - - - - - |
84 | | |
85 | | class Static_Bit_Model // static model for binary data |
86 | | { |
87 | | public: |
88 | | |
89 | | Static_Bit_Model(void); |
90 | | |
91 | | void set_probability_0(double); // set probability of symbol '0' |
92 | | |
93 | | private: // . . . . . . . . . . . . . . . . . . . . . . |
94 | | unsigned bit_0_prob; |
95 | | friend class Arithmetic_Codec; |
96 | | }; |
97 | | |
98 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
99 | | |
100 | | class Static_Data_Model // static model for general data |
101 | | { |
102 | | public: |
103 | | |
104 | | Static_Data_Model(void); |
105 | | ~Static_Data_Model(void); |
106 | | |
107 | 0 | unsigned model_symbols(void) { return data_symbols; } |
108 | | |
109 | | void set_distribution(unsigned number_of_symbols, |
110 | | const double probability[] = 0); // 0 means uniform |
111 | | |
112 | | private: // . . . . . . . . . . . . . . . . . . . . . . |
113 | | unsigned * distribution, * decoder_table; |
114 | | unsigned data_symbols, last_symbol, table_size, table_shift; |
115 | | friend class Arithmetic_Codec; |
116 | | }; |
117 | | |
118 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
119 | | |
120 | | class Adaptive_Bit_Model // adaptive model for binary data |
121 | | { |
122 | | public: |
123 | | |
124 | | Adaptive_Bit_Model(void); |
125 | | |
126 | | void reset(void); // reset to equiprobable model |
127 | | |
128 | | private: // . . . . . . . . . . . . . . . . . . . . . . |
129 | | void update(void); |
130 | | unsigned update_cycle, bits_until_update; |
131 | | unsigned bit_0_prob, bit_0_count, bit_count; |
132 | | friend class Arithmetic_Codec; |
133 | | }; |
134 | | |
135 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
136 | | |
137 | | class Adaptive_Data_Model // adaptive model for binary data |
138 | | { |
139 | | public: |
140 | | |
141 | | Adaptive_Data_Model(void); |
142 | | Adaptive_Data_Model(unsigned number_of_symbols); |
143 | | ~Adaptive_Data_Model(void); |
144 | | |
145 | 0 | unsigned model_symbols(void) { return data_symbols; } |
146 | | |
147 | | void reset(void); // reset to equiprobable model |
148 | | void set_alphabet(unsigned number_of_symbols); |
149 | | |
150 | | private: // . . . . . . . . . . . . . . . . . . . . . . |
151 | | void update(bool); |
152 | | unsigned * distribution, * symbol_count, * decoder_table; |
153 | | unsigned total_count, update_cycle, symbols_until_update; |
154 | | unsigned data_symbols, last_symbol, table_size, table_shift; |
155 | | friend class Arithmetic_Codec; |
156 | | }; |
157 | | |
158 | | |
159 | | // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
160 | | // - - Encoder and decoder class - - - - - - - - - - - - - - - - - - - - - - - |
161 | | |
162 | | // Class with both the arithmetic encoder and decoder. All compressed data is |
163 | | // saved to a memory buffer |
164 | | |
165 | | class Arithmetic_Codec |
166 | | { |
167 | | public: |
168 | | |
169 | | Arithmetic_Codec(void); |
170 | | ~Arithmetic_Codec(void); |
171 | | Arithmetic_Codec(unsigned max_code_bytes, |
172 | | unsigned char * user_buffer = 0); // 0 = assign new |
173 | | |
174 | 0 | unsigned char * buffer(void) { return code_buffer; } |
175 | | |
176 | | void set_buffer(unsigned max_code_bytes, |
177 | | unsigned char * user_buffer = 0); // 0 = assign new |
178 | | |
179 | | void start_encoder(void); |
180 | | void start_decoder(void); |
181 | | void read_from_file(FILE * code_file); // read code data, start decoder |
182 | | |
183 | | unsigned stop_encoder(void); // returns number of bytes used |
184 | | unsigned write_to_file(FILE * code_file); // stop encoder, write code data |
185 | | void stop_decoder(void); |
186 | | |
187 | | void put_bit(unsigned bit); |
188 | | unsigned get_bit(void); |
189 | | |
190 | | void put_bits(unsigned data, unsigned number_of_bits); |
191 | | unsigned get_bits(unsigned number_of_bits); |
192 | | |
193 | | void encode(unsigned bit, |
194 | | Static_Bit_Model &); |
195 | | unsigned decode(Static_Bit_Model &); |
196 | | |
197 | | void encode(unsigned data, |
198 | | Static_Data_Model &); |
199 | | unsigned decode(Static_Data_Model &); |
200 | | |
201 | | void encode(unsigned bit, |
202 | | Adaptive_Bit_Model &); |
203 | | unsigned decode(Adaptive_Bit_Model &); |
204 | | |
205 | | void encode(unsigned data, |
206 | | Adaptive_Data_Model &); |
207 | | unsigned decode(Adaptive_Data_Model &); |
208 | | |
209 | | // This section was added by K. Mammou |
210 | | void ExpGolombEncode(unsigned int symbol, |
211 | | int k, |
212 | | Static_Bit_Model & bModel0, |
213 | | Adaptive_Bit_Model & bModel1) |
214 | 0 | { |
215 | 0 | while(1) |
216 | 0 | { |
217 | 0 | if (symbol >= (unsigned int)(1<<k)) |
218 | 0 | { |
219 | 0 | encode(1, bModel1); |
220 | 0 | symbol = symbol - (1<<k); |
221 | 0 | k++; |
222 | 0 | } |
223 | 0 | else |
224 | 0 | { |
225 | 0 | encode(0, bModel1); // now terminated zero of unary part |
226 | 0 | while (k--) // next binary part |
227 | 0 | { |
228 | 0 | encode((signed short)((symbol>>k)&1), bModel0); |
229 | 0 | } |
230 | 0 | break; |
231 | 0 | } |
232 | 0 | } |
233 | 0 | } |
234 | | |
235 | | |
236 | | unsigned ExpGolombDecode(int k, |
237 | | Static_Bit_Model & bModel0, |
238 | | Adaptive_Bit_Model & bModel1) |
239 | 0 | { |
240 | 0 | unsigned int l; |
241 | 0 | int symbol = 0; |
242 | 0 | int binary_symbol = 0; |
243 | 0 | do |
244 | 0 | { |
245 | 0 | l=decode(bModel1); |
246 | 0 | if (l==1) |
247 | 0 | { |
248 | 0 | symbol += (1<<k); |
249 | 0 | k++; |
250 | 0 | } |
251 | 0 | } |
252 | 0 | while (l!=0); |
253 | 0 | while (k--) //next binary part |
254 | 0 | if (decode(bModel0)==1) |
255 | 0 | { |
256 | 0 | binary_symbol |= (1<<k); |
257 | 0 | } |
258 | 0 | return (unsigned int) (symbol+binary_symbol); |
259 | 0 | } |
260 | | //---------------------------------------------------------- |
261 | | |
262 | | private: // . . . . . . . . . . . . . . . . . . . . . . |
263 | | void propagate_carry(void); |
264 | | void renorm_enc_interval(void); |
265 | | void renorm_dec_interval(void); |
266 | | unsigned char * code_buffer, * new_buffer, * ac_pointer; |
267 | | unsigned base, value, length; // arithmetic coding state |
268 | | unsigned buffer_size, mode; // mode: 0 = undef, 1 = encoder, 2 = decoder |
269 | | }; |
270 | | inline long DecodeIntACEGC(Arithmetic_Codec & acd, |
271 | | Adaptive_Data_Model & mModelValues, |
272 | | Static_Bit_Model & bModel0, |
273 | | Adaptive_Bit_Model & bModel1, |
274 | | const unsigned long exp_k, |
275 | | const unsigned long M) |
276 | 0 | { |
277 | 0 | unsigned long uiValue = acd.decode(mModelValues); |
278 | 0 | if (uiValue == M) |
279 | 0 | { |
280 | 0 | uiValue += acd.ExpGolombDecode(exp_k, bModel0, bModel1); |
281 | 0 | } |
282 | 0 | return UIntToInt(uiValue); |
283 | 0 | } |
284 | | inline unsigned long DecodeUIntACEGC(Arithmetic_Codec & acd, |
285 | | Adaptive_Data_Model & mModelValues, |
286 | | Static_Bit_Model & bModel0, |
287 | | Adaptive_Bit_Model & bModel1, |
288 | | const unsigned long exp_k, |
289 | | const unsigned long M) |
290 | 0 | { |
291 | 0 | unsigned long uiValue = acd.decode(mModelValues); |
292 | 0 | if (uiValue == M) |
293 | 0 | { |
294 | 0 | uiValue += acd.ExpGolombDecode(exp_k, bModel0, bModel1); |
295 | 0 | } |
296 | 0 | return uiValue; |
297 | 0 | } |
298 | | |
299 | | inline void EncodeIntACEGC(long predResidual, |
300 | | Arithmetic_Codec & ace, |
301 | | Adaptive_Data_Model & mModelValues, |
302 | | Static_Bit_Model & bModel0, |
303 | | Adaptive_Bit_Model & bModel1, |
304 | | const unsigned long M) |
305 | 0 | { |
306 | 0 | unsigned long uiValue = IntToUInt(predResidual); |
307 | 0 | if (uiValue < M) |
308 | 0 | { |
309 | 0 | ace.encode(uiValue, mModelValues); |
310 | 0 | } |
311 | 0 | else |
312 | 0 | { |
313 | 0 | ace.encode(M, mModelValues); |
314 | 0 | ace.ExpGolombEncode(uiValue-M, 0, bModel0, bModel1); |
315 | 0 | } |
316 | 0 | } |
317 | | inline void EncodeUIntACEGC(long predResidual, |
318 | | Arithmetic_Codec & ace, |
319 | | Adaptive_Data_Model & mModelValues, |
320 | | Static_Bit_Model & bModel0, |
321 | | Adaptive_Bit_Model & bModel1, |
322 | | const unsigned long M) |
323 | 0 | { |
324 | 0 | unsigned long uiValue = (unsigned long) predResidual; |
325 | 0 | if (uiValue < M) |
326 | 0 | { |
327 | 0 | ace.encode(uiValue, mModelValues); |
328 | 0 | } |
329 | 0 | else |
330 | 0 | { |
331 | 0 | ace.encode(M, mModelValues); |
332 | 0 | ace.ExpGolombEncode(uiValue-M, 0, bModel0, bModel1); |
333 | 0 | } |
334 | 0 | } |
335 | | |
336 | | } |
337 | | /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ |
338 | | |
339 | | #endif |
340 | | |