mirror of
https://github.com/tumic0/QtPBFImagePlugin.git
synced 2025-04-20 12:39:10 +02:00
146 lines
3.4 KiB
C++
146 lines
3.4 KiB
C++
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QFile>
|
|
#include <QDebug>
|
|
#include "sprites.h"
|
|
|
|
static QImage sdf2img(const QImage &sdf, const QColor &color)
|
|
{
|
|
QImage img(sdf.convertToFormat(QImage::Format_ARGB32));
|
|
quint32 argb = color.rgba();
|
|
uchar *bits = img.bits();
|
|
int bpl = img.bytesPerLine();
|
|
|
|
for (int y = 0; y < img.height(); y++) {
|
|
for (int x = 0; x < img.width(); x++) {
|
|
quint32 *pixel = (quint32*)(bits + y * bpl + x * 4);
|
|
*pixel = ((*pixel >> 24) < 192) ? 0 : argb;
|
|
}
|
|
}
|
|
|
|
return img;
|
|
}
|
|
|
|
Sprites::Sprite::Sprite(const QJsonObject &json)
|
|
{
|
|
int x, y, width, height;
|
|
|
|
if (json.contains("x") && json["x"].isDouble())
|
|
x = json["x"].toInt();
|
|
else
|
|
return;
|
|
if (json.contains("y") && json["y"].isDouble())
|
|
y = json["y"].toInt();
|
|
else
|
|
return;
|
|
if (json.contains("width") && json["width"].isDouble())
|
|
width = json["width"].toInt();
|
|
else
|
|
return;
|
|
if (json.contains("height") && json["height"].isDouble())
|
|
height = json["height"].toInt();
|
|
else
|
|
return;
|
|
|
|
_rect = QRect(x, y, width, height);
|
|
|
|
|
|
if (json.contains("pixelRatio") && json["pixelRatio"].isDouble())
|
|
_pixelRatio = json["pixelRatio"].toDouble();
|
|
else
|
|
_pixelRatio = 1.0;
|
|
|
|
if (json.contains("sdf") && json["sdf"].isBool())
|
|
_sdf = json["sdf"].toBool();
|
|
else
|
|
_sdf = false;
|
|
}
|
|
|
|
bool Sprites::load(const QString &jsonFile, const QString &imageFile)
|
|
{
|
|
QFile file(jsonFile);
|
|
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
|
qCritical() << jsonFile << ": error opening file";
|
|
return false;
|
|
}
|
|
QByteArray ba(file.readAll());
|
|
|
|
QJsonParseError error;
|
|
QJsonDocument doc(QJsonDocument::fromJson(ba, &error));
|
|
if (doc.isNull()) {
|
|
qCritical() << jsonFile << ":" << error.errorString();
|
|
return false;
|
|
}
|
|
|
|
QJsonObject json(doc.object());
|
|
for (QJsonObject::const_iterator it = json.constBegin();
|
|
it != json.constEnd(); it++) {
|
|
QJsonValue val(*it);
|
|
if (val.isObject()) {
|
|
Sprite s(val.toObject());
|
|
if (s.rect().isValid())
|
|
_sprites.insert(it.key(), s);
|
|
else
|
|
qWarning() << it.key() << ": invalid sprite definition";
|
|
} else
|
|
qWarning() << it.key() << ": invalid sprite definition";
|
|
}
|
|
|
|
// Loading the sprites atlas image must be deferred until all image plugins
|
|
// are loaded, otherwise reading the image will cause a deadlock in Qt!
|
|
_imageFile = imageFile;
|
|
|
|
return true;
|
|
}
|
|
|
|
QImage Sprites::sprite(const Sprite &sprite, const QColor &color, qreal scale)
|
|
{
|
|
if (!_img.rect().contains(sprite.rect()))
|
|
return QImage();
|
|
|
|
QImage img(_img.copy(sprite.rect()));
|
|
img.setDevicePixelRatio(sprite.pixelRatio());
|
|
|
|
if (sprite.sdf()) {
|
|
if (scale != 1.0) {
|
|
QSize size(img.size().width() * scale, img.size().height() * scale);
|
|
QImage simg(img.scaled(size, Qt::IgnoreAspectRatio,
|
|
Qt::SmoothTransformation));
|
|
return sdf2img(simg, color);
|
|
} else
|
|
return sdf2img(img, color);
|
|
} else
|
|
return img;
|
|
}
|
|
|
|
QImage Sprites::icon(const QString &name, const QColor &color, qreal size)
|
|
{
|
|
if (name.isNull())
|
|
return QImage();
|
|
|
|
_lock.lock();
|
|
if (_init <= 0) {
|
|
if (_init < 0) {
|
|
_lock.unlock();
|
|
return QImage();
|
|
}
|
|
|
|
_img = QImage(_imageFile);
|
|
if (_img.isNull()) {
|
|
qWarning() << _imageFile << ": invalid sprite atlas image";
|
|
_init = -1;
|
|
_lock.unlock();
|
|
return QImage();
|
|
}
|
|
|
|
_init = 1;
|
|
}
|
|
_lock.unlock();
|
|
|
|
QMap<QString, Sprite>::const_iterator it = _sprites.constFind(name);
|
|
if (it == _sprites.constEnd())
|
|
return QImage();
|
|
|
|
return sprite(*it, color, size);
|
|
}
|