summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2019-10-15 14:26:06 +0200
committerAlexandru Croitor <alexandru.croitor@qt.io>2019-10-15 14:26:06 +0200
commita56d52b553b16b8f944c62368cdc38db6784b7c3 (patch)
treecc4e76d1f0c493b53480f14617284037b01bf784
parent36c362412b8829c61a1292c654a7d9e2a8c290e9 (diff)
parent89caeeb5bd5e34242afc76e71868deb1b2874af0 (diff)
Merge remote-tracking branch 'origin/dev' into wip/cmake
-rw-r--r--dependencies.yaml4
-rw-r--r--dist/changes-5.12.524
-rw-r--r--dist/changes-5.13.124
-rw-r--r--src/3rdparty/libwebp.pri25
-rw-r--r--src/imageformats/configure.json162
-rw-r--r--src/plugins/imageformats/tiff/qtiffhandler.cpp19
-rw-r--r--src/plugins/imageformats/webp/qwebphandler.cpp79
-rw-r--r--src/plugins/imageformats/webp/qwebphandler_p.h3
-rw-r--r--tests/auto/tiff/tst_qtiff.cpp38
9 files changed, 258 insertions, 120 deletions
diff --git a/dependencies.yaml b/dependencies.yaml
new file mode 100644
index 0000000..e81522d
--- /dev/null
+++ b/dependencies.yaml
@@ -0,0 +1,4 @@
+dependencies:
+ ../qtbase:
+ ref: e164d61ca8263fc4b46fdd916e1ea77c7dd2b735
+ required: true
diff --git a/dist/changes-5.12.5 b/dist/changes-5.12.5
new file mode 100644
index 0000000..dd232ff
--- /dev/null
+++ b/dist/changes-5.12.5
@@ -0,0 +1,24 @@
+Qt 5.12.5 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.4.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Third-Party Code *
+****************************************************************************
+
+ - Update bundled libwebp to version 1.0.3
diff --git a/dist/changes-5.13.1 b/dist/changes-5.13.1
new file mode 100644
index 0000000..9716883
--- /dev/null
+++ b/dist/changes-5.13.1
@@ -0,0 +1,24 @@
+Qt 5.13.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.13.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.13 series is binary compatible with the 5.12.x series.
+Applications compiled for 5.12 will continue to run with 5.13.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Third-Party Code *
+****************************************************************************
+
+ - Update bundled libwebp to version 1.0.3
diff --git a/src/3rdparty/libwebp.pri b/src/3rdparty/libwebp.pri
index 3e839a2..6f49549 100644
--- a/src/3rdparty/libwebp.pri
+++ b/src/3rdparty/libwebp.pri
@@ -123,18 +123,21 @@ integrity {
QMAKE_CFLAGS += -c99
}
-equals(QT_ARCH, arm)|equals(QT_ARCH, arm64) {
- SOURCES_FOR_NEON += \
- $$PWD/libwebp/src/dsp/alpha_processing_neon.c \
- $$PWD/libwebp/src/dsp/dec_neon.c \
- $$PWD/libwebp/src/dsp/enc_neon.c \
- $$PWD/libwebp/src/dsp/filters_neon.c \
- $$PWD/libwebp/src/dsp/lossless_enc_neon.c \
- $$PWD/libwebp/src/dsp/lossless_neon.c \
- $$PWD/libwebp/src/dsp/rescaler_neon.c \
- $$PWD/libwebp/src/dsp/upsampling_neon.c \
- $$PWD/libwebp/src/dsp/yuv_neon.c
+SOURCES_FOR_NEON += \
+ $$PWD/libwebp/src/dsp/alpha_processing_neon.c \
+ $$PWD/libwebp/src/dsp/dec_neon.c \
+ $$PWD/libwebp/src/dsp/enc_neon.c \
+ $$PWD/libwebp/src/dsp/filters_neon.c \
+ $$PWD/libwebp/src/dsp/lossless_enc_neon.c \
+ $$PWD/libwebp/src/dsp/lossless_neon.c \
+ $$PWD/libwebp/src/dsp/rescaler_neon.c \
+ $$PWD/libwebp/src/dsp/upsampling_neon.c \
+ $$PWD/libwebp/src/dsp/yuv_neon.c
+
+android {
+ arm64-v8a|equals(QT_ARCH, arm64): SOURCES += $$SOURCES_FOR_NEON
+} else: equals(QT_ARCH, arm)|equals(QT_ARCH, arm64) {
contains(QT_CPU_FEATURES.$$QT_ARCH, neon) {
# Default compiler settings include this feature, so just add to SOURCES
SOURCES += $$SOURCES_FOR_NEON
diff --git a/src/imageformats/configure.json b/src/imageformats/configure.json
index 03d59d3..3b38fae 100644
--- a/src/imageformats/configure.json
+++ b/src/imageformats/configure.json
@@ -16,135 +16,103 @@
"libraries": {
"jasper": {
- "label": "jasper",
+ "headers": "jasper/jasper.h",
"test": {
- "label": "Jasper(header in /usr/include)",
- "type": "compile",
- "test": {
- "include": [
- "string.h",
- "jasper/jasper.h"
- ],
- "qmake": [
- "msvc: LIBS += libjasper.lib",
- "else: LIBS += -ljasper"
- ],
- "main": [
- "// This version of Jasper is broken, according to the old Qt Solutions docs",
- "if (strcmp(JAS_VERSION, \"1.900.0\") == 0)",
- " return 1;",
- "return 0;"
- ]
- }
+ "include": [
+ "string.h",
+ "jasper/jasper.h"
+ ],
+ "head": [
+ "constexpr bool streq(const char *a, const char *b)",
+ "{",
+ " return a[0] == b[0] && (!a[0] || streq(a + 1, b + 1));",
+ "}"
+ ],
+ "main": [
+ "static_assert(!streq(JAS_VERSION, \"1.900.0\"),",
+ " \"JasPer version 1.900.0 is considered broken.\");"
+ ]
},
"sources": [
"-ljasper"
]
},
"mng": {
- "label": "mng",
+ "headers": "libmng.h",
"test": {
- "label": "MNG(header in /usr/include)",
- "type": "compile",
- "test": {
- "include": [
- "stdio.h",
- "libmng.h"
- ],
- "qmake": [
- "LIBS += -lmng"
- ],
- "main": [
- "mng_handle hMNG;",
- "mng_cleanup(&hMNG);",
+ "include": [
+ "stdio.h",
+ "libmng.h"
+ ],
+ "main": [
+ "mng_handle hMNG;",
+ "mng_cleanup(&hMNG);",
"#if defined(MNG_VERSION_MAJOR)",
"#if MNG_VERSION_MAJOR < 1 || (MNG_VERSION_MAJOR == 1 && MNG_VERSION_MINOR == 0 && MNG_VERSION_RELEASE < 9)",
"#error System libmng version is less than 1.0.9",
"#endif",
- "#endif",
- "return 0;"
- ]
- }
+ "#endif"
+ ]
},
"sources": [
"-lmng"
]
},
"tiff": {
- "label": "tiff",
+ "headers": "tiffio.h",
"test": {
- "label": "TIFF(header in /usr/include)",
- "type": "compile",
- "test": {
- "include": "tiffio.h",
- "qmake": [
- "unix|mingw: LIBS += -ltiff",
- "else:win32: LIBS += libtiff.lib"
- ],
- "main": [
- "#if !defined(TIFF_VERSION) && defined(TIFF_VERSION_CLASSIC)",
- "// libtiff 4.0 splits it into TIFF_VERSION_CLASSIC and TIFF_VERSION_BIG",
- "# define TIFF_VERSION TIFF_VERSION_CLASSIC",
- "#endif",
-
- "#if !defined(TIFF_VERSION)",
- "# error \"Required libtiff not found\"",
- "#elif TIFF_VERSION < 42",
- "# error \"unsupported tiff version\"",
- "#endif",
+ "main": [
+ "#if !defined(TIFF_VERSION) && defined(TIFF_VERSION_CLASSIC)",
+ "// libtiff 4.0 splits it into TIFF_VERSION_CLASSIC and TIFF_VERSION_BIG",
+ "# define TIFF_VERSION TIFF_VERSION_CLASSIC",
+ "#endif",
- "tdata_t buffer = _TIFFmalloc(128);",
- "_TIFFfree(buffer);",
+ "#if !defined(TIFF_VERSION)",
+ "# error \"Required libtiff not found\"",
+ "#elif TIFF_VERSION < 42",
+ "# error \"unsupported tiff version\"",
+ "#endif",
- "// some libtiff implementations where TIFF_VERSION >= 42 do not",
- "// have TIFFReadRGBAImageOriented(), so let's check for it",
- "TIFFReadRGBAImageOriented(0, 0, 0, 0, 0, 0);",
+ "tdata_t buffer = _TIFFmalloc(128);",
+ "_TIFFfree(buffer);",
- "return 0;"
- ]
- }
+ "// some libtiff implementations where TIFF_VERSION >= 42 do not",
+ "// have TIFFReadRGBAImageOriented(), so let's check for it",
+ "TIFFReadRGBAImageOriented(0, 0, 0, 0, 0, 0);"
+ ]
},
"sources": [
"-ltiff"
]
},
"webp": {
- "label": "webp",
+ "headers": [
+ "webp/decode.h",
+ "webp/encode.h",
+ "webp/demux.h",
+ "webp/mux.h"
+ ],
"test": {
- "label": "WebP(header in /usr/include)",
- "type": "compile",
- "test": {
- "include": [
- "webp/decode.h",
- "webp/encode.h",
- "webp/demux.h"
- ],
- "qmake": [
- "LIBS += -lwebp -lwebpdemux"
- ],
- "main": [
- "#if WEBP_ABI_IS_INCOMPATIBLE(WEBP_DECODER_ABI_VERSION, 0x0203) || WEBP_ABI_IS_INCOMPATIBLE(WEBP_ENCODER_ABI_VERSION, 0x0202)",
- "#error \"Incompatible libwebp version\"",
- "#endif",
-
- "WebPDecoderConfig config;",
- "WebPDecBuffer *output_buffer = &config.output;",
- "WebPBitstreamFeatures *bitstream = &config.input;",
- "WebPPicture picture;",
- "picture.use_argb = 0;",
- "WebPConfig config2;",
- "config2.lossless = 0;",
- "WebPData data = {};",
- "WebPDemuxer *demuxer = WebPDemux(&data);",
- "WebPIterator iter;",
- "iter.frame_num = 0;",
+ "main": [
+ "#if WEBP_ABI_IS_INCOMPATIBLE(WEBP_DECODER_ABI_VERSION, 0x0203) || WEBP_ABI_IS_INCOMPATIBLE(WEBP_ENCODER_ABI_VERSION, 0x0202)",
+ "#error \"Incompatible libwebp version\"",
+ "#endif",
- "return 0;"
- ]
- }
+ "WebPDecoderConfig config;",
+ "WebPDecBuffer *output_buffer = &config.output;",
+ "WebPBitstreamFeatures *bitstream = &config.input;",
+ "WebPPicture picture;",
+ "picture.use_argb = 0;",
+ "WebPConfig config2;",
+ "config2.lossless = 0;",
+ "WebPData data = {};",
+ "WebPDemuxer *demuxer = WebPDemux(&data);",
+ "WebPIterator iter;",
+ "iter.frame_num = 0;"
+ ]
},
"sources": [
- "-lwebp -lwebpdemux"
+ "-lwebp -lwebpdemux -lwebpmux"
]
}
},
diff --git a/src/plugins/imageformats/tiff/qtiffhandler.cpp b/src/plugins/imageformats/tiff/qtiffhandler.cpp
index 9f1c090..57def2c 100644
--- a/src/plugins/imageformats/tiff/qtiffhandler.cpp
+++ b/src/plugins/imageformats/tiff/qtiffhandler.cpp
@@ -39,6 +39,7 @@
#include "qtiffhandler_p.h"
#include <qvariant.h>
+#include <qcolorspace.h>
#include <qdebug.h>
#include <qimage.h>
#include <qglobal.h>
@@ -487,6 +488,15 @@ bool QTiffHandler::read(QImage *image)
}
}
+ uint32 count;
+ void *profile;
+ if (TIFFGetField(tiff, TIFFTAG_ICCPROFILE, &count, &profile)) {
+ QByteArray iccProfile(reinterpret_cast<const char *>(profile), count);
+ image->setColorSpace(QColorSpace::fromIccProfile(iccProfile));
+ }
+ // We do not handle colorimetric metadat not on ICC profile form, it seems to be a lot
+ // less common, and would need additional API in QColorSpace.
+
return true;
}
@@ -591,7 +601,14 @@ bool QTiffHandler::write(const QImage &image)
TIFFClose(tiff);
return false;
}
-
+ // set color space
+ if (image.colorSpace().isValid()) {
+ QByteArray iccProfile = image.colorSpace().iccProfile();
+ if (!TIFFSetField(tiff, TIFFTAG_ICCPROFILE, iccProfile.size(), reinterpret_cast<const void *>(iccProfile.constData()))) {
+ TIFFClose(tiff);
+ return false;
+ }
+ }
// configure image depth
const QImage::Format format = image.format();
if (format == QImage::Format_Mono || format == QImage::Format_MonoLSB) {
diff --git a/src/plugins/imageformats/webp/qwebphandler.cpp b/src/plugins/imageformats/webp/qwebphandler.cpp
index 4d6bcbe..f0b8caf 100644
--- a/src/plugins/imageformats/webp/qwebphandler.cpp
+++ b/src/plugins/imageformats/webp/qwebphandler.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the WebP plugins in the Qt ImageFormats module.
@@ -38,6 +38,7 @@
****************************************************************************/
#include "qwebphandler_p.h"
+#include "webp/mux.h"
#include "webp/encode.h"
#include <qcolor.h>
#include <qimage.h>
@@ -51,6 +52,7 @@ QWebpHandler::QWebpHandler() :
m_quality(75),
m_scanState(ScanNotScanned),
m_features(),
+ m_formatFlags(0),
m_loop(0),
m_frameCount(0),
m_demuxer(NULL),
@@ -151,6 +153,7 @@ bool QWebpHandler::ensureDemuxer()
if (m_demuxer == NULL)
return false;
+ m_formatFlags = WebPDemuxGetI(m_demuxer, WEBP_FF_FORMAT_FLAGS);
return true;
}
@@ -160,6 +163,16 @@ bool QWebpHandler::read(QImage *image)
return false;
if (m_iter.frame_num == 0) {
+ // Read global meta-data chunks first
+ WebPChunkIterator metaDataIter;
+ if ((m_formatFlags & ICCP_FLAG) && WebPDemuxGetChunk(m_demuxer, "ICCP", 1, &metaDataIter)) {
+ const QByteArray iccProfile = QByteArray::fromRawData(reinterpret_cast<const char *>(metaDataIter.chunk.bytes),
+ metaDataIter.chunk.size);
+ m_colorSpace = QColorSpace::fromIccProfile(iccProfile);
+ // ### consider parsing EXIF and/or XMP metadata too.
+ WebPDemuxReleaseChunkIterator(&metaDataIter);
+ }
+
// Go to first frame
if (!WebPDemuxGetFrame(m_demuxer, 1, &m_iter))
return false;
@@ -201,23 +214,21 @@ bool QWebpHandler::read(QImage *image)
*image = *m_composited;
}
+ image->setColorSpace(m_colorSpace);
return true;
}
-static int pictureWriter(const quint8 *data, size_t data_size, const WebPPicture *const pic)
-{
- QIODevice *io = reinterpret_cast<QIODevice*>(pic->custom_ptr);
-
- return data_size ? ((quint64)(io->write((const char*)data, data_size)) == data_size) : 1;
-}
-
bool QWebpHandler::write(const QImage &image)
{
if (image.isNull()) {
qWarning() << "source image is null.";
return false;
}
+ if (std::max(image.width(), image.height()) > WEBP_MAX_DIMENSION) {
+ qWarning() << "QWebpHandler::write() source image too large for WebP: " << image.size();
+ return false;
+ }
QImage srcImage = image;
bool alpha = srcImage.hasAlphaChannel();
@@ -257,8 +268,10 @@ bool QWebpHandler::write(const QImage &image)
config.quality = 70; // For lossless, specifies compression effort; 70 is libwebp default
}
config.alpha_quality = config.quality;
- picture.writer = pictureWriter;
- picture.custom_ptr = device();
+ WebPMemoryWriter writer;
+ WebPMemoryWriterInit(&writer);
+ picture.writer = WebPMemoryWrite;
+ picture.custom_ptr = &writer;
if (!WebPEncode(&config, &picture)) {
qWarning() << "failed to encode webp picture, error code: " << picture.error_code;
@@ -266,9 +279,53 @@ bool QWebpHandler::write(const QImage &image)
return false;
}
+ bool res = false;
+ if (image.colorSpace().isValid()) {
+ int copy_data = 0;
+ WebPMux *mux = WebPMuxNew();
+ WebPData image_data = { writer.mem, writer.size };
+ WebPMuxSetImage(mux, &image_data, copy_data);
+ uint8_t vp8xChunk[10];
+ uint8_t flags = 0x20; // Has ICCP chunk, no XMP, EXIF or animation.
+ if (image.hasAlphaChannel())
+ flags |= 0x10;
+ vp8xChunk[0] = flags;
+ vp8xChunk[1] = 0;
+ vp8xChunk[2] = 0;
+ vp8xChunk[3] = 0;
+ const unsigned width = image.width() - 1;
+ const unsigned height = image.height() - 1;
+ vp8xChunk[4] = width & 0xff;
+ vp8xChunk[5] = (width >> 8) & 0xff;
+ vp8xChunk[6] = (width >> 16) & 0xff;
+ vp8xChunk[7] = height & 0xff;
+ vp8xChunk[8] = (height >> 8) & 0xff;
+ vp8xChunk[9] = (height >> 16) & 0xff;
+ WebPData vp8x_data = { vp8xChunk, 10 };
+ if (WebPMuxSetChunk(mux, "VP8X", &vp8x_data, copy_data) == WEBP_MUX_OK) {
+ QByteArray iccProfile = image.colorSpace().iccProfile();
+ WebPData iccp_data = {
+ reinterpret_cast<const uint8_t *>(iccProfile.constData()),
+ static_cast<size_t>(iccProfile.size())
+ };
+ if (WebPMuxSetChunk(mux, "ICCP", &iccp_data, copy_data) == WEBP_MUX_OK) {
+ WebPData output_data;
+ if (WebPMuxAssemble(mux, &output_data) == WEBP_MUX_OK) {
+ res = (output_data.size ==
+ static_cast<size_t>(device()->write(reinterpret_cast<const char *>(output_data.bytes), output_data.size)));
+ }
+ WebPDataClear(&output_data);
+ }
+ }
+ WebPMuxDelete(mux);
+ }
+ if (!res) {
+ res = (writer.size ==
+ static_cast<size_t>(device()->write(reinterpret_cast<const char *>(writer.mem), writer.size)));
+ }
WebPPictureFree(&picture);
- return true;
+ return res;
}
QVariant QWebpHandler::option(ImageOption option) const
diff --git a/src/plugins/imageformats/webp/qwebphandler_p.h b/src/plugins/imageformats/webp/qwebphandler_p.h
index 31574b4..96a8811 100644
--- a/src/plugins/imageformats/webp/qwebphandler_p.h
+++ b/src/plugins/imageformats/webp/qwebphandler_p.h
@@ -41,6 +41,7 @@
#define QWEBPHANDLER_P_H
#include <QtGui/qcolor.h>
+#include <QtGui/qcolorspace.h>
#include <QtGui/qimage.h>
#include <QtGui/qimageiohandler.h>
#include <QtCore/qbytearray.h>
@@ -90,6 +91,7 @@ private:
int m_quality;
mutable ScanState m_scanState;
WebPBitstreamFeatures m_features;
+ uint32_t m_formatFlags;
int m_loop;
int m_frameCount;
QColor m_bgColor;
@@ -97,6 +99,7 @@ private:
WebPData m_webpData;
WebPDemuxer *m_demuxer;
WebPIterator m_iter;
+ QColorSpace m_colorSpace;
QImage *m_composited; // For animation frames composition
};
diff --git a/tests/auto/tiff/tst_qtiff.cpp b/tests/auto/tiff/tst_qtiff.cpp
index 29d85df..87fdfa8 100644
--- a/tests/auto/tiff/tst_qtiff.cpp
+++ b/tests/auto/tiff/tst_qtiff.cpp
@@ -87,6 +87,9 @@ private slots:
void readRgba64();
void readGray16();
+ void colorSpace_data();
+ void colorSpace();
+
private:
QString prefix;
};
@@ -624,5 +627,40 @@ void tst_qtiff::readGray16()
QCOMPARE(image.format(), QImage::Format_Grayscale16);
}
+void tst_qtiff::colorSpace_data()
+{
+ QTest::addColumn<decltype(QColorSpace::SRgb)>("namedColorSpace");
+
+ QTest::newRow("sRGB") << QColorSpace::SRgb;
+ QTest::newRow("sRGB(linear)") << QColorSpace::SRgbLinear;
+ QTest::newRow("AdobeRGB") << QColorSpace::AdobeRgb;
+ QTest::newRow("DisplayP3") << QColorSpace::DisplayP3;
+ QTest::newRow("ProPhotoRgb") << QColorSpace::ProPhotoRgb;
+}
+
+void tst_qtiff::colorSpace()
+{
+ QFETCH(decltype(QColorSpace::SRgb), namedColorSpace);
+
+ QImage image(prefix + "colorful.bmp");
+ QVERIFY(!image.isNull());
+
+ image.setColorSpace(namedColorSpace);
+
+ QByteArray output;
+ QBuffer buf(&output);
+ QVERIFY(buf.open(QIODevice::WriteOnly));
+ QImageWriter writer(&buf, "tiff");
+ writer.write(image);
+ buf.close();
+
+ QVERIFY(buf.open(QIODevice::ReadOnly));
+ QImageReader reader(&buf);
+ QImage image2 = reader.read();
+
+ QCOMPARE(image2.colorSpace(), namedColorSpace);
+ QCOMPARE(image2, image);
+}
+
QTEST_MAIN(tst_qtiff)
#include "tst_qtiff.moc"