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