1 /*
2 ===============================================================================
3
4 FILE: laswriteitemcompressed_v4.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_v4.hpp"
33
34 #include <assert.h>
35 #include <string.h>
36 #include <stdio.h>
37
38 /*
39 ===============================================================================
40 LASwriteItemCompressed_POINT14_v4
41 ===============================================================================
42 */
43
44 typedef struct LASpoint14
45 {
46 I32 X;
47 I32 Y;
48 I32 Z;
49 U16 intensity;
50 U8 legacy_return_number : 3;
51 U8 legacy_number_of_returns : 3;
52 U8 scan_direction_flag : 1;
53 U8 edge_of_flight_line : 1;
54 U8 legacy_classification : 5;
55 U8 legacy_flags : 3;
56 I8 legacy_scan_angle_rank;
57 U8 user_data;
58 U16 point_source_ID;
59
60 // LAS 1.4 only
61 I16 scan_angle;
62 U8 legacy_point_type : 2;
63 U8 scanner_channel : 2;
64 U8 classification_flags : 4;
65 U8 classification;
66 U8 return_number : 4;
67 U8 number_of_returns : 4;
68
69 // LASlib internal use only
70 U8 deleted_flag;
71
72 // for 8 byte alignment of the GPS time
73 U8 dummy[2];
74
75 // compressed LASzip 1.4 points only
76 BOOL gps_time_change;
77
78 F64 gps_time;
79 U16 rgb[4];
80 // LASwavepacket wavepacket;
81 } LASpoint14;
82
83 #define LASZIP_GPSTIME_MULTI 500
84 #define LASZIP_GPSTIME_MULTI_MINUS -10
85 #define LASZIP_GPSTIME_MULTI_CODE_FULL (LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 1)
86
87 #define LASZIP_GPSTIME_MULTI_TOTAL (LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS + 5)
88
LASwriteItemCompressed_POINT14_v4(ArithmeticEncoder * enc)89 LASwriteItemCompressed_POINT14_v4::LASwriteItemCompressed_POINT14_v4(ArithmeticEncoder* enc)
90 {
91 /* not used as a encoder. just gives access to outstream */
92
93 assert(enc);
94 this->enc = enc;
95
96 /* zero outstreams and encoders */
97
98 outstream_channel_returns_XY = 0;
99 outstream_Z = 0;
100 outstream_classification = 0;
101 outstream_flags = 0;
102 outstream_intensity = 0;
103 outstream_scan_angle = 0;
104 outstream_user_data = 0;
105 outstream_point_source = 0;
106 outstream_gps_time = 0;
107
108 enc_channel_returns_XY = 0;
109 enc_Z = 0;
110 enc_classification = 0;
111 enc_flags = 0;
112 enc_intensity = 0;
113 enc_scan_angle = 0;
114 enc_user_data = 0;
115 enc_point_source = 0;
116 enc_gps_time = 0;
117
118 /* mark the four scanner channel contexts as uninitialized */
119
120 U32 c;
121 for (c = 0; c < 4; c++)
122 {
123 contexts[c].m_changed_values[0] = 0;
124 }
125 current_context = 0;
126
127 /* number of bytes per layer */
128
129 num_bytes_channel_returns_XY = 0;
130 num_bytes_Z = 0;
131 num_bytes_classification = 0;
132 num_bytes_flags = 0;
133 num_bytes_intensity = 0;
134 num_bytes_scan_angle = 0;
135 num_bytes_user_data = 0;
136 num_bytes_point_source = 0;
137 num_bytes_gps_time = 0;
138 }
139
~LASwriteItemCompressed_POINT14_v4()140 LASwriteItemCompressed_POINT14_v4::~LASwriteItemCompressed_POINT14_v4()
141 {
142 U32 c, i;
143
144 /* destroy all initialized scanner channel contexts */
145
146 for (c = 0; c < 4; c++)
147 {
148 if (contexts[c].m_changed_values[0])
149 {
150 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[0]);
151 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[1]);
152 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[2]);
153 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[3]);
154 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[4]);
155 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[5]);
156 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[6]);
157 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_changed_values[7]);
158 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_scanner_channel);
159 for (i = 0; i < 16; i++)
160 {
161 if (contexts[c].m_number_of_returns[i]) enc_channel_returns_XY->destroySymbolModel(contexts[c].m_number_of_returns[i]);
162 if (contexts[c].m_return_number[i]) enc_channel_returns_XY->destroySymbolModel(contexts[c].m_return_number[i]);
163 }
164 enc_channel_returns_XY->destroySymbolModel(contexts[c].m_return_number_gps_same);
165 delete contexts[c].ic_dX;
166 delete contexts[c].ic_dY;
167 delete contexts[c].ic_Z;
168 for (i = 0; i < 64; i++)
169 {
170 if (contexts[c].m_classification[i]) enc_classification->destroySymbolModel(contexts[c].m_classification[i]);
171 if (contexts[c].m_flags[i]) enc_flags->destroySymbolModel(contexts[c].m_flags[i]);
172 if (contexts[c].m_user_data[i]) enc_user_data->destroySymbolModel(contexts[c].m_user_data[i]);
173 }
174 delete contexts[c].ic_intensity;
175 delete contexts[c].ic_scan_angle;
176 delete contexts[c].ic_point_source_ID;
177 enc_gps_time->destroySymbolModel(contexts[c].m_gpstime_multi);
178 enc_gps_time->destroySymbolModel(contexts[c].m_gpstime_0diff);
179 delete contexts[c].ic_gpstime;
180 }
181 }
182
183 /* destroy all encoders and outstreams */
184
185 if (outstream_channel_returns_XY)
186 {
187 delete enc_channel_returns_XY;
188 delete enc_Z;
189 delete enc_classification;
190 delete enc_flags;
191 delete enc_intensity;
192 delete enc_scan_angle;
193 delete enc_user_data;
194 delete enc_point_source;
195 delete enc_gps_time;
196
197 delete outstream_channel_returns_XY;
198 delete outstream_Z;
199 delete outstream_classification;
200 delete outstream_flags;
201 delete outstream_intensity;
202 delete outstream_scan_angle;
203 delete outstream_user_data;
204 delete outstream_point_source;
205 delete outstream_gps_time;
206 }
207 }
208
createAndInitModelsAndCompressors(U32 context,const U8 * item)209 inline BOOL LASwriteItemCompressed_POINT14_v4::createAndInitModelsAndCompressors(U32 context, const U8* item)
210 {
211 I32 i;
212
213 /* should only be called when context is unused */
214
215 assert(contexts[context].unused);
216
217 /* first create all entropy models and integer compressors (if needed) */
218
219 if (contexts[context].m_changed_values[0] == 0)
220 {
221 /* for the channel_returns_XY layer */
222
223 contexts[context].m_changed_values[0] = enc_channel_returns_XY->createSymbolModel(128);
224 contexts[context].m_changed_values[1] = enc_channel_returns_XY->createSymbolModel(128);
225 contexts[context].m_changed_values[2] = enc_channel_returns_XY->createSymbolModel(128);
226 contexts[context].m_changed_values[3] = enc_channel_returns_XY->createSymbolModel(128);
227 contexts[context].m_changed_values[4] = enc_channel_returns_XY->createSymbolModel(128);
228 contexts[context].m_changed_values[5] = enc_channel_returns_XY->createSymbolModel(128);
229 contexts[context].m_changed_values[6] = enc_channel_returns_XY->createSymbolModel(128);
230 contexts[context].m_changed_values[7] = enc_channel_returns_XY->createSymbolModel(128);
231 contexts[context].m_scanner_channel = enc_channel_returns_XY->createSymbolModel(3);
232 for (i = 0; i < 16; i++)
233 {
234 contexts[context].m_number_of_returns[i] = 0;
235 contexts[context].m_return_number[i] = 0;
236 }
237 contexts[context].m_return_number_gps_same = enc_channel_returns_XY->createSymbolModel(13);
238
239 contexts[context].ic_dX = new IntegerCompressor(enc_channel_returns_XY, 32, 2); // 32 bits, 2 context
240 contexts[context].ic_dY = new IntegerCompressor(enc_channel_returns_XY, 32, 22); // 32 bits, 22 contexts
241
242 /* for the Z layer */
243
244 contexts[context].ic_Z = new IntegerCompressor(enc_Z, 32, 20); // 32 bits, 20 contexts
245
246 /* for the classification layer */
247 /* for the flags layer */
248 /* for the user_data layer */
249
250 for (i = 0; i < 64; i++)
251 {
252 contexts[context].m_classification[i] = 0;
253 contexts[context].m_flags[i] = 0;
254 contexts[context].m_user_data[i] = 0;
255 }
256
257 /* for the intensity layer */
258
259 contexts[context].ic_intensity = new IntegerCompressor(enc_intensity, 16, 4);
260
261 /* for the scan_angle layer */
262
263 contexts[context].ic_scan_angle = new IntegerCompressor(enc_scan_angle, 16, 2);
264
265 /* for the point_source_ID layer */
266
267 contexts[context].ic_point_source_ID = new IntegerCompressor(enc_point_source, 16);
268
269 /* for the gps_time layer */
270
271 contexts[context].m_gpstime_multi = enc_gps_time->createSymbolModel(LASZIP_GPSTIME_MULTI_TOTAL);
272 contexts[context].m_gpstime_0diff = enc_gps_time->createSymbolModel(5);
273 contexts[context].ic_gpstime = new IntegerCompressor(enc_gps_time, 32, 9); // 32 bits, 9 contexts
274 }
275
276 /* then init entropy models and integer compressors */
277
278 /* for the channel_returns_XY layer */
279
280 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[0]);
281 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[1]);
282 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[2]);
283 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[3]);
284 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[4]);
285 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[5]);
286 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[6]);
287 enc_channel_returns_XY->initSymbolModel(contexts[context].m_changed_values[7]);
288 enc_channel_returns_XY->initSymbolModel(contexts[context].m_scanner_channel);
289 for (i = 0; i < 16; i++)
290 {
291 if (contexts[context].m_number_of_returns[i]) enc_channel_returns_XY->initSymbolModel(contexts[context].m_number_of_returns[i]);
292 if (contexts[context].m_return_number[i]) enc_channel_returns_XY->initSymbolModel(contexts[context].m_return_number[i]);
293 }
294 enc_channel_returns_XY->initSymbolModel(contexts[context].m_return_number_gps_same);
295 contexts[context].ic_dX->initCompressor();
296 contexts[context].ic_dY->initCompressor();
297 for (i = 0; i < 12; i++)
298 {
299 contexts[context].last_X_diff_median5[i].init();
300 contexts[context].last_Y_diff_median5[i].init();
301 }
302
303 /* for the Z layer */
304
305 contexts[context].ic_Z->initCompressor();
306 for (i = 0; i < 8; i++)
307 {
308 contexts[context].last_Z[i] = ((LASpoint14*)item)->Z;
309 }
310
311 /* for the classification layer */
312 /* for the flags layer */
313 /* for the user_data layer */
314
315 for (i = 0; i < 64; i++)
316 {
317 if (contexts[context].m_classification[i]) enc_classification->initSymbolModel(contexts[context].m_classification[i]);
318 if (contexts[context].m_flags[i]) enc_flags->initSymbolModel(contexts[context].m_flags[i]);
319 if (contexts[context].m_user_data[i]) enc_user_data->initSymbolModel(contexts[context].m_user_data[i]);
320 }
321
322 /* for the intensity layer */
323
324 contexts[context].ic_intensity->initCompressor();
325 for (i = 0; i < 8; i++)
326 {
327 contexts[context].last_intensity[i] = ((LASpoint14*)item)->intensity;
328 }
329
330 /* for the scan_angle layer */
331
332 contexts[context].ic_scan_angle->initCompressor();
333
334 /* for the point_source_ID layer */
335
336 contexts[context].ic_point_source_ID->initCompressor();
337
338 /* for the gps_time layer */
339
340 enc_gps_time->initSymbolModel(contexts[context].m_gpstime_multi);
341 enc_gps_time->initSymbolModel(contexts[context].m_gpstime_0diff);
342 contexts[context].ic_gpstime->initCompressor();
343 contexts[context].last = 0, contexts[context].next = 0;
344 contexts[context].last_gpstime_diff[0] = 0;
345 contexts[context].last_gpstime_diff[1] = 0;
346 contexts[context].last_gpstime_diff[2] = 0;
347 contexts[context].last_gpstime_diff[3] = 0;
348 contexts[context].multi_extreme_counter[0] = 0;
349 contexts[context].multi_extreme_counter[1] = 0;
350 contexts[context].multi_extreme_counter[2] = 0;
351 contexts[context].multi_extreme_counter[3] = 0;
352 contexts[context].last_gpstime[0].f64 = ((LASpoint14*)item)->gps_time;
353 contexts[context].last_gpstime[1].u64 = 0;
354 contexts[context].last_gpstime[2].u64 = 0;
355 contexts[context].last_gpstime[3].u64 = 0;
356
357 /* init current context from item */
358
359 memcpy(contexts[context].last_item, item, sizeof(LASpoint14));
360 ((LASpoint14*)contexts[context].last_item)->gps_time_change = FALSE;
361
362 contexts[context].unused = FALSE;
363
364 return TRUE;
365 }
366
init(const U8 * item,U32 & context)367 BOOL LASwriteItemCompressed_POINT14_v4::init(const U8* item, U32& context)
368 {
369 /* on the first init create outstreams and encoders */
370
371 if (outstream_channel_returns_XY == 0)
372 {
373 if (IS_LITTLE_ENDIAN())
374 {
375 outstream_channel_returns_XY = new ByteStreamOutArrayLE();
376 outstream_Z = new ByteStreamOutArrayLE();
377 outstream_classification = new ByteStreamOutArrayLE();
378 outstream_flags = new ByteStreamOutArrayLE();
379 outstream_intensity = new ByteStreamOutArrayLE();
380 outstream_scan_angle = new ByteStreamOutArrayLE();
381 outstream_user_data = new ByteStreamOutArrayLE();
382 outstream_point_source = new ByteStreamOutArrayLE();
383 outstream_gps_time = new ByteStreamOutArrayLE();
384 }
385 else
386 {
387 outstream_channel_returns_XY = new ByteStreamOutArrayBE();
388 outstream_Z = new ByteStreamOutArrayBE();
389 outstream_classification = new ByteStreamOutArrayBE();
390 outstream_flags = new ByteStreamOutArrayBE();
391 outstream_intensity = new ByteStreamOutArrayBE();
392 outstream_scan_angle = new ByteStreamOutArrayBE();
393 outstream_user_data = new ByteStreamOutArrayBE();
394 outstream_point_source = new ByteStreamOutArrayBE();
395 outstream_gps_time = new ByteStreamOutArrayBE();
396 }
397
398 /* create layer encoders */
399
400 enc_channel_returns_XY = new ArithmeticEncoder();
401 enc_Z = new ArithmeticEncoder();
402 enc_classification = new ArithmeticEncoder();
403 enc_flags = new ArithmeticEncoder();
404 enc_intensity = new ArithmeticEncoder();
405 enc_scan_angle = new ArithmeticEncoder();
406 enc_user_data = new ArithmeticEncoder();
407 enc_point_source = new ArithmeticEncoder();
408 enc_gps_time = new ArithmeticEncoder();
409 }
410 else
411 {
412 /* otherwise just seek back */
413
414 outstream_channel_returns_XY->seek(0);
415 outstream_Z->seek(0);
416 outstream_classification->seek(0);
417 outstream_flags->seek(0);
418 outstream_intensity->seek(0);
419 outstream_scan_angle->seek(0);
420 outstream_user_data->seek(0);
421 outstream_point_source->seek(0);
422 outstream_gps_time->seek(0);
423 }
424
425 /* init layer encoders */
426
427 enc_channel_returns_XY->init(outstream_channel_returns_XY);
428 enc_Z->init(outstream_Z);
429 enc_classification->init(outstream_classification);
430 enc_flags->init(outstream_flags);
431 enc_intensity->init(outstream_intensity);
432 enc_scan_angle->init(outstream_scan_angle);
433 enc_user_data->init(outstream_user_data);
434 enc_point_source->init(outstream_point_source);
435 enc_gps_time->init(outstream_gps_time);
436
437 /* set changed booleans to FALSE */
438
439 changed_classification = FALSE;
440 changed_flags = FALSE;
441 changed_intensity = FALSE;
442 changed_scan_angle = FALSE;
443 changed_user_data = FALSE;
444 changed_point_source = FALSE;
445 changed_gps_time = FALSE;
446
447 /* mark the four scanner channel contexts as unused */
448
449 U32 c;
450 for (c = 0; c < 4; c++)
451 {
452 contexts[c].unused = TRUE;
453 }
454
455 /* set scanner channel as current context */
456
457 current_context = ((LASpoint14*)item)->scanner_channel;
458 context = current_context; // the POINT14 writer sets context for all other items
459
460 /* create and init entropy models and integer compressors (and init context from item) */
461
462 createAndInitModelsAndCompressors(current_context, item);
463
464 return TRUE;
465 }
466
write(const U8 * item,U32 & context)467 inline BOOL LASwriteItemCompressed_POINT14_v4::write(const U8* item, U32& context)
468 {
469 // get last
470
471 U8* last_item = contexts[current_context].last_item;
472
473 ////////////////////////////////////////
474 // compress returns_XY layer
475 ////////////////////////////////////////
476
477 // create single (3) / first (1) / last (2) / intermediate (0) context from last point return
478
479 I32 lpr = (((LASpoint14*)last_item)->return_number == 1 ? 1 : 0); // first?
480 lpr += (((LASpoint14*)last_item)->return_number >= ((LASpoint14*)last_item)->number_of_returns ? 2 : 0); // last?
481
482 // add info whether the GPS time changed in the last return to the context
483
484 lpr += (((LASpoint14*)last_item)->gps_time_change ? 4 : 0);
485
486 // get the (potentially new) context
487
488 U32 scanner_channel = ((LASpoint14*)item)->scanner_channel;
489
490 // if context has changed (and the new context already exists) get last for new context
491
492 if (scanner_channel != current_context)
493 {
494 if (contexts[scanner_channel].unused == FALSE)
495 {
496 last_item = contexts[scanner_channel].last_item;
497 }
498 }
499
500 // determine changed attributes
501
502 BOOL point_source_change = (((LASpoint14*)item)->point_source_ID != ((LASpoint14*)last_item)->point_source_ID);
503 BOOL gps_time_change = (((LASpoint14*)item)->gps_time != ((LASpoint14*)last_item)->gps_time);
504 BOOL scan_angle_change = (((LASpoint14*)item)->scan_angle != ((LASpoint14*)last_item)->scan_angle);
505
506 // get last and current return counts
507
508 U32 last_n = ((LASpoint14*)last_item)->number_of_returns;
509 U32 last_r = ((LASpoint14*)last_item)->return_number;
510
511 U32 n = ((LASpoint14*)item)->number_of_returns;
512 U32 r = ((LASpoint14*)item)->return_number;
513
514 // create the 7 bit mask that encodes various changes (its value ranges from 0 to 127)
515
516 I32 changed_values = ((scanner_channel != current_context) << 6) | // scanner channel compared to last point (same = 0 / different = 1)
517 (point_source_change << 5) | // point source ID compared to last point from *same* scanner channel (same = 0 / different = 1)
518 (gps_time_change << 4) | // GPS time stamp compared to last point from *same* scanner channel (same = 0 / different = 1)
519 (scan_angle_change << 3) | // scan angle compared to last point from *same* scanner channel (same = 0 / different = 1)
520 ((n != last_n) << 2); // number of returns compared to last point from *same* scanner channel (same = 0 / different = 1)
521
522 // return number compared to last point of *same* scanner channel (same = 0 / plus one mod 16 = 1 / minus one mod 16 = 2 / other difference = 3)
523
524 if (r != last_r)
525 {
526 if (r == ((last_r + 1) % 16))
527 {
528 changed_values |= 1;
529 }
530 else if (r == ((last_r + 15) % 16))
531 {
532 changed_values |= 2;
533 }
534 else
535 {
536 changed_values |= 3;
537 }
538 }
539
540 // compress the 7 bit mask that encodes changes with last point return context
541
542 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_changed_values[lpr], changed_values);
543
544 // if scanner channel has changed, record change
545
546 if (changed_values & (1 << 6))
547 {
548 I32 diff = scanner_channel - current_context;
549 if (diff > 0)
550 {
551 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_scanner_channel, diff - 1); // curr = last + (sym + 1)
552 }
553 else
554 {
555 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_scanner_channel, diff + 4 - 1); // curr = (last + (sym + 1)) % 4
556 }
557 // maybe create and init entropy models and integer compressors
558 if (contexts[scanner_channel].unused)
559 {
560 // create and init entropy models and integer compressors (and init context from last item)
561 createAndInitModelsAndCompressors(scanner_channel, contexts[current_context].last_item);
562 // get last for new context
563 last_item = contexts[scanner_channel].last_item;
564 }
565 // switch context to current scanner channel
566 current_context = scanner_channel;
567 }
568 context = current_context; // the POINT14 writer sets context for all other items
569
570 // if number of returns is different we compress it
571
572 if (changed_values & (1 << 2))
573 {
574 if (contexts[current_context].m_number_of_returns[last_n] == 0)
575 {
576 contexts[current_context].m_number_of_returns[last_n] = enc_channel_returns_XY->createSymbolModel(16);
577 enc_channel_returns_XY->initSymbolModel(contexts[current_context].m_number_of_returns[last_n]);
578 }
579 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_number_of_returns[last_n], n);
580 }
581
582 // if return number is different and difference is bigger than +1 / -1 we compress how it is different
583
584 if ((changed_values & 3) == 3)
585 {
586 if (gps_time_change) // if the GPS time has changed
587 {
588 if (contexts[current_context].m_return_number[last_r] == 0)
589 {
590 contexts[current_context].m_return_number[last_r] = enc_channel_returns_XY->createSymbolModel(16);
591 enc_channel_returns_XY->initSymbolModel(contexts[current_context].m_return_number[last_r]);
592 }
593 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_return_number[last_r], r);
594 }
595 else // if the GPS time has not changed
596 {
597 I32 diff = r - last_r;
598 if (diff > 1)
599 {
600 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_return_number_gps_same, diff - 2); // r = last_r + (sym + 2) with sym = diff - 2
601 }
602 else
603 {
604 enc_channel_returns_XY->encodeSymbol(contexts[current_context].m_return_number_gps_same, diff + 16 - 2); // r = (last_r + (sym + 2)) % 16 with sym = diff + 16 - 2
605 }
606 }
607 }
608
609 // get return map m and return level l context for current point
610
611 U32 m = number_return_map_6ctx[n][r];
612 U32 l = number_return_level_8ctx[n][r];
613
614 // create single (3) / first (1) / last (2) / intermediate (0) return context for current point
615
616 I32 cpr = (r == 1 ? 2 : 0); // first ?
617 cpr += (r >= n ? 1 : 0); // last ?
618
619 U32 k_bits;
620 I32 median, diff;
621
622 // compress X coordinate
623 median = contexts[current_context].last_X_diff_median5[(m<<1) | gps_time_change].get();
624 diff = ((LASpoint14*)item)->X - ((LASpoint14*)last_item)->X;
625 contexts[current_context].ic_dX->compress(median, diff, n==1);
626 contexts[current_context].last_X_diff_median5[(m<<1) | gps_time_change].add(diff);
627
628 // compress Y coordinate
629 k_bits = contexts[current_context].ic_dX->getK();
630 median = contexts[current_context].last_Y_diff_median5[(m<<1) | gps_time_change].get();
631 diff = ((LASpoint14*)item)->Y - ((LASpoint14*)last_item)->Y;
632 contexts[current_context].ic_dY->compress(median, diff, (n==1) + ( k_bits < 20 ? U32_ZERO_BIT_0(k_bits) : 20 ));
633 contexts[current_context].last_Y_diff_median5[(m<<1) | gps_time_change].add(diff);
634
635 ////////////////////////////////////////
636 // compress Z layer
637 ////////////////////////////////////////
638
639 k_bits = (contexts[current_context].ic_dX->getK() + contexts[current_context].ic_dY->getK()) / 2;
640 contexts[current_context].ic_Z->compress(contexts[current_context].last_Z[l], ((LASpoint14*)item)->Z, (n==1) + (k_bits < 18 ? U32_ZERO_BIT_0(k_bits) : 18));
641 contexts[current_context].last_Z[l] = ((LASpoint14*)item)->Z;
642
643 ////////////////////////////////////////
644 // compress classifications layer
645 ////////////////////////////////////////
646
647 U32 last_classification = ((LASpoint14*)last_item)->classification;
648 U32 classification = ((LASpoint14*)item)->classification;
649
650 if (classification != last_classification)
651 {
652 changed_classification = TRUE;
653 }
654
655 I32 ccc = ((last_classification & 0x1F) << 1) + (cpr == 3 ? 1 : 0);
656 if (contexts[current_context].m_classification[ccc] == 0)
657 {
658 contexts[current_context].m_classification[ccc] = enc_classification->createSymbolModel(256);
659 enc_classification->initSymbolModel(contexts[current_context].m_classification[ccc]);
660 }
661 enc_classification->encodeSymbol(contexts[current_context].m_classification[ccc], classification);
662
663 ////////////////////////////////////////
664 // compress flags layer
665 ////////////////////////////////////////
666
667 U32 last_flags = (((LASpoint14*)last_item)->edge_of_flight_line << 5) | (((LASpoint14*)last_item)->scan_direction_flag << 4) | ((LASpoint14*)last_item)->classification_flags;
668 U32 flags = (((LASpoint14*)item)->edge_of_flight_line << 5) | (((LASpoint14*)item)->scan_direction_flag << 4) | ((LASpoint14*)item)->classification_flags;
669
670 if (flags != last_flags)
671 {
672 changed_flags = TRUE;
673 }
674
675 if (contexts[current_context].m_flags[last_flags] == 0)
676 {
677 contexts[current_context].m_flags[last_flags] = enc_flags->createSymbolModel(64);
678 enc_flags->initSymbolModel(contexts[current_context].m_flags[last_flags]);
679 }
680 enc_flags->encodeSymbol(contexts[current_context].m_flags[last_flags], flags);
681
682 ////////////////////////////////////////
683 // compress intensity layer
684 ////////////////////////////////////////
685
686 if (((LASpoint14*)item)->intensity != ((LASpoint14*)last_item)->intensity)
687 {
688 changed_intensity = TRUE;
689 }
690 contexts[current_context].ic_intensity->compress(contexts[current_context].last_intensity[(cpr<<1) | gps_time_change], ((LASpoint14*)item)->intensity, cpr);
691 contexts[current_context].last_intensity[(cpr<<1) | gps_time_change] = ((LASpoint14*)item)->intensity;
692
693 ////////////////////////////////////////
694 // compress scan_angle layer
695 ////////////////////////////////////////
696
697 if (scan_angle_change)
698 {
699 changed_scan_angle = TRUE;
700 contexts[current_context].ic_scan_angle->compress(((LASpoint14*)last_item)->scan_angle, ((LASpoint14*)item)->scan_angle, gps_time_change); // if the GPS time has changed
701 }
702
703 ////////////////////////////////////////
704 // compress user_data layer
705 ////////////////////////////////////////
706
707 if (((LASpoint14*)item)->user_data != ((LASpoint14*)last_item)->user_data)
708 {
709 changed_user_data = TRUE;
710 }
711 if (contexts[current_context].m_user_data[((LASpoint14*)last_item)->user_data/4] == 0)
712 {
713 contexts[current_context].m_user_data[((LASpoint14*)last_item)->user_data/4] = enc_user_data->createSymbolModel(256);
714 enc_user_data->initSymbolModel(contexts[current_context].m_user_data[((LASpoint14*)last_item)->user_data/4]);
715 }
716 enc_user_data->encodeSymbol(contexts[current_context].m_user_data[((LASpoint14*)last_item)->user_data/4], ((LASpoint14*)item)->user_data);
717
718 ////////////////////////////////////////
719 // compress point_source layer
720 ////////////////////////////////////////
721
722 if (point_source_change)
723 {
724 changed_point_source = TRUE;
725 contexts[current_context].ic_point_source_ID->compress(((LASpoint14*)last_item)->point_source_ID, ((LASpoint14*)item)->point_source_ID);
726 }
727
728 ////////////////////////////////////////
729 // compress gps_time layer
730 ////////////////////////////////////////
731
732 if (gps_time_change) // if the GPS time has changed
733 {
734 changed_gps_time = TRUE;
735
736 U64I64F64 gps_time;
737 gps_time.f64 = ((LASpoint14*)item)->gps_time;
738
739 write_gps_time(gps_time);
740 }
741
742 // copy the last item
743 memcpy(last_item, item, sizeof(LASpoint14));
744 // remember if the last point had a gps_time_change
745 ((LASpoint14*)last_item)->gps_time_change = gps_time_change;
746
747 return TRUE;
748 }
749
chunk_sizes()750 inline BOOL LASwriteItemCompressed_POINT14_v4::chunk_sizes()
751 {
752 U32 num_bytes = 0;
753 ByteStreamOut* outstream = enc->getByteStreamOut();
754
755 // finish the encoders
756
757 enc_channel_returns_XY->done();
758 enc_Z->done();
759 if (changed_classification)
760 {
761 enc_classification->done();
762 }
763 if (changed_flags)
764 {
765 enc_flags->done();
766 }
767 if (changed_intensity)
768 {
769 enc_intensity->done();
770 }
771 if (changed_scan_angle)
772 {
773 enc_scan_angle->done();
774 }
775 if (changed_user_data)
776 {
777 enc_user_data->done();
778 }
779 if (changed_point_source)
780 {
781 enc_point_source->done();
782 }
783 if (changed_gps_time)
784 {
785 enc_gps_time->done();
786 }
787
788 // output the sizes of all layer (i.e.. number of bytes per layer)
789
790 num_bytes = (U32)outstream_channel_returns_XY->getCurr();
791 num_bytes_channel_returns_XY += num_bytes;
792 outstream->put32bitsLE(((U8*)&num_bytes));
793
794 num_bytes = (U32)outstream_Z->getCurr();
795 num_bytes_Z += num_bytes;
796 outstream->put32bitsLE(((U8*)&num_bytes));
797
798 if (changed_classification)
799 {
800 num_bytes = (U32)outstream_classification->getCurr();
801 num_bytes_classification += num_bytes;
802 }
803 else
804 {
805 num_bytes = 0;
806 }
807 outstream->put32bitsLE(((U8*)&num_bytes));
808
809 if (changed_flags)
810 {
811 num_bytes = (U32)outstream_flags->getCurr();
812 num_bytes_flags += num_bytes;
813 }
814 else
815 {
816 num_bytes = 0;
817 }
818 outstream->put32bitsLE(((U8*)&num_bytes));
819
820 if (changed_intensity)
821 {
822 num_bytes = (U32)outstream_intensity->getCurr();
823 num_bytes_intensity += num_bytes;
824 }
825 else
826 {
827 num_bytes = 0;
828 }
829 outstream->put32bitsLE(((U8*)&num_bytes));
830
831 if (changed_scan_angle)
832 {
833 num_bytes = (U32)outstream_scan_angle->getCurr();
834 num_bytes_scan_angle += num_bytes;
835 }
836 else
837 {
838 num_bytes = 0;
839 }
840 outstream->put32bitsLE(((U8*)&num_bytes));
841
842 if (changed_user_data)
843 {
844 num_bytes = (U32)outstream_user_data->getCurr();
845 num_bytes_user_data += num_bytes;
846 }
847 else
848 {
849 num_bytes = 0;
850 }
851 outstream->put32bitsLE(((U8*)&num_bytes));
852
853 if (changed_point_source)
854 {
855 num_bytes = (U32)outstream_point_source->getCurr();
856 num_bytes_point_source += num_bytes;
857 }
858 else
859 {
860 num_bytes = 0;
861 }
862 outstream->put32bitsLE(((U8*)&num_bytes));
863
864 if (changed_gps_time)
865 {
866 num_bytes = (U32)outstream_gps_time->getCurr();
867 num_bytes_gps_time += num_bytes;
868 }
869 else
870 {
871 num_bytes = 0;
872 }
873 outstream->put32bitsLE(((U8*)&num_bytes));
874
875 return TRUE;
876 }
877
chunk_bytes()878 inline BOOL LASwriteItemCompressed_POINT14_v4::chunk_bytes()
879 {
880 U32 num_bytes = 0;
881 ByteStreamOut* outstream = enc->getByteStreamOut();
882
883 // output the bytes of all layers
884
885 num_bytes = (U32)outstream_channel_returns_XY->getCurr();
886 outstream->putBytes(outstream_channel_returns_XY->getData(), num_bytes);
887
888 num_bytes = (U32)outstream_Z->getCurr();
889 outstream->putBytes(outstream_Z->getData(), num_bytes);
890
891 if (changed_classification)
892 {
893 num_bytes = (U32)outstream_classification->getCurr();
894 outstream->putBytes(outstream_classification->getData(), num_bytes);
895 }
896 else
897 {
898 num_bytes = 0;
899 }
900
901 if (changed_flags)
902 {
903 num_bytes = (U32)outstream_flags->getCurr();
904 outstream->putBytes(outstream_flags->getData(), num_bytes);
905 }
906 else
907 {
908 num_bytes = 0;
909 }
910
911 if (changed_intensity)
912 {
913 num_bytes = (U32)outstream_intensity->getCurr();
914 outstream->putBytes(outstream_intensity->getData(), num_bytes);
915 }
916 else
917 {
918 num_bytes = 0;
919 }
920
921 if (changed_scan_angle)
922 {
923 num_bytes = (U32)outstream_scan_angle->getCurr();
924 outstream->putBytes(outstream_scan_angle->getData(), num_bytes);
925 }
926 else
927 {
928 num_bytes = 0;
929 }
930
931 if (changed_user_data)
932 {
933 num_bytes = (U32)outstream_user_data->getCurr();
934 outstream->putBytes(outstream_user_data->getData(), num_bytes);
935 }
936 else
937 {
938 num_bytes = 0;
939 }
940
941 if (changed_point_source)
942 {
943 num_bytes = (U32)outstream_point_source->getCurr();
944 outstream->putBytes(outstream_point_source->getData(), num_bytes);
945 }
946 else
947 {
948 num_bytes = 0;
949 }
950
951 if (changed_gps_time)
952 {
953 num_bytes = (U32)outstream_gps_time->getCurr();
954 outstream->putBytes(outstream_gps_time->getData(), num_bytes);
955 }
956 else
957 {
958 num_bytes = 0;
959 }
960
961 return TRUE;
962 }
963
write_gps_time(const U64I64F64 gps_time)964 void LASwriteItemCompressed_POINT14_v4::write_gps_time(const U64I64F64 gps_time)
965 {
966 if (contexts[current_context].last_gpstime_diff[contexts[current_context].last] == 0) // if the last integer difference was zero
967 {
968 // calculate the difference between the two doubles as an integer
969 I64 curr_gpstime_diff_64 = gps_time.i64 - contexts[current_context].last_gpstime[contexts[current_context].last].i64;
970 I32 curr_gpstime_diff = (I32)curr_gpstime_diff_64;
971 if (curr_gpstime_diff_64 == (I64)(curr_gpstime_diff))
972 {
973 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_0diff, 0); // the difference can be represented with 32 bits
974 contexts[current_context].ic_gpstime->compress(0, curr_gpstime_diff, 0);
975 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = curr_gpstime_diff;
976 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
977 }
978 else // the difference is huge
979 {
980 U32 i;
981 // maybe the double belongs to another time sequence
982 for (i = 1; i < 4; i++)
983 {
984 I64 other_gpstime_diff_64 = gps_time.i64 - contexts[current_context].last_gpstime[(contexts[current_context].last+i)&3].i64;
985 I32 other_gpstime_diff = (I32)other_gpstime_diff_64;
986 if (other_gpstime_diff_64 == (I64)(other_gpstime_diff))
987 {
988 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_0diff, i+1); // it belongs to another sequence
989 contexts[current_context].last = (contexts[current_context].last+i)&3;
990 write_gps_time(gps_time);
991 return;
992 }
993 }
994 // no other sequence found. start new sequence.
995 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_0diff, 1);
996 contexts[current_context].ic_gpstime->compress((I32)(contexts[current_context].last_gpstime[contexts[current_context].last].u64 >> 32), (I32)(gps_time.u64 >> 32), 8);
997 enc_gps_time->writeInt((U32)(gps_time.u64));
998 contexts[current_context].next = (contexts[current_context].next+1)&3;
999 contexts[current_context].last = contexts[current_context].next;
1000 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = 0;
1001 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1002 }
1003 contexts[current_context].last_gpstime[contexts[current_context].last].i64 = gps_time.i64;
1004 }
1005 else // the last integer difference was *not* zero
1006 {
1007 // calculate the difference between the two doubles as an integer
1008 I64 curr_gpstime_diff_64 = gps_time.i64 - contexts[current_context].last_gpstime[contexts[current_context].last].i64;
1009 I32 curr_gpstime_diff = (I32)curr_gpstime_diff_64;
1010
1011 // if the current gpstime difference can be represented with 32 bits
1012 if (curr_gpstime_diff_64 == (I64)(curr_gpstime_diff))
1013 {
1014 // compute multiplier between current and last integer difference
1015 F32 multi_f = (F32)curr_gpstime_diff / (F32)(contexts[current_context].last_gpstime_diff[contexts[current_context].last]);
1016 I32 multi = I32_QUANTIZE(multi_f);
1017
1018 // compress the residual curr_gpstime_diff in dependance on the multiplier
1019 if (multi == 1)
1020 {
1021 // this is the case we assume we get most often for regular spaced pulses
1022 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, 1);
1023 contexts[current_context].ic_gpstime->compress(contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 1);
1024 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1025 }
1026 else if (multi > 0)
1027 {
1028 if (multi < LASZIP_GPSTIME_MULTI) // positive multipliers up to LASZIP_GPSTIME_MULTI are compressed directly
1029 {
1030 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, multi);
1031 if (multi < 10)
1032 contexts[current_context].ic_gpstime->compress(multi*contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 2);
1033 else
1034 contexts[current_context].ic_gpstime->compress(multi*contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 3);
1035 }
1036 else
1037 {
1038 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, LASZIP_GPSTIME_MULTI);
1039 contexts[current_context].ic_gpstime->compress(LASZIP_GPSTIME_MULTI*contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 4);
1040 contexts[current_context].multi_extreme_counter[contexts[current_context].last]++;
1041 if (contexts[current_context].multi_extreme_counter[contexts[current_context].last] > 3)
1042 {
1043 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = curr_gpstime_diff;
1044 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1045 }
1046 }
1047 }
1048 else if (multi < 0)
1049 {
1050 if (multi > LASZIP_GPSTIME_MULTI_MINUS) // negative multipliers larger than LASZIP_GPSTIME_MULTI_MINUS are compressed directly
1051 {
1052 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, LASZIP_GPSTIME_MULTI - multi);
1053 contexts[current_context].ic_gpstime->compress(multi*contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 5);
1054 }
1055 else
1056 {
1057 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, LASZIP_GPSTIME_MULTI - LASZIP_GPSTIME_MULTI_MINUS);
1058 contexts[current_context].ic_gpstime->compress(LASZIP_GPSTIME_MULTI_MINUS*contexts[current_context].last_gpstime_diff[contexts[current_context].last], curr_gpstime_diff, 6);
1059 contexts[current_context].multi_extreme_counter[contexts[current_context].last]++;
1060 if (contexts[current_context].multi_extreme_counter[contexts[current_context].last] > 3)
1061 {
1062 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = curr_gpstime_diff;
1063 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1064 }
1065 }
1066 }
1067 else
1068 {
1069 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, 0);
1070 contexts[current_context].ic_gpstime->compress(0, curr_gpstime_diff, 7);
1071 contexts[current_context].multi_extreme_counter[contexts[current_context].last]++;
1072 if (contexts[current_context].multi_extreme_counter[contexts[current_context].last] > 3)
1073 {
1074 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = curr_gpstime_diff;
1075 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1076 }
1077 }
1078 }
1079 else // the difference is huge
1080 {
1081 U32 i;
1082 // maybe the double belongs to another time sequence
1083 for (i = 1; i < 4; i++)
1084 {
1085 I64 other_gpstime_diff_64 = gps_time.i64 - contexts[current_context].last_gpstime[(contexts[current_context].last+i)&3].i64;
1086 I32 other_gpstime_diff = (I32)other_gpstime_diff_64;
1087 if (other_gpstime_diff_64 == (I64)(other_gpstime_diff))
1088 {
1089 // it belongs to this sequence
1090 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, LASZIP_GPSTIME_MULTI_CODE_FULL+i);
1091 contexts[current_context].last = (contexts[current_context].last+i)&3;
1092 write_gps_time(gps_time);
1093 return;
1094 }
1095 }
1096 // no other sequence found. start new sequence.
1097 enc_gps_time->encodeSymbol(contexts[current_context].m_gpstime_multi, LASZIP_GPSTIME_MULTI_CODE_FULL);
1098 contexts[current_context].ic_gpstime->compress((I32)(contexts[current_context].last_gpstime[contexts[current_context].last].u64 >> 32), (I32)(gps_time.u64 >> 32), 8);
1099 enc_gps_time->writeInt((U32)(gps_time.u64));
1100 contexts[current_context].next = (contexts[current_context].next+1)&3;
1101 contexts[current_context].last = contexts[current_context].next;
1102 contexts[current_context].last_gpstime_diff[contexts[current_context].last] = 0;
1103 contexts[current_context].multi_extreme_counter[contexts[current_context].last] = 0;
1104 }
1105 contexts[current_context].last_gpstime[contexts[current_context].last].i64 = gps_time.i64;
1106 }
1107 }
1108
1109 /*
1110 ===============================================================================
1111 LASwriteItemCompressed_RGB14_v4
1112 ===============================================================================
1113 */
1114
LASwriteItemCompressed_RGB14_v4(ArithmeticEncoder * enc)1115 LASwriteItemCompressed_RGB14_v4::LASwriteItemCompressed_RGB14_v4(ArithmeticEncoder* enc)
1116 {
1117 /* not used as a encoder. just gives access to outstream */
1118
1119 assert(enc);
1120 this->enc = enc;
1121
1122 /* zero outstreams and encoders */
1123
1124 outstream_RGB = 0;
1125
1126 enc_RGB = 0;
1127
1128 /* zero num_bytes and init booleans */
1129
1130 num_bytes_RGB = 0;
1131
1132 changed_RGB = FALSE;
1133
1134 /* mark the four scanner channel contexts as uninitialized */
1135
1136 U32 c;
1137 for (c = 0; c < 4; c++)
1138 {
1139 contexts[c].m_byte_used = 0;
1140 }
1141 current_context = 0;
1142 }
1143
~LASwriteItemCompressed_RGB14_v4()1144 LASwriteItemCompressed_RGB14_v4::~LASwriteItemCompressed_RGB14_v4()
1145 {
1146 /* destroy all initialized scanner channel contexts */
1147
1148 U32 c;
1149 for (c = 0; c < 4; c++)
1150 {
1151 if (contexts[c].m_byte_used)
1152 {
1153 enc_RGB->destroySymbolModel(contexts[c].m_byte_used);
1154 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_0);
1155 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_1);
1156 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_2);
1157 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_3);
1158 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_4);
1159 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_5);
1160 }
1161 }
1162
1163 /* destroy all outstreams and encoders */
1164
1165 if (outstream_RGB)
1166 {
1167 delete outstream_RGB;
1168
1169 delete enc_RGB;
1170 }
1171 }
1172
createAndInitModelsAndCompressors(U32 context,const U8 * item)1173 inline BOOL LASwriteItemCompressed_RGB14_v4::createAndInitModelsAndCompressors(U32 context, const U8* item)
1174 {
1175 /* should only be called when context is unused */
1176
1177 assert(contexts[context].unused);
1178
1179 /* first create all entropy models (if needed) */
1180
1181 if (contexts[context].m_byte_used == 0)
1182 {
1183 contexts[context].m_byte_used = enc_RGB->createSymbolModel(128);
1184 contexts[context].m_rgb_diff_0 = enc_RGB->createSymbolModel(256);
1185 contexts[context].m_rgb_diff_1 = enc_RGB->createSymbolModel(256);
1186 contexts[context].m_rgb_diff_2 = enc_RGB->createSymbolModel(256);
1187 contexts[context].m_rgb_diff_3 = enc_RGB->createSymbolModel(256);
1188 contexts[context].m_rgb_diff_4 = enc_RGB->createSymbolModel(256);
1189 contexts[context].m_rgb_diff_5 = enc_RGB->createSymbolModel(256);
1190 }
1191
1192 /* then init entropy models */
1193
1194 enc_RGB->initSymbolModel(contexts[context].m_byte_used);
1195 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_0);
1196 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_1);
1197 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_2);
1198 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_3);
1199 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_4);
1200 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_5);
1201
1202 /* init current context from item */
1203
1204 memcpy(contexts[context].last_item, item, 6);
1205
1206 contexts[context].unused = FALSE;
1207
1208 return TRUE;
1209 }
1210
init(const U8 * item,U32 & context)1211 BOOL LASwriteItemCompressed_RGB14_v4::init(const U8* item, U32& context)
1212 {
1213 /* on the first init create outstreams and encoders */
1214
1215 if (outstream_RGB == 0)
1216 {
1217 /* create outstreams */
1218
1219 if (IS_LITTLE_ENDIAN())
1220 {
1221 outstream_RGB = new ByteStreamOutArrayLE();
1222 }
1223 else
1224 {
1225 outstream_RGB = new ByteStreamOutArrayBE();
1226 }
1227
1228 /* create layer encoders */
1229
1230 enc_RGB = new ArithmeticEncoder();
1231 }
1232 else
1233 {
1234 /* otherwise just seek back */
1235
1236 outstream_RGB->seek(0);
1237 }
1238
1239 /* init layer encoders */
1240
1241 enc_RGB->init(outstream_RGB);
1242
1243 /* set changed booleans to FALSE */
1244
1245 changed_RGB = FALSE;
1246
1247 /* mark the four scanner channel contexts as unused */
1248
1249 U32 c;
1250 for (c = 0; c < 4; c++)
1251 {
1252 contexts[c].unused = TRUE;
1253 }
1254
1255 /* set scanner channel as current context */
1256
1257 current_context = context; // all other items use context set by POINT14 writer
1258
1259 /* create and init entropy models and integer compressors (and init contect from item) */
1260
1261 createAndInitModelsAndCompressors(current_context, item);
1262
1263 return TRUE;
1264 }
1265
write(const U8 * item,U32 & context)1266 inline BOOL LASwriteItemCompressed_RGB14_v4::write(const U8* item, U32& context)
1267 {
1268 // get last
1269
1270 U16* last_item = contexts[current_context].last_item;
1271
1272 // check for context switch
1273
1274 if (current_context != context)
1275 {
1276 current_context = context; // all other items use context set by POINT14 writer
1277 if (contexts[current_context].unused)
1278 {
1279 createAndInitModelsAndCompressors(current_context, (U8*)last_item);
1280 }
1281 last_item = contexts[current_context].last_item;
1282 }
1283
1284 // compress
1285
1286 I32 diff_l = 0;
1287 I32 diff_h = 0;
1288 I32 corr;
1289 U32 sym = ((last_item[0]&0x00FF) != (((U16*)item)[0]&0x00FF)) << 0;
1290 sym |= ((last_item[0]&0xFF00) != (((U16*)item)[0]&0xFF00)) << 1;
1291 sym |= ((last_item[1]&0x00FF) != (((U16*)item)[1]&0x00FF)) << 2;
1292 sym |= ((last_item[1]&0xFF00) != (((U16*)item)[1]&0xFF00)) << 3;
1293 sym |= ((last_item[2]&0x00FF) != (((U16*)item)[2]&0x00FF)) << 4;
1294 sym |= ((last_item[2]&0xFF00) != (((U16*)item)[2]&0xFF00)) << 5;
1295 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;
1296 enc_RGB->encodeSymbol(contexts[current_context].m_byte_used, sym);
1297 if (sym & (1 << 0))
1298 {
1299 diff_l = ((int)(((U16*)item)[0]&255)) - (last_item[0]&255);
1300 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_0, U8_FOLD(diff_l));
1301 }
1302 if (sym & (1 << 1))
1303 {
1304 diff_h = ((int)(((U16*)item)[0]>>8)) - (last_item[0]>>8);
1305 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_1, U8_FOLD(diff_h));
1306 }
1307 if (sym & (1 << 6))
1308 {
1309 if (sym & (1 << 2))
1310 {
1311 corr = ((int)(((U16*)item)[1]&255)) - U8_CLAMP(diff_l + (last_item[1]&255));
1312 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_2, U8_FOLD(corr));
1313 }
1314 if (sym & (1 << 4))
1315 {
1316 diff_l = (diff_l + (((U16*)item)[1]&255) - (last_item[1]&255)) / 2;
1317 corr = ((int)(((U16*)item)[2]&255)) - U8_CLAMP(diff_l + (last_item[2]&255));
1318 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_4, U8_FOLD(corr));
1319 }
1320 if (sym & (1 << 3))
1321 {
1322 corr = ((int)(((U16*)item)[1]>>8)) - U8_CLAMP(diff_h + (last_item[1]>>8));
1323 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_3, U8_FOLD(corr));
1324 }
1325 if (sym & (1 << 5))
1326 {
1327 diff_h = (diff_h + (((U16*)item)[1]>>8) - (last_item[1]>>8)) / 2;
1328 corr = ((int)(((U16*)item)[2]>>8)) - U8_CLAMP(diff_h + (last_item[2]>>8));
1329 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_5, U8_FOLD(corr));
1330 }
1331 }
1332 if (sym)
1333 {
1334 changed_RGB = TRUE;
1335 }
1336 memcpy(last_item, item, 6);
1337
1338 return TRUE;
1339 }
1340
chunk_sizes()1341 inline BOOL LASwriteItemCompressed_RGB14_v4::chunk_sizes()
1342 {
1343 U32 num_bytes = 0;
1344 ByteStreamOut* outstream = enc->getByteStreamOut();
1345
1346 // finish the encoders
1347
1348 enc_RGB->done();
1349
1350 // output the sizes of all layer (i.e.. number of bytes per layer)
1351
1352 if (changed_RGB)
1353 {
1354 num_bytes = (U32)outstream_RGB->getCurr();
1355 num_bytes_RGB += num_bytes;
1356 }
1357 else
1358 {
1359 num_bytes = 0;
1360 }
1361 outstream->put32bitsLE(((U8*)&num_bytes));
1362
1363 return TRUE;
1364 }
1365
chunk_bytes()1366 inline BOOL LASwriteItemCompressed_RGB14_v4::chunk_bytes()
1367 {
1368 U32 num_bytes = 0;
1369 ByteStreamOut* outstream = enc->getByteStreamOut();
1370
1371 // output the bytes of all layers
1372
1373 if (changed_RGB)
1374 {
1375 num_bytes = (U32)outstream_RGB->getCurr();
1376 outstream->putBytes(outstream_RGB->getData(), num_bytes);
1377 }
1378
1379 return TRUE;
1380 }
1381
1382 /*
1383 ===============================================================================
1384 LASwriteItemCompressed_RGBNIR14_v4
1385 ===============================================================================
1386 */
1387
LASwriteItemCompressed_RGBNIR14_v4(ArithmeticEncoder * enc)1388 LASwriteItemCompressed_RGBNIR14_v4::LASwriteItemCompressed_RGBNIR14_v4(ArithmeticEncoder* enc)
1389 {
1390 /* not used as a encoder. just gives access to outstream */
1391
1392 assert(enc);
1393 this->enc = enc;
1394
1395 /* zero outstreams and encoders */
1396
1397 outstream_RGB = 0;
1398 outstream_NIR = 0;
1399
1400 enc_RGB = 0;
1401 enc_NIR = 0;
1402
1403 /* zero num_bytes and init booleans */
1404
1405 num_bytes_RGB = 0;
1406 num_bytes_NIR = 0;
1407
1408 changed_RGB = FALSE;
1409 changed_NIR = FALSE;
1410
1411 /* mark the four scanner channel contexts as uninitialized */
1412
1413 U32 c;
1414 for (c = 0; c < 4; c++)
1415 {
1416 contexts[c].m_rgb_bytes_used = 0;
1417 }
1418 current_context = 0;
1419 }
1420
~LASwriteItemCompressed_RGBNIR14_v4()1421 LASwriteItemCompressed_RGBNIR14_v4::~LASwriteItemCompressed_RGBNIR14_v4()
1422 {
1423 /* destroy all initialized scanner channel contexts */
1424
1425 U32 c;
1426 for (c = 0; c < 4; c++)
1427 {
1428 if (contexts[c].m_rgb_bytes_used)
1429 {
1430 enc_RGB->destroySymbolModel(contexts[c].m_rgb_bytes_used);
1431 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_0);
1432 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_1);
1433 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_2);
1434 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_3);
1435 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_4);
1436 enc_RGB->destroySymbolModel(contexts[c].m_rgb_diff_5);
1437
1438 enc_NIR->destroySymbolModel(contexts[c].m_nir_bytes_used);
1439 enc_NIR->destroySymbolModel(contexts[c].m_nir_diff_0);
1440 enc_NIR->destroySymbolModel(contexts[c].m_nir_diff_1);
1441 }
1442 }
1443
1444 /* destroy all outstreams and encoders */
1445
1446 if (outstream_RGB)
1447 {
1448 delete outstream_RGB;
1449 delete outstream_NIR;
1450
1451 delete enc_RGB;
1452 delete enc_NIR;
1453 }
1454 }
1455
createAndInitModelsAndCompressors(U32 context,const U8 * item)1456 inline BOOL LASwriteItemCompressed_RGBNIR14_v4::createAndInitModelsAndCompressors(U32 context, const U8* item)
1457 {
1458 /* should only be called when context is unused */
1459
1460 assert(contexts[context].unused);
1461
1462 /* first create all entropy models (if needed) */
1463
1464 if (contexts[context].m_rgb_bytes_used == 0)
1465 {
1466 contexts[context].m_rgb_bytes_used = enc_RGB->createSymbolModel(128);
1467 contexts[context].m_rgb_diff_0 = enc_RGB->createSymbolModel(256);
1468 contexts[context].m_rgb_diff_1 = enc_RGB->createSymbolModel(256);
1469 contexts[context].m_rgb_diff_2 = enc_RGB->createSymbolModel(256);
1470 contexts[context].m_rgb_diff_3 = enc_RGB->createSymbolModel(256);
1471 contexts[context].m_rgb_diff_4 = enc_RGB->createSymbolModel(256);
1472 contexts[context].m_rgb_diff_5 = enc_RGB->createSymbolModel(256);
1473
1474 contexts[context].m_nir_bytes_used = enc_RGB->createSymbolModel(4);
1475 contexts[context].m_nir_diff_0 = enc_RGB->createSymbolModel(256);
1476 contexts[context].m_nir_diff_1 = enc_RGB->createSymbolModel(256);
1477 }
1478
1479 /* then init entropy models */
1480
1481 enc_RGB->initSymbolModel(contexts[context].m_rgb_bytes_used);
1482 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_0);
1483 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_1);
1484 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_2);
1485 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_3);
1486 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_4);
1487 enc_RGB->initSymbolModel(contexts[context].m_rgb_diff_5);
1488
1489 enc_NIR->initSymbolModel(contexts[context].m_nir_bytes_used);
1490 enc_NIR->initSymbolModel(contexts[context].m_nir_diff_0);
1491 enc_NIR->initSymbolModel(contexts[context].m_nir_diff_1);
1492
1493 /* init current context from item */
1494
1495 memcpy(contexts[context].last_item, item, 8);
1496
1497 contexts[context].unused = FALSE;
1498
1499 return TRUE;
1500 }
1501
init(const U8 * item,U32 & context)1502 BOOL LASwriteItemCompressed_RGBNIR14_v4::init(const U8* item, U32& context)
1503 {
1504 /* on the first init create outstreams and encoders */
1505
1506 if (outstream_RGB == 0)
1507 {
1508 /* create outstreams */
1509
1510 if (IS_LITTLE_ENDIAN())
1511 {
1512 outstream_RGB = new ByteStreamOutArrayLE();
1513 outstream_NIR = new ByteStreamOutArrayLE();
1514 }
1515 else
1516 {
1517 outstream_RGB = new ByteStreamOutArrayBE();
1518 outstream_NIR = new ByteStreamOutArrayBE();
1519 }
1520
1521 /* create layer encoders */
1522
1523 enc_RGB = new ArithmeticEncoder();
1524 enc_NIR = new ArithmeticEncoder();
1525 }
1526 else
1527 {
1528 /* otherwise just seek back */
1529
1530 outstream_RGB->seek(0);
1531 outstream_NIR->seek(0);
1532 }
1533
1534 /* init layer encoders */
1535
1536 enc_RGB->init(outstream_RGB);
1537 enc_NIR->init(outstream_NIR);
1538
1539 /* set changed booleans to FALSE */
1540
1541 changed_RGB = FALSE;
1542 changed_NIR = FALSE;
1543
1544 /* mark the four scanner channel contexts as unused */
1545
1546 U32 c;
1547 for (c = 0; c < 4; c++)
1548 {
1549 contexts[c].unused = TRUE;
1550 }
1551
1552 /* set scanner channel as current context */
1553
1554 current_context = context; // ll other items use context set by POINT14 writer
1555
1556 /* create and init entropy models and integer compressors (and init context from item) */
1557
1558 createAndInitModelsAndCompressors(current_context, item);
1559
1560 return TRUE;
1561 }
1562
write(const U8 * item,U32 & context)1563 inline BOOL LASwriteItemCompressed_RGBNIR14_v4::write(const U8* item, U32& context)
1564 {
1565 // get last
1566
1567 U16* last_item = contexts[current_context].last_item;
1568
1569 // check for context switch
1570
1571 if (current_context != context)
1572 {
1573 current_context = context; // all other items use context set by POINT14 writer
1574 if (contexts[current_context].unused)
1575 {
1576 createAndInitModelsAndCompressors(current_context, (U8*)last_item);
1577 }
1578 last_item = contexts[current_context].last_item;
1579 }
1580
1581 // compress
1582
1583 I32 diff_l = 0;
1584 I32 diff_h = 0;
1585 I32 corr;
1586 U32 sym = ((last_item[0]&0x00FF) != (((U16*)item)[0]&0x00FF)) << 0;
1587 sym |= ((last_item[0]&0xFF00) != (((U16*)item)[0]&0xFF00)) << 1;
1588 sym |= ((last_item[1]&0x00FF) != (((U16*)item)[1]&0x00FF)) << 2;
1589 sym |= ((last_item[1]&0xFF00) != (((U16*)item)[1]&0xFF00)) << 3;
1590 sym |= ((last_item[2]&0x00FF) != (((U16*)item)[2]&0x00FF)) << 4;
1591 sym |= ((last_item[2]&0xFF00) != (((U16*)item)[2]&0xFF00)) << 5;
1592 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;
1593 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_bytes_used, sym);
1594 if (sym & (1 << 0))
1595 {
1596 diff_l = ((int)(((U16*)item)[0]&255)) - (last_item[0]&255);
1597 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_0, U8_FOLD(diff_l));
1598 }
1599 if (sym & (1 << 1))
1600 {
1601 diff_h = ((int)(((U16*)item)[0]>>8)) - (last_item[0]>>8);
1602 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_1, U8_FOLD(diff_h));
1603 }
1604 if (sym & (1 << 6))
1605 {
1606 if (sym & (1 << 2))
1607 {
1608 corr = ((int)(((U16*)item)[1]&255)) - U8_CLAMP(diff_l + (last_item[1]&255));
1609 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_2, U8_FOLD(corr));
1610 }
1611 if (sym & (1 << 4))
1612 {
1613 diff_l = (diff_l + (((U16*)item)[1]&255) - (last_item[1]&255)) / 2;
1614 corr = ((int)(((U16*)item)[2]&255)) - U8_CLAMP(diff_l + (last_item[2]&255));
1615 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_4, U8_FOLD(corr));
1616 }
1617 if (sym & (1 << 3))
1618 {
1619 corr = ((int)(((U16*)item)[1]>>8)) - U8_CLAMP(diff_h + (last_item[1]>>8));
1620 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_3, U8_FOLD(corr));
1621 }
1622 if (sym & (1 << 5))
1623 {
1624 diff_h = (diff_h + (((U16*)item)[1]>>8) - (last_item[1]>>8)) / 2;
1625 corr = ((int)(((U16*)item)[2]>>8)) - U8_CLAMP(diff_h + (last_item[2]>>8));
1626 enc_RGB->encodeSymbol(contexts[current_context].m_rgb_diff_5, U8_FOLD(corr));
1627 }
1628 }
1629 if (sym)
1630 {
1631 changed_RGB = TRUE;
1632 }
1633
1634 sym = ((last_item[3]&0x00FF) != (((U16*)item)[3]&0x00FF)) << 0;
1635 sym |= ((last_item[3]&0xFF00) != (((U16*)item)[3]&0xFF00)) << 1;
1636 enc_NIR->encodeSymbol(contexts[current_context].m_nir_bytes_used, sym);
1637 if (sym & (1 << 0))
1638 {
1639 diff_l = ((int)(((U16*)item)[3]&255)) - (last_item[3]&255);
1640 enc_NIR->encodeSymbol(contexts[current_context].m_nir_diff_0, U8_FOLD(diff_l));
1641 }
1642 if (sym & (1 << 1))
1643 {
1644 diff_h = ((int)(((U16*)item)[3]>>8)) - (last_item[3]>>8);
1645 enc_NIR->encodeSymbol(contexts[current_context].m_nir_diff_1, U8_FOLD(diff_h));
1646 }
1647 if (sym)
1648 {
1649 changed_NIR = TRUE;
1650 }
1651
1652 memcpy(last_item, item, 8);
1653 return TRUE;
1654 }
1655
chunk_sizes()1656 inline BOOL LASwriteItemCompressed_RGBNIR14_v4::chunk_sizes()
1657 {
1658 U32 num_bytes = 0;
1659 ByteStreamOut* outstream = enc->getByteStreamOut();
1660
1661 // finish the encoders
1662
1663 enc_RGB->done();
1664 enc_NIR->done();
1665
1666 // output the sizes of all layer (i.e.. number of bytes per layer)
1667
1668 if (changed_RGB)
1669 {
1670 num_bytes = (U32)outstream_RGB->getCurr();
1671 num_bytes_RGB += num_bytes;
1672 }
1673 else
1674 {
1675 num_bytes = 0;
1676 }
1677 outstream->put32bitsLE(((U8*)&num_bytes));
1678
1679 if (changed_NIR)
1680 {
1681 num_bytes = (U32)outstream_NIR->getCurr();
1682 num_bytes_NIR += num_bytes;
1683 }
1684 else
1685 {
1686 num_bytes = 0;
1687 }
1688 outstream->put32bitsLE(((U8*)&num_bytes));
1689
1690 return TRUE;
1691 }
1692
chunk_bytes()1693 inline BOOL LASwriteItemCompressed_RGBNIR14_v4::chunk_bytes()
1694 {
1695 U32 num_bytes = 0;
1696 ByteStreamOut* outstream = enc->getByteStreamOut();
1697
1698 // output the bytes of all layers
1699
1700 if (changed_RGB)
1701 {
1702 num_bytes = (U32)outstream_RGB->getCurr();
1703 outstream->putBytes(outstream_RGB->getData(), num_bytes);
1704 }
1705 else
1706 {
1707 num_bytes = 0;
1708 }
1709
1710 if (changed_NIR)
1711 {
1712 num_bytes = (U32)outstream_NIR->getCurr();
1713 outstream->putBytes(outstream_NIR->getData(), num_bytes);
1714 }
1715 else
1716 {
1717 num_bytes = 0;
1718 }
1719
1720 return TRUE;
1721 }
1722
1723 /*
1724 ===============================================================================
1725 LASwriteItemCompressed_WAVEPACKET14_v4
1726 ===============================================================================
1727 */
1728
LASwriteItemCompressed_WAVEPACKET14_v4(ArithmeticEncoder * enc)1729 LASwriteItemCompressed_WAVEPACKET14_v4::LASwriteItemCompressed_WAVEPACKET14_v4(ArithmeticEncoder* enc)
1730 {
1731 /* not used as a encoder. just gives access to outstream */
1732
1733 assert(enc);
1734 this->enc = enc;
1735
1736 /* zero outstreams and encoders */
1737
1738 outstream_wavepacket = 0;
1739
1740 enc_wavepacket = 0;
1741
1742 /* zero num_bytes and init booleans */
1743
1744 num_bytes_wavepacket = 0;
1745
1746 changed_wavepacket = FALSE;
1747
1748 /* mark the four scanner channel contexts as uninitialized */
1749
1750 U32 c;
1751 for (c = 0; c < 4; c++)
1752 {
1753 contexts[c].m_packet_index = 0;
1754 }
1755 current_context = 0;
1756 }
1757
~LASwriteItemCompressed_WAVEPACKET14_v4()1758 LASwriteItemCompressed_WAVEPACKET14_v4::~LASwriteItemCompressed_WAVEPACKET14_v4()
1759 {
1760 /* destroy all initialized scanner channel contexts */
1761
1762 U32 c;
1763 for (c = 0; c < 4; c++)
1764 {
1765 if (contexts[c].m_packet_index)
1766 {
1767 enc_wavepacket->destroySymbolModel(contexts[c].m_packet_index);
1768 enc_wavepacket->destroySymbolModel(contexts[c].m_offset_diff[0]);
1769 enc_wavepacket->destroySymbolModel(contexts[c].m_offset_diff[1]);
1770 enc_wavepacket->destroySymbolModel(contexts[c].m_offset_diff[2]);
1771 enc_wavepacket->destroySymbolModel(contexts[c].m_offset_diff[3]);
1772 delete contexts[c].ic_offset_diff;
1773 delete contexts[c].ic_packet_size;
1774 delete contexts[c].ic_return_point;
1775 delete contexts[c].ic_xyz;
1776 }
1777 }
1778
1779 /* destroy all outstreams and encoders */
1780
1781 if (outstream_wavepacket)
1782 {
1783 delete outstream_wavepacket;
1784
1785 delete enc_wavepacket;
1786 }
1787 }
1788
createAndInitModelsAndCompressors(U32 context,const U8 * item)1789 inline BOOL LASwriteItemCompressed_WAVEPACKET14_v4::createAndInitModelsAndCompressors(U32 context, const U8* item)
1790 {
1791 /* should only be called when context is unused */
1792
1793 assert(contexts[context].unused);
1794
1795 /* first create all entropy models (if needed) */
1796
1797 if (contexts[context].m_packet_index == 0)
1798 {
1799 contexts[context].m_packet_index = enc_wavepacket->createSymbolModel(256);
1800 contexts[context].m_offset_diff[0] = enc_wavepacket->createSymbolModel(4);
1801 contexts[context].m_offset_diff[1] = enc_wavepacket->createSymbolModel(4);
1802 contexts[context].m_offset_diff[2] = enc_wavepacket->createSymbolModel(4);
1803 contexts[context].m_offset_diff[3] = enc_wavepacket->createSymbolModel(4);
1804 contexts[context].ic_offset_diff = new IntegerCompressor(enc_wavepacket, 32);
1805 contexts[context].ic_packet_size = new IntegerCompressor(enc_wavepacket, 32);
1806 contexts[context].ic_return_point = new IntegerCompressor(enc_wavepacket, 32);
1807 contexts[context].ic_xyz = new IntegerCompressor(enc_wavepacket, 32, 3);
1808 }
1809
1810 /* then init entropy models */
1811
1812 enc_wavepacket->initSymbolModel(contexts[context].m_packet_index);
1813 enc_wavepacket->initSymbolModel(contexts[context].m_offset_diff[0]);
1814 enc_wavepacket->initSymbolModel(contexts[context].m_offset_diff[1]);
1815 enc_wavepacket->initSymbolModel(contexts[context].m_offset_diff[2]);
1816 enc_wavepacket->initSymbolModel(contexts[context].m_offset_diff[3]);
1817 contexts[context].ic_offset_diff->initCompressor();
1818 contexts[context].ic_packet_size->initCompressor();
1819 contexts[context].ic_return_point->initCompressor();
1820 contexts[context].ic_xyz->initCompressor();
1821
1822 /* init current context from item */
1823
1824 contexts[context].last_diff_32 = 0;
1825 contexts[context].sym_last_offset_diff = 0;
1826 memcpy(contexts[context].last_item, item, 29);
1827
1828 contexts[context].unused = FALSE;
1829
1830 return TRUE;
1831 }
1832
init(const U8 * item,U32 & context)1833 BOOL LASwriteItemCompressed_WAVEPACKET14_v4::init(const U8* item, U32& context)
1834 {
1835 /* on the first init create outstreams and encoders */
1836
1837 if (outstream_wavepacket == 0)
1838 {
1839 /* create outstreams */
1840
1841 if (IS_LITTLE_ENDIAN())
1842 {
1843 outstream_wavepacket = new ByteStreamOutArrayLE();
1844 }
1845 else
1846 {
1847 outstream_wavepacket = new ByteStreamOutArrayBE();
1848 }
1849
1850 /* create layer encoders */
1851
1852 enc_wavepacket = new ArithmeticEncoder();
1853 }
1854 else
1855 {
1856 /* otherwise just seek back */
1857
1858 outstream_wavepacket->seek(0);
1859 }
1860
1861 /* init layer encoders */
1862
1863 enc_wavepacket->init(outstream_wavepacket);
1864
1865 /* set changed booleans to FALSE */
1866
1867 changed_wavepacket = FALSE;
1868
1869 /* mark the four scanner channel contexts as unused */
1870
1871 U32 c;
1872 for (c = 0; c < 4; c++)
1873 {
1874 contexts[c].unused = TRUE;
1875 }
1876
1877 /* set scanner channel as current context */
1878
1879 current_context = context; // all other items use context set by POINT14 writer
1880
1881 /* create and init entropy models and integer compressors (and init contect from item) */
1882
1883 createAndInitModelsAndCompressors(current_context, item);
1884
1885 return TRUE;
1886 }
1887
write(const U8 * item,U32 & context)1888 inline BOOL LASwriteItemCompressed_WAVEPACKET14_v4::write(const U8* item, U32& context)
1889 {
1890 // get last
1891
1892 U8* last_item = contexts[current_context].last_item;
1893
1894 // check for context switch
1895
1896 if (current_context != context)
1897 {
1898 current_context = context; // all other items use context set by POINT14 writer
1899 if (contexts[current_context].unused)
1900 {
1901 createAndInitModelsAndCompressors(current_context, (U8*)last_item);
1902 }
1903 last_item = contexts[current_context].last_item;
1904 }
1905
1906 if (memcmp(item, last_item, 29) != 0)
1907 {
1908 changed_wavepacket = TRUE;
1909 }
1910
1911 // compress
1912
1913 enc_wavepacket->encodeSymbol(contexts[current_context].m_packet_index, (U32)(item[0]));
1914
1915 LASwavepacket13 this_item_m = LASwavepacket13::unpack(item+1);
1916 LASwavepacket13 last_item_m = LASwavepacket13::unpack(last_item+1);
1917
1918 // calculate the difference between the two offsets
1919 I64 curr_diff_64 = this_item_m.offset - last_item_m.offset;
1920 I32 curr_diff_32 = (I32)curr_diff_64;
1921
1922 // if the current difference can be represented with 32 bits
1923 if (curr_diff_64 == (I64)(curr_diff_32))
1924 {
1925 if (curr_diff_32 == 0) // current difference is zero
1926 {
1927 enc_wavepacket->encodeSymbol(contexts[current_context].m_offset_diff[contexts[current_context].sym_last_offset_diff], 0);
1928 contexts[current_context].sym_last_offset_diff = 0;
1929 }
1930 else if (curr_diff_32 == (I32)last_item_m.packet_size)
1931 {
1932 enc_wavepacket->encodeSymbol(contexts[current_context].m_offset_diff[contexts[current_context].sym_last_offset_diff], 1);
1933 contexts[current_context].sym_last_offset_diff = 1;
1934 }
1935 else //
1936 {
1937 enc_wavepacket->encodeSymbol(contexts[current_context].m_offset_diff[contexts[current_context].sym_last_offset_diff], 2);
1938 contexts[current_context].sym_last_offset_diff = 2;
1939 contexts[current_context].ic_offset_diff->compress(contexts[current_context].last_diff_32, curr_diff_32);
1940 contexts[current_context].last_diff_32 = curr_diff_32;
1941 }
1942 }
1943 else
1944 {
1945 enc_wavepacket->encodeSymbol(contexts[current_context].m_offset_diff[contexts[current_context].sym_last_offset_diff], 3);
1946 contexts[current_context].sym_last_offset_diff = 3;
1947
1948 enc_wavepacket->writeInt64(this_item_m.offset);
1949 }
1950
1951 contexts[current_context].ic_packet_size->compress(last_item_m.packet_size, this_item_m.packet_size);
1952 contexts[current_context].ic_return_point->compress(last_item_m.return_point.i32, this_item_m.return_point.i32);
1953 contexts[current_context].ic_xyz->compress(last_item_m.x.i32, this_item_m.x.i32, 0);
1954 contexts[current_context].ic_xyz->compress(last_item_m.y.i32, this_item_m.y.i32, 1);
1955 contexts[current_context].ic_xyz->compress(last_item_m.z.i32, this_item_m.z.i32, 2);
1956
1957 memcpy(last_item, item, 29);
1958 return TRUE;
1959 }
1960
chunk_sizes()1961 inline BOOL LASwriteItemCompressed_WAVEPACKET14_v4::chunk_sizes()
1962 {
1963 U32 num_bytes = 0;
1964 ByteStreamOut* outstream = enc->getByteStreamOut();
1965
1966 // finish the encoders
1967
1968 enc_wavepacket->done();
1969
1970 // output the sizes of all layer (i.e.. number of bytes per layer)
1971
1972 if (changed_wavepacket)
1973 {
1974 num_bytes = (U32)outstream_wavepacket->getCurr();
1975 num_bytes_wavepacket += num_bytes;
1976 }
1977 else
1978 {
1979 num_bytes = 0;
1980 }
1981 outstream->put32bitsLE(((U8*)&num_bytes));
1982
1983 return TRUE;
1984 }
1985
chunk_bytes()1986 inline BOOL LASwriteItemCompressed_WAVEPACKET14_v4::chunk_bytes()
1987 {
1988 U32 num_bytes = 0;
1989 ByteStreamOut* outstream = enc->getByteStreamOut();
1990
1991 // output the bytes of all layers
1992
1993 if (changed_wavepacket)
1994 {
1995 num_bytes = (U32)outstream_wavepacket->getCurr();
1996 outstream->putBytes(outstream_wavepacket->getData(), num_bytes);
1997 }
1998
1999 return TRUE;
2000 }
2001
2002 /*
2003 ===============================================================================
2004 LASwriteItemCompressed_BYTE14_v4
2005 ===============================================================================
2006 */
2007
LASwriteItemCompressed_BYTE14_v4(ArithmeticEncoder * enc,U32 number)2008 LASwriteItemCompressed_BYTE14_v4::LASwriteItemCompressed_BYTE14_v4(ArithmeticEncoder* enc, U32 number)
2009 {
2010 /* not used as a encoder. just gives access to outstream */
2011
2012 assert(enc);
2013 this->enc = enc;
2014
2015 /* must be more than one byte */
2016
2017 assert(number);
2018 this->number = number;
2019
2020 /* zero outstream and encoder pointer arrays */
2021
2022 outstream_Bytes = 0;
2023
2024 enc_Bytes = 0;
2025
2026 /* number of bytes per layer */
2027
2028 num_bytes_Bytes = new U32[number];
2029
2030 changed_Bytes = new BOOL[number];
2031
2032 U32 i;
2033 for (i = 0; i < number; i++)
2034 {
2035 num_bytes_Bytes[i] = 0;
2036
2037 changed_Bytes[i] = FALSE;
2038 }
2039
2040 /* mark the four scanner channel contexts as uninitialized */
2041
2042 U32 c;
2043 for (c = 0; c < 4; c++)
2044 {
2045 contexts[c].m_bytes = 0;
2046 }
2047 current_context = 0;
2048 }
2049
~LASwriteItemCompressed_BYTE14_v4()2050 LASwriteItemCompressed_BYTE14_v4::~LASwriteItemCompressed_BYTE14_v4()
2051 {
2052 /* destroy all initialized scanner channel contexts */
2053
2054 U32 c, i;
2055 for (c = 0; c < 4; c++)
2056 {
2057 if (contexts[c].m_bytes)
2058 {
2059 for (i = 0; i < number; i++)
2060 {
2061 enc_Bytes[i]->destroySymbolModel(contexts[c].m_bytes[i]);
2062 }
2063 delete [] contexts[c].m_bytes;
2064 delete [] contexts[c].last_item;
2065 }
2066 }
2067
2068 /* destroy all outstream and encoder arrays */
2069
2070 if (outstream_Bytes)
2071 {
2072 for (i = 0; i < number; i++)
2073 {
2074 if (outstream_Bytes[i])
2075 {
2076 delete outstream_Bytes[i];
2077 delete enc_Bytes[i];
2078 }
2079 }
2080
2081 delete [] outstream_Bytes;
2082 delete [] enc_Bytes;
2083 }
2084
2085 /* destroy all other arrays */
2086
2087 if (num_bytes_Bytes) delete [] num_bytes_Bytes;
2088
2089 if (changed_Bytes) delete [] changed_Bytes;
2090 }
2091
createAndInitModelsAndCompressors(U32 context,const U8 * item)2092 inline BOOL LASwriteItemCompressed_BYTE14_v4::createAndInitModelsAndCompressors(U32 context, const U8* item)
2093 {
2094 U32 i;
2095
2096 /* should only be called when context is unused */
2097
2098 assert(contexts[context].unused);
2099
2100 /* first create all entropy models and last items (if needed) */
2101
2102 if (contexts[context].m_bytes == 0)
2103 {
2104 contexts[context].m_bytes = new ArithmeticModel*[number];
2105 for (i = 0; i < number; i++)
2106 {
2107 contexts[context].m_bytes[i] = enc_Bytes[i]->createSymbolModel(256);
2108 enc_Bytes[i]->initSymbolModel(contexts[context].m_bytes[i]);
2109 }
2110
2111 /* create last item */
2112 contexts[context].last_item = new U8[number];
2113 }
2114
2115 /* then init entropy models */
2116
2117 for (i = 0; i < number; i++)
2118 {
2119 enc_Bytes[i]->initSymbolModel(contexts[context].m_bytes[i]);
2120 }
2121
2122 /* init current context from item */
2123
2124 memcpy(contexts[context].last_item, item, number);
2125
2126 contexts[context].unused = FALSE;
2127
2128 return TRUE;
2129 }
2130
init(const U8 * item,U32 & context)2131 BOOL LASwriteItemCompressed_BYTE14_v4::init(const U8* item, U32& context)
2132 {
2133 U32 i;
2134
2135 /* on the first init create outstreams and encoders */
2136
2137 if (outstream_Bytes == 0)
2138 {
2139 /* create outstreams pointer array */
2140
2141 outstream_Bytes = new ByteStreamOutArray*[number];
2142
2143 /* create outstreams */
2144
2145 if (IS_LITTLE_ENDIAN())
2146 {
2147 for (i = 0; i < number; i++)
2148 {
2149 outstream_Bytes[i] = new ByteStreamOutArrayLE();
2150 }
2151 }
2152 else
2153 {
2154 for (i = 0; i < number; i++)
2155 {
2156 outstream_Bytes[i] = new ByteStreamOutArrayBE();
2157 }
2158 }
2159
2160 /* create encoder pointer array */
2161
2162 enc_Bytes = new ArithmeticEncoder*[number];
2163
2164 /* create layer encoders */
2165
2166 for (i = 0; i < number; i++)
2167 {
2168 enc_Bytes[i] = new ArithmeticEncoder();
2169 }
2170 }
2171 else
2172 {
2173 /* otherwise just seek back */
2174
2175 for (i = 0; i < number; i++)
2176 {
2177 outstream_Bytes[i]->seek(0);
2178 }
2179 }
2180
2181 /* init layer encoders */
2182
2183 for (i = 0; i < number; i++)
2184 {
2185 enc_Bytes[i]->init(outstream_Bytes[i]);
2186 }
2187
2188 /* set changed booleans to FALSE */
2189
2190 for (i = 0; i < number; i++)
2191 {
2192 changed_Bytes[i] = FALSE;
2193 }
2194
2195 /* mark the four scanner channel contexts as unused */
2196
2197 U32 c;
2198 for (c = 0; c < 4; c++)
2199 {
2200 contexts[c].unused = TRUE;
2201 }
2202
2203 /* set scanner channel as current context */
2204
2205 current_context = context; // all other items use context set by POINT14 writer
2206
2207 /* create and init entropy models and integer compressors (and init context from item) */
2208
2209 createAndInitModelsAndCompressors(current_context, item);
2210
2211 return TRUE;
2212 }
2213
write(const U8 * item,U32 & context)2214 inline BOOL LASwriteItemCompressed_BYTE14_v4::write(const U8* item, U32& context)
2215 {
2216 // get last
2217
2218 U8* last_item = contexts[current_context].last_item;
2219
2220 // check for context switch
2221
2222 if (current_context != context)
2223 {
2224 current_context = context; // all other items use context set by POINT14 writer
2225 if (contexts[current_context].unused)
2226 {
2227 createAndInitModelsAndCompressors(current_context, last_item);
2228 }
2229 last_item = contexts[current_context].last_item;
2230 }
2231
2232 // compress
2233
2234 U32 i;
2235 I32 diff;
2236 for (i = 0; i < number; i++)
2237 {
2238 diff = item[i] - last_item[i];
2239 enc_Bytes[i]->encodeSymbol(contexts[current_context].m_bytes[i], U8_FOLD(diff));
2240 if (diff)
2241 {
2242 changed_Bytes[i] = TRUE;
2243 last_item[i] = item[i];
2244 }
2245 }
2246 return TRUE;
2247 }
2248
chunk_sizes()2249 inline BOOL LASwriteItemCompressed_BYTE14_v4::chunk_sizes()
2250 {
2251 U32 i;
2252 U32 num_bytes = 0;
2253 ByteStreamOut* outstream = enc->getByteStreamOut();
2254
2255 // output the sizes of all layer (i.e.. number of bytes per layer)
2256
2257 for (i = 0; i < number; i++)
2258 {
2259 // finish the encoders
2260 enc_Bytes[i]->done();
2261
2262 if (changed_Bytes[i])
2263 {
2264 num_bytes = (U32)outstream_Bytes[i]->getCurr();
2265 num_bytes_Bytes[i] += num_bytes;
2266 }
2267 else
2268 {
2269 num_bytes = 0;
2270 }
2271 outstream->put32bitsLE(((U8*)&num_bytes));
2272 }
2273
2274 return TRUE;
2275 }
2276
chunk_bytes()2277 inline BOOL LASwriteItemCompressed_BYTE14_v4::chunk_bytes()
2278 {
2279 U32 i;
2280 U32 num_bytes = 0;
2281 ByteStreamOut* outstream = enc->getByteStreamOut();
2282
2283 // output the bytes of all layers
2284
2285 for (i = 0; i < number; i++)
2286 {
2287 if (changed_Bytes[i])
2288 {
2289 num_bytes = (U32)outstream_Bytes[i]->getCurr();
2290 outstream->putBytes(outstream_Bytes[i]->getData(), num_bytes);
2291 }
2292 else
2293 {
2294 num_bytes = 0;
2295 }
2296 }
2297
2298 return TRUE;
2299 }
2300