Как сохранить QPixmap в JSON, через QByteArray?

у меня есть QByteArray, который я хочу сохранить в файле JSON с помощью Qt, а также иметь возможность читать из него снова. Поскольку JSON изначально не может хранить необработанные данные, я думаю, что лучшим способом, вероятно, будет строка? Цель состоит в том, чтобы сохранить QPixmap таким образом:

{
  "format" : "jpg",
  "data" : "...jibberish..."
}

как этого достичь и как снова прочитать из этого объекта JSON (я использую Qt5)? То, что у меня сейчас есть, выглядит так:

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());

но полученный "jibberish" - это способ сократить, чтобы содержать целое изображение.

1 ответов


A QString невозможно построить из произвольного QByteArray. Вам нужно кодировать массив байтов так, чтобы он сначала конвертировался в строку. Это несколько вводит в заблуждение, что QString является конструктивным из QByteArray С точки зрения семантики C++. Является ли он действительно конструктивным, зависит от того, что находится в QByteArray.

QByteArray::toBase64 и fromBase64 - это один из способов сделать это.

поскольку вы хотите сохранить pixmap без потери его содержимого, вы не следует сохранять его в формате с потерями, таком как JPG. Вместо этого используйте PNG. Используйте JPG только в том случае, если вы не загружаете и не сохраняете один и тот же pixmap при выполнении полной схемы JSON->pixmap->json.

есть еще один gotcha: для pixmap для хранения или загрузки, он должен внутренне преобразовать в/из QImage. Это включает в себя потенциально преобразования цветового формата. Такие преобразования могут привести к потере данных. Вы должны быть осторожны, чтобы убедиться, что любые roundtrips сделаны с тем же формат.

в идеале, вы должны использовать QImage вместо QPixmap. В современном Qt a QPixmap это просто тонкая обертка вокруг QImage в любом случае.

// 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);
}