diff options
author | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2017-10-25 15:15:09 +0200 |
---|---|---|
committer | Eirik Aavitsland <eirik.aavitsland@qt.io> | 2017-10-30 08:11:38 +0000 |
commit | c7f2abe551c027a8eddb01dd7445dcf1fb829171 (patch) | |
tree | 280d76f8406710fc9eefa714ea4e2f9ebf00f0d6 | |
parent | b0631ce6ed816e16869b87165ce8d7e34643afe8 (diff) | |
download | qtimageformats-c7f2abe551c027a8eddb01dd7445dcf1fb829171.tar.gz |
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.pro | 2 | ||||
-rw-r--r-- | src/plugins/imageformats/macheif/macheif.json | 4 | ||||
-rw-r--r-- | src/plugins/imageformats/macheif/macheif.pro | 20 | ||||
-rw-r--r-- | src/plugins/imageformats/macheif/main.cpp | 90 | ||||
-rw-r--r-- | src/plugins/imageformats/macheif/qmacheifhandler.cpp | 117 | ||||
-rw-r--r-- | src/plugins/imageformats/macheif/qmacheifhandler.h | 76 | ||||
-rw-r--r-- | src/plugins/imageformats/macjp2/macjp2.pro | 8 | ||||
-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.pri | 5 | ||||
-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.pro | 1 | ||||
-rw-r--r-- | tests/auto/heif/heif.pro | 8 | ||||
-rw-r--r-- | tests/auto/heif/tst_qheif.cpp | 70 | ||||
-rw-r--r-- | tests/shared/images/heif.qrc | 5 | ||||
-rw-r--r-- | tests/shared/images/heif/col320x480.heic | bin | 0 -> 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 Binary files differnew file mode 100644 index 0000000..6ca3c7b --- /dev/null +++ b/tests/shared/images/heif/col320x480.heic |