summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEirik Aavitsland <eirik.aavitsland@qt.io>2017-10-25 15:15:09 +0200
committerEirik Aavitsland <eirik.aavitsland@qt.io>2017-10-30 08:11:38 +0000
commitc7f2abe551c027a8eddb01dd7445dcf1fb829171 (patch)
tree280d76f8406710fc9eefa714ea4e2f9ebf00f0d6
parentb0631ce6ed816e16869b87165ce8d7e34643afe8 (diff)
Add native Darwin handler for the HEIF (.heic) format
Adds basic support for still images encoded with the HEIF standard introduced in macOS Sierra and IOS 11. Uses the Core Graphics Image I/O Framework as codec backend. Reuses the helper class from the macjp2 handler. Change-Id: I5f0c7891b189a916cccd2c27eacbac12416ce209 Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
-rw-r--r--src/plugins/imageformats/imageformats.pro2
-rw-r--r--src/plugins/imageformats/macheif/macheif.json4
-rw-r--r--src/plugins/imageformats/macheif/macheif.pro20
-rw-r--r--src/plugins/imageformats/macheif/main.cpp90
-rw-r--r--src/plugins/imageformats/macheif/qmacheifhandler.cpp117
-rw-r--r--src/plugins/imageformats/macheif/qmacheifhandler.h76
-rw-r--r--src/plugins/imageformats/macjp2/macjp2.pro8
-rw-r--r--src/plugins/imageformats/shared/qiiofhelpers.cpp (renamed from src/plugins/imageformats/macjp2/qiiofhelpers.cpp)18
-rw-r--r--src/plugins/imageformats/shared/qiiofhelpers.pri5
-rw-r--r--src/plugins/imageformats/shared/qiiofhelpers_p.h (renamed from src/plugins/imageformats/macjp2/qiiofhelpers_p.h)6
-rw-r--r--tests/auto/auto.pro1
-rw-r--r--tests/auto/heif/heif.pro8
-rw-r--r--tests/auto/heif/tst_qheif.cpp70
-rw-r--r--tests/shared/images/heif.qrc5
-rw-r--r--tests/shared/images/heif/col320x480.heicbin0 -> 29004 bytes
15 files changed, 423 insertions, 7 deletions
diff --git a/src/plugins/imageformats/imageformats.pro b/src/plugins/imageformats/imageformats.pro
index 8c79379..d6c59ee 100644
--- a/src/plugins/imageformats/imageformats.pro
+++ b/src/plugins/imageformats/imageformats.pro
@@ -6,6 +6,8 @@ SUBDIRS = \
wbmp \
webp
+darwin: SUBDIRS += macheif
+
qtConfig(regularexpression): \
SUBDIRS += icns
diff --git a/src/plugins/imageformats/macheif/macheif.json b/src/plugins/imageformats/macheif/macheif.json
new file mode 100644
index 0000000..52b0a89
--- /dev/null
+++ b/src/plugins/imageformats/macheif/macheif.json
@@ -0,0 +1,4 @@
+{
+ "Keys": [ "heic", "heif" ],
+ "MimeTypes": [ "image/heic", "image/heif" ]
+}
diff --git a/src/plugins/imageformats/macheif/macheif.pro b/src/plugins/imageformats/macheif/macheif.pro
new file mode 100644
index 0000000..38e8087
--- /dev/null
+++ b/src/plugins/imageformats/macheif/macheif.pro
@@ -0,0 +1,20 @@
+TARGET = qmacheif
+PLUGIN_TYPE = imageformats
+PLUGIN_CLASS_NAME = QMacHeifPlugin
+
+LIBS += -framework CoreFoundation -framework CoreGraphics -framework ImageIO
+
+QT += core-private gui-private
+
+SOURCES += \
+ qmacheifhandler.cpp \
+ main.cpp
+
+HEADERS += \
+ qmacheifhandler.h
+
+include (../shared/qiiofhelpers.pri)
+
+OTHER_FILES += macheif.json
+
+load(qt_plugin)
diff --git a/src/plugins/imageformats/macheif/main.cpp b/src/plugins/imageformats/macheif/main.cpp
new file mode 100644
index 0000000..12d9a4a
--- /dev/null
+++ b/src/plugins/imageformats/macheif/main.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the MacHeif plugin in the Qt ImageFormats module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_IMAGEFORMATPLUGIN
+
+#include <qmacheifhandler.h>
+#include <qiiofhelpers_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QMacHeifPlugin : public QImageIOPlugin
+{
+ Q_OBJECT
+ Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" FILE "macheif.json")
+
+public:
+ Capabilities capabilities(QIODevice *device, const QByteArray &format) const override;
+ QImageIOHandler *create(QIODevice *device, const QByteArray &format = QByteArray()) const override;
+};
+
+QImageIOPlugin::Capabilities QMacHeifPlugin::capabilities(QIODevice *device, const QByteArray &format) const
+{
+ static const Capabilities sysCaps = QIIOFHelpers::systemCapabilities(QStringLiteral("public.heic"));
+
+ if (!sysCaps)
+ return 0;
+ if (format == "heic" || format == "heif")
+ return sysCaps;
+ if (!format.isEmpty())
+ return 0;
+ if (!device->isOpen())
+ return 0;
+
+ Capabilities cap;
+ if (sysCaps.testFlag(CanRead) && device->isReadable() && QMacHeifHandler::canRead(device))
+ cap |= CanRead;
+ if (sysCaps.testFlag(CanWrite) && device->isWritable())
+ cap |= CanWrite;
+ return cap;
+}
+
+QImageIOHandler *QMacHeifPlugin::create(QIODevice *device, const QByteArray &format) const
+{
+ QMacHeifHandler *handler = new QMacHeifHandler();
+ handler->setDevice(device);
+ handler->setFormat(format);
+ return handler;
+}
+
+QT_END_NAMESPACE
+
+#include "main.moc"
+
+#endif // !QT_NO_IMAGEFORMATPLUGIN
diff --git a/src/plugins/imageformats/macheif/qmacheifhandler.cpp b/src/plugins/imageformats/macheif/qmacheifhandler.cpp
new file mode 100644
index 0000000..7c63e52
--- /dev/null
+++ b/src/plugins/imageformats/macheif/qmacheifhandler.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the MacHeif plugin in the Qt ImageFormats module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmacheifhandler.h"
+#include "qiiofhelpers_p.h"
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QMacHeifHandlerPrivate
+{
+ Q_DECLARE_PUBLIC(QMacHeifHandler)
+ Q_DISABLE_COPY(QMacHeifHandlerPrivate)
+public:
+ QMacHeifHandlerPrivate(QMacHeifHandler *q_ptr)
+ : writeQuality(-1), q_ptr(q_ptr)
+ {}
+
+ int writeQuality;
+ QMacHeifHandler *q_ptr;
+};
+
+
+QMacHeifHandler::QMacHeifHandler()
+ : d_ptr(new QMacHeifHandlerPrivate(this))
+{
+}
+
+QMacHeifHandler::~QMacHeifHandler()
+{
+}
+
+bool QMacHeifHandler::canRead(QIODevice *iod)
+{
+ bool bCanRead = false;
+ char buf[12];
+ if (iod && iod->peek(buf, 12) == 12) {
+ bCanRead = (!qstrncmp(buf + 4, "ftyp", 4) &&
+ (!qstrncmp(buf + 8, "heic", 4) ||
+ !qstrncmp(buf + 8, "heix", 4) ||
+ !qstrncmp(buf + 8, "mif1", 4)));
+ }
+ return bCanRead;
+}
+
+bool QMacHeifHandler::canRead() const
+{
+ if (canRead(device())) {
+ setFormat("heic");
+ return true;
+ }
+ return false;
+}
+
+bool QMacHeifHandler::read(QImage *image)
+{
+ return QIIOFHelpers::readImage(this, image);
+}
+
+bool QMacHeifHandler::write(const QImage &image)
+{
+ return QIIOFHelpers::writeImage(this, image, QStringLiteral("public.heic"));
+}
+
+QVariant QMacHeifHandler::option(ImageOption option) const
+{
+ return QVariant();
+}
+
+void QMacHeifHandler::setOption(ImageOption option, const QVariant &value)
+{
+ Q_UNUSED(option)
+ Q_UNUSED(value)
+}
+
+bool QMacHeifHandler::supportsOption(ImageOption option) const
+{
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/imageformats/macheif/qmacheifhandler.h b/src/plugins/imageformats/macheif/qmacheifhandler.h
new file mode 100644
index 0000000..6e94a59
--- /dev/null
+++ b/src/plugins/imageformats/macheif/qmacheifhandler.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the MacHeif plugin in the Qt ImageFormats module.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMACHEIFHANDLER_H
+#define QMACHEIFHANDLER_H
+
+#include <QScopedPointer>
+#include <QImageIOHandler>
+
+QT_BEGIN_NAMESPACE
+
+class QImage;
+class QByteArray;
+class QIODevice;
+class QVariant;
+class QMacHeifHandlerPrivate;
+
+class QMacHeifHandler : public QImageIOHandler
+{
+public:
+ QMacHeifHandler();
+ ~QMacHeifHandler();
+
+ bool canRead() const override;
+ bool read(QImage *image) override;
+ bool write(const QImage &image) override;
+ QVariant option(ImageOption option) const override;
+ void setOption(ImageOption option, const QVariant &value) override;
+ bool supportsOption(ImageOption option) const override;
+
+ static bool canRead(QIODevice *iod);
+
+private:
+ Q_DECLARE_PRIVATE(QMacHeifHandler)
+ QScopedPointer<QMacHeifHandlerPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QMACHEIFHANDLER_P_H
diff --git a/src/plugins/imageformats/macjp2/macjp2.pro b/src/plugins/imageformats/macjp2/macjp2.pro
index 66aafb4..9a44b69 100644
--- a/src/plugins/imageformats/macjp2/macjp2.pro
+++ b/src/plugins/imageformats/macjp2/macjp2.pro
@@ -8,12 +8,12 @@ QT += core-private gui-private
SOURCES += \
qmacjp2handler.cpp \
- main.cpp \
- qiiofhelpers.cpp
+ main.cpp
HEADERS += \
- qmacjp2handler.h \
- qiiofhelpers_p.h
+ qmacjp2handler.h
+
+include (../shared/qiiofhelpers.pri)
OTHER_FILES += macjp2.json
diff --git a/src/plugins/imageformats/macjp2/qiiofhelpers.cpp b/src/plugins/imageformats/shared/qiiofhelpers.cpp
index c894932..2cd8b74 100644
--- a/src/plugins/imageformats/macjp2/qiiofhelpers.cpp
+++ b/src/plugins/imageformats/shared/qiiofhelpers.cpp
@@ -98,6 +98,24 @@ static size_t cbPutBytes(void *info, const void *buffer, size_t count)
typedef QImage (*cgImageToQImagePtr)(CGImageRef image);
typedef CGImageRef (*qImageToCGImagePtr)(const QImage &image);
+QImageIOPlugin::Capabilities QIIOFHelpers::systemCapabilities(const QString &uti)
+{
+ QImageIOPlugin::Capabilities res;
+ QCFString cfUti(uti);
+
+ QCFType<CFArrayRef> cfSourceTypes = CGImageSourceCopyTypeIdentifiers();
+ CFIndex len = CFArrayGetCount(cfSourceTypes);
+ if (CFArrayContainsValue(cfSourceTypes, CFRangeMake(0, len), cfUti))
+ res |= QImageIOPlugin::CanRead;
+
+ QCFType<CFArrayRef> cfDestTypes = CGImageDestinationCopyTypeIdentifiers();
+ len = CFArrayGetCount(cfDestTypes);
+ if (CFArrayContainsValue(cfDestTypes, CFRangeMake(0, len), cfUti))
+ res |= QImageIOPlugin::CanWrite;
+
+ return res;
+}
+
bool QIIOFHelpers::readImage(QImageIOHandler *q_ptr, QImage *out)
{
static const CGDataProviderSequentialCallbacks cgCallbacks = { 0, &cbGetBytes, &cbSkipForward, &cbRewind, nullptr };
diff --git a/src/plugins/imageformats/shared/qiiofhelpers.pri b/src/plugins/imageformats/shared/qiiofhelpers.pri
new file mode 100644
index 0000000..8824281
--- /dev/null
+++ b/src/plugins/imageformats/shared/qiiofhelpers.pri
@@ -0,0 +1,5 @@
+INCLUDEPATH += $$PWD
+
+HEADERS += $$PWD/qiiofhelpers_p.h
+
+SOURCES += $$PWD/qiiofhelpers.cpp
diff --git a/src/plugins/imageformats/macjp2/qiiofhelpers_p.h b/src/plugins/imageformats/shared/qiiofhelpers_p.h
index ef5a022..da51731 100644
--- a/src/plugins/imageformats/macjp2/qiiofhelpers_p.h
+++ b/src/plugins/imageformats/shared/qiiofhelpers_p.h
@@ -51,10 +51,9 @@
// We mean it.
//
-QT_BEGIN_NAMESPACE
+#include <QImageIOPlugin>
-class QImageIOHandler;
-class QImage;
+QT_BEGIN_NAMESPACE
/*
Functions to utilize the native ImageIO Framework in OS X and iOS
@@ -63,6 +62,7 @@ Functions to utilize the native ImageIO Framework in OS X and iOS
class QIIOFHelpers
{
public:
+ static QImageIOPlugin::Capabilities systemCapabilities(const QString &uti);
static bool readImage(QImageIOHandler *q_ptr, QImage *out);
static bool writeImage(QImageIOHandler *q_ptr, const QImage &in, const QString &uti);
};
diff --git a/tests/auto/auto.pro b/tests/auto/auto.pro
index bf0f8e5..daa1dfb 100644
--- a/tests/auto/auto.pro
+++ b/tests/auto/auto.pro
@@ -6,5 +6,6 @@ SUBDIRS = \
icns \
jp2 \
webp \
+ heif \
mng \
tiff
diff --git a/tests/auto/heif/heif.pro b/tests/auto/heif/heif.pro
new file mode 100644
index 0000000..9ef1085
--- /dev/null
+++ b/tests/auto/heif/heif.pro
@@ -0,0 +1,8 @@
+TARGET = tst_qheif
+
+QT = core gui testlib
+CONFIG -= app_bundle
+CONFIG += testcase
+
+SOURCES += tst_qheif.cpp
+RESOURCES += $$PWD/../../shared/images/heif.qrc
diff --git a/tests/auto/heif/tst_qheif.cpp b/tests/auto/heif/tst_qheif.cpp
new file mode 100644
index 0000000..faf22fa
--- /dev/null
+++ b/tests/auto/heif/tst_qheif.cpp
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the autotests in the Qt ImageFormats module.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtGui/QtGui>
+
+class tst_qheif: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void initTestCase();
+ void readImage_data();
+ void readImage();
+};
+
+void tst_qheif::initTestCase()
+{
+ if (!QImageReader::supportedImageFormats().contains("heic"))
+ QSKIP("The image format handler is not installed.");
+}
+
+void tst_qheif::readImage_data()
+{
+ QTest::addColumn<QString>("fileName");
+ QTest::addColumn<QSize>("size");
+
+ QTest::newRow("col") << QString("col320x480.heic") << QSize(320, 480);
+}
+
+void tst_qheif::readImage()
+{
+ QFETCH(QString, fileName);
+ QFETCH(QSize, size);
+
+ QString path = QStringLiteral(":/heif/") + fileName;
+ QImageReader reader(path);
+ QVERIFY(reader.canRead());
+ QImage image = reader.read();
+ QVERIFY(!image.isNull());
+ QCOMPARE(image.size(), size);
+}
+
+QTEST_MAIN(tst_qheif)
+#include "tst_qheif.moc"
diff --git a/tests/shared/images/heif.qrc b/tests/shared/images/heif.qrc
new file mode 100644
index 0000000..2a41c36
--- /dev/null
+++ b/tests/shared/images/heif.qrc
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="/">
+ <file>heif/col320x480.heic</file>
+ </qresource>
+</RCC>
diff --git a/tests/shared/images/heif/col320x480.heic b/tests/shared/images/heif/col320x480.heic
new file mode 100644
index 0000000..6ca3c7b
--- /dev/null
+++ b/tests/shared/images/heif/col320x480.heic
Binary files differ