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