mirror of
https://github.com/qgis/QGIS.git
synced 2025-02-23 00:02:38 -05:00
226 lines
5.5 KiB
C++
226 lines
5.5 KiB
C++
/*
|
|
===============================================================================
|
|
|
|
FILE: decompressor.hpp
|
|
|
|
CONTENTS:
|
|
Integer decompressor
|
|
|
|
PROGRAMMERS:
|
|
|
|
martin.isenburg@rapidlasso.com - http://rapidlasso.com
|
|
uday.karan@gmail.com - Hobu, Inc.
|
|
|
|
COPYRIGHT:
|
|
|
|
(c) 2007-2014, martin isenburg, rapidlasso - tools to catch reality
|
|
(c) 2014, Uday Verma, Hobu, Inc.
|
|
|
|
This is free software; you can redistribute and/or modify it under the
|
|
terms of the Apache Public License 2.0 published by the Apache Software
|
|
Foundation. See the COPYING file for more information.
|
|
|
|
This software is distributed WITHOUT ANY WARRANTY and without even the
|
|
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
CHANGE HISTORY:
|
|
|
|
===============================================================================
|
|
*/
|
|
|
|
|
|
#ifndef __decompressor_hpp__
|
|
#define __decompressor_hpp__
|
|
|
|
#include "model.hpp"
|
|
|
|
#include <vector>
|
|
#include <memory>
|
|
#include <cassert>
|
|
|
|
namespace lazperf
|
|
{
|
|
namespace decompressors
|
|
{
|
|
struct integer {
|
|
integer(uint32_t bits = 16, uint32_t contexts = 1, uint32_t bits_high = 8, uint32_t range = 0):
|
|
bits(bits), contexts(contexts), bits_high(bits_high), range(range) {
|
|
if (range) { // the corrector's significant bits and range
|
|
corr_bits = 0;
|
|
corr_range = range;
|
|
while (range)
|
|
{
|
|
range = range >> 1;
|
|
corr_bits++;
|
|
}
|
|
if (corr_range == (1u << (corr_bits-1)))
|
|
{
|
|
corr_bits--;
|
|
}
|
|
// the corrector must fall into this interval
|
|
corr_min = -((int32_t)(corr_range/2));
|
|
corr_max = corr_min + corr_range - 1;
|
|
}
|
|
else if (bits && bits < 32) {
|
|
corr_bits = bits;
|
|
corr_range = 1u << bits;
|
|
// the corrector must fall into this interval
|
|
corr_min = -((int32_t)(corr_range/2));
|
|
corr_max = corr_min + corr_range - 1;
|
|
}
|
|
else {
|
|
corr_bits = 32;
|
|
corr_range = 0;
|
|
// the corrector must fall into this interval
|
|
corr_min = (std::numeric_limits<int32_t>::min)();
|
|
corr_max = (std::numeric_limits<int32_t>::max)();
|
|
}
|
|
|
|
k = 0;
|
|
}
|
|
|
|
void init() {
|
|
using models::arithmetic;
|
|
using models::arithmetic_bit;
|
|
|
|
uint32_t i;
|
|
|
|
// maybe create the models
|
|
if (mBits.empty()) {
|
|
for (i = 0; i < contexts; i++)
|
|
mBits.push_back(arithmetic(corr_bits+1));
|
|
|
|
#ifndef COMPRESS_ONLY_K
|
|
// mcorrector0 is already initialized
|
|
for (i = 1; i <= corr_bits; i++) {
|
|
uint32_t v = i <= bits_high ? 1 << i : 1 << bits_high;
|
|
mCorrector.push_back(arithmetic(v));
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
|
|
template<
|
|
typename TDecoder
|
|
>
|
|
int32_t decompress(TDecoder& dec, int32_t pred, uint32_t context) {
|
|
int32_t real = pred + readCorrector(dec, mBits[context]);
|
|
if (real < 0) real += corr_range;
|
|
else if ((uint32_t)(real) >= corr_range) real -= corr_range;
|
|
|
|
return real;
|
|
}
|
|
|
|
inline unsigned int getK() const { return k; }
|
|
|
|
template<
|
|
typename TDecoder,
|
|
typename TEntroyModel
|
|
>
|
|
int32_t readCorrector(TDecoder& dec, TEntroyModel& mBits) {
|
|
int32_t c;
|
|
|
|
// decode within which interval the corrector is falling
|
|
|
|
k = dec.decodeSymbol(mBits);
|
|
|
|
// decode the exact location of the corrector within the interval
|
|
|
|
#ifdef COMPRESS_ONLY_K
|
|
if (k) // then c is either smaller than 0 or bigger than 1
|
|
{
|
|
if (k < 32)
|
|
{
|
|
c = dec.readBits(k);
|
|
|
|
if (c >= (1<<(k-1))) // if c is in the interval [ 2^(k-1) ... + 2^k - 1 ]
|
|
{
|
|
// so we translate c back into the interval [ 2^(k-1) + 1 ... 2^k ] by adding 1
|
|
c += 1;
|
|
}
|
|
else // otherwise c is in the interval [ 0 ... + 2^(k-1) - 1 ]
|
|
{
|
|
// so we translate c back into the interval [ - (2^k - 1) ... - (2^(k-1)) ] by subtracting (2^k - 1)
|
|
c -= ((1<<k) - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
c = corr_min;
|
|
}
|
|
}
|
|
else // then c is either 0 or 1
|
|
{
|
|
c = dec.readBit();
|
|
}
|
|
#else // COMPRESS_ONLY_K
|
|
if (k) // then c is either smaller than 0 or bigger than 1
|
|
{
|
|
if (k < 32)
|
|
{
|
|
if (k <= bits_high) // for small k we can do this in one step
|
|
{
|
|
// decompress c with the range coder
|
|
c = dec.decodeSymbol(mCorrector[k-1]);
|
|
}
|
|
else
|
|
{
|
|
// for larger k we need to do this in two steps
|
|
int k1 = k-bits_high;
|
|
// decompress higher bits with table
|
|
c = dec.decodeSymbol(mCorrector[k-1]);
|
|
// read lower bits raw
|
|
int c1 = dec.readBits(k1);
|
|
// put the corrector back together
|
|
c = (c << k1) | c1;
|
|
}
|
|
// translate c back into its correct interval
|
|
if (c >= (1<<(k-1))) // if c is in the interval [ 2^(k-1) ... + 2^k - 1 ]
|
|
{
|
|
// so we translate c back into the interval [ 2^(k-1) + 1 ... 2^k ] by adding 1
|
|
c += 1;
|
|
}
|
|
else // otherwise c is in the interval [ 0 ... + 2^(k-1) - 1 ]
|
|
{
|
|
// so we translate c back into the interval [ - (2^k - 1) ... - (2^(k-1)) ] by subtracting (2^k - 1)
|
|
c -= ((1<<k) - 1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
c = corr_min;
|
|
}
|
|
}
|
|
else // then c is either 0 or 1
|
|
{
|
|
c = dec.decodeBit(mCorrector0);
|
|
}
|
|
#endif // COMPRESS_ONLY_K
|
|
|
|
return c;
|
|
}
|
|
|
|
uint32_t k;
|
|
|
|
uint32_t bits;
|
|
|
|
uint32_t contexts;
|
|
uint32_t bits_high;
|
|
uint32_t range;
|
|
|
|
uint32_t corr_bits;
|
|
uint32_t corr_range;
|
|
int32_t corr_min;
|
|
int32_t corr_max;
|
|
|
|
|
|
std::vector<models::arithmetic> mBits;
|
|
|
|
models::arithmetic_bit mCorrector0;
|
|
std::vector<models::arithmetic> mCorrector;
|
|
};
|
|
} // namespace decompressors
|
|
} // namespace lazperf
|
|
|
|
#endif // __decompressor_hpp__
|