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>
This commit is contained in:
parent
795af729d3
commit
345f86a2d8
@ -43,6 +43,7 @@
|
|||||||
|
|
||||||
#include "qtextodfwriter_p.h"
|
#include "qtextodfwriter_p.h"
|
||||||
|
|
||||||
|
#include <QImageReader>
|
||||||
#include <QImageWriter>
|
#include <QImageWriter>
|
||||||
#include <QTextListFormat>
|
#include <QTextListFormat>
|
||||||
#include <QTextList>
|
#include <QTextList>
|
||||||
@ -410,6 +411,29 @@ void QTextOdfWriter::writeBlock(QXmlStreamWriter &writer, const QTextBlock &bloc
|
|||||||
writer.writeEndElement(); // list-item
|
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
|
void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextFragment &fragment) const
|
||||||
{
|
{
|
||||||
writer.writeStartElement(drawNS, QString::fromLatin1("frame"));
|
writer.writeStartElement(drawNS, QString::fromLatin1("frame"));
|
||||||
@ -420,46 +444,71 @@ void QTextOdfWriter::writeInlineCharacter(QXmlStreamWriter &writer, const QTextF
|
|||||||
QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
|
QTextImageFormat imageFormat = fragment.charFormat().toImageFormat();
|
||||||
writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());
|
writer.writeAttribute(drawNS, QString::fromLatin1("name"), imageFormat.name());
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
QString mimeType;
|
||||||
|
qreal width = 0;
|
||||||
|
qreal height = 0;
|
||||||
|
|
||||||
QImage image;
|
QImage image;
|
||||||
QString name = imageFormat.name();
|
QString name = imageFormat.name();
|
||||||
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
|
if (name.startsWith(QLatin1String(":/"))) // auto-detect resources
|
||||||
name.prepend(QLatin1String("qrc"));
|
name.prepend(QLatin1String("qrc"));
|
||||||
QUrl url = QUrl(name);
|
QUrl url = QUrl(name);
|
||||||
const QVariant data = m_document->resource(QTextDocument::ImageResource, url);
|
const QVariant variant = m_document->resource(QTextDocument::ImageResource, url);
|
||||||
if (data.type() == QVariant::Image) {
|
if (variant.type() == QVariant::Image) {
|
||||||
image = qvariant_cast<QImage>(data);
|
image = qvariant_cast<QImage>(variant);
|
||||||
} else if (data.type() == QVariant::ByteArray) {
|
} else if (variant.type() == QVariant::ByteArray) {
|
||||||
image.loadFromData(data.toByteArray());
|
data = variant.toByteArray();
|
||||||
}
|
|
||||||
|
|
||||||
if (image.isNull()) {
|
QBuffer buffer(&data);
|
||||||
if (image.isNull()) { // try direct loading
|
buffer.open(QIODevice::ReadOnly);
|
||||||
name = imageFormat.name(); // remove qrc:/ prefix again
|
probeImageData(&buffer, &image, &mimeType, &width, &height);
|
||||||
image.load(name);
|
} 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()) {
|
if (! image.isNull()) {
|
||||||
QBuffer imageBytes;
|
QBuffer imageBytes;
|
||||||
QString filename = m_strategy->createUniqueImageName();
|
|
||||||
int imgQuality = imageFormat.quality();
|
int imgQuality = imageFormat.quality();
|
||||||
if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) {
|
if (imgQuality >= 100 || imgQuality < 0 || image.hasAlphaChannel()) {
|
||||||
QImageWriter imageWriter(&imageBytes, "png");
|
QImageWriter imageWriter(&imageBytes, "png");
|
||||||
imageWriter.write(image);
|
imageWriter.write(image);
|
||||||
m_strategy->addFile(filename, QString::fromLatin1("image/png"), imageBytes.data());
|
|
||||||
|
data = imageBytes.data();
|
||||||
|
mimeType = QStringLiteral("image/png");
|
||||||
} else {
|
} else {
|
||||||
// Write images without alpha channel as jpg with quality set by QTextImageFormat
|
// Write images without alpha channel as jpg with quality set by QTextImageFormat
|
||||||
QImageWriter imageWriter(&imageBytes, "jpg");
|
QImageWriter imageWriter(&imageBytes, "jpg");
|
||||||
imageWriter.setQuality(imgQuality);
|
imageWriter.setQuality(imgQuality);
|
||||||
imageWriter.write(image);
|
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)
|
width = image.width();
|
||||||
? imageFormat.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));
|
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.writeAttribute(svgNS, QString::fromLatin1("height"), pixelToPoint(height));
|
||||||
writer.writeStartElement(drawNS, QString::fromLatin1("image"));
|
writer.writeStartElement(drawNS, QString::fromLatin1("image"));
|
||||||
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
|
writer.writeAttribute(xlinkNS, QString::fromLatin1("href"), filename);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user