1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-12 14:20:48 +01:00
GPXSee/src/map/IMG/huffmantable.cpp

100 lines
2.2 KiB
C++
Raw Normal View History

#include "common/garmin.h"
#include "huffmantable.h"
2021-09-20 21:43:17 +02:00
using namespace Garmin;
2021-04-10 15:27:40 +02:00
using namespace IMG;
static inline quint32 readVUint32(const quint8 *buffer, quint32 bytes)
{
quint32 val = 0;
2021-10-22 22:04:46 +02:00
for (quint32 i = 0; i < bytes; i++)
val |= ((quint32)*(buffer + i)) << (i * 8);
return val;
}
bool HuffmanTable::load(const RGNFile *rgn, SubFile::Handle &rgnHdl)
{
if (!_buffer.load(rgn, rgnHdl))
return false;
2021-10-22 22:04:46 +02:00
_aclBits = (quint8)_buffer.at(0) & 0x0F;
_huffman = (quint8)_buffer.at(0) & 0x10;
_symBits = (quint8)_buffer.at(1);
_symBytes = bs(_symBits);
_bsrchEntries = (quint8)_buffer.at(2);
_symbolBits = (quint8)_buffer.at(3);
_symbolBytes = bs(_symbolBits);
_aclEntryBytes = _symbolBytes + 1;
_indexBytes = vs(_buffer.at(4));
_bsrchEntryBytes = _symBytes + _indexBytes + 1;
2021-10-23 17:28:06 +02:00
_bsrchTable = (const quint8*)(_buffer.constData()) + 4 + _indexBytes;
2021-10-22 22:04:46 +02:00
_aclTable = _bsrchTable + _bsrchEntryBytes * _bsrchEntries;
_huffmanTable = _aclTable + (_aclEntryBytes << _aclBits);
return (_symBits <= 32 && _symbolBits <= 32 && _symbolBits >= 8);
}
quint32 HuffmanTable::symbol(quint32 data, quint8 &size) const
{
2021-10-22 22:04:46 +02:00
quint32 lo, hi;
2021-10-23 17:28:06 +02:00
const quint8 *tp;
2021-10-22 22:04:46 +02:00
if (!_aclBits) {
hi = _bsrchEntries - 1;
lo = 0;
} else {
2021-10-22 22:04:46 +02:00
quint32 offset = _aclEntryBytes * (data >> (32 - _aclBits));
tp = _aclTable + offset;
2021-10-22 22:04:46 +02:00
if (*tp & 1) {
size = *tp >> 1;
2021-10-22 22:04:46 +02:00
return readVUint32(tp + 1, _symbolBytes);;
}
2021-10-22 22:04:46 +02:00
lo = *tp >> 1;
hi = *(tp + 1);
}
2021-10-22 22:04:46 +02:00
tp = _bsrchTable + (lo * _bsrchEntryBytes);
data >>= 32 - _symBits;
2021-10-22 22:04:46 +02:00
while (lo < hi) {
2021-10-23 17:28:06 +02:00
const quint8 *prev = tp;
2021-10-22 22:04:46 +02:00
quint32 m = (lo + 1 + hi) >> 1;
tp = _bsrchTable + (m * _bsrchEntryBytes);
quint32 nd = readVUint32(tp, _symBytes);
if (data <= nd) {
if (data == nd)
2021-10-22 22:04:46 +02:00
lo = m;
else
tp = prev;
2021-10-22 22:04:46 +02:00
hi = m - (data < nd);
m = lo;
}
2021-10-22 22:04:46 +02:00
lo = m;
}
2021-10-22 22:04:46 +02:00
quint32 i = readVUint32(tp, _symBytes);
tp = tp + _symBytes;
size = *tp;
2021-10-22 22:04:46 +02:00
if (!_huffman)
return readVUint32(tp + 1, _symbolBytes);
else {
2021-10-22 22:04:46 +02:00
quint32 bi = readVUint32(tp + 1, _indexBytes);
quint32 ci = (data - i) >> (_symBits - size);
quint32 si = (ci + bi) * _symbolBits;
quint32 sbi = si & 7;
quint32 shift = 8 - sbi;
tp = _huffmanTable + (si >> 3);
quint32 val = readVUint32(tp + 1, bs(_symbolBits - shift));
2021-10-22 22:04:46 +02:00
return (val << shift) | (*tp >> sbi);
2021-10-22 22:04:46 +02:00
}
}