QtPBFImagePlugin/src/pbfhandler.cpp

105 lines
2.2 KiB
C++
Raw Normal View History

2018-10-29 00:11:23 +01:00
#include <QImage>
#include <QIODevice>
#include <QtEndian>
2019-01-01 21:27:07 +01:00
#include <QDebug>
2018-10-29 00:11:23 +01:00
#include "gzip.h"
2019-01-01 21:27:07 +01:00
#include "tile.h"
#include "style.h"
2018-10-29 00:11:23 +01:00
#include "pbfhandler.h"
2019-10-03 01:01:40 +02:00
#define TILE_SIZE 512
2018-11-03 00:38:53 +01:00
#define GZIP_MAGIC 0x1F8B0800
#define GZIP_MAGIC_MASK 0xFFFFFF00
#define PBF_MAGIC 0x1A000000
#define PBF_MAGIC_MASK 0xFF000000
2018-10-29 00:11:23 +01:00
2018-11-10 08:09:42 +01:00
static bool isMagic(quint32 magic, quint32 mask, quint32 value)
{
return ((qFromBigEndian(value) & mask) == magic);
}
static bool isGZIPPBF(quint32 magic)
{
return isMagic(GZIP_MAGIC, GZIP_MAGIC_MASK, magic);
}
static bool isPlainPBF(quint32 magic)
{
return isMagic(PBF_MAGIC, PBF_MAGIC_MASK, magic);
}
2018-10-29 00:11:23 +01:00
bool PBFHandler::canRead() const
{
2018-11-13 22:49:39 +01:00
if (canRead(device())) {
setFormat("pbf");
return true;
} else
return false;
2018-10-29 00:11:23 +01:00
}
bool PBFHandler::canRead(QIODevice *device)
{
quint32 magic;
qint64 size = device->peek((char*)&magic, sizeof(magic));
if (size != sizeof(magic))
return false;
2018-11-10 08:09:42 +01:00
return (isGZIPPBF(magic) || isPlainPBF(magic));
2018-10-29 00:11:23 +01:00
}
bool PBFHandler::read(QImage *image)
{
quint32 magic;
if (device()->peek((char*)&magic, sizeof(magic)) != sizeof(magic))
return false;
QByteArray ba;
2018-11-10 08:09:42 +01:00
if (isGZIPPBF(magic))
ba = Gzip::uncompress(device()->readAll());
2018-11-10 08:09:42 +01:00
else if (isPlainPBF(magic))
ba = device()->readAll();
2018-10-29 00:11:23 +01:00
if (ba.isNull())
return false;
2019-01-01 21:27:07 +01:00
vector_tile::Tile data;
if (!data.ParseFromArray(ba.constData(), ba.size())) {
qCritical() << "Invalid PBF data";
return false;
}
2018-10-29 00:11:23 +01:00
bool ok;
int zoom = format().toInt(&ok);
QSize size = _scaledSize.isValid()
? _scaledSize : QSize(TILE_SIZE, TILE_SIZE);
2018-11-17 21:54:51 +01:00
QPointF scale = _scaledSize.isValid()
2019-10-03 08:38:48 +02:00
? QPointF((qreal)_scaledSize.width() / TILE_SIZE,
(qreal)_scaledSize.height() / TILE_SIZE) : QPointF(1.0, 1.0);
2018-11-14 00:03:46 +01:00
*image = QImage(size, QImage::Format_ARGB32_Premultiplied);
2019-01-01 21:27:07 +01:00
Tile tile(image, ok ? zoom : -1, scale);
_style->render(data, tile);
2019-01-01 21:27:07 +01:00
return true;
2018-10-29 00:11:23 +01:00
}
bool PBFHandler::supportsOption(ImageOption option) const
{
return (option == Size || option == ScaledSize);
}
void PBFHandler::setOption(QImageIOHandler::ImageOption option,
const QVariant &value)
{
if (option == ScaledSize)
_scaledSize = value.toSize();
2018-10-29 00:11:23 +01:00
}
QVariant PBFHandler::option(ImageOption option) const
{
2018-11-03 00:38:53 +01:00
return (option == Size) ? QSize(TILE_SIZE, TILE_SIZE) : QVariant();
2018-10-29 00:11:23 +01:00
}