1 /*
2 ===============================================================================
3 
4   FILE:  field_byte14.cpp
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 
Byte14Base(size_t count)38 Byte14Base::Byte14Base(size_t count) : count_(count), last_channel_(-1),
39     chan_ctxs_ { count_, count_, count_, count_ }
40 {}
41 
count() const42 size_t Byte14Base::count() const
43 {
44     return count_;
45 }
46 
47 // COMPRESSOR
48 
Byte14Compressor(OutCbStream & stream,size_t count)49 Byte14Compressor::Byte14Compressor(OutCbStream& stream, size_t count) :
50     Byte14Base(count), stream_(stream), valid_(count_),
51     byte_enc_(count, encoders::arithmetic<MemoryStream>(true))
52 {}
53 
writeSizes()54 void Byte14Compressor::writeSizes()
55 {
56     for (size_t i = 0; i < count_; ++i)
57     {
58         if (valid_[i])
59         {
60             byte_enc_[i].done();
61             stream_ << byte_enc_[i].num_encoded();
62         }
63         else
64             stream_ << (uint32_t)0;
65     }
66 }
67 
writeData()68 void Byte14Compressor::writeData()
69 {
70     int32_t total = 0;
71     for (size_t i = 0; i < count_; ++i)
72     {
73         if (valid_[i])
74         {
75             stream_.putBytes(byte_enc_[i].encoded_bytes(), byte_enc_[i].num_encoded());
76             total += utils::sum(byte_enc_[i].encoded_bytes(), byte_enc_[i].num_encoded());
77         }
78     }
79     LAZDEBUG(std::cerr << "BYTE      : " << total << "\n");
80 }
81 
compress(const char * buf,int & sc)82 const char *Byte14Compressor::compress(const char *buf, int& sc)
83 {
84     // don't have the first data yet, just push it to our
85     // have last stuff and move on
86     if (last_channel_ == -1)
87     {
88         ChannelCtx& c = chan_ctxs_[sc];
89         stream_.putBytes((const unsigned char *)buf, count_);
90         c.last_.assign(buf, buf + count_);
91         c.have_last_ = true;
92         last_channel_ = sc;
93         return buf + count_;
94     }
95     ChannelCtx& c = chan_ctxs_[sc];
96     las::byte14 *pLastBytes = &chan_ctxs_[last_channel_].last_;
97     if (!c.have_last_)
98     {
99         c.have_last_ = true;
100         c.last_ = *pLastBytes;
101         pLastBytes = &c.last_;
102     }
103     // This mess is because of the broken-ness of the handling for last in v3, where
104     // 'last_point' only gets updated on the first context switch in the LASzip code.
105     las::byte14& lastBytes = *pLastBytes;
106 
107     for (size_t i = 0; i < count_; ++i, ++buf)
108     {
109         int32_t diff = *(const uint8_t *)buf - lastBytes[i];
110         byte_enc_[i].encodeSymbol(c.byte_model_[i], (uint8_t)diff);
111         if (diff)
112         {
113             valid_[i] = true;
114             lastBytes[i] = *buf;
115         }
116     }
117 
118     last_channel_ = sc;
119     return buf + count_;
120 }
121 
122 // DECOMPRESSOR
123 
Byte14Decompressor(InCbStream & stream,size_t count)124 Byte14Decompressor::Byte14Decompressor(InCbStream& stream, size_t count) : Byte14Base(count),
125     stream_(stream), byte_cnt_(count_), byte_dec_(count_, decoders::arithmetic<MemoryStream>())
126 {}
127 
readSizes()128 void Byte14Decompressor::readSizes()
129 {
130     for (size_t i = 0; i < count_; ++i)
131         stream_ >> byte_cnt_[i];
132 }
133 
readData()134 void Byte14Decompressor::readData()
135 {
136     for (size_t i = 0; i < count_; ++i)
137         byte_dec_[i].initStream(stream_, byte_cnt_[i]);
138 }
139 
dumpSums()140 void Byte14Decompressor::dumpSums()
141 {
142     std::cout << "BYTE     : " << sumByte.value() << "\n";
143 }
144 
decompress(char * buf,int & sc)145 char *Byte14Decompressor::decompress(char *buf, int& sc)
146 {
147     if (last_channel_ == -1)
148     {
149         ChannelCtx& c = chan_ctxs_[sc];
150         stream_.getBytes((unsigned char *)buf, count_);
151         c.last_.assign(buf, buf + count_);
152         c.have_last_ = true;
153         last_channel_ = sc;
154         return buf + count_;
155     }
156 
157     ChannelCtx& c = chan_ctxs_[sc];
158     las::byte14 *pLastByte = &chan_ctxs_[last_channel_].last_;
159     if (sc != last_channel_)
160     {
161         last_channel_ = sc;
162         if (!c.have_last_)
163         {
164             c.have_last_ = true;
165             c.last_ = *pLastByte;
166             pLastByte = &chan_ctxs_[last_channel_].last_;
167         }
168     }
169     las::byte14& lastByte = *pLastByte;
170 
171     for (size_t i = 0; i < count_; ++i, buf++)
172     {
173         if (byte_cnt_[i])
174         {
175             *buf = lastByte[i] + byte_dec_[i].decodeSymbol(c.byte_model_[i]);
176             lastByte[i] = *buf;
177         }
178         else
179             *buf = lastByte[i];
180     }
181     LAZDEBUG(sumByte.add(lastByte.data(), count_));
182 
183     return buf;
184 }
185 
186 } // namespace detail
187 } // namespace lazperf
188