1 /*
2 ===============================================================================
3
4 FILE: laswriteitemcompressed_v2.cpp
5
6 CONTENTS:
7
8 see corresponding header file
9
10 PROGRAMMERS:
11
12 martin.isenburg@rapidlasso.com - http://rapidlasso.com
13
14 COPYRIGHT:
15
16 (c) 2007-2017, martin isenburg, rapidlasso - fast tools to catch reality
17
18 This is free software; you can redistribute and/or modify it under the
19 terms of the GNU Lesser General Licence as published by the Free Software
20 Foundation. See the COPYING file for more information.
21
22 This software is distributed WITHOUT ANY WARRANTY and without even the
23 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
24
25 CHANGE HISTORY:
26
27 see corresponding header file
28
29 ===============================================================================
30 */
31
32 #include "laswriteitemcompressed_v2.hpp"
33
34 #include <assert.h>
35 #include <string.h>
36
37 /*
38 ===============================================================================
39 LASwriteItemCompressed_POINT10_v2
40 ===============================================================================
41 */
42
43 struct LASpoint10
44 {
45 I32 x;
46 I32 y;
47 I32 z;
48 U16 intensity;
49 U8 return_number : 3;
50 U8 number_of_returns_of_given_pulse : 3;
51 U8 scan_direction_flag : 1;
52 U8 edge_of_flight_line : 1;
53 U8 classification;
54 I8 scan_angle_rank;
55 U8 user_data;
56 U16 point_source_ID;
57 };
58
LASwriteItemCompressed_POINT10_v2(ArithmeticEncoder * enc)59 LASwriteItemCompressed_POINT10_v2::LASwriteItemCompressed_POINT10_v2(ArithmeticEncoder* enc)
60 {
61 U32 i;
62
63 /* set encoder */
64 assert(enc);
65 this->enc = enc;
66
67 /* create models and integer compressors */
68 m_changed_values = enc->createSymbolModel(64);
69 ic_intensity = new IntegerCompressor(enc, 16, 4);
70 m_scan_angle_rank[0] = enc->createSymbolModel(256);
71 m_scan_angle_rank[1] = enc->createSymbolModel(256);
72 ic_point_source_ID = new IntegerCompressor(enc, 16);
73 for (i = 0; i < 256; i++)
74 {
75 m_bit_byte[i] = 0;
76 m_classification[i] = 0;
77 m_user_data[i] = 0;
78 }
79 ic_dx = new IntegerCompressor(enc, 32, 2); // 32 bits, 2 context
80 ic_dy = new IntegerCompressor(enc, 32, 22); // 32 bits, 22 contexts
81 ic_z = new IntegerCompressor(enc, 32, 20); // 32 bits, 20 contexts
82 }
83
~LASwriteItemCompressed_POINT10_v2()84 LASwriteItemCompressed_POINT10_v2::~LASwriteItemCompressed_POINT10_v2()
85 {
86 U32 i;
87
88 enc->destroySymbolModel(m_changed_values);
89 delete ic_intensity;
90 enc->destroySymbolModel(m_scan_angle_rank[0]);
91 enc->destroySymbolModel(m_scan_angle_rank[1]);
92 delete ic_point_source_ID;
93 for (i = 0; i < 256; i++)
94 {
95 if (m_bit_byte[i]) enc->destroySymbolModel(m_bit_byte[i]);
96 if (m_classification[i]) enc->destroySymbolModel(m_classification[i]);
97 if (m_user_data[i]) enc->destroySymbolModel(m_user_data[i]);
98 }
99 delete ic_dx;
100 delete ic_dy;
101 delete ic_z;
102 }
103
init(const U8 * item,U32 & context)104 BOOL LASwriteItemCompressed_POINT10_v2::init(const U8* item, U32& context)
105 {
106 U32 i;
107
108 /* init state */
109 for (i=0; i < 16; i++)
110 {
111 last_x_diff_median5[i].init();
112 last_y_diff_median5[i].init();
113 last_intensity[i] = 0;
114 last_height[i/2] = 0;
115 }
116
117 /* init models and integer compressors */
118 enc->initSymbolModel(m_changed_values);
119 ic_intensity->initCompressor();
120 enc->initSymbolModel(m_scan_angle_rank[0]);
121 enc->initSymbolModel(m_scan_angle_rank[1]);
122 ic_point_source_ID->initCompressor();
123 for (i = 0; i < 256; i++)
124 {
125 if (m_bit_byte[i]) enc->initSymbolModel(m_bit_byte[i]);
126 if (m_classification[i]) enc->initSymbolModel(m_classification[i]);
127 if (m_user_data[i]) enc->initSymbolModel(m_user_data[i]);
128 }
129 ic_dx->initCompressor();
130 ic_dy->initCompressor();
131 ic_z->initCompressor();
132
133 /* init last item */
134 memcpy(last_item, item, 20);
135
136 return TRUE;
137 }
138
write(const U8 * item,U32 & context)139 inline BOOL LASwriteItemCompressed_POINT10_v2::write(const U8* item, U32& context)
140 {
141 U32 r = ((LASpoint10*)item)->return_number;
142 U32 n = ((LASpoint10*)item)->number_of_returns_of_given_pulse;
143 U32 m = number_return_map[n][r];
144 U32 l = number_return_level[n][r];
145 U32 k_bits;
146 I32 median, diff;
147
148 // compress which other values have changed
149 I32 changed_values = (((last_item[14] != item[14]) << 5) | // bit_byte
150 ((last_intensity[m] != ((LASpoint10*)item)->intensity) << 4) |
151 ((last_item[15] != item[15]) << 3) | // classification
152 ((last_item[16] != item[16]) << 2) | // scan_angle_rank
153 ((last_item[17] != item[17]) << 1) | // user_data
154 (((LASpoint10*)last_item)->point_source_ID != ((LASpoint10*)item)->point_source_ID));
155
156 enc->encodeSymbol(m_changed_values, changed_values);
157
158 // compress the bit_byte (edge_of_flight_line, scan_direction_flag, returns, ...) if it has changed
159 if (changed_values & 32)
160 {
161 if (m_bit_byte[last_item[14]] == 0)
162 {
163 m_bit_byte[last_item[14]] = enc->createSymbolModel(256);
164 enc->initSymbolModel(m_bit_byte[last_item[14]]);
165 }
166 enc->encodeSymbol(m_bit_byte[last_item[14]], item[14]);
167 }
168
169 // compress the intensity if it has changed
170 if (changed_values & 16)
171 {
172 ic_intensity->compress(last_intensity[m], ((LASpoint10*)item)->intensity, (m < 3 ? m : 3));
173 last_intensity[m] = ((LASpoint10*)item)->intensity;
174 }
175
176 // compress the classification ... if it has changed
177 if (changed_values & 8)
178 {
179 if (m_classification[last_item[15]] == 0)
180 {
181 m_classification[last_item[15]] = enc->createSymbolModel(256);
182 enc->initSymbolModel(m_classification[last_item[15]]);
183 }
184 enc->encodeSymbol(m_classification[last_item[15]], item[15]);
185 }
186
187 // compress the scan_angle_rank ... if it has changed
188 if (changed_values & 4)
189 {
190 enc->encodeSymbol(m_scan_angle_rank[((LASpoint10*)item)->scan_direction_flag], U8_FOLD(item[16]-last_item[16]));
191 }
192
193 // compress the user_data ... if it has changed
194 if (changed_values & 2)
195 {
196 if (m_user_data[last_item[17]] == 0)
197 {
198 m_user_data[last_item[17]] = enc->createSymbolModel(256);
199 enc->initSymbolModel(m_user_data[last_item[17]]);
200 }
201 enc->encodeSymbol(m_user_data[last_item[17]], item[17]);
202 }
203
204 // compress the point_source_ID ... if it has changed
205 if (changed_values & 1)
206 {
207 ic_point_source_ID->compress(((LASpoint10*)last_item)->point_source_ID, ((LASpoint10*)item)->point_source_ID);
208 }
209
210 // compress x coordinate
211 median = last_x_diff_median5[m].get();
212 diff = ((LASpoint10*)item)->x - ((LASpoint10*)last_item)->x;
213 ic_dx->compress(median, diff, n==1);
214 last_x_diff_median5[m].add(diff);
215
216 // compress y coordinate
217 k_bits = ic_dx->getK();
218 median = last_y_diff_median5[m].get();
219 diff = ((LASpoint10*)item)->y - ((LASpoint10*)last_item)->y;
220 ic_dy->compress(median, diff, (n==1) + ( k_bits < 20 ? U32_ZERO_BIT_0(k_bits) : 20 ));
221 last_y_diff_median5[m].add(diff);
222
223 // compress z coordinate
224 k_bits = (ic_dx->getK() + ic_dy->getK()) / 2;
225 ic_z->compress(last_height[l], ((LASpoint10*)item)->z, (n==1) + (k_bits < 18 ? U32_ZERO_BIT_0(k_bits) : 18));
226 last_height[l] = ((LASpoint10*)item)->z;
227
228 // copy the last item
229 memcpy(last_item, item, 20);
230 return TRUE;
231 }
232
233 /*
234 ===============================================================================
235 LASwriteItemCompressed_GPSTIME11_v2
236 ===============================================================================
237 */
238
239 #define LASZIP_GPSTIME_MULTI 500
240 #define LASZIP_GPSTIME_MULTI_MINUS -10
241 #define LASZIP_GPSTIME_MULTI_UNCHANGED (LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 1)
242 #define LASZIP_GPSTIME_MULTI_CODE_FULL (LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 2)
243
244 #define LASZIP_GPSTIME_MULTI_TOTAL (LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 6)
245
LASwriteItemCompressed_GPSTIME11_v2(ArithmeticEncoder * enc)246 LASwriteItemCompressed_GPSTIME11_v2::LASwriteItemCompressed_GPSTIME11_v2(ArithmeticEncoder* enc)
247 {
248 /* set encoder */
249 assert(enc);
250 this->enc = enc;
251 /* create entropy models and integer compressors */
252 m_gpstime_multi = enc->createSymbolModel(LASZIP_GPSTIME_MULTI_TOTAL);
253 m_gpstime_0diff = enc->createSymbolModel(6);
254 ic_gpstime = new IntegerCompressor(enc, 32, 9); // 32 bits, 9 contexts
255 }
256
~LASwriteItemCompressed_GPSTIME11_v2()257 LASwriteItemCompressed_GPSTIME11_v2::~LASwriteItemCompressed_GPSTIME11_v2()
258 {
259 enc->destroySymbolModel(m_gpstime_multi);
260 enc->destroySymbolModel(m_gpstime_0diff);
261 delete ic_gpstime;
262 }
263
init(const U8 * item,U32 & context)264 BOOL LASwriteItemCompressed_GPSTIME11_v2::init(const U8* item, U32& context)
265 {
266 /* init state */
267 last = 0, next = 0;
268 last_gpstime_diff[0] = 0;
269 last_gpstime_diff[1] = 0;
270 last_gpstime_diff[2] = 0;
271 last_gpstime_diff[3] = 0;
272 multi_extreme_counter[0] = 0;
273 multi_extreme_counter[1] = 0;
274 multi_extreme_counter[2] = 0;
275 multi_extreme_counter[3] = 0;
276
277 /* init models and integer compressors */
278 enc->initSymbolModel(m_gpstime_multi);
279 enc->initSymbolModel(m_gpstime_0diff);
280 ic_gpstime->initCompressor();
281
282 /* init last item */
283 last_gpstime[0].u64 = *((U64*)item);
284 last_gpstime[1].u64 = 0;
285 last_gpstime[2].u64 = 0;
286 last_gpstime[3].u64 = 0;
287 return TRUE;
288 }
289
write(const U8 * item,U32 & context)290 inline BOOL LASwriteItemCompressed_GPSTIME11_v2::write(const U8* item, U32& context)
291 {
292 U64I64F64 this_gpstime;
293 this_gpstime.i64 = *((I64*)item);
294
295 if (last_gpstime_diff[last] == 0) // if the last integer difference was zero
296 {
297 if (this_gpstime.i64 == last_gpstime[last].i64)
298 {
299 enc->encodeSymbol(m_gpstime_0diff, 0); // the doubles have not changed
300 }
301 else
302 {
303 // calculate the difference between the two doubles as an integer
304 I64 curr_gpstime_diff_64 = this_gpstime.i64 - last_gpstime[last].i64;
305 I32 curr_gpstime_diff = (I32)curr_gpstime_diff_64;
306 if (curr_gpstime_diff_64 == (I64)(curr_gpstime_diff))
307 {
308 enc->encodeSymbol(m_gpstime_0diff, 1); // the difference can be represented with 32 bits
309 ic_gpstime->compress(0, curr_gpstime_diff, 0);
310 last_gpstime_diff[last] = curr_gpstime_diff;
311 multi_extreme_counter[last] = 0;
312 }
313 else // the difference is huge
314 {
315 U32 i;
316 // maybe the double belongs to another time sequence
317 for (i = 1; i < 4; i++)
318 {
319 I64 other_gpstime_diff_64 = this_gpstime.i64 - last_gpstime[(last+i)&3].i64;
320 I32 other_gpstime_diff = (I32)other_gpstime_diff_64;
321 if (other_gpstime_diff_64 == (I64)(other_gpstime_diff))
322 {
323 enc->encodeSymbol(m_gpstime_0diff, i+2); // it belongs to another sequence
324 last = (last+i)&3;
325 return write(item, context);
326 }
327 }
328 // no other sequence found. start new sequence.
329 enc->encodeSymbol(m_gpstime_0diff, 2);
330 ic_gpstime->compress((I32)(last_gpstime[last].u64 >> 32), (I32)(this_gpstime.u64 >> 32), 8);
331 enc->writeInt((U32)(this_gpstime.u64));
332 next = (next+1)&3;
333 last = next;
334 last_gpstime_diff[last] = 0;
335 multi_extreme_counter[last] = 0;
336 }
337 last_gpstime[last].i64 = this_gpstime.i64;
338 }
339 }
340 else // the last integer difference was *not* zero
341 {
342 if (this_gpstime.i64 == last_gpstime[last].i64)
343 {
344 // if the doubles have not changed use a special symbol
345 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI_UNCHANGED);
346 }
347 else
348 {
349 // calculate the difference between the two doubles as an integer
350 I64 curr_gpstime_diff_64 = this_gpstime.i64 - last_gpstime[last].i64;
351 I32 curr_gpstime_diff = (I32)curr_gpstime_diff_64;
352
353 // if the current gpstime difference can be represented with 32 bits
354 if (curr_gpstime_diff_64 == (I64)(curr_gpstime_diff))
355 {
356 // compute multiplier between current and last integer difference
357 F32 multi_f = (F32)curr_gpstime_diff / (F32)(last_gpstime_diff[last]);
358 I32 multi = I32_QUANTIZE(multi_f);
359
360 // compress the residual curr_gpstime_diff in dependance on the multiplier
361 if (multi == 1)
362 {
363 // this is the case we assume we get most often for regular spaced pulses
364 enc->encodeSymbol(m_gpstime_multi, 1);
365 ic_gpstime->compress(last_gpstime_diff[last], curr_gpstime_diff, 1);
366 multi_extreme_counter[last] = 0;
367 }
368 else if (multi > 0)
369 {
370 if (multi < LASZIP_GPSTIME_MULTI) // positive multipliers up to LASZIP_GPSTIME_MULTI are compressed directly
371 {
372 enc->encodeSymbol(m_gpstime_multi, multi);
373 if (multi < 10)
374 ic_gpstime->compress(multi*last_gpstime_diff[last], curr_gpstime_diff, 2);
375 else
376 ic_gpstime->compress(multi*last_gpstime_diff[last], curr_gpstime_diff, 3);
377 }
378 else
379 {
380 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI);
381 ic_gpstime->compress(LASZIP_GPSTIME_MULTI*last_gpstime_diff[last], curr_gpstime_diff, 4);
382 multi_extreme_counter[last]++;
383 if (multi_extreme_counter[last] > 3)
384 {
385 last_gpstime_diff[last] = curr_gpstime_diff;
386 multi_extreme_counter[last] = 0;
387 }
388 }
389 }
390 else if (multi < 0)
391 {
392 if (multi > LASZIP_GPSTIME_MULTI_MINUS) // negative multipliers larger than LASZIP_GPSTIME_MULTI_MINUS are compressed directly
393 {
394 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI - multi);
395 ic_gpstime->compress(multi*last_gpstime_diff[last], curr_gpstime_diff, 5);
396 }
397 else
398 {
399 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS);
400 ic_gpstime->compress(LASZIP_GPSTIME_MULTI_MINUS*last_gpstime_diff[last], curr_gpstime_diff, 6);
401 multi_extreme_counter[last]++;
402 if (multi_extreme_counter[last] > 3)
403 {
404 last_gpstime_diff[last] = curr_gpstime_diff;
405 multi_extreme_counter[last] = 0;
406 }
407 }
408 }
409 else
410 {
411 enc->encodeSymbol(m_gpstime_multi, 0);
412 ic_gpstime->compress(0, curr_gpstime_diff, 7);
413 multi_extreme_counter[last]++;
414 if (multi_extreme_counter[last] > 3)
415 {
416 last_gpstime_diff[last] = curr_gpstime_diff;
417 multi_extreme_counter[last] = 0;
418 }
419 }
420 }
421 else // the difference is huge
422 {
423 U32 i;
424 // maybe the double belongs to another time sequence
425 for (i = 1; i < 4; i++)
426 {
427 I64 other_gpstime_diff_64 = this_gpstime.i64 - last_gpstime[(last+i)&3].i64;
428 I32 other_gpstime_diff = (I32)other_gpstime_diff_64;
429 if (other_gpstime_diff_64 == (I64)(other_gpstime_diff))
430 {
431 // it belongs to this sequence
432 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI_CODE_FULL+i);
433 last = (last+i)&3;
434 return write(item, context);
435 }
436 }
437 // no other sequence found. start new sequence.
438 enc->encodeSymbol(m_gpstime_multi, LASZIP_GPSTIME_MULTI_CODE_FULL);
439 ic_gpstime->compress((I32)(last_gpstime[last].u64 >> 32), (I32)(this_gpstime.u64 >> 32), 8);
440 enc->writeInt((U32)(this_gpstime.u64));
441 next = (next+1)&3;
442 last = next;
443 last_gpstime_diff[last] = 0;
444 multi_extreme_counter[last] = 0;
445 }
446 last_gpstime[last].i64 = this_gpstime.i64;
447 }
448 }
449 return TRUE;
450 }
451
452 /*
453 ===============================================================================
454 LASwriteItemCompressed_RGB12_v2
455 ===============================================================================
456 */
457
LASwriteItemCompressed_RGB12_v2(ArithmeticEncoder * enc)458 LASwriteItemCompressed_RGB12_v2::LASwriteItemCompressed_RGB12_v2(ArithmeticEncoder* enc)
459 {
460 /* set encoder */
461 assert(enc);
462 this->enc = enc;
463
464 /* create models and integer compressors */
465 m_byte_used = enc->createSymbolModel(128);
466 m_rgb_diff_0 = enc->createSymbolModel(256);
467 m_rgb_diff_1 = enc->createSymbolModel(256);
468 m_rgb_diff_2 = enc->createSymbolModel(256);
469 m_rgb_diff_3 = enc->createSymbolModel(256);
470 m_rgb_diff_4 = enc->createSymbolModel(256);
471 m_rgb_diff_5 = enc->createSymbolModel(256);
472 }
473
~LASwriteItemCompressed_RGB12_v2()474 LASwriteItemCompressed_RGB12_v2::~LASwriteItemCompressed_RGB12_v2()
475 {
476 enc->destroySymbolModel(m_byte_used);
477 enc->destroySymbolModel(m_rgb_diff_0);
478 enc->destroySymbolModel(m_rgb_diff_1);
479 enc->destroySymbolModel(m_rgb_diff_2);
480 enc->destroySymbolModel(m_rgb_diff_3);
481 enc->destroySymbolModel(m_rgb_diff_4);
482 enc->destroySymbolModel(m_rgb_diff_5);
483 }
484
init(const U8 * item,U32 & context)485 BOOL LASwriteItemCompressed_RGB12_v2::init(const U8* item, U32& context)
486 {
487 /* init state */
488
489 /* init models and integer compressors */
490 enc->initSymbolModel(m_byte_used);
491 enc->initSymbolModel(m_rgb_diff_0);
492 enc->initSymbolModel(m_rgb_diff_1);
493 enc->initSymbolModel(m_rgb_diff_2);
494 enc->initSymbolModel(m_rgb_diff_3);
495 enc->initSymbolModel(m_rgb_diff_4);
496 enc->initSymbolModel(m_rgb_diff_5);
497
498 /* init last item */
499 memcpy(last_item, item, 6);
500 return TRUE;
501 }
502
write(const U8 * item,U32 & context)503 inline BOOL LASwriteItemCompressed_RGB12_v2::write(const U8* item, U32& context)
504 {
505 I32 diff_l = 0;
506 I32 diff_h = 0;
507 I32 corr;
508 U32 sym = ((last_item[0]&0x00FF) != (((U16*)item)[0]&0x00FF)) << 0;
509 sym |= ((last_item[0]&0xFF00) != (((U16*)item)[0]&0xFF00)) << 1;
510 sym |= ((last_item[1]&0x00FF) != (((U16*)item)[1]&0x00FF)) << 2;
511 sym |= ((last_item[1]&0xFF00) != (((U16*)item)[1]&0xFF00)) << 3;
512 sym |= ((last_item[2]&0x00FF) != (((U16*)item)[2]&0x00FF)) << 4;
513 sym |= ((last_item[2]&0xFF00) != (((U16*)item)[2]&0xFF00)) << 5;
514 sym |= (((((U16*)item)[0]&0x00FF) != (((U16*)item)[1]&0x00FF)) || ((((U16*)item)[0]&0x00FF) != (((U16*)item)[2]&0x00FF)) || ((((U16*)item)[0]&0xFF00) != (((U16*)item)[1]&0xFF00)) || ((((U16*)item)[0]&0xFF00) != (((U16*)item)[2]&0xFF00))) << 6;
515 enc->encodeSymbol(m_byte_used, sym);
516 if (sym & (1 << 0))
517 {
518 diff_l = ((int)(((U16*)item)[0]&255)) - (last_item[0]&255);
519 enc->encodeSymbol(m_rgb_diff_0, U8_FOLD(diff_l));
520 }
521 if (sym & (1 << 1))
522 {
523 diff_h = ((int)(((U16*)item)[0]>>8)) - (last_item[0]>>8);
524 enc->encodeSymbol(m_rgb_diff_1, U8_FOLD(diff_h));
525 }
526 if (sym & (1 << 6))
527 {
528 if (sym & (1 << 2))
529 {
530 corr = ((int)(((U16*)item)[1]&255)) - U8_CLAMP(diff_l + (last_item[1]&255));
531 enc->encodeSymbol(m_rgb_diff_2, U8_FOLD(corr));
532 }
533 if (sym & (1 << 4))
534 {
535 diff_l = (diff_l + (((U16*)item)[1]&255) - (last_item[1]&255)) / 2;
536 corr = ((int)(((U16*)item)[2]&255)) - U8_CLAMP(diff_l + (last_item[2]&255));
537 enc->encodeSymbol(m_rgb_diff_4, U8_FOLD(corr));
538 }
539 if (sym & (1 << 3))
540 {
541 corr = ((int)(((U16*)item)[1]>>8)) - U8_CLAMP(diff_h + (last_item[1]>>8));
542 enc->encodeSymbol(m_rgb_diff_3, U8_FOLD(corr));
543 }
544 if (sym & (1 << 5))
545 {
546 diff_h = (diff_h + (((U16*)item)[1]>>8) - (last_item[1]>>8)) / 2;
547 corr = ((int)(((U16*)item)[2]>>8)) - U8_CLAMP(diff_h + (last_item[2]>>8));
548 enc->encodeSymbol(m_rgb_diff_5, U8_FOLD(corr));
549 }
550 }
551 memcpy(last_item, item, 6);
552 return TRUE;
553 }
554
555 /*
556 ===============================================================================
557 LASwriteItemCompressed_BYTE_v2
558 ===============================================================================
559 */
560
LASwriteItemCompressed_BYTE_v2(ArithmeticEncoder * enc,U32 number)561 LASwriteItemCompressed_BYTE_v2::LASwriteItemCompressed_BYTE_v2(ArithmeticEncoder* enc, U32 number)
562 {
563 U32 i;
564
565 /* set encoder */
566 assert(enc);
567 this->enc = enc;
568 assert(number);
569 this->number = number;
570
571 /* create models and integer compressors */
572 m_byte = new ArithmeticModel*[number];
573 for (i = 0; i < number; i++)
574 {
575 m_byte[i] = enc->createSymbolModel(256);
576 }
577
578 /* create last item */
579 last_item = new U8[number];
580 }
581
~LASwriteItemCompressed_BYTE_v2()582 LASwriteItemCompressed_BYTE_v2::~LASwriteItemCompressed_BYTE_v2()
583 {
584 U32 i;
585 for (i = 0; i < number; i++)
586 {
587 enc->destroySymbolModel(m_byte[i]);
588 }
589 delete [] m_byte;
590 delete [] last_item;
591 }
592
init(const U8 * item,U32 & context)593 BOOL LASwriteItemCompressed_BYTE_v2::init(const U8* item, U32& context)
594 {
595 U32 i;
596 /* init state */
597
598 /* init models and integer compressors */
599 for (i = 0; i < number; i++)
600 {
601 enc->initSymbolModel(m_byte[i]);
602 }
603
604 /* init last point */
605 memcpy(last_item, item, number);
606 return TRUE;
607 }
608
write(const U8 * item,U32 & context)609 inline BOOL LASwriteItemCompressed_BYTE_v2::write(const U8* item, U32& context)
610 {
611 U32 i;
612 I32 diff;
613 for (i = 0; i < number; i++)
614 {
615 diff = item[i] - last_item[i];
616 enc->encodeSymbol(m_byte[i], U8_FOLD(diff));
617 }
618 memcpy(last_item, item, number);
619 return TRUE;
620 }
621
622