1 /*
2 ===============================================================================
3 
4   PROGRAMMERS:
5 
6     martin.isenburg@rapidlasso.com  -  http://rapidlasso.com
7     uday.karan@gmail.com - Hobu, Inc.
8 
9   COPYRIGHT:
10 
11     (c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality
12     (c) 2014, Uday Verma, Hobu, Inc.
13 
14     This is free software; you can redistribute and/or modify it under the
15     terms of the GNU Lesser General Licence as published by the Free Software
16     Foundation. See the COPYING file for more information.
17 
18     This software is distributed WITHOUT ANY WARRANTY and without even the
19     implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
20 
21   CHANGE HISTORY:
22 
23 ===============================================================================
24 */
25 
26 #include "../las.hpp"
27 //#include "../types.hpp"
28 
29 namespace lazperf
30 {
31 namespace detail
32 {
33 
34 namespace
35 {
36 
color_diff_bits(const las::rgb & this_val,const las::rgb & last)37 unsigned int color_diff_bits(const las::rgb& this_val, const las::rgb& last)
38 {
39     const las::rgb& a = last;
40     const las::rgb& b = this_val;
41 
42 #define __flag_diff(x,y,f) ((((x) ^ (y)) & (f)) != 0)
43                 unsigned int r =
44                     (__flag_diff(a.r, b.r, 0x00FF) << 0) |
45                     (__flag_diff(a.r, b.r, 0xFF00) << 1) |
46                     (__flag_diff(a.g, b.g, 0x00FF) << 2) |
47                     (__flag_diff(a.g, b.g, 0xFF00) << 3) |
48                     (__flag_diff(a.b, b.b, 0x00FF) << 4) |
49                     (__flag_diff(a.b, b.b, 0xFF00) << 5) |
50                     (__flag_diff(b.r, b.g, 0x00FF) |
51                      __flag_diff(b.r, b.b, 0x00FF) |
52                      __flag_diff(b.r, b.g, 0xFF00) |
53                      __flag_diff(b.r, b.b, 0xFF00)) << 6;
54 #undef __flag_diff
55 
56     return r;
57 }
58 
59 } // unnamed namespace
60 
Rgb10Base()61 Rgb10Base::Rgb10Base() : have_last_(false), last(), m_byte_used(128), m_rgb_diff_0(256),
62     m_rgb_diff_1(256), m_rgb_diff_2(256), m_rgb_diff_3(256), m_rgb_diff_4(256),
63     m_rgb_diff_5(256)
64 {}
65 
66 // COMPRESSOR
67 
Rgb10Compressor(encoders::arithmetic<OutCbStream> & encoder)68 Rgb10Compressor::Rgb10Compressor(encoders::arithmetic<OutCbStream>& encoder) : enc_(encoder)
69 {}
70 
compress(const char * buf)71 const char *Rgb10Compressor::compress(const char *buf)
72 {
73     las::rgb this_val(buf);
74 
75     if (!have_last_) {
76         // don't have the first data yet, just push it to our
77         // have last stuff and move on
78         have_last_ = true;
79         last = this_val;
80 
81         enc_.getOutStream().putBytes((const unsigned char*)buf, sizeof(las::rgb));
82         return buf + sizeof(las::rgb);
83     }
84 
85     // compress color
86     int diff_l = 0;
87     int diff_h = 0;
88     int corr;
89 
90     unsigned int sym = detail::color_diff_bits(this_val, last);
91 
92     enc_.encodeSymbol(m_byte_used, sym);
93 
94     // high and low R
95     if (sym & (1 << 0))
96     {
97         diff_l = (this_val.r & 0xFF) - (last.r & 0xFF);
98         enc_.encodeSymbol(m_rgb_diff_0, uint8_t(diff_l));
99     }
100     if (sym & (1 << 1))
101     {
102         diff_h = static_cast<int>(this_val.r >> 8) - (last.r >> 8);
103         enc_.encodeSymbol(m_rgb_diff_1, uint8_t(diff_h));
104     }
105 
106     if (sym & (1 << 6))
107     {
108         if (sym & (1 << 2))
109         {
110             corr = static_cast<int>(this_val.g & 0xFF) -
111                 utils::clamp<uint8_t>(diff_l + (last.g & 0xFF));
112             enc_.encodeSymbol(m_rgb_diff_2, uint8_t(corr));
113         }
114 
115         if (sym & (1 << 4))
116         {
117             diff_l = (diff_l + (this_val.g & 0xFF) - (last.g & 0xFF)) / 2;
118             corr = static_cast<int>(this_val.b & 0xFF) -
119                 utils::clamp<uint8_t>(diff_l + (last.b & 0xFF));
120             enc_.encodeSymbol(m_rgb_diff_4, uint8_t(corr));
121         }
122 
123         if (sym & (1 << 3))
124         {
125             corr = static_cast<int>(this_val.g >> 8) -
126                 utils::clamp<uint8_t>(diff_h + (last.g >> 8));
127             enc_.encodeSymbol(m_rgb_diff_3, uint8_t(corr));
128         }
129 
130         if (sym & (1 << 5))
131         {
132             diff_h = (diff_h + ((this_val.g >> 8)) - (last.g >> 8)) / 2;
133             corr = static_cast<int>(this_val.b >> 8) -
134                 utils::clamp<uint8_t>(diff_h + (last.b >> 8));
135             enc_.encodeSymbol(m_rgb_diff_5, uint8_t(corr));
136         }
137     }
138 
139     last = this_val;
140     return buf + sizeof(las::rgb);
141 }
142 
143 // DECOMPRESSOR
144 
Rgb10Decompressor(decoders::arithmetic<InCbStream> & decoder)145 Rgb10Decompressor::Rgb10Decompressor(decoders::arithmetic<InCbStream>& decoder) : dec_(decoder)
146 {}
147 
decompress(char * buf)148 char *Rgb10Decompressor::decompress(char *buf)
149 {
150     if (!have_last_) {
151         // don't have the first data yet, read the whole point out of the stream
152         have_last_ = true;
153 
154         dec_.getInStream().getBytes((unsigned char*)buf, sizeof(las::rgb));
155 
156         last.unpack(buf);
157         return buf + sizeof(las::rgb);
158     }
159 
160     unsigned char corr;
161     int diff = 0;
162     unsigned int sym = dec_.decodeSymbol(m_byte_used);
163 
164     las::rgb this_val;
165 
166     if (sym & (1 << 0))
167     {
168         corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_0));
169         this_val.r = static_cast<unsigned short>(uint8_t(corr + (last.r & 0xFF)));
170     }
171     else
172     {
173         this_val.r = last.r & 0xFF;
174     }
175 
176     if (sym & (1 << 1))
177     {
178         corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_1));
179         this_val.r |= (static_cast<unsigned short>(uint8_t(corr + (last.r >> 8))) << 8);
180     }
181     else
182     {
183         this_val.r |= last.r & 0xFF00;
184     }
185 
186     if (sym & (1 << 6))
187     {
188         diff = (this_val.r & 0xFF) - (last.r & 0xFF);
189 
190         if (sym & (1 << 2))
191         {
192             corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_2));
193             this_val.g = static_cast<unsigned short>(uint8_t(corr +
194                 utils::clamp<uint8_t>(diff + (last.g & 0xFF))));
195         }
196         else
197         {
198             this_val.g = last.g & 0xFF;
199         }
200 
201         if (sym & (1 << 4))
202         {
203             corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_4));
204             diff = (diff + (this_val.g & 0xFF) - (last.g & 0xFF)) / 2;
205             this_val.b = static_cast<unsigned short>(uint8_t(corr +
206                 utils::clamp<uint8_t>(diff + (last.b & 0xFF))));
207         }
208         else
209         {
210             this_val.b = last.b & 0xFF;
211         }
212 
213         diff = (this_val.r >> 8) - (last.r >> 8);
214         if (sym & (1 << 3))
215         {
216             corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_3));
217             this_val.g |= static_cast<unsigned short>(uint8_t(corr +
218                 utils::clamp<uint8_t>(diff + (last.g >> 8)))) << 8;
219         }
220         else {
221             this_val.g |= last.g & 0xFF00;
222         }
223 
224         if (sym & (1 << 5))
225         {
226             corr = static_cast<unsigned char>(dec_.decodeSymbol(m_rgb_diff_5));
227             diff = (diff + (this_val.g >> 8) - (last.g >> 8)) / 2;
228 
229             this_val.b |= static_cast<unsigned short>(uint8_t(corr +
230                 utils::clamp<uint8_t>(diff + (last.b >> 8)))) << 8;
231         }
232         else {
233             this_val.b |= (last.b & 0xFF00);
234         }
235     }
236     else
237     {
238         this_val.g = this_val.r;
239         this_val.b = this_val.r;
240     }
241 
242     last = this_val;
243     last.pack(buf);
244     return buf + sizeof(las::rgb);
245 }
246 
247 } // namespace detail
248 } // namespace lazperf
249