Speed up document saving

If there are images need to be saved, such as the model turnaround reference sheet and texture images, the document saving may be slow because of image encoding to png, now, all the images are pre encoded when the first load, so the document saving could be speed up by avoid the cost of image encoding.
master
Jeremy Hu 2018-11-11 21:08:13 +08:00
parent dff8e40ef8
commit 39cfe6537d
5 changed files with 31 additions and 16 deletions

View File

@ -7,6 +7,7 @@
#include <QApplication> #include <QApplication>
#include <QVector3D> #include <QVector3D>
#include <functional> #include <functional>
#include <QBuffer>
#include "document.h" #include "document.h"
#include "util.h" #include "util.h"
#include "snapshotxml.h" #include "snapshotxml.h"
@ -719,6 +720,10 @@ void Document::setNodeBoneMark(QUuid nodeId, BoneMark mark)
void Document::updateTurnaround(const QImage &image) void Document::updateTurnaround(const QImage &image)
{ {
turnaround = image; turnaround = image;
turnaroundPngByteArray.clear();
QBuffer pngBuffer(&turnaroundPngByteArray);
pngBuffer.open(QIODevice::WriteOnly);
turnaround.save(&pngBuffer, "PNG");
emit turnaroundChanged(); emit turnaroundChanged();
} }

View File

@ -1102,13 +1102,8 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
if (modelXml.size() > 0) if (modelXml.size() > 0)
ds3Writer.add("model.xml", "model", &modelXml); ds3Writer.add("model.xml", "model", &modelXml);
QByteArray imageByteArray; if (!m_document->turnaround.isNull() && m_document->turnaroundPngByteArray.size() > 0) {
QBuffer pngBuffer(&imageByteArray); ds3Writer.add("canvas.png", "asset", &m_document->turnaroundPngByteArray);
if (!m_document->turnaround.isNull()) {
pngBuffer.open(QIODevice::WriteOnly);
m_document->turnaround.save(&pngBuffer, "PNG");
if (imageByteArray.size() > 0)
ds3Writer.add("canvas.png", "asset", &imageByteArray);
} }
std::set<QUuid> imageIds; std::set<QUuid> imageIds;
@ -1133,15 +1128,11 @@ void DocumentWindow::saveTo(const QString &saveAsFilename)
} }
for (const auto &imageId: imageIds) { for (const auto &imageId: imageIds) {
const QImage *image = ImageForever::get(imageId); const QByteArray *pngByteArray = ImageForever::getPngByteArray(imageId);
if (nullptr == image) if (nullptr == pngByteArray)
continue; continue;
QByteArray imageByteArray; if (pngByteArray->size() > 0)
QBuffer pngBuffer(&imageByteArray); ds3Writer.add("images/" + imageId.toString() + ".png", "asset", pngByteArray);
pngBuffer.open(QIODevice::WriteOnly);
image->save(&pngBuffer, "PNG");
if (imageByteArray.size() > 0)
ds3Writer.add("images/" + imageId.toString() + ".png", "asset", &imageByteArray);
} }
if (ds3Writer.save(filename)) { if (ds3Writer.save(filename)) {

View File

@ -1,12 +1,14 @@
#include <map> #include <map>
#include <QMutex> #include <QMutex>
#include <QMutexLocker> #include <QMutexLocker>
#include <QBuffer>
#include "imageforever.h" #include "imageforever.h"
struct ImageForeverItem struct ImageForeverItem
{ {
QImage *image; QImage *image;
QUuid id; QUuid id;
QByteArray *imageByteArray;
}; };
static std::map<QUuid, ImageForeverItem> g_foreverMap; static std::map<QUuid, ImageForeverItem> g_foreverMap;
static std::map<qint64, QUuid> g_foreverCacheKeyToIdMap; static std::map<qint64, QUuid> g_foreverCacheKeyToIdMap;
@ -21,6 +23,15 @@ const QImage *ImageForever::get(const QUuid &id)
return findResult->second.image; return findResult->second.image;
} }
const QByteArray *ImageForever::getPngByteArray(const QUuid &id)
{
QMutexLocker locker(&g_mapMutex);
auto findResult = g_foreverMap.find(id);
if (findResult == g_foreverMap.end())
return nullptr;
return findResult->second.imageByteArray;
}
QUuid ImageForever::add(const QImage *image, QUuid toId) QUuid ImageForever::add(const QImage *image, QUuid toId)
{ {
QMutexLocker locker(&g_mapMutex); QMutexLocker locker(&g_mapMutex);
@ -35,7 +46,11 @@ QUuid ImageForever::add(const QImage *image, QUuid toId)
if (g_foreverMap.find(newId) != g_foreverMap.end()) if (g_foreverMap.find(newId) != g_foreverMap.end())
return newId; return newId;
QImage *newImage = new QImage(*image); QImage *newImage = new QImage(*image);
g_foreverMap[newId] = {newImage, newId}; QByteArray *imageByteArray = new QByteArray();
QBuffer pngBuffer(imageByteArray);
pngBuffer.open(QIODevice::WriteOnly);
newImage->save(&pngBuffer, "PNG");
g_foreverMap[newId] = {newImage, newId, imageByteArray};
g_foreverCacheKeyToIdMap[newImage->cacheKey()] = newId; g_foreverCacheKeyToIdMap[newImage->cacheKey()] = newId;
return newId; return newId;
} }

View File

@ -2,11 +2,13 @@
#define DUST3D_IMAGE_FOREVER_H #define DUST3D_IMAGE_FOREVER_H
#include <QImage> #include <QImage>
#include <QUuid> #include <QUuid>
#include <QByteArray>
class ImageForever class ImageForever
{ {
public: public:
static const QImage *get(const QUuid &id); static const QImage *get(const QUuid &id);
static const QByteArray *getPngByteArray(const QUuid &id);
static QUuid add(const QImage *image, QUuid toId=QUuid()); static QUuid add(const QImage *image, QUuid toId=QUuid());
}; };

View File

@ -5,6 +5,7 @@
#include <QString> #include <QString>
#include <cmath> #include <cmath>
#include <QImage> #include <QImage>
#include <QByteArray>
#include "bonemark.h" #include "bonemark.h"
#include "theme.h" #include "theme.h"
#include "meshloader.h" #include "meshloader.h"
@ -200,6 +201,7 @@ public:
bool zlocked = false; bool zlocked = false;
bool radiusLocked = false; bool radiusLocked = false;
QImage turnaround; QImage turnaround;
QByteArray turnaroundPngByteArray;
std::map<QUuid, SkeletonPart> partMap; std::map<QUuid, SkeletonPart> partMap;
std::map<QUuid, SkeletonNode> nodeMap; std::map<QUuid, SkeletonNode> nodeMap;
std::map<QUuid, SkeletonEdge> edgeMap; std::map<QUuid, SkeletonEdge> edgeMap;