pointcloud/lib/lazperf_adapter.cpp
2017-03-14 14:36:39 +01:00

264 lines
5.6 KiB
C++

/***********************************************************************
* lazperf_adapter.cpp
*
* LazPerf compression/decompression
*
* Copyright (c) 2016 Paul Blottiere, Oslandia
*
***********************************************************************/
#include "lazperf_adapter.hpp"
#ifdef HAVE_LAZPERF
/**********************************************************************
* C API
*/
size_t
lazperf_compress_from_uncompressed(const PCPATCH_UNCOMPRESSED *pa, uint8_t **compressed)
{
size_t size = 1;
LazPerfBuf buf;
LazPerfCompressor engine(pa->schema, buf);
if (engine.compress(pa->data, pa->datasize) == pa->npoints)
{
size = buf.buf.size();
*compressed = (uint8_t*) malloc(size);
*compressed = (uint8_t*) memcpy(*compressed, buf.data(), size);
}
// log
// lazperf_dump(pa);
// lazperf_dump(*compressed, size);
return size;
}
size_t
lazperf_uncompress_from_compressed(const PCPATCH_LAZPERF *pa, uint8_t **decompressed)
{
size_t size = -1;
size_t datasize = pa->schema->size * pa->npoints;
LazPerfBuf buf;
buf.putBytes(pa->lazperf, pa->lazperfsize);
LazPerfDecompressor engine(pa->schema, buf);
*decompressed = (uint8_t*) malloc(datasize);
if (engine.decompress(*decompressed, datasize) == pa->npoints)
size = buf.buf.size();
// log
// lazperf_dump(pa);
// lazperf_dump(*decompressed, datasize);
return size;
}
/**********************************************************************
* INTERNAL CPP
*/
// utility functions
void
lazperf_dump(uint8_t *data, const size_t size)
{
std::cout << "DUMP DATA: " << std::endl;
std::cout << " - datasize: " << size << std::endl;
std::cout << " - data: ";
for (int i = 0; i < size; ++i)
printf("%02x ", data[i]);
std::cout << std::endl;
}
void
lazperf_dump(const PCPATCH_UNCOMPRESSED* p)
{
std::cout << std::endl;
std::cout << "DUMP UNCOMPRESSED PATCH: " << std::endl;
std::cout << " - type: " << p->type << std::endl;
std::cout << " - schema->size " << p->schema->size << std::endl;
std::cout << " - readonly: " << p->readonly << std::endl;
std::cout << " - npoints: " << p->npoints << std::endl;
std::cout << " - maxpoints: " << p->maxpoints << std::endl;
std::cout << " - datasize: " << p->datasize << std::endl;
std::cout << " - data: ";
for (int i = 0; i < p->datasize; ++i)
printf("%02x ", p->data[i]);
std::cout << std::endl;
}
void
lazperf_dump(const PCPATCH_LAZPERF* p)
{
std::cout << std::endl;
std::cout << "DUMP LAZPERF PATCH: " << std::endl;
std::cout << " - type: " << p->type << std::endl;
std::cout << " - schema->size " << p->schema->size << std::endl;
std::cout << " - readonly: " << p->readonly << std::endl;
std::cout << " - npoints: " << p->npoints << std::endl;
std::cout << " - lazperfsize: " << p->lazperfsize << std::endl;
std::cout << " - lazperf: ";
for (int i = 0; i < p->lazperfsize; ++i)
printf("%02x ", p->lazperf[i]);
std::cout << std::endl;
}
// LazPerf class
template<typename LazPerfEngine, typename LazPerfCoder>
LazPerf<LazPerfEngine, LazPerfCoder>::LazPerf(const PCSCHEMA *pcschema, LazPerfBuf &buf)
: _pcschema(pcschema)
, _coder(buf)
, _pointsize(0)
{
}
template<typename LazPerfEngine, typename LazPerfCoder>
LazPerf<LazPerfEngine, LazPerfCoder>::~LazPerf()
{
}
template<typename LazPerfEngine, typename LazPerfCoder>
void
LazPerf<LazPerfEngine, LazPerfCoder>::initSchema()
{
for (int i = 0; i < _pcschema->ndims; i++)
addField(_pcschema->dims[i]);
}
template<typename LazPerfEngine, typename LazPerfCoder>
bool
LazPerf<LazPerfEngine, LazPerfCoder>::addField(const PCDIMENSION *dim)
{
bool rc = true;
switch(dim->interpretation)
{
case PC_INT8:
{
_engine->template add_field<I8>();
break;
}
case PC_UINT8:
{
_engine->template add_field<U8>();
break;
}
case PC_INT16:
{
_engine->template add_field<I16>();
break;
}
case PC_UINT16:
{
_engine->template add_field<U16>();
break;
}
case PC_INT32:
{
_engine->template add_field<I32>();
break;
}
case PC_UINT32:
{
_engine->template add_field<U32>();
break;
}
case PC_INT64:
{
_engine->template add_field<I32>();
_engine->template add_field<I32>();
break;
}
case PC_UINT64:
{
_engine->template add_field<U32>();
_engine->template add_field<U32>();
break;
}
case PC_DOUBLE:
{
_engine->template add_field<U32>();
_engine->template add_field<U32>();
break;
}
case PC_FLOAT:
{
_engine->template add_field<I32>();
break;
}
case PC_UNKNOWN:
default:
rc = false;
}
if (rc)
_pointsize += dim->size;
return rc;
}
// LazPerf Compressor
LazPerfCompressor::LazPerfCompressor(const PCSCHEMA *pcschema, LazPerfBuf &output)
: LazPerf(pcschema, output)
{
_engine = laszip::formats::make_dynamic_compressor(_coder);
initSchema();
}
LazPerfCompressor::~LazPerfCompressor()
{
}
size_t
LazPerfCompressor::compress(const uint8_t *input, const size_t inputsize)
{
size_t size = 0;
const uint8_t *end = input + inputsize;
while (input + _pointsize <= end)
{
_engine->compress((const char*) input);
input += _pointsize;
size++;
}
_coder.done();
return size;
}
// LazPerf Decompressor
LazPerfDecompressor::LazPerfDecompressor(const PCSCHEMA *pcschema, LazPerfBuf &input)
: LazPerf(pcschema, input)
{
_engine = laszip::formats::make_dynamic_decompressor(_coder);
initSchema();
}
LazPerfDecompressor::~LazPerfDecompressor()
{
}
size_t
LazPerfDecompressor::decompress(uint8_t *output, const size_t outputsize)
{
size_t size = 0;
const uint8_t *end = output + outputsize;
while (output + _pointsize <= end)
{
_engine->decompress((char*) output);
output += _pointsize;
size++;
}
return size;
}
#endif // HAVE_LAZPERF