diff options
author | Andrew den Exter <andrew.den.exter@jollamobile.com> | 2019-05-13 11:57:00 +1000 |
---|---|---|
committer | Andrew den Exter <andrew.den.exter@qinetic.com.au> | 2019-05-13 13:03:01 +1000 |
commit | 345f86a2d8d69c6d3cbae314028902f090f39a43 (patch) | |
tree | 69e432f3d5db50560ad54cbe5f957201638b0937 /src/gui/text | |
parent | 795af729d38343e16b0902323609cd1e959a5973 (diff) |
Avoid re-encoding embedded images when writing an ODF file
If an embedded image is already encodeded as an png or jpg write the
data as is instead of decoding to a QImage and re-encoding as a new
image.
Change-Id: I479ae1fddbf59900a500497dd1bdf7449c21f273
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/gui/text')
-rw-r--r-- | src/gui/text/qtextodfwriter.cpp | 87 |
1 files changed, 68 insertions, 19 deletions
diff --git a/src/gui/text/qtextodfwriter.cpp b/src/gui/text/qtextodfwriter.cpp index 103e0a8222..1a96f7608f 100644 --- a/src/gui/text/qtextodfwriter.cpp +++ b/src/gui/text/qtextodfwriter.cpp @@ -43,6 +43,7 @@ #include "qtextodfwriter_p.h" +#include <QImageReader> #include <QImageWriter> #include <QTextListFormat> #include <QTextList> @@ -410,6 +411,29 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc writer.writeEndElement(); // list-item } +static bool probeImageData(QIODevice *device, QImage *image, QString *mimeType, qreal *width, qreal *height) +{ + QImageReader reader(device); + const QByteArray format = reader.format().toLower(); + if (format == "png") { + *mimeType = QStringLiteral("image/png"); + } else if (format == "jpg") { + *mimeType = QStringLiteral("image/jpg"); + } else if (format == "svg") { + *mimeType = QStringLiteral("image/svg+xml"); + } else { + *image = reader.read(); + return false; + } + + const QSize size = reader.size(); + + *width = size.width(); + *height = size.height(); + + return true; +} + void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const { writer.writeStartElement(drawNS, QString::fromLatin1("frame")); @@ -420,46 +444,71 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF QTextImageFormat imageFormat = fragment.charFormat().toImageFormat(); writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name()); + QByteArray data; + QString mimeType; + qreal width = 0; + qreal height = 0; + QImage image; QString name = imageFormat.name(); if (name.startsWith(QLatin1String(":/"))) // auto-detect resources name.prepend(QLatin1String("qrc")); QUrl url = QUrl(name); - const QVariant data = m_document->resource(QTextDocument::ImageResource, url); - if (data.type() == QVariant::Image) { - image = qvariant_cast<QImage>(data); - } else if (data.type() == QVariant::ByteArray) { - image.loadFromData(data.toByteArray()); - } - - if (image.isNull()) { - if (image.isNull()) { // try direct loading - name = imageFormat.name(); // remove qrc:/ prefix again - image.load(name); + const QVariant variant = m_document->resource(QTextDocument::ImageResource, url); + if (variant.type() == QVariant::Image) { + image = qvariant_cast<QImage>(variant); + } else if (variant.type() == QVariant::ByteArray) { + data = variant.toByteArray(); + + QBuffer buffer(&data); + buffer.open(QIODevice::ReadOnly); + probeImageData(&buffer, &image, &mimeType, &width, &height); + } else { + // try direct loading + QFile file(imageFormat.name()); + if (file.open(QIODevice::ReadOnly) && !probeImageData(&file, &image, &mimeType, &width, &height)) { + file.seek(0); + data = file.readAll(); } } if (! image.isNull()) { QBuffer imageBytes; - QString filename = m_strategy->createUniqueImageName(); + int imgQuality = imageFormat.quality(); if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) { QImageWriter imageWriter(&imageBytes, "png"); imageWriter.write(image); - m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data()); + + data = imageBytes.data(); + mimeType = QStringLiteral("image/png"); } else { // Write images without alpha channel as jpg with quality set by QTextImageFormat QImageWriter imageWriter(&imageBytes, "jpg"); imageWriter.setQuality(imgQuality); imageWriter.write(image); - m_strategy->addFile(filename, QString::fromLatin1("image/jpg"), imageBytes.data()); + + data = imageBytes.data(); + mimeType = QStringLiteral("image/jpg"); } - // get the width/height from the format. - qreal width = imageFormat.hasProperty(QTextFormat::ImageWidth) - ? imageFormat.width() : image.width(); + + width = image.width(); + height = image.height(); + } + + if (!data.isEmpty()) { + if (imageFormat.hasProperty(QTextFormat::ImageWidth)) { + width = imageFormat.width(); + } + if (imageFormat.hasProperty(QTextFormat::ImageHeight)) { + height = imageFormat.height(); + } + + QString filename = m_strategy->createUniqueImageName(); + + m_strategy->addFile(filename, mimeType, data); + writer.writeAttribute(svgNS, QString::fromLatin1("width"), pixelToPoint(width)); - qreal height = imageFormat.hasProperty(QTextFormat::ImageHeight) - ? imageFormat.height() : image.height(); writer.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height)); writer.writeStartElement(drawNS, QString::fromLatin1("image")); writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename); |