I have a QByteArray
, which I want to save in a JSON file using Qt and also be able to read from it again. Since JSON natively can't store raw data, I think the best way would probably be a string? The goal is to save a QPixmap this way:
{
"format" : "jpg",
"data" : "...jibberish..."
}
How do I achieve this and how do I read from this JSON Object again (I am using Qt5)? What I have right now looks this way:
QPixmap p;
...
QByteArray ba;
QBuffer buffer(&ba);
buffer.open(QIODevice::WriteOnly);
p.save(&buffer, "jpg");
QJsonObject json;
gameObject["data"] = QString(buffer.data());
QJsonDocument doc(json);
file.write(doc.toJson());
But the resulting 'jibberish' is way to short to contain the whole image.
A QString
cannot be constructed from an arbitrary QByteArray
. You need to encode the byte array such that it is convertible to a string first. It is somewhat misleading that a QString
is constructible from a QByteArray
from the C++ semantics point of view. Whether it is really constructible depends on what's in the QByteArray
.
QByteArray::toBase64
and fromBase64
are one way of doing it.
Since you would want to save the pixmap without losing its contents, you should not save it in a lossy format like JPG. Use PNG instead. Only use JPG if you're not repeatedly loading and storing the same pixmap while doing the full json->pixmap->json circuit.
There's another gotcha: for a pixmap to store or load itself, it needs to internally convert to/from QImage
. This involves potentially color format conversions. Such conversions may lose data. You have to be careful to ensure that any roundtrips are made with the same format.
Ideally, you should be using QImage
instead of a QPixmap
. In modern Qt, a QPixmap
is just a thin wrapper around a QImage
anyway.
// https://github.com/KubaO/stackoverflown/tree/master/questions/pixmap-to-json-32376119
#include <QtGui>
QJsonValue jsonValFromPixmap(const QPixmap &p) {
QBuffer buffer;
buffer.open(QIODevice::WriteOnly);
p.save(&buffer, "PNG");
auto const encoded = buffer.data().toBase64();
return {QLatin1String(encoded)};
}
QPixmap pixmapFrom(const QJsonValue &val) {
auto const encoded = val.toString().toLatin1();
QPixmap p;
p.loadFromData(QByteArray::fromBase64(encoded), "PNG");
return p;
}
int main(int argc, char **argv) {
QGuiApplication app{argc, argv};
QImage img{32, 32, QImage::Format_RGB32};
img.fill(Qt::red);
auto pix = QPixmap::fromImage(img);
auto val = jsonValFromPixmap(pix);
auto pix2 = pixmapFrom(val);
auto img2 = pix2.toImage();
Q_ASSERT(img == img2);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With