Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kimageformats for openSUSE:Factory 
checked in at 2021-03-16 15:40:45
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kimageformats (Old)
 and      /work/SRC/openSUSE:Factory/.kimageformats.new.2401 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kimageformats"

Tue Mar 16 15:40:45 2021 rev:90 rq:878814 version:5.80.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kimageformats/kimageformats.changes      
2021-02-17 18:12:10.677971919 +0100
+++ /work/SRC/openSUSE:Factory/.kimageformats.new.2401/kimageformats.changes    
2021-03-16 15:42:02.656810557 +0100
@@ -1,0 +2,14 @@
+Sun Mar  7 09:26:56 UTC 2021 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.80.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/5/5.80.0
+- Changes since 5.79.0:
+  * Fix Non-square Radiance/RGBE/.hdr images failing to load (kde#433877)
+  * Check the input buffer before passing it to libheif
+  * Check primaries returned from libavif
+  * Add plugin for High Efficiency Image File Format (HEIF)
+  * Quality option can be returned without parsing input file.
+
+-------------------------------------------------------------------

Old:
----
  kimageformats-5.79.0.tar.xz
  kimageformats-5.79.0.tar.xz.sig

New:
----
  kimageformats-5.80.0.tar.xz
  kimageformats-5.80.0.tar.xz.sig

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ kimageformats.spec ++++++
--- /var/tmp/diff_new_pack.WXttdy/_old  2021-03-16 15:42:03.204811433 +0100
+++ /var/tmp/diff_new_pack.WXttdy/_new  2021-03-16 15:42:03.204811433 +0100
@@ -19,7 +19,7 @@
 %if 0%{?suse_version} > 1500
 %define with_avif 1
 %endif
-%define _tar_path 5.79
+%define _tar_path 5.80
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
@@ -27,7 +27,7 @@
 # Only needed for the package signature condition
 %bcond_without lang
 Name:           kimageformats
-Version:        5.79.0
+Version:        5.80.0
 Release:        0
 Summary:        Image format plugins for Qt
 License:        LGPL-2.1-or-later


++++++ kimageformats-5.79.0.tar.xz -> kimageformats-5.80.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/.gitignore 
new/kimageformats-5.80.0/.gitignore
--- old/kimageformats-5.79.0/.gitignore 2021-02-02 09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/.gitignore 2021-03-04 22:57:23.000000000 +0100
@@ -21,3 +21,4 @@
 *.unc-backup*
 .cmake/
 /.clang-format
+/compile_commands.json
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/CMakeLists.txt 
new/kimageformats-5.80.0/CMakeLists.txt
--- old/kimageformats-5.79.0/CMakeLists.txt     2021-02-02 09:28:32.000000000 
+0100
+++ new/kimageformats-5.80.0/CMakeLists.txt     2021-03-04 22:57:23.000000000 
+0100
@@ -1,11 +1,11 @@
-cmake_minimum_required(VERSION 3.5)
+cmake_minimum_required(VERSION 3.6)
 
 project(KImageFormats)
 
 set (CMAKE_CXX_STANDARD 14)
 
 include(FeatureSummary)
-find_package(ECM 5.79.0  NO_MODULE)
+find_package(ECM 5.80.0  NO_MODULE)
 set_package_properties(ECM PROPERTIES TYPE REQUIRED DESCRIPTION "Extra CMake 
Modules." URL "https://commits.kde.org/extra-cmake-modules";)
 feature_summary(WHAT REQUIRED_PACKAGES_NOT_FOUND 
FATAL_ON_MISSING_REQUIRED_PACKAGES)
 
@@ -54,11 +54,18 @@
     PURPOSE "Required for the QImage plugin for AVIF images"
 )
 
+option(KIMAGEFORMATS_HEIF "Enable plugin for HEIF format" OFF)
+if(KIMAGEFORMATS_HEIF)
+    include(FindPkgConfig)
+    pkg_check_modules(LibHeif IMPORTED_TARGET libheif>=1.10.0)
+endif()
+add_feature_info(LibHeif LibHeif_FOUND "required for the QImage plugin for 
HEIF/HEIC images")
+
 add_definitions(-DQT_NO_FOREACH)
 # 050d00 (5.13) triggers a BIC in qimageiohandler.h, in Qt 5.13, so do not 
enable that until we can require 5.14
 # https://codereview.qt-project.org/c/qt/qtbase/+/279215
 add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x050e00)
-add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054B00)
+add_definitions(-DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x054F00)
 add_subdirectory(src)
 if (BUILD_TESTING)
     add_subdirectory(autotests)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/autotests/CMakeLists.txt 
new/kimageformats-5.80.0/autotests/CMakeLists.txt
--- old/kimageformats-5.79.0/autotests/CMakeLists.txt   2021-02-02 
09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/autotests/CMakeLists.txt   2021-03-04 
22:57:23.000000000 +0100
@@ -76,6 +76,12 @@
     )
 endif()
 
+if (LibHeif_FOUND)
+    kimageformats_read_tests(
+        heif
+    )
+endif()
+
 # Allow some fuzziness when reading this formats, to allow for
 # rounding errors (eg: in alpha blending).
 kimageformats_read_tests(FUZZ 1
Binary files old/kimageformats-5.79.0/autotests/read/hdr/rgb-landscape.hdr and 
new/kimageformats-5.80.0/autotests/read/hdr/rgb-landscape.hdr differ
Binary files old/kimageformats-5.79.0/autotests/read/hdr/rgb-landscape.png and 
new/kimageformats-5.80.0/autotests/read/hdr/rgb-landscape.png differ
Binary files old/kimageformats-5.79.0/autotests/read/hdr/rgb-portrait.hdr and 
new/kimageformats-5.80.0/autotests/read/hdr/rgb-portrait.hdr differ
Binary files old/kimageformats-5.79.0/autotests/read/hdr/rgb-portrait.png and 
new/kimageformats-5.80.0/autotests/read/hdr/rgb-portrait.png differ
Binary files old/kimageformats-5.79.0/autotests/read/heif/rgb.heif and 
new/kimageformats-5.80.0/autotests/read/heif/rgb.heif differ
Binary files old/kimageformats-5.79.0/autotests/read/heif/rgb.png and 
new/kimageformats-5.80.0/autotests/read/heif/rgb.png differ
Binary files old/kimageformats-5.79.0/autotests/read/heif/rgba.heif and 
new/kimageformats-5.80.0/autotests/read/heif/rgba.heif differ
Binary files old/kimageformats-5.79.0/autotests/read/heif/rgba.png and 
new/kimageformats-5.80.0/autotests/read/heif/rgba.png differ
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/CMakeLists.txt 
new/kimageformats-5.80.0/src/imageformats/CMakeLists.txt
--- old/kimageformats-5.79.0/src/imageformats/CMakeLists.txt    2021-02-02 
09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/CMakeLists.txt    2021-03-04 
22:57:23.000000000 +0100
@@ -71,6 +71,15 @@
 
 ##################################
 
+if (LibHeif_FOUND)
+    kimageformats_add_plugin(kimg_heif JSON "heif.json" SOURCES heif.cpp)
+    target_link_libraries(kimg_heif PkgConfig::LibHeif)
+    kde_target_enable_exceptions(kimg_heif PRIVATE)
+    install(FILES heif.desktop DESTINATION 
${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)
+endif()
+
+##################################
+
 kimageformats_add_plugin(kimg_pcx JSON "pcx.json" SOURCES pcx.cpp)
 install(FILES pcx.desktop DESTINATION 
${KDE_INSTALL_KSERVICES5DIR}/qimageioplugins/)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/avif.cpp 
new/kimageformats-5.80.0/src/imageformats/avif.cpp
--- old/kimageformats-5.79.0/src/imageformats/avif.cpp  2021-02-02 
09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/avif.cpp  2021-03-04 
22:57:23.000000000 +0100
@@ -12,6 +12,7 @@
 #include <QColorSpace>
 
 #include "avif_p.h"
+#include <cfloat>
 
 
 QAVIFHandler::QAVIFHandler() :
@@ -102,7 +103,7 @@
 
     decodeResult = avifDecoderSetIOMemory(m_decoder, m_rawAvifData.data, 
m_rawAvifData.size);
     if (decodeResult != AVIF_RESULT_OK) {
-        qWarning("ERROR: avifDecoderSetIOMemory failed: %s\n", 
avifResultToString(decodeResult));
+        qWarning("ERROR: avifDecoderSetIOMemory failed: %s", 
avifResultToString(decodeResult));
 
         avifDecoderDestroy(m_decoder);
         m_decoder = nullptr;
@@ -112,7 +113,7 @@
 
     decodeResult = avifDecoderParse(m_decoder);
     if (decodeResult != AVIF_RESULT_OK) {
-        qWarning("ERROR: Failed to parse input: %s\n", 
avifResultToString(decodeResult));
+        qWarning("ERROR: Failed to parse input: %s", 
avifResultToString(decodeResult));
 
         avifDecoderDestroy(m_decoder);
         m_decoder = nullptr;
@@ -147,7 +148,7 @@
             return false;
         }
     } else {
-        qWarning("ERROR: Failed to decode image: %s\n", 
avifResultToString(decodeResult));
+        qWarning("ERROR: Failed to decode image: %s", 
avifResultToString(decodeResult));
     }
 
     avifDecoderDestroy(m_decoder);
@@ -195,16 +196,17 @@
     if (m_decoder->image->icc.data && (m_decoder->image->icc.size > 0)) {
         
result.setColorSpace(QColorSpace::fromIccProfile(QByteArray::fromRawData((const 
char *) m_decoder->image->icc.data, (int) m_decoder->image->icc.size)));
         if (! result.colorSpace().isValid()) {
-            qWarning("Invalid QColorSpace created from ICC!\n");
+            qWarning("Invalid QColorSpace created from ICC!");
         }
     } else {
-        float prim[8]; // outPrimaries: rX, rY, gX, gY, bX, bY, wX, wY
+        float prim[8] = { 0.64f, 0.33f, 0.3f, 0.6f, 0.15f, 0.06f, 0.3127f, 
0.329f };
+        // outPrimaries: rX, rY, gX, gY, bX, bY, wX, wY
         avifColorPrimariesGetValues(m_decoder->image->colorPrimaries, prim);
 
-        QPointF redPoint(prim[0], prim[1]);
-        QPointF greenPoint(prim[2], prim[3]);
-        QPointF bluePoint(prim[4], prim[5]);
-        QPointF whitePoint(prim[6], prim[7]);
+        const QPointF redPoint(QAVIFHandler::CompatibleChromacity(prim[0], 
prim[1]));
+        const QPointF greenPoint(QAVIFHandler::CompatibleChromacity(prim[2], 
prim[3]));
+        const QPointF bluePoint(QAVIFHandler::CompatibleChromacity(prim[4], 
prim[5]));
+        const QPointF whitePoint(QAVIFHandler::CompatibleChromacity(prim[6], 
prim[7]));
 
 
         QColorSpace::TransferFunction q_trc = 
QColorSpace::TransferFunction::Custom;
@@ -257,7 +259,7 @@
         }
 
         if (! result.colorSpace().isValid()) {
-            qWarning("Invalid QColorSpace created from NCLX/CICP!\n");
+            qWarning("Invalid QColorSpace created from NCLX/CICP!");
         }
     }
 
@@ -296,7 +298,7 @@
 
     avifResult res = avifImageYUVToRGB(m_decoder->image, &rgb);
     if (res != AVIF_RESULT_OK) {
-        qWarning("ERROR in avifImageYUVToRGB: %s\n", avifResultToString(res));
+        qWarning("ERROR in avifImageYUVToRGB: %s", avifResultToString(res));
         return false;
     }
 
@@ -338,7 +340,7 @@
         }
 
         else { //Zero values, we need to avoid 0 divide.
-            qWarning("ERROR: Wrong values in avifCleanApertureBox\n");
+            qWarning("ERROR: Wrong values in avifCleanApertureBox");
         }
     }
 
@@ -680,7 +682,7 @@
 
         res = avifImageRGBToYUV(avif, &rgb);
         if (res != AVIF_RESULT_OK) {
-            qWarning("ERROR in avifImageRGBToYUV: %s\n", 
avifResultToString(res));
+            qWarning("ERROR in avifImageRGBToYUV: %s", 
avifResultToString(res));
             return false;
         }
     }
@@ -709,11 +711,11 @@
         if (status > 0) {
             return true;
         } else if (status == -1) {
-            qWarning("Write error: %s\n", 
qUtf8Printable(device()->errorString()));
+            qWarning("Write error: %s", 
qUtf8Printable(device()->errorString()));
             return false;
         }
     } else {
-        qWarning("ERROR: Failed to encode: %s\n", avifResultToString(res));
+        qWarning("ERROR: Failed to encode: %s", avifResultToString(res));
     }
 
     return false;
@@ -722,13 +724,15 @@
 
 QVariant QAVIFHandler::option(ImageOption option) const
 {
+    if (option == Quality) {
+        return m_quality;
+    }
+
     if (!supportsOption(option) || !ensureParsed()) {
         return QVariant();
     }
 
     switch (option) {
-    case Quality:
-        return m_quality;
     case Size:
         return m_current_image.size();
     case Animation:
@@ -808,14 +812,14 @@
     avifResult decodeResult = avifDecoderNextImage(m_decoder);
 
     if (decodeResult != AVIF_RESULT_OK) {
-        qWarning("ERROR: Failed to decode Next image in sequence: %s\n", 
avifResultToString(decodeResult));
+        qWarning("ERROR: Failed to decode Next image in sequence: %s", 
avifResultToString(decodeResult));
         m_parseState = ParseAvifError;
         return false;
     }
 
     if ((m_container_width != m_decoder->image->width) ||
             (m_container_height != m_decoder->image->height)) {
-        qWarning("Decoded image sequence size (%dx%d) do not match first image 
size (%dx%d)!\n",
+        qWarning("Decoded image sequence size (%dx%d) do not match first image 
size (%dx%d)!",
                  m_decoder->image->width, m_decoder->image->height,
                  m_container_width, m_container_height);
 
@@ -857,14 +861,14 @@
     avifResult decodeResult = avifDecoderNthImage(m_decoder, imageNumber);
 
     if (decodeResult != AVIF_RESULT_OK) {
-        qWarning("ERROR: Failed to decode %d th Image in sequence: %s\n", 
imageNumber, avifResultToString(decodeResult));
+        qWarning("ERROR: Failed to decode %d th Image in sequence: %s", 
imageNumber, avifResultToString(decodeResult));
         m_parseState = ParseAvifError;
         return false;
     }
 
     if ((m_container_width != m_decoder->image->width) ||
             (m_container_height != m_decoder->image->height)) {
-        qWarning("Decoded image sequence size (%dx%d) do not match declared 
container size (%dx%d)!\n",
+        qWarning("Decoded image sequence size (%dx%d) do not match declared 
container size (%dx%d)!",
                  m_decoder->image->width, m_decoder->image->height,
                  m_container_width, m_container_height);
 
@@ -910,6 +914,18 @@
     return 1;
 }
 
+QPointF QAVIFHandler::CompatibleChromacity(qreal chrX, qreal chrY)
+{
+    chrX = qBound(qreal(0.0), chrX, qreal(1.0));
+    chrY = qBound(qreal(DBL_MIN), chrY, qreal(1.0));
+
+    if ((chrX + chrY) > qreal(1.0)) {
+        chrX = qreal(1.0) - chrY;
+    }
+
+    return QPointF(chrX, chrY);
+}
+
 QImageIOPlugin::Capabilities QAVIFPlugin::capabilities(QIODevice *device, 
const QByteArray &format) const
 {
     if (format == "avif") {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/avif_p.h 
new/kimageformats-5.80.0/src/imageformats/avif_p.h
--- old/kimageformats-5.79.0/src/imageformats/avif_p.h  2021-02-02 
09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/avif_p.h  2021-03-04 
22:57:23.000000000 +0100
@@ -14,6 +14,7 @@
 #include <qimageiohandler.h>
 #include <QImageIOPlugin>
 #include <QByteArray>
+#include <QPointF>
 #include <avif/avif.h>
 
 class QAVIFHandler : public QImageIOHandler
@@ -41,6 +42,7 @@
 
   int loopCount() const override;
 private:
+  static QPointF CompatibleChromacity(qreal chrX, qreal chrY);
   bool ensureParsed() const;
   bool ensureDecoder();
   bool decode_one_frame();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/hdr.cpp 
new/kimageformats-5.80.0/src/imageformats/hdr.cpp
--- old/kimageformats-5.79.0/src/imageformats/hdr.cpp   2021-02-02 
09:28:32.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/hdr.cpp   2021-03-04 
22:57:23.000000000 +0100
@@ -227,8 +227,15 @@
         qCDebug(HDRPLUGIN) << "Invalid HDR file, the first line after the 
header didn't have the expected format:" << line;
         return false;
     }
-    const int width = match.captured(2).toInt();
-    const int height = match.captured(4).toInt();
+
+    if ( (match.captured(1).at(1) != u'Y') ||
+         (match.captured(3).at(1) != u'X') ) {
+        qCDebug(HDRPLUGIN) << "Unsupported image orientation in HDR file.";
+        return false;
+    }
+
+    const int width = match.captured(4).toInt();
+    const int height = match.captured(2).toInt();
 
     QDataStream s(device());
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/heif.cpp 
new/kimageformats-5.80.0/src/imageformats/heif.cpp
--- old/kimageformats-5.79.0/src/imageformats/heif.cpp  1970-01-01 
01:00:00.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/heif.cpp  2021-03-04 
22:57:23.000000000 +0100
@@ -0,0 +1,739 @@
+/*
+    High Efficiency Image File Format (HEIF) support for QImage.
+
+    SPDX-FileCopyrightText: 2020 Sirius Bakke <[email protected]>
+    SPDX-FileCopyrightText: 2021 Daniel Novomesky <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#include "heif_p.h"
+#include "libheif/heif_cxx.h"
+
+#include <QPointF>
+#include <QColorSpace>
+#include <QDebug>
+#include <QSysInfo>
+#include <string.h>
+
+namespace   // Private.
+{
+
+struct HeifQIODeviceWriter : public heif::Context::Writer {
+    HeifQIODeviceWriter(QIODevice *device) : m_ioDevice(device) {}
+
+    heif_error write(const void *data, size_t size) override
+    {
+        heif_error error;
+        error.code = heif_error_Ok;
+        error.subcode = heif_suberror_Unspecified;
+        error.message = errorOkMessage;
+
+        qint64 bytesWritten = m_ioDevice->write(static_cast<const char 
*>(data), size);
+
+        if (bytesWritten < static_cast<qint64>(size)) {
+            error.code = heif_error_Encoding_error;
+            error.message = QIODeviceWriteErrorMessage;
+            error.subcode = heif_suberror_Cannot_write_output_data;
+        }
+
+        return error;
+    }
+
+    static constexpr const char *errorOkMessage = "Success";
+    static constexpr const char *QIODeviceWriteErrorMessage = "Bytes written 
to QIODevice are smaller than input data size";
+
+private:
+    QIODevice *m_ioDevice;
+};
+
+} // namespace
+
+HEIFHandler::HEIFHandler() :
+    m_parseState(ParseHeicNotParsed),
+    m_quality(100)
+{
+}
+
+bool HEIFHandler::canRead() const
+{
+    if (m_parseState == ParseHeicNotParsed && !canRead(device())) {
+        return false;
+    }
+
+    if (m_parseState != ParseHeicError) {
+        setFormat("heif");
+        return true;
+    }
+    return false;
+}
+
+bool HEIFHandler::read(QImage *outImage)
+{
+    if (!ensureParsed()) {
+        return false;
+    }
+
+    *outImage = m_current_image;
+    return true;
+}
+
+bool HEIFHandler::write(const QImage &image)
+{
+    if (image.format() == QImage::Format_Invalid || image.isNull()) {
+        qWarning("No image data to save");
+        return false;
+    }
+
+    int save_depth; //8 or 10bit per channel
+    QImage::Format tmpformat; //format for temporary image
+    const bool save_alpha = image.hasAlphaChannel();
+
+    switch (image.format()) {
+    case QImage::Format_BGR30:
+    case QImage::Format_A2BGR30_Premultiplied:
+    case QImage::Format_RGB30:
+    case QImage::Format_A2RGB30_Premultiplied:
+    case QImage::Format_Grayscale16:
+    case QImage::Format_RGBX64:
+    case QImage::Format_RGBA64:
+    case QImage::Format_RGBA64_Premultiplied:
+        save_depth = 10;
+        break;
+    default:
+        if (image.depth() > 32) {
+            save_depth = 10;
+        } else {
+            save_depth = 8;
+        }
+        break;
+    }
+
+    heif_chroma chroma;
+    if (save_depth > 8) {
+        if (save_alpha) {
+            tmpformat = QImage::Format_RGBA64;
+            chroma = (QSysInfo::ByteOrder == QSysInfo::LittleEndian) ? 
heif_chroma_interleaved_RRGGBBAA_LE : heif_chroma_interleaved_RRGGBBAA_BE;
+        } else {
+            tmpformat = QImage::Format_RGBX64;
+            chroma = (QSysInfo::ByteOrder == QSysInfo::LittleEndian) ? 
heif_chroma_interleaved_RRGGBB_LE : heif_chroma_interleaved_RRGGBB_BE;
+        }
+    } else {
+        if (save_alpha) {
+            tmpformat = QImage::Format_RGBA8888;
+            chroma = heif_chroma_interleaved_RGBA;
+        } else {
+            tmpformat = QImage::Format_RGB888;
+            chroma = heif_chroma_interleaved_RGB;
+        }
+
+    }
+
+    const QImage tmpimage = image.convertToFormat(tmpformat);
+
+    try {
+        heif::Context ctx;
+        heif::Image heifImage;
+        heifImage.create(tmpimage.width(), tmpimage.height(), 
heif_colorspace_RGB, chroma);
+
+        if (tmpimage.colorSpace().isValid()) {
+            QByteArray iccprofile = tmpimage.colorSpace().iccProfile();
+            if (iccprofile.size() > 0) {
+                std::vector<uint8_t> rawProfile(iccprofile.begin(), 
iccprofile.end());
+                heifImage.set_raw_color_profile(heif_color_profile_type_prof, 
rawProfile);
+            }
+        }
+
+        heifImage.add_plane(heif_channel_interleaved, image.width(), 
image.height(), save_depth);
+        int stride = 0;
+        uint8_t *const dst = heifImage.get_plane(heif_channel_interleaved, 
&stride);
+        size_t rowbytes;
+
+        switch (save_depth) {
+        case 10:
+            if (save_alpha) {
+                for (int y = 0; y < tmpimage.height(); y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(tmpimage.constScanLine(y));
+                    uint16_t *dest_word = reinterpret_cast<uint16_t *>(dst + 
(y * stride));
+                    for (int x = 0; x < tmpimage.width(); x++) {
+                        int tmp_pixelval;
+                        //R
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //G
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //B
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //A
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                    }
+                }
+            } else { //no alpha channel
+                for (int y = 0; y < tmpimage.height(); y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(tmpimage.constScanLine(y));
+                    uint16_t *dest_word = reinterpret_cast<uint16_t *>(dst + 
(y * stride));
+                    for (int x = 0; x < tmpimage.width(); x++) {
+                        int tmp_pixelval;
+                        //R
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //G
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //B
+                        tmp_pixelval = (int)(((float)(*src_word) / 65535.0f) * 
1023.0f + 0.5f);
+                        *dest_word = qBound(0, tmp_pixelval, 1023);
+                        src_word++;
+                        dest_word++;
+                        //X
+                        src_word++;
+                    }
+                }
+            }
+            break;
+        case 8:
+            rowbytes = save_alpha ? (tmpimage.width() * 4) : (tmpimage.width() 
* 3);
+            for (int y = 0; y < tmpimage.height(); y++) {
+                memcpy(dst + (y * stride), tmpimage.constScanLine(y), 
rowbytes);
+            }
+            break;
+        default:
+            qWarning() << "Unsupported depth:" << save_depth;
+            return false;
+            break;
+        }
+
+        heif::Encoder encoder(heif_compression_HEVC);
+
+        encoder.set_lossy_quality(m_quality);
+        if (m_quality > 90) {
+            if (m_quality == 100) {
+                encoder.set_lossless(true);
+            }
+            encoder.set_string_parameter("chroma", "444");
+        }
+
+        heif::Context::EncodingOptions encodingOptions;
+        encodingOptions.save_alpha_channel = save_alpha;
+
+        if ((tmpimage.width() % 2 == 1) || (tmpimage.height() % 2 == 1)) {
+            qWarning() << "Image has odd dimension!\nUse even-numbered 
dimension(s) for better compatibility with other HEIF implementations.";
+            if (save_alpha) {
+                // This helps to save alpha channel when image has odd 
dimension
+                encodingOptions.macOS_compatibility_workaround = 0;
+            }
+        }
+
+        ctx.encode_image(heifImage, encoder, encodingOptions);
+
+        HeifQIODeviceWriter writer(device());
+
+        ctx.write(writer);
+
+    } catch (const heif::Error &err) {
+        qWarning() << "libheif error:" << err.get_message().c_str();
+        return false;
+    }
+
+    return true;
+}
+
+bool HEIFHandler::canRead(QIODevice *device)
+{
+    if (!device) {
+        qWarning("HEIFHandler::canRead() called with no device");
+        return false;
+    }
+
+    const QByteArray header = device->peek(28);
+    return HEIFHandler::isSupportedBMFFType(header);
+}
+
+bool HEIFHandler::isSupportedBMFFType(const QByteArray &header)
+{
+    if (header.size() < 28) {
+        return false;
+    }
+
+    const char *buffer = header.constData();
+    if (qstrncmp(buffer + 4, "ftyp", 4) == 0) {
+        if (qstrncmp(buffer + 8, "heic", 4) == 0) {
+            return true;
+        }
+        if (qstrncmp(buffer + 8, "heis", 4) == 0) {
+            return true;
+        }
+        if (qstrncmp(buffer + 8, "heix", 4) == 0) {
+            return true;
+        }
+
+        /* we want to avoid loading AVIF files via this plugin */
+        if (qstrncmp(buffer + 8, "mif1", 4) == 0) {
+            for (int offset = 16; offset <= 24; offset += 4) {
+                if (qstrncmp(buffer + offset, "avif", 4) == 0) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        if (qstrncmp(buffer + 8, "mif2", 4) == 0) {
+            return true;
+        }
+        if (qstrncmp(buffer + 8, "msf1", 4) == 0) {
+            return true;
+        }
+    }
+
+    return false;
+}
+
+QVariant HEIFHandler::option(ImageOption option) const
+{
+    if (option == Quality) {
+        return m_quality;
+    }
+
+    if (!supportsOption(option) || !ensureParsed()) {
+        return QVariant();
+    }
+
+    switch (option) {
+    case Size:
+        return m_current_image.size();
+        break;
+    default:
+        return QVariant();
+        break;
+    }
+}
+
+void HEIFHandler::setOption(ImageOption option, const QVariant &value)
+{
+    switch (option) {
+    case Quality:
+        m_quality = value.toInt();
+        if (m_quality > 100) {
+            m_quality = 100;
+        } else if (m_quality < 0) {
+            m_quality = 100;
+        }
+        break;
+    default:
+        QImageIOHandler::setOption(option, value);
+        break;
+    }
+}
+
+bool HEIFHandler::supportsOption(ImageOption option) const
+{
+    return option == Quality
+           || option == Size;
+}
+
+bool HEIFHandler::ensureParsed() const
+{
+    if (m_parseState == ParseHeicSuccess) {
+        return true;
+    }
+    if (m_parseState == ParseHeicError) {
+        return false;
+    }
+
+    HEIFHandler *that = const_cast<HEIFHandler *>(this);
+
+    return that->ensureDecoder();
+}
+bool HEIFHandler::ensureDecoder()
+{
+    if (m_parseState != ParseHeicNotParsed) {
+        if (m_parseState == ParseHeicSuccess) {
+            return true;
+        }
+        return false;
+    }
+
+    const QByteArray buffer = device()->readAll();
+    if (!HEIFHandler::isSupportedBMFFType(buffer)) {
+        m_parseState = ParseHeicError;
+        return false;
+    }
+
+    try {
+        heif::Context ctx;
+        ctx.read_from_memory_without_copy((const void *)(buffer.constData()),
+                                          buffer.size());
+
+        heif::ImageHandle handle = ctx.get_primary_image_handle();
+
+        const bool hasAlphaChannel = handle.has_alpha_channel();
+        const int bit_depth = handle.get_luma_bits_per_pixel();
+        heif_chroma chroma;
+
+        QImage::Format target_image_format;
+
+        if (bit_depth == 10 || bit_depth == 12) {
+            if (hasAlphaChannel) {
+                chroma = (QSysInfo::ByteOrder == QSysInfo::LittleEndian) ? 
heif_chroma_interleaved_RRGGBBAA_LE : heif_chroma_interleaved_RRGGBBAA_BE;
+                target_image_format = QImage::Format_RGBA64;
+            } else {
+                chroma = (QSysInfo::ByteOrder == QSysInfo::LittleEndian) ? 
heif_chroma_interleaved_RRGGBB_LE : heif_chroma_interleaved_RRGGBB_BE;
+                target_image_format = QImage::Format_RGBX64;
+            }
+        } else if (bit_depth == 8) {
+            if (hasAlphaChannel) {
+                chroma = heif_chroma_interleaved_RGBA;
+                target_image_format = QImage::Format_ARGB32;
+            } else {
+                chroma = heif_chroma_interleaved_RGB;
+                target_image_format = QImage::Format_RGB32;
+            }
+        } else {
+            m_parseState = ParseHeicError;
+            if (bit_depth > 0) {
+                qWarning() << "Unsupported bit depth:" << bit_depth;
+            } else {
+                qWarning() << "Undefined bit depth.";
+            }
+            return false;
+        }
+
+
+        heif::Image img = handle.decode_image(heif_colorspace_RGB, chroma);
+
+        const int imageWidth = img.get_width(heif_channel_interleaved);
+        const int imageHeight = img.get_height(heif_channel_interleaved);
+
+        QSize imageSize(imageWidth, imageHeight);
+
+        if (!imageSize.isValid()) {
+            m_parseState = ParseHeicError;
+            qWarning() << "HEIC image size invalid:" << imageSize;
+            return false;
+        }
+
+        int stride = 0;
+        const uint8_t *const src = img.get_plane(heif_channel_interleaved, 
&stride);
+
+        if (!src || stride <= 0) {
+            m_parseState = ParseHeicError;
+            qWarning() << "HEIC data pixels information not valid!";
+            return false;
+        }
+
+        m_current_image = QImage(imageSize, target_image_format);
+        if (m_current_image.isNull()) {
+            m_parseState = ParseHeicError;
+            qWarning() << "Unable to allocate memory!";
+            return false;
+        }
+
+        switch (bit_depth) {
+        case 12:
+            if (hasAlphaChannel) {
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(src + (y * stride));
+                    uint16_t *dest_data = reinterpret_cast<uint16_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int tmpvalue;
+                        //R
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //G
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //B
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //A
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                    }
+                }
+            } else { //no alpha channel
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(src + (y * stride));
+                    uint16_t *dest_data = reinterpret_cast<uint16_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int tmpvalue;
+                        //R
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //G
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //B
+                        tmpvalue = (int)(((float)(0x0fff & (*src_word)) / 
4095.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //X = 0xffff
+                        *dest_data = 0xffff;
+                        dest_data++;
+                    }
+                }
+            }
+            break;
+        case 10:
+            if (hasAlphaChannel) {
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(src + (y * stride));
+                    uint16_t *dest_data = reinterpret_cast<uint16_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int tmpvalue;
+                        //R
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //G
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //B
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //A
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                    }
+                }
+            } else { //no alpha channel
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint16_t *src_word = reinterpret_cast<const uint16_t 
*>(src + (y * stride));
+                    uint16_t *dest_data = reinterpret_cast<uint16_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int tmpvalue;
+                        //R
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //G
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //B
+                        tmpvalue = (int)(((float)(0x03ff & (*src_word)) / 
1023.0f) * 65535.0f + 0.5f);
+                        tmpvalue = qBound(0, tmpvalue, 65535);
+                        *dest_data = (uint16_t) tmpvalue;
+                        src_word++;
+                        dest_data++;
+                        //X = 0xffff
+                        *dest_data = 0xffff;
+                        dest_data++;
+                    }
+                }
+            }
+            break;
+        case 8:
+            if (hasAlphaChannel) {
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint8_t *src_byte = src + (y * stride);
+                    uint32_t *dest_pixel = reinterpret_cast<uint32_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int red = *src_byte++;
+                        int green = *src_byte++;
+                        int blue = *src_byte++;
+                        int alpha = *src_byte++;
+                        *dest_pixel = qRgba(red, green, blue, alpha);
+                        dest_pixel++;
+                    }
+                }
+            } else { //no alpha channel
+                for (int y = 0; y < imageHeight; y++) {
+                    const uint8_t *src_byte = src + (y * stride);
+                    uint32_t *dest_pixel = reinterpret_cast<uint32_t 
*>(m_current_image.scanLine(y));
+                    for (int x = 0; x < imageWidth; x++) {
+                        int red = *src_byte++;
+                        int green = *src_byte++;
+                        int blue = *src_byte++;
+                        *dest_pixel = qRgb(red, green, blue);
+                        dest_pixel++;
+                    }
+                }
+
+            }
+            break;
+        default:
+            m_parseState = ParseHeicError;
+            qWarning() << "Unsupported bit depth:" << bit_depth;
+            return false;
+            break;
+        }
+
+        heif_color_profile_type profileType = 
heif_image_handle_get_color_profile_type(handle.get_raw_image_handle());
+        struct heif_error err;
+        if (profileType == heif_color_profile_type_prof || profileType == 
heif_color_profile_type_rICC) {
+            int rawProfileSize = (int) 
heif_image_handle_get_raw_color_profile_size(handle.get_raw_image_handle());
+            if (rawProfileSize > 0) {
+                QByteArray ba(rawProfileSize, 0);
+                err = 
heif_image_handle_get_raw_color_profile(handle.get_raw_image_handle(), 
ba.data());
+                if (err.code) {
+                    qWarning() << "icc profile loading failed";
+                } else {
+                    
m_current_image.setColorSpace(QColorSpace::fromIccProfile(ba));
+                    if (!m_current_image.colorSpace().isValid()) {
+                        qWarning() << "icc profile is invalid";
+                    }
+                }
+            } else {
+                qWarning() << "icc profile is empty";
+            }
+
+        } else if (profileType == heif_color_profile_type_nclx) {
+            struct heif_color_profile_nclx *nclx = nullptr;
+            err = 
heif_image_handle_get_nclx_color_profile(handle.get_raw_image_handle(), &nclx);
+            if (err.code || !nclx) {
+                qWarning() << "nclx profile loading failed";
+            } else {
+                const QPointF redPoint(nclx->color_primary_red_x, 
nclx->color_primary_red_y);
+                const QPointF greenPoint(nclx->color_primary_green_x, 
nclx->color_primary_green_y);
+                const QPointF bluePoint(nclx->color_primary_blue_x, 
nclx->color_primary_blue_y);
+                const QPointF whitePoint(nclx->color_primary_white_x, 
nclx->color_primary_white_y);
+
+                QColorSpace::TransferFunction q_trc = 
QColorSpace::TransferFunction::Custom;
+                float q_trc_gamma = 0.0f;
+
+                switch (nclx->transfer_characteristics) {
+                case 4:
+                    q_trc = QColorSpace::TransferFunction::Gamma;
+                    q_trc_gamma = 2.2f;
+                    break;
+                case 5:
+                    q_trc = QColorSpace::TransferFunction::Gamma;
+                    q_trc_gamma = 2.8f;
+                    break;
+                case 8:
+                    q_trc = QColorSpace::TransferFunction::Linear;
+                    break;
+                case 2:
+                case 13:
+                    q_trc =  QColorSpace::TransferFunction::SRgb;
+                    break;
+                default:
+                    qWarning("CICP color_primaries: %d, 
transfer_characteristics: %d\nThe colorspace is unsupported by this plug-in 
yet.",
+                             nclx->color_primaries, 
nclx->transfer_characteristics);
+                    q_trc = QColorSpace::TransferFunction::SRgb;
+                    break;
+                }
+
+                if (q_trc != QColorSpace::TransferFunction::Custom) {   //we 
create new colorspace using Qt
+                    switch (nclx->color_primaries) {
+                    case 1:
+                    case 2:
+                        
m_current_image.setColorSpace(QColorSpace(QColorSpace::Primaries::SRgb, q_trc, 
q_trc_gamma));
+                        break;
+                    case 12:
+                        
m_current_image.setColorSpace(QColorSpace(QColorSpace::Primaries::DciP3D65, 
q_trc, q_trc_gamma));
+                        break;
+                    default:
+                        m_current_image.setColorSpace(QColorSpace(whitePoint, 
redPoint, greenPoint, bluePoint, q_trc, q_trc_gamma));
+                        break;
+                    }
+                }
+                heif_nclx_color_profile_free(nclx);
+
+                if (!m_current_image.colorSpace().isValid()) {
+                    qWarning() << "invalid color profile created from NCLX";
+                }
+
+            }
+
+        } else {
+            m_current_image.setColorSpace(QColorSpace(QColorSpace::SRgb));
+        }
+
+    } catch (const heif::Error &err) {
+        m_parseState = ParseHeicError;
+        qWarning() << "libheif error:" << err.get_message().c_str();
+        return false;
+    }
+
+    m_parseState = ParseHeicSuccess;
+    return true;
+}
+
+QImageIOPlugin::Capabilities HEIFPlugin::capabilities(QIODevice *device, const 
QByteArray &format) const
+{
+    if (format == "heif" || format == "heic") {
+        Capabilities format_cap;
+        if (heif_have_decoder_for_format(heif_compression_HEVC)) {
+            format_cap |= CanRead;
+        }
+        if (heif_have_encoder_for_format(heif_compression_HEVC)) {
+            format_cap |= CanWrite;
+        }
+        return format_cap;
+    }
+    if (!format.isEmpty()) {
+        return {};
+    }
+    if (!device->isOpen()) {
+        return {};
+    }
+
+    Capabilities cap;
+    if (device->isReadable() && HEIFHandler::canRead(device) && 
heif_have_decoder_for_format(heif_compression_HEVC)) {
+        cap |= CanRead;
+    }
+
+    if (device->isWritable() && 
heif_have_encoder_for_format(heif_compression_HEVC)) {
+        cap |= CanWrite;
+    }
+    return cap;
+}
+
+QImageIOHandler *HEIFPlugin::create(QIODevice *device, const QByteArray 
&format) const
+{
+    QImageIOHandler *handler = new HEIFHandler;
+    handler->setDevice(device);
+    handler->setFormat(format);
+    return handler;
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/heif.desktop 
new/kimageformats-5.80.0/src/imageformats/heif.desktop
--- old/kimageformats-5.79.0/src/imageformats/heif.desktop      1970-01-01 
01:00:00.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/heif.desktop      2021-03-04 
22:57:23.000000000 +0100
@@ -0,0 +1,7 @@
+[Desktop Entry]
+Type=Service
+X-KDE-ServiceTypes=QImageIOPlugins
+X-KDE-ImageFormat=heif
+X-KDE-MimeType=image/heif
+X-KDE-Read=true
+X-KDE-Write=true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/heif.json 
new/kimageformats-5.80.0/src/imageformats/heif.json
--- old/kimageformats-5.79.0/src/imageformats/heif.json 1970-01-01 
01:00:00.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/heif.json 2021-03-04 
22:57:23.000000000 +0100
@@ -0,0 +1,4 @@
+{
+    "Keys": [ "heif", "heic" ],
+    "MimeTypes": [ "image/heif", "image/heif" ]
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.79.0/src/imageformats/heif_p.h 
new/kimageformats-5.80.0/src/imageformats/heif_p.h
--- old/kimageformats-5.79.0/src/imageformats/heif_p.h  1970-01-01 
01:00:00.000000000 +0100
+++ new/kimageformats-5.80.0/src/imageformats/heif_p.h  2021-03-04 
22:57:23.000000000 +0100
@@ -0,0 +1,57 @@
+/*
+    High Efficiency Image File Format (HEIF) support for QImage.
+
+    SPDX-FileCopyrightText: 2020 Sirius Bakke <[email protected]>
+    SPDX-FileCopyrightText: 2021 Daniel Novomesky <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.0-or-later
+*/
+
+#ifndef KIMG_HEIF_P_H
+#define KIMG_HEIF_P_H
+
+#include <QByteArray>
+#include <QImage>
+#include <QImageIOPlugin>
+
+class HEIFHandler : public QImageIOHandler
+{
+public:
+    HEIFHandler();
+
+    bool canRead() const override;
+    bool read(QImage *image) override;
+    bool write(const QImage &image) override;
+
+    static bool canRead(QIODevice *device);
+
+    QVariant option(ImageOption option) const override;
+    void setOption(ImageOption option, const QVariant &value) override;
+    bool supportsOption(ImageOption option) const override;
+private:
+    static bool isSupportedBMFFType(const QByteArray &header);
+    bool ensureParsed() const;
+    bool ensureDecoder();
+
+    enum ParseHeicState {
+        ParseHeicError = -1,
+        ParseHeicNotParsed = 0,
+        ParseHeicSuccess = 1
+    };
+
+    ParseHeicState m_parseState;
+    int m_quality;
+    QImage m_current_image;
+};
+
+class HEIFPlugin : public QImageIOPlugin
+{
+    Q_OBJECT
+    Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QImageIOHandlerFactoryInterface" 
FILE "heif.json")
+
+public:
+    Capabilities capabilities(QIODevice *device, const QByteArray &format) 
const override;
+    QImageIOHandler *create(QIODevice *device, const QByteArray &format = 
QByteArray()) const override;
+};
+
+#endif // KIMG_HEIF_P_H

Reply via email to