1 /*
2 ===============================================================================
3
4 FILE: field_nir14.hpp
5
6 CONTENTS:
7
8
9 PROGRAMMERS:
10
11 martin.isenburg@rapidlasso.com - http://rapidlasso.com
12 uday.karan@gmail.com - Hobu, Inc.
13
14 COPYRIGHT:
15
16 (c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality
17 (c) 2014, Uday Verma, Hobu, Inc.
18
19 This is free software; you can redistribute and/or modify it under the
20 terms of the GNU Lesser General Licence as published by the Free Software
21 Foundation. See the COPYING file for more information.
22
23 This software is distributed WITHOUT ANY WARRANTY and without even the
24 implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
25
26 CHANGE HISTORY:
27
28 ===============================================================================
29 */
30
31 #include "../las.hpp"
32
33 namespace lazperf
34 {
35 namespace detail
36 {
37
38 // COMPRESSOR
39
writeSizes()40 void Nir14Compressor::writeSizes()
41 {
42 nir_enc_.done();
43 stream_ << nir_enc_.num_encoded();
44 }
45
writeData()46 void Nir14Compressor::writeData()
47 {
48 LAZDEBUG(std::cerr << "NIR : " <<
49 utils::sum(nir_enc_.encoded_bytes(), nir_enc_.num_encoded()) << "\n");
50
51 if (nir_enc_.num_encoded())
52 stream_.putBytes(nir_enc_.encoded_bytes(), nir_enc_.num_encoded());
53 }
54
compress(const char * buf,int & sc)55 const char *Nir14Compressor::compress(const char *buf, int& sc)
56 {
57 const las::nir14 nir(buf);
58
59 // don't have the first data yet, just push it to our
60 // have last stuff and move on
61 if (last_channel_ == -1)
62 {
63 ChannelCtx& c = chan_ctxs_[sc];
64 stream_.putBytes((const unsigned char*)&nir, sizeof(las::nir14));
65 c.last_ = nir;
66 c.have_last_ = true;
67 last_channel_ = sc;
68 return buf + sizeof(las::nir14);
69 }
70
71 ChannelCtx& c = chan_ctxs_[sc];
72 las::nir14 *pLastNir = &chan_ctxs_[last_channel_].last_;
73 if (!c.have_last_)
74 {
75 c.have_last_ = true;
76 c.last_ = *pLastNir;
77 pLastNir = &c.last_;
78 }
79 // This mess is because of the broken-ness of the handling for last in v3, where
80 // 'last_point' only gets updated on the first context switch in the LASzip code.
81 las::nir14& lastNir = *pLastNir;
82
83 bool lowChange = (lastNir.val & 0xFF) != (nir.val & 0xFF);
84 bool highChange = (lastNir.val & 0xFF00) != (nir.val & 0xFF00);
85 int32_t sym = lowChange | (highChange << 1);
86 if (sym)
87 nir_enc_.makeValid();
88 nir_enc_.encodeSymbol(c.used_model_, sym);
89
90 if (lowChange)
91 {
92 int32_t diff = (nir.val & 0xFF) - (lastNir.val & 0xFF);
93 nir_enc_.encodeSymbol(c.diff_model_[0], uint8_t(diff));
94 }
95 if (highChange)
96 {
97 int32_t diff = (nir.val >> 8) - (lastNir.val >> 8);
98 nir_enc_.encodeSymbol(c.diff_model_[1], uint8_t(diff));
99 }
100
101 lastNir = nir;
102 last_channel_ = sc;
103 return buf + sizeof(las::nir14);
104 }
105
106 // DECOMPRESSOR
107
dumpSums()108 void Nir14Decompressor::dumpSums()
109 {
110 std::cout << "NIR : " << sumNir.value() << "\n";
111 }
112
readSizes()113 void Nir14Decompressor::readSizes()
114 {
115 stream_ >> nir_cnt_;
116 }
117
readData()118 void Nir14Decompressor::readData()
119 {
120 nir_dec_.initStream(stream_, nir_cnt_);
121 }
122
decompress(char * buf,int & sc)123 char *Nir14Decompressor::decompress(char *buf, int& sc)
124 {
125 if (last_channel_ == -1)
126 {
127 ChannelCtx& c = chan_ctxs_[sc];
128 stream_.getBytes((unsigned char*)buf, sizeof(las::nir14));
129 c.last_.unpack(buf);
130 c.have_last_ = true;
131 last_channel_ = sc;
132 return buf + sizeof(las::nir14);
133 }
134 if (nir_cnt_ == 0)
135 {
136 las::nir14 *nir = reinterpret_cast<las::nir14 *>(buf);
137 *nir = chan_ctxs_[last_channel_].last_;
138 return buf + sizeof(las::nir14);
139 }
140
141 ChannelCtx& c = chan_ctxs_[sc];
142 las::nir14 *pLastNir = &chan_ctxs_[last_channel_].last_;
143 if (sc != last_channel_)
144 {
145 last_channel_ = sc;
146 if (!c.have_last_)
147 {
148 c.have_last_ = true;
149 c.last_ = *pLastNir;
150 pLastNir = &chan_ctxs_[last_channel_].last_;
151 }
152 }
153 las::nir14& lastNir = *pLastNir;
154
155 uint32_t sym = nir_dec_.decodeSymbol(c.used_model_);
156
157 las::nir14 nir;
158
159 if (sym & (1 << 0))
160 {
161 uint8_t corr = (uint8_t)nir_dec_.decodeSymbol(c.diff_model_[0]);
162 nir.val = uint8_t(corr + (lastNir.val & 0xFF));
163 }
164 else
165 nir.val = lastNir.val & 0xFF;
166
167 if (sym & (1 << 1))
168 {
169 uint8_t corr = (uint8_t)nir_dec_.decodeSymbol(c.diff_model_[1]);
170 nir.val |= (static_cast<uint16_t>(uint8_t(corr + (lastNir.val >> 8))) << 8);
171 }
172 else
173 nir.val |= lastNir.val & 0xFF00;
174 LAZDEBUG(sumNir.add(nir));
175
176 lastNir = nir;
177 nir.pack(buf);
178 return buf + sizeof(las::nir14);
179 }
180
181 } // namespace detail
182 } // namespace lazperf
183