/* =============================================================================== FILE: lasreaditemcompressed_v1.cpp CONTENTS: see corresponding header file PROGRAMMERS: martin.isenburg@rapidlasso.com - http://rapidlasso.com COPYRIGHT: (c) 2007-2017, martin isenburg, rapidlasso - fast tools to catch reality This is free software; you can redistribute and/or modify it under the terms of the GNU Lesser General Licence as published by the Free Software Foundation. See the COPYING file for more information. This software is distributed WITHOUT ANY WARRANTY and without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. CHANGE HISTORY: see corresponding header file =============================================================================== */ #include "lasreaditemcompressed_v1.hpp" #include "laszip_common_v1.hpp" #include #include /* =============================================================================== LASreadItemCompressed_POINT10_v1 =============================================================================== */ struct LASpoint10 { I32 x; I32 y; I32 z; U16 intensity; U8 return_number : 3; U8 number_of_returns_of_given_pulse : 3; U8 scan_direction_flag : 1; U8 edge_of_flight_line : 1; U8 classification; I8 scan_angle_rank; U8 user_data; U16 point_source_ID; }; LASreadItemCompressed_POINT10_v1::LASreadItemCompressed_POINT10_v1(ArithmeticDecoder* dec) { U32 i; /* set decoder */ assert(dec); this->dec = dec; /* create models and integer compressors */ ic_dx = new IntegerCompressor(dec, 32); // 32 bits, 1 context ic_dy = new IntegerCompressor(dec, 32, 20); // 32 bits, 20 contexts ic_z = new IntegerCompressor(dec, 32, 20); // 32 bits, 20 contexts ic_intensity = new IntegerCompressor(dec, 16); ic_scan_angle_rank = new IntegerCompressor(dec, 8, 2); ic_point_source_ID = new IntegerCompressor(dec, 16); m_changed_values = dec->createSymbolModel(64); for (i = 0; i < 256; i++) { m_bit_byte[i] = 0; m_classification[i] = 0; m_user_data[i] = 0; } } LASreadItemCompressed_POINT10_v1::~LASreadItemCompressed_POINT10_v1() { U32 i; delete ic_dx; delete ic_dy; delete ic_z; delete ic_intensity; delete ic_scan_angle_rank; delete ic_point_source_ID; dec->destroySymbolModel(m_changed_values); for (i = 0; i < 256; i++) { if (m_bit_byte[i]) dec->destroySymbolModel(m_bit_byte[i]); if (m_classification[i]) dec->destroySymbolModel(m_classification[i]); if (m_user_data[i]) dec->destroySymbolModel(m_user_data[i]); } } BOOL LASreadItemCompressed_POINT10_v1::init(const U8* item, U32& context) { U32 i; /* init state */ last_x_diff[0] = last_x_diff[1] = last_x_diff[2] = 0; last_y_diff[0] = last_y_diff[1] = last_y_diff[2] = 0; last_incr = 0; /* init models and integer compressors */ ic_dx->initDecompressor(); ic_dy->initDecompressor(); ic_z->initDecompressor(); ic_intensity->initDecompressor(); ic_scan_angle_rank->initDecompressor(); ic_point_source_ID->initDecompressor(); dec->initSymbolModel(m_changed_values); for (i = 0; i < 256; i++) { if (m_bit_byte[i]) dec->initSymbolModel(m_bit_byte[i]); if (m_classification[i]) dec->initSymbolModel(m_classification[i]); if (m_user_data[i]) dec->initSymbolModel(m_user_data[i]); } /* init last item */ memcpy(last_item, item, 20); return TRUE; } inline void LASreadItemCompressed_POINT10_v1::read(U8* item, U32& context) { // find median difference for x and y from 3 preceding differences I32 median_x; if (last_x_diff[0] < last_x_diff[1]) { if (last_x_diff[1] < last_x_diff[2]) median_x = last_x_diff[1]; else if (last_x_diff[0] < last_x_diff[2]) median_x = last_x_diff[2]; else median_x = last_x_diff[0]; } else { if (last_x_diff[0] < last_x_diff[2]) median_x = last_x_diff[0]; else if (last_x_diff[1] < last_x_diff[2]) median_x = last_x_diff[2]; else median_x = last_x_diff[1]; } I32 median_y; if (last_y_diff[0] < last_y_diff[1]) { if (last_y_diff[1] < last_y_diff[2]) median_y = last_y_diff[1]; else if (last_y_diff[0] < last_y_diff[2]) median_y = last_y_diff[2]; else median_y = last_y_diff[0]; } else { if (last_y_diff[0] < last_y_diff[2]) median_y = last_y_diff[0]; else if (last_y_diff[1] < last_y_diff[2]) median_y = last_y_diff[2]; else median_y = last_y_diff[1]; } // decompress x y z coordinates I32 x_diff = ic_dx->decompress(median_x); ((LASpoint10*)last_item)->x += x_diff; // we use the number k of bits corrector bits to switch contexts U32 k_bits = ic_dx->getK(); I32 y_diff = ic_dy->decompress(median_y, (k_bits < 19 ? k_bits : 19)); ((LASpoint10*)last_item)->y += y_diff; k_bits = (k_bits + ic_dy->getK())/2; ((LASpoint10*)last_item)->z = ic_z->decompress(((LASpoint10*)last_item)->z, (k_bits < 19 ? k_bits : 19)); // decompress which other values have changed I32 changed_values = dec->decodeSymbol(m_changed_values); if (changed_values) { // decompress the intensity if it has changed if (changed_values & 32) { ((LASpoint10*)last_item)->intensity = (U16)ic_intensity->decompress(((LASpoint10*)last_item)->intensity); } // decompress the edge_of_flight_line, scan_direction_flag, ... if it has changed if (changed_values & 16) { if (m_bit_byte[last_item[14]] == 0) { m_bit_byte[last_item[14]] = dec->createSymbolModel(256); dec->initSymbolModel(m_bit_byte[last_item[14]]); } last_item[14] = (U8)dec->decodeSymbol(m_bit_byte[last_item[14]]); } // decompress the classification ... if it has changed if (changed_values & 8) { if (m_classification[last_item[15]] == 0) { m_classification[last_item[15]] = dec->createSymbolModel(256); dec->initSymbolModel(m_classification[last_item[15]]); } last_item[15] = (U8)dec->decodeSymbol(m_classification[last_item[15]]); } // decompress the scan_angle_rank ... if it has changed if (changed_values & 4) { last_item[16] = (U8)ic_scan_angle_rank->decompress(last_item[16], k_bits < 3); } // decompress the user_data ... if it has changed if (changed_values & 2) { if (m_user_data[last_item[17]] == 0) { m_user_data[last_item[17]] = dec->createSymbolModel(256); dec->initSymbolModel(m_user_data[last_item[17]]); } last_item[17] = (U8)dec->decodeSymbol(m_user_data[last_item[17]]); } // decompress the point_source_ID ... if it has changed if (changed_values & 1) { ((LASpoint10*)last_item)->point_source_ID = (U16)ic_point_source_ID->decompress(((LASpoint10*)last_item)->point_source_ID); } } // record the difference last_x_diff[last_incr] = x_diff; last_y_diff[last_incr] = y_diff; last_incr++; if (last_incr > 2) last_incr = 0; // copy the last point memcpy(item, last_item, 20); } /* =============================================================================== LASreadItemCompressed_GPSTIME11_v1 =============================================================================== */ #define LASZIP_GPSTIME_MULTIMAX 512 LASreadItemCompressed_GPSTIME11_v1::LASreadItemCompressed_GPSTIME11_v1(ArithmeticDecoder* dec) { /* set decoder */ assert(dec); this->dec = dec; /* create entropy models and integer compressors */ m_gpstime_multi = dec->createSymbolModel(LASZIP_GPSTIME_MULTIMAX); m_gpstime_0diff = dec->createSymbolModel(3); ic_gpstime = new IntegerCompressor(dec, 32, 6); // 32 bits, 6 contexts } LASreadItemCompressed_GPSTIME11_v1::~LASreadItemCompressed_GPSTIME11_v1() { dec->destroySymbolModel(m_gpstime_multi); dec->destroySymbolModel(m_gpstime_0diff); delete ic_gpstime; } BOOL LASreadItemCompressed_GPSTIME11_v1::init(const U8* item, U32& context) { /* init state */ last_gpstime_diff = 0; multi_extreme_counter = 0; /* init models and integer compressors */ dec->initSymbolModel(m_gpstime_multi); dec->initSymbolModel(m_gpstime_0diff); ic_gpstime->initDecompressor(); /* init last item */ last_gpstime.u64 = *((U64*)item); return TRUE; } inline void LASreadItemCompressed_GPSTIME11_v1::read(U8* item, U32& context) { I32 multi; if (last_gpstime_diff == 0) // if the last integer difference was zero { multi = dec->decodeSymbol(m_gpstime_0diff); if (multi == 1) // the difference can be represented with 32 bits { last_gpstime_diff = ic_gpstime->decompress(0, 0); last_gpstime.i64 += last_gpstime_diff; } else if (multi == 2) // the difference is huge { last_gpstime.u64 = dec->readInt64(); } } else { multi = dec->decodeSymbol(m_gpstime_multi); if (multi < LASZIP_GPSTIME_MULTIMAX-2) { I32 gpstime_diff; if (multi == 1) { gpstime_diff = ic_gpstime->decompress(last_gpstime_diff, 1); last_gpstime_diff = gpstime_diff; multi_extreme_counter = 0; } else if (multi == 0) { gpstime_diff = ic_gpstime->decompress(last_gpstime_diff/4, 2); multi_extreme_counter++; if (multi_extreme_counter > 3) { last_gpstime_diff = gpstime_diff; multi_extreme_counter = 0; } } else if (multi < 10) { gpstime_diff = ic_gpstime->decompress(multi*last_gpstime_diff, 3); } else if (multi < 50) { gpstime_diff = ic_gpstime->decompress(multi*last_gpstime_diff, 4); } else { gpstime_diff = ic_gpstime->decompress(multi*last_gpstime_diff, 5); if (multi == LASZIP_GPSTIME_MULTIMAX-3) { multi_extreme_counter++; if (multi_extreme_counter > 3) { last_gpstime_diff = gpstime_diff; multi_extreme_counter = 0; } } } last_gpstime.i64 += gpstime_diff; } else if (multi < LASZIP_GPSTIME_MULTIMAX-1) { last_gpstime.u64 = dec->readInt64(); } } *((I64*)item) = last_gpstime.i64; } /* =============================================================================== LASreadItemCompressed_RGB12_v1 =============================================================================== */ LASreadItemCompressed_RGB12_v1::LASreadItemCompressed_RGB12_v1(ArithmeticDecoder* dec) { /* set decoder */ assert(dec); this->dec = dec; /* create models and integer compressors */ m_byte_used = dec->createSymbolModel(64); ic_rgb = new IntegerCompressor(dec, 8, 6); /* create last item */ last_item = new U8[6]; } LASreadItemCompressed_RGB12_v1::~LASreadItemCompressed_RGB12_v1() { dec->destroySymbolModel(m_byte_used); delete ic_rgb; delete [] last_item; } BOOL LASreadItemCompressed_RGB12_v1::init(const U8* item, U32& context) { /* init state */ /* init models and integer compressors */ dec->initSymbolModel(m_byte_used); ic_rgb->initDecompressor(); /* init last item */ memcpy(last_item, item, 6); return TRUE; } inline void LASreadItemCompressed_RGB12_v1::read(U8* item, U32& context) { U32 sym = dec->decodeSymbol(m_byte_used); if (sym & (1 << 0)) ((U16*)item)[0] = (U16)ic_rgb->decompress(((U16*)last_item)[0]&255, 0); else ((U16*)item)[0] = (U16)(((U16*)last_item)[0]&0xFF); if (sym & (1 << 1)) ((U16*)item)[0] |= (((U16)ic_rgb->decompress(((U16*)last_item)[0]>>8, 1)) << 8); else ((U16*)item)[0] |= (((U16*)last_item)[0]&0xFF00); if (sym & (1 << 2)) ((U16*)item)[1] = (U16)ic_rgb->decompress(((U16*)last_item)[1]&255, 2); else ((U16*)item)[1] = (U16)(((U16*)last_item)[1]&0xFF); if (sym & (1 << 3)) ((U16*)item)[1] |= (((U16)ic_rgb->decompress(((U16*)last_item)[1]>>8, 3)) << 8); else ((U16*)item)[1] |= (((U16*)last_item)[1]&0xFF00); if (sym & (1 << 4)) ((U16*)item)[2] = (U16)ic_rgb->decompress(((U16*)last_item)[2]&255, 4); else ((U16*)item)[2] = (U16)(((U16*)last_item)[2]&0xFF); if (sym & (1 << 5)) ((U16*)item)[2] |= (((U16)ic_rgb->decompress(((U16*)last_item)[2]>>8, 5)) << 8); else ((U16*)item)[2] |= (((U16*)last_item)[2]&0xFF00); memcpy(last_item, item, 6); } /* =============================================================================== LASreadItemCompressed_WAVEPACKET13_v1 =============================================================================== */ LASreadItemCompressed_WAVEPACKET13_v1::LASreadItemCompressed_WAVEPACKET13_v1(ArithmeticDecoder* dec) { /* set decoder */ assert(dec); this->dec = dec; /* create models and integer compressors */ m_packet_index = dec->createSymbolModel(256); m_offset_diff[0] = dec->createSymbolModel(4); m_offset_diff[1] = dec->createSymbolModel(4); m_offset_diff[2] = dec->createSymbolModel(4); m_offset_diff[3] = dec->createSymbolModel(4); ic_offset_diff = new IntegerCompressor(dec, 32); ic_packet_size = new IntegerCompressor(dec, 32); ic_return_point = new IntegerCompressor(dec, 32); ic_xyz = new IntegerCompressor(dec, 32, 3); /* create last item */ last_item = new U8[28]; } LASreadItemCompressed_WAVEPACKET13_v1::~LASreadItemCompressed_WAVEPACKET13_v1() { dec->destroySymbolModel(m_packet_index); dec->destroySymbolModel(m_offset_diff[0]); dec->destroySymbolModel(m_offset_diff[1]); dec->destroySymbolModel(m_offset_diff[2]); dec->destroySymbolModel(m_offset_diff[3]); delete ic_offset_diff; delete ic_packet_size; delete ic_return_point; delete ic_xyz; delete [] last_item; } BOOL LASreadItemCompressed_WAVEPACKET13_v1::init(const U8* item, U32& context) { /* init state */ last_diff_32 = 0; sym_last_offset_diff = 0; /* init models and integer compressors */ dec->initSymbolModel(m_packet_index); dec->initSymbolModel(m_offset_diff[0]); dec->initSymbolModel(m_offset_diff[1]); dec->initSymbolModel(m_offset_diff[2]); dec->initSymbolModel(m_offset_diff[3]); ic_offset_diff->initDecompressor(); ic_packet_size->initDecompressor(); ic_return_point->initDecompressor(); ic_xyz->initDecompressor(); /* init last item */ item++; memcpy(last_item, item, 28); return TRUE; } inline void LASreadItemCompressed_WAVEPACKET13_v1::read(U8* item, U32& context) { item[0] = (U8)(dec->decodeSymbol(m_packet_index)); item++; LASwavepacket13 this_item_m; LASwavepacket13 last_item_m = LASwavepacket13::unpack(last_item); sym_last_offset_diff = dec->decodeSymbol(m_offset_diff[sym_last_offset_diff]); if (sym_last_offset_diff == 0) { this_item_m.offset = last_item_m.offset; } else if (sym_last_offset_diff == 1) { this_item_m.offset = last_item_m.offset + last_item_m.packet_size; } else if (sym_last_offset_diff == 2) { last_diff_32 = ic_offset_diff->decompress(last_diff_32); this_item_m.offset = last_item_m.offset + last_diff_32; } else { this_item_m.offset = dec->readInt64(); } this_item_m.packet_size = ic_packet_size->decompress(last_item_m.packet_size); this_item_m.return_point.i32 = ic_return_point->decompress(last_item_m.return_point.i32); this_item_m.x.i32 = ic_xyz->decompress(last_item_m.x.i32, 0); this_item_m.y.i32 = ic_xyz->decompress(last_item_m.y.i32, 1); this_item_m.z.i32 = ic_xyz->decompress(last_item_m.z.i32, 2); this_item_m.pack(item); memcpy(last_item, item, 28); } /* =============================================================================== LASreadItemCompressed_BYTE_v1 =============================================================================== */ LASreadItemCompressed_BYTE_v1::LASreadItemCompressed_BYTE_v1(ArithmeticDecoder* dec, U32 number) { /* set decoder */ assert(dec); this->dec = dec; assert(number); this->number = number; /* create models and integer compressors */ ic_byte = new IntegerCompressor(dec, 8, number); /* create last item */ last_item = new U8[number]; } LASreadItemCompressed_BYTE_v1::~LASreadItemCompressed_BYTE_v1() { delete ic_byte; delete [] last_item; } BOOL LASreadItemCompressed_BYTE_v1::init(const U8* item, U32& context) { /* init state */ /* init models and integer compressors */ ic_byte->initDecompressor(); /* init last item */ memcpy(last_item, item, number); return TRUE; } inline void LASreadItemCompressed_BYTE_v1::read(U8* item, U32& context) { U32 i; for (i = 0; i < number; i++) { item[i] = (U8)(ic_byte->decompress(last_item[i], i)); } memcpy(last_item, item, number); } // vim: set ts=2 sw=2 expandtabs