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