1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 05:34:47 +01:00

Added support for pseudo-NT IMG maps (e.g. TopoHispania)

This commit is contained in:
Martin Tůma 2019-09-05 22:31:13 +02:00
parent fcaacb4b6a
commit 37a0eec48f
14 changed files with 116 additions and 85 deletions

View File

@ -9,7 +9,7 @@
#define CHECK(condition) \
if (!(condition)) { \
_errorString = "Invalid/corrupted IMG file"; \
_errorString = "Unsupported or invalid IMG file"; \
return; \
}
@ -85,11 +85,6 @@ IMG::IMG(const QString &fileName)
&& read(type, sizeof(type)) && readValue(size) && readValue(part));
SubFile::Type tt = SubFile::type(type);
if (tt == SubFile::GMP) {
_errorString = "NT maps not supported";
return;
}
QString fn(QByteArray(name, sizeof(name)));
if (SubFile::isTileFile(tt)) {
VectorTile *tile;
@ -101,7 +96,7 @@ IMG::IMG(const QString &fileName)
tile = *it;
SubFile *file = part ? tile->file(tt)
: tile->addFile(this, tt, size);
: tile->addFile(this, tt);
CHECK(file);
_file.seek(offset + 0x20);
@ -114,7 +109,7 @@ IMG::IMG(const QString &fileName)
} else if (tt == SubFile::TYP) {
SubFile *typ = 0;
if (typFile.isNull()) {
_typ = new SubFile(this, size);
_typ = new SubFile(this);
typ = _typ;
typFile = fn;
} else if (fn == typFile)
@ -166,7 +161,7 @@ void IMG::load()
{
Q_ASSERT(!_style);
if (_typ && _typ->isValid())
if (_typ)
_style = new Style(_typ);
else {
QFile typFile(ProgramPaths::typFile());

View File

@ -56,11 +56,11 @@ bool LBLFile::init()
quint16 codepage;
quint8 multiplier, poiMultiplier;
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readByte(hdl, multiplier)
&& readByte(hdl, _encoding) && seek(hdl, 0x57)
&& readByte(hdl, _encoding) && seek(hdl, _gmpOffset + 0x57)
&& readUInt32(hdl, _poiOffset) && readUInt32(hdl, _poiSize)
&& readByte(hdl, poiMultiplier) && seek(hdl, 0xAA)
&& readByte(hdl, poiMultiplier) && seek(hdl, _gmpOffset + 0xAA)
&& readUInt16(hdl, codepage)))
return false;

View File

@ -9,9 +9,12 @@ class QTextCodec;
class LBLFile : public SubFile
{
public:
LBLFile(IMG *img, quint32 size)
: SubFile(img, size), _codec(0), _offset(0), _size(0), _poiOffset(0),
LBLFile(IMG *img)
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
Label label(Handle &hdl, quint32 offset, bool poi = false);

View File

@ -5,7 +5,7 @@ bool NETFile::init()
Handle hdl;
quint8 multiplier;
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
if (!(seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readByte(hdl, multiplier)))
return false;

View File

@ -6,8 +6,9 @@
class NETFile : public SubFile
{
public:
NETFile(IMG *img, quint32 size)
: SubFile(img, size), _offset(0), _size(0), _multiplier(0) {}
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _multiplier(0) {}
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
_offset(0), _size(0), _multiplier(0) {}
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);

View File

@ -85,17 +85,31 @@ bool RGNFile::BitStream::finish()
bool RGNFile::init()
{
Handle hdl;
quint16 hdrLen;
if (!(seek(hdl, 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size) && readUInt32(hdl, _polygonsOffset)
&& readUInt32(hdl, _polygonsSize) && seek(hdl, 0x39)
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
&& seek(hdl, 0x55) && readUInt32(hdl, _pointsOffset)
&& readUInt32(hdl, _pointsSize)))
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size)))
return false;
if (_offset + _size > size())
if (hdrLen >= 0x5D) {
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
&& seek(hdl, _gmpOffset + 0x39) && readUInt32(hdl, _linesOffset)
&& readUInt32(hdl, _linesSize) && seek(hdl, _gmpOffset + 0x55)
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)))
return false;
}
if (hdrLen >= 0x7D) {
quint32 dictOffset, dictSize;
if (!(seek(hdl, _gmpOffset + 0x71) && readUInt32(hdl, dictOffset)
&& readUInt32(hdl, dictSize)))
return false;
if (dictSize || dictOffset) {
qWarning("%s: NT compression not supported", qPrintable(fileName()));
return false;
}
}
return true;
}
@ -404,9 +418,6 @@ void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
{
Handle rgnHdl, lblHdl, netHdl;
if (!_size && !init())
return;
QVector<RGNFile::Segment> seg(segments(rgnHdl, subdiv));
for (int i = 0; i < seg.size(); i++) {
switch (seg.at(i).type()) {
@ -436,9 +447,6 @@ void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
{
Handle rgnHdl, lblHdl;
if (!_size && !init())
return;
if (polygons && subdiv->polygonsOffset() != subdiv->polygonsEnd()) {
quint32 start = _polygonsOffset + subdiv->polygonsOffset();
quint32 end = subdiv->polygonsEnd()

View File

@ -11,10 +11,15 @@ class NETFile;
class RGNFile : public SubFile
{
public:
RGNFile(IMG *img, quint32 size)
: SubFile(img, size), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(), _linesOffset(), _linesSize(), _pointsOffset(),
_pointsSize() {}
RGNFile(IMG *img)
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
_pointsSize(0) {}
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
_linesSize(0), _pointsOffset(0), _pointsSize(0) {}
bool init();
void objects(const RectC &rect, const SubDiv *subdiv, LBLFile *lbl,
NETFile *net, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
@ -73,7 +78,6 @@ private:
static bool sign(BitStream &bs, int &val);
static int bitSize(quint8 baseSize, bool variableSign, bool extraBit);
bool init();
QVector<Segment> segments(Handle &hdl, const SubDiv *subdiv) const;
bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,

View File

@ -942,7 +942,7 @@ Style::Style(SubFile *typ)
defaultPolygonStyle();
defaultPointStyle();
if (typ && typ->isValid())
if (typ)
parseTYPFile(typ);
}

View File

@ -20,21 +20,13 @@ SubFile::Type SubFile::type(const char str[3])
return Unknown;
}
SubFile::SubFile(QFile *file) : _img(0), _file(file), _size(0)
SubFile::SubFile(QFile *file) :_gmpOffset(0), _img(0), _file(file), _blocks(0)
{
if (!_file->open(QIODevice::ReadOnly))
qWarning("Error opening %s: %s", qPrintable(_file->fileName()),
qPrintable(_file->errorString()));
}
bool SubFile::isValid() const
{
return _file
? _file->isOpen()
: ((quint32)_img->blockSize() * (quint32)_blocks.size() - _size
< (quint32)_img->blockSize());
}
bool SubFile::seek(Handle &handle, quint32 pos) const
{
Q_ASSERT(_img || _file);
@ -46,9 +38,9 @@ bool SubFile::seek(Handle &handle, quint32 pos) const
int blockNum = pos / blockSize;
if (handle.blockNum != blockNum) {
if (blockNum >= _blocks.size())
if (blockNum >= _blocks->size())
return false;
if (!_img->readBlock(_blocks.at(blockNum), handle.data))
if (!_img->readBlock(_blocks->at(blockNum), handle.data))
return false;
handle.blockNum = blockNum;
}
@ -74,11 +66,6 @@ bool SubFile::readByte(Handle &handle, quint8 &val) const
}
}
quint32 SubFile::size() const
{
return _file ? (quint32)_file->size() : _size;
}
QString SubFile::fileName() const
{
return _file ? _file->fileName() : _img->fileName();
@ -88,15 +75,15 @@ QString SubFile::fileName() const
QDebug operator<<(QDebug dbg, const SubFile &file)
{
bool continuous = true;
for (int i = 1; i < file._blocks.size(); i++) {
if (file._blocks.at(i) != file._blocks.at(i-1) + 1) {
for (int i = 1; i < file._blocks->size(); i++) {
if (file._blocks->at(i) != file._blocks->at(i-1) + 1) {
continuous = false;
break;
}
}
dbg.nospace() << "SubFile(" << file._size << ", " << file._blocks.size()
<< ", " << continuous << ")";
dbg.nospace() << "SubFile(" << file._blocks->size() << ", "
<< continuous << ")";
return dbg.space();
}
#endif // QT_NO_DEBUG

View File

@ -22,13 +22,14 @@ public:
int pos;
};
SubFile(IMG *img, quint32 size) : _img(img), _file(0), _size(size) {}
SubFile(IMG *img) : _gmpOffset(0), _img(img), _file(0),
_blocks(&_blockData) {}
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
_file(0), _blocks(&(gmp->_blockData)) {}
SubFile(QFile *file);
void addBlock(quint16 block) {_blocks.append(block);}
bool isValid() const;
void addBlock(quint16 block) {_blocks->append(block);}
quint32 size() const;
bool seek(Handle &handle, quint32 pos) const;
bool readByte(Handle &handle, quint8 &val) const;
@ -80,20 +81,26 @@ public:
return true;
}
quint16 offset() const {return _blocks.first();}
quint16 offset() const {return _blocks->first();}
QString fileName() const;
static Type type(const char str[3]);
static bool isTileFile(Type type)
{return (type == TRE || type == LBL || type == RGN || type == NET);}
{
return (type == TRE || type == LBL || type == RGN || type == NET
|| type == GMP);
}
friend QDebug operator<<(QDebug dbg, const SubFile &file);
protected:
quint32 _gmpOffset;
private:
IMG *_img;
QFile *_file;
quint32 _size;
QVector<quint16> _blocks;
QVector<quint16> *_blocks;
QVector<quint16> _blockData;
};
#ifndef QT_NO_DEBUG

View File

@ -43,28 +43,28 @@ bool TREFile::init()
quint8 locked;
quint16 hdrLen;
if (!(seek(hdl, 0) && readUInt16(hdl, hdrLen)
&& seek(hdl, 0x0D) && readByte(hdl, locked)))
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x0D) && readByte(hdl, locked)))
return false;
// Tile bounds
qint32 north, east, south, west;
if (!(seek(hdl, 0x15) && readInt24(hdl, north) && readInt24(hdl, east)
&& readInt24(hdl, south) && readInt24(hdl, west)))
if (!(seek(hdl, _gmpOffset + 0x15) && readInt24(hdl, north)
&& readInt24(hdl, east) && readInt24(hdl, south) && readInt24(hdl, west)))
return false;
_bounds = RectC(Coordinates(toWGS84(west), toWGS84(north)),
Coordinates(toWGS84(east), toWGS84(south)));
// Levels & subdivs info
quint32 levelsOffset, levelsSize, subdivSize;
if (!(seek(hdl, 0x21) && readUInt32(hdl, levelsOffset)
if (!(seek(hdl, _gmpOffset + 0x21) && readUInt32(hdl, levelsOffset)
&& readUInt32(hdl, levelsSize) && readUInt32(hdl, _subdivOffset)
&& readUInt32(hdl, subdivSize)))
return false;
// TRE7 info
if (hdrLen > 0x9A) {
if (!(seek(hdl, 0x7C) && readUInt32(hdl, _extended.offset)
if (!(seek(hdl, _gmpOffset + 0x7C) && readUInt32(hdl, _extended.offset)
&& readUInt32(hdl, _extended.size)
&& readUInt16(hdl, _extended.itemSize)))
return false;
@ -80,7 +80,7 @@ bool TREFile::init()
if (locked) {
quint32 key;
quint8 unlocked[64];
if (!seek(hdl, 0xAA) || !readUInt32(hdl, key))
if (!seek(hdl, _gmpOffset + 0xAA) || !readUInt32(hdl, key))
return false;
unlock(unlocked, levels, levelsSize, key);
memcpy(levels, unlocked, levelsSize);

View File

@ -13,7 +13,8 @@ class SubDiv;
class TREFile : public SubFile
{
public:
TREFile(IMG *img, quint32 size) : SubFile(img, size) {}
TREFile(IMG *img) : SubFile(img) {}
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
~TREFile();
bool init();

View File

@ -11,26 +11,31 @@ SubFile *VectorTile::file(SubFile::Type type)
return _lbl;
case SubFile::NET:
return _net;
case SubFile::GMP:
return _gmp;
default:
return 0;
}
}
SubFile *VectorTile::addFile(IMG *img, SubFile::Type type, quint32 size)
SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
{
switch (type) {
case SubFile::TRE:
_tre = new TREFile(img, size);
_tre = new TREFile(img);
return _tre;
case SubFile::RGN:
_rgn = new RGNFile(img, size);
_rgn = new RGNFile(img);
return _rgn;
case SubFile::LBL:
_lbl = new LBLFile(img, size);
_lbl = new LBLFile(img);
return _lbl;
case SubFile::NET:
_net = new NETFile(img, size);
_net = new NETFile(img);
return _net;
case SubFile::GMP:
_gmp = new SubFile(img);
return _gmp;
default:
return 0;
}
@ -38,14 +43,30 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type, quint32 size)
bool VectorTile::init()
{
if (!(_tre && _tre->isValid() && _tre->init() && _rgn
&& _rgn->isValid()))
if (_gmp && !initGMP())
return false;
if (_lbl && !_lbl->isValid())
if (!(_tre && _tre->init() && _rgn && _rgn->init()))
return false;
if (_net && !_net->isValid())
return true;
}
bool VectorTile::initGMP()
{
SubFile::Handle hdl;
quint32 tre, rgn, lbl, net;
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
&& _gmp->readUInt32(hdl, rgn) && _gmp->readUInt32(hdl, lbl)
&& _gmp->readUInt32(hdl, net)))
return false;
_tre = new TREFile(_gmp, tre);
_rgn = new RGNFile(_gmp, rgn);
_lbl = new LBLFile(_gmp, lbl);
_net = new NETFile(_gmp, net);
return true;
}

View File

@ -10,8 +10,9 @@
class VectorTile {
public:
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0) {}
~VectorTile() {delete _tre; delete _rgn; delete _lbl; delete _net;}
VectorTile() : _tre(0), _rgn(0), _lbl(0), _net(0), _gmp(0) {}
~VectorTile()
{delete _tre; delete _rgn; delete _lbl; delete _net; delete _gmp;}
bool init();
void clear() {_tre->clear();}
@ -19,7 +20,7 @@ public:
const RectC &bounds() const {return _tre->bounds();}
SubFile *file(SubFile::Type type);
SubFile *addFile(IMG *img, SubFile::Type type, quint32 size);
SubFile *addFile(IMG *img, SubFile::Type type);
void objects(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points) const;
@ -27,10 +28,13 @@ public:
friend QDebug operator<<(QDebug dbg, const VectorTile &tile);
private:
bool initGMP();
TREFile *_tre;
RGNFile *_rgn;
LBLFile *_lbl;
NETFile *_net;
SubFile *_gmp;
};
#ifndef QT_NO_DEBUG