mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-02-26 04:00:49 +01:00
Added support for ozf2 files
This commit is contained in:
parent
75bd388be0
commit
ccf91bb29f
@ -91,7 +91,8 @@ HEADERS += src/config.h \
|
|||||||
src/latlon.h \
|
src/latlon.h \
|
||||||
src/utm.h \
|
src/utm.h \
|
||||||
src/lambertconic.h \
|
src/lambertconic.h \
|
||||||
src/ellipsoid.h
|
src/ellipsoid.h \
|
||||||
|
src/ozf.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/gui.cpp \
|
src/gui.cpp \
|
||||||
src/poi.cpp \
|
src/poi.cpp \
|
||||||
@ -156,7 +157,8 @@ SOURCES += src/main.cpp \
|
|||||||
src/transversemercator.cpp \
|
src/transversemercator.cpp \
|
||||||
src/utm.cpp \
|
src/utm.cpp \
|
||||||
src/lambertconic.cpp \
|
src/lambertconic.cpp \
|
||||||
src/ellipsoid.cpp
|
src/ellipsoid.cpp \
|
||||||
|
src/ozf.cpp
|
||||||
RESOURCES += gpxsee.qrc
|
RESOURCES += gpxsee.qrc
|
||||||
TRANSLATIONS = lang/gpxsee_cs.ts \
|
TRANSLATIONS = lang/gpxsee_cs.ts \
|
||||||
lang/gpxsee_sv.ts
|
lang/gpxsee_sv.ts
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "transversemercator.h"
|
#include "transversemercator.h"
|
||||||
#include "utm.h"
|
#include "utm.h"
|
||||||
#include "lambertconic.h"
|
#include "lambertconic.h"
|
||||||
|
#include "ozf.h"
|
||||||
#include "offlinemap.h"
|
#include "offlinemap.h"
|
||||||
|
|
||||||
|
|
||||||
@ -303,11 +304,16 @@ bool OfflineMap::getImageInfo(const QString &path)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_imgPath.endsWith("ozf2")) {
|
||||||
|
_ozf.load(_imgPath);
|
||||||
|
_size = _ozf.size();
|
||||||
|
} else {
|
||||||
QImageReader img(_imgPath);
|
QImageReader img(_imgPath);
|
||||||
_size = img.size();
|
_size = img.size();
|
||||||
|
}
|
||||||
if (!_size.isValid()) {
|
if (!_size.isValid()) {
|
||||||
qWarning("%s: %s: error reading map image", qPrintable(_name),
|
qWarning("%s: %s: error reading map image", qPrintable(_name),
|
||||||
qPrintable(ii.absoluteFilePath()));
|
qPrintable(_imgPath));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +525,7 @@ void OfflineMap::load()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_img && !_imgPath.isNull()) {
|
if (!_img && !_imgPath.isNull() && !_ozf.isOpen()) {
|
||||||
_img = new QImage(_imgPath);
|
_img = new QImage(_imgPath);
|
||||||
if (_img->isNull())
|
if (_img->isNull())
|
||||||
qWarning("%s: error loading map image", qPrintable(_imgPath));
|
qWarning("%s: error loading map image", qPrintable(_imgPath));
|
||||||
@ -567,6 +573,31 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect)
|
|||||||
painter->fillRect(QRectF(QPoint(x, y), _tileSize),
|
painter->fillRect(QRectF(QPoint(x, y), _tileSize),
|
||||||
Qt::white);
|
Qt::white);
|
||||||
} else
|
} else
|
||||||
|
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (_ozf.isOpen()) {
|
||||||
|
QPoint tl = QPoint((int)floor(rect.left()
|
||||||
|
/ (qreal)_ozf.tileSize().width()) * _ozf.tileSize().width(),
|
||||||
|
(int)floor(rect.top() / _ozf.tileSize().height())
|
||||||
|
* _ozf.tileSize().height());
|
||||||
|
|
||||||
|
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
|
||||||
|
for (int i = 0; i < ceil(s.width() / _ozf.tileSize().width()); i++) {
|
||||||
|
for (int j = 0; j < ceil(s.height() / _ozf.tileSize().height());
|
||||||
|
j++) {
|
||||||
|
int x = tl.x() + i * _ozf.tileSize().width();
|
||||||
|
int y = tl.y() + j * _ozf.tileSize().height();
|
||||||
|
|
||||||
|
QPixmap pixmap;
|
||||||
|
QString key = _ozf.fileName() + "/" + QString::number(x)
|
||||||
|
+ "_" + QString::number(y);
|
||||||
|
if (!QPixmapCache::find(key, &pixmap)) {
|
||||||
|
pixmap = _ozf.tile(x, y);
|
||||||
|
if (!pixmap.isNull())
|
||||||
|
QPixmapCache::insert(key, pixmap);
|
||||||
|
}
|
||||||
|
|
||||||
painter->drawPixmap(QPoint(x, y), pixmap);
|
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QTransform>
|
#include <QTransform>
|
||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "tar.h"
|
#include "tar.h"
|
||||||
|
#include "ozf.h"
|
||||||
#include "coordinates.h"
|
#include "coordinates.h"
|
||||||
#include "projection.h"
|
#include "projection.h"
|
||||||
|
|
||||||
@ -84,6 +85,7 @@ private:
|
|||||||
QTransform _transform, _inverted;
|
QTransform _transform, _inverted;
|
||||||
qreal _resolution;
|
qreal _resolution;
|
||||||
|
|
||||||
|
OZF _ozf;
|
||||||
Tar _tar;
|
Tar _tar;
|
||||||
QString _tarPath;
|
QString _tarPath;
|
||||||
QImage *_img;
|
QImage *_img;
|
||||||
|
149
src/ozf.cpp
Normal file
149
src/ozf.cpp
Normal file
@ -0,0 +1,149 @@
|
|||||||
|
#include <QtEndian>
|
||||||
|
#include <QFile>
|
||||||
|
#include "ozf.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define OZF2_MAGIC 0x7778
|
||||||
|
#define OZF2_SEPARATOR 0x77777777
|
||||||
|
|
||||||
|
template<class T> bool OZF::readValue(T &val)
|
||||||
|
{
|
||||||
|
T data;
|
||||||
|
|
||||||
|
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sizeof(T) > 1)
|
||||||
|
val = qFromLittleEndian(data);
|
||||||
|
else
|
||||||
|
val = data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OZF::readHeaders()
|
||||||
|
{
|
||||||
|
quint16 magic;
|
||||||
|
quint32 separator;
|
||||||
|
|
||||||
|
if (!readValue(magic) || magic != OZF2_MAGIC) {
|
||||||
|
qWarning("%s: not a OZF2 file", qPrintable(_file.fileName()));
|
||||||
|
_file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_file.seek(_file.pos() + 52))
|
||||||
|
return false;
|
||||||
|
if (!readValue(separator))
|
||||||
|
return false;
|
||||||
|
if (separator != OZF2_SEPARATOR)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OZF::readTileTable()
|
||||||
|
{
|
||||||
|
quint32 offset, bgr0, w, h;
|
||||||
|
quint16 x, y;
|
||||||
|
|
||||||
|
|
||||||
|
if (!_file.seek(_file.size() - 4))
|
||||||
|
return false;
|
||||||
|
// table offset
|
||||||
|
if (!readValue(offset))
|
||||||
|
return false;
|
||||||
|
if (!_file.seek(offset))
|
||||||
|
return false;
|
||||||
|
// tiles offset (zoom level 0)
|
||||||
|
if (!readValue(offset))
|
||||||
|
return false;
|
||||||
|
if (!_file.seek(offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!readValue(w))
|
||||||
|
return false;
|
||||||
|
if (!readValue(h))
|
||||||
|
return false;
|
||||||
|
if (!readValue(x))
|
||||||
|
return false;
|
||||||
|
if (!readValue(y))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_size = QSize(w, h);
|
||||||
|
_dim = QSize(x, y);
|
||||||
|
|
||||||
|
_palette = QVector<quint32>(256);
|
||||||
|
for (int i = 0; i < _palette.size(); i++) {
|
||||||
|
if (!readValue(bgr0))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
quint32 b = (bgr0 & 0x000000FF);
|
||||||
|
quint32 g = (bgr0 & 0x0000FF00) >> 8;
|
||||||
|
quint32 r = (bgr0 & 0x00FF0000) >> 16;
|
||||||
|
quint32 argb = 0xFF000000 | r << 16 | g << 8 | b;
|
||||||
|
|
||||||
|
_palette[i] = argb;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tiles = QVector<quint32>(_dim.width() * _dim.height() + 1);
|
||||||
|
for (int i = 0; i < _tiles.size(); i++)
|
||||||
|
if (!readValue(_tiles[i]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OZF::load(const QString &path)
|
||||||
|
{
|
||||||
|
_file.setFileName(path);
|
||||||
|
if (!_file.open(QIODevice::ReadOnly))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!readHeaders()) {
|
||||||
|
_file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readTileTable()) {
|
||||||
|
_file.close();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap OZF::blankTile()
|
||||||
|
{
|
||||||
|
QPixmap p(tileSize());
|
||||||
|
p.fill();
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap OZF::tile(int x, int y)
|
||||||
|
{
|
||||||
|
Q_ASSERT(_file.isOpen());
|
||||||
|
|
||||||
|
int i = (y/tileSize().height()) * _dim.width() + (x/tileSize().width());
|
||||||
|
if (i >= _tiles.size() - 1 || i < 0)
|
||||||
|
return blankTile();
|
||||||
|
|
||||||
|
int size = _tiles.at(i+1) - _tiles.at(i);
|
||||||
|
if (!_file.seek(_tiles.at(i)))
|
||||||
|
return blankTile();
|
||||||
|
|
||||||
|
QByteArray ba = _file.read(size);
|
||||||
|
if (ba.size() != size)
|
||||||
|
return blankTile();
|
||||||
|
quint32 bes = qToBigEndian(tileSize().width() * tileSize().height());
|
||||||
|
ba.prepend(QByteArray((char*)&bes, sizeof(bes)));
|
||||||
|
QByteArray uba = qUncompress(ba);
|
||||||
|
if (uba.size() != tileSize().width() * tileSize().height())
|
||||||
|
return blankTile();
|
||||||
|
|
||||||
|
QImage img((const uchar*)uba.constData(), tileSize().width(),
|
||||||
|
tileSize().height(), QImage::Format_Indexed8);
|
||||||
|
img.setColorTable(_palette);
|
||||||
|
|
||||||
|
return QPixmap::fromImage(img.mirrored());
|
||||||
|
}
|
37
src/ozf.h
Normal file
37
src/ozf.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
#ifndef OZF_H
|
||||||
|
#define OZF_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QSize>
|
||||||
|
#include <QColor>
|
||||||
|
#include <QVector>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QPixmap>
|
||||||
|
|
||||||
|
class OZF
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool load(const QString &path);
|
||||||
|
|
||||||
|
QString fileName() const {return _file.fileName();}
|
||||||
|
bool isOpen() const {return _file.isOpen();}
|
||||||
|
|
||||||
|
QSize size() const {return _size;}
|
||||||
|
QSize tileSize() const {return QSize(64, 64);}
|
||||||
|
QPixmap tile(int x, int y);
|
||||||
|
|
||||||
|
private:
|
||||||
|
template<class T> bool readValue(T &val);
|
||||||
|
bool readHeaders();
|
||||||
|
bool readTileTable();
|
||||||
|
QPixmap blankTile();
|
||||||
|
|
||||||
|
QSize _size;
|
||||||
|
QSize _dim;
|
||||||
|
QVector<QRgb> _palette;
|
||||||
|
QVector<quint32> _tiles;
|
||||||
|
|
||||||
|
QFile _file;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // OZF_H
|
@ -55,14 +55,18 @@ bool Tar::load(const QString &path)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
while ((ret = _file.read(buffer, BLOCKSIZE)) > 0) {
|
while ((ret = _file.read(buffer, BLOCKSIZE)) > 0) {
|
||||||
if (ret < BLOCKSIZE)
|
if (ret < BLOCKSIZE) {
|
||||||
|
_file.close();
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
size = number(hdr->size, sizeof(hdr->size));
|
size = number(hdr->size, sizeof(hdr->size));
|
||||||
if (size)
|
if (size)
|
||||||
_index.insert(hdr->name, Info(size, _file.pos()));
|
_index.insert(hdr->name, Info(size, _file.pos()));
|
||||||
if (!_file.seek(_file.pos() + BLOCKCOUNT(size) * BLOCKSIZE))
|
if (!_file.seek(_file.pos() + BLOCKCOUNT(size) * BLOCKSIZE)) {
|
||||||
|
_file.close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -73,6 +77,7 @@ QByteArray Tar::file(const QString &name)
|
|||||||
if (it == _index.end())
|
if (it == _index.end())
|
||||||
return QByteArray();
|
return QByteArray();
|
||||||
|
|
||||||
|
Q_ASSERT(_file.isOpen());
|
||||||
if (_file.seek(it.value().offset()))
|
if (_file.seek(it.value().offset()))
|
||||||
return _file.read(it.value().size());
|
return _file.read(it.value().size());
|
||||||
else
|
else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user