Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package kimageformats for openSUSE:Factory 
checked in at 2022-03-14 19:34:32
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/kimageformats (Old)
 and      /work/SRC/openSUSE:Factory/.kimageformats.new.25692 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "kimageformats"

Mon Mar 14 19:34:32 2022 rev:104 rq:961252 version:5.92.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/kimageformats/kimageformats.changes      
2022-02-24 18:21:51.494683870 +0100
+++ /work/SRC/openSUSE:Factory/.kimageformats.new.25692/kimageformats.changes   
2022-03-14 19:35:58.502047873 +0100
@@ -1,0 +2,13 @@
+Mon Mar  7 09:26:59 UTC 2022 - Christophe Giboudeaux <[email protected]>
+
+- Update to 5.92.0
+  * New feature release
+  * For more details please see:
+  * https://kde.org/announcements/frameworks/5/5.92.0
+- Changes since 5.91.0:
+  * Add Qt6 Android CI
+  * Add write tests for heif/avif/jxl
+  * jxl: encoding improvements
+  * avif: adjust dimension and memory limits
+
+-------------------------------------------------------------------

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

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

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

Other differences:
------------------
++++++ kimageformats.spec ++++++
--- /var/tmp/diff_new_pack.IYbKnk/_old  2022-03-14 19:35:59.134048631 +0100
+++ /var/tmp/diff_new_pack.IYbKnk/_new  2022-03-14 19:35:59.138048636 +0100
@@ -22,7 +22,7 @@
 %if 0%{?suse_version} > 1500 || (0%{?is_opensuse} && 0%{?sle_version} >= 
150300)
 %define with_heif 1
 %endif
-%define _tar_path 5.91
+%define _tar_path 5.92
 # Full KF5 version (e.g. 5.33.0)
 %{!?_kf5_version: %global _kf5_version %{version}}
 # Last major and minor KF5 version (e.g. 5.33)
@@ -30,7 +30,7 @@
 # Only needed for the package signature condition
 %bcond_without released
 Name:           kimageformats
-Version:        5.91.0
+Version:        5.92.0
 Release:        0
 Summary:        Image format plugins for Qt
 License:        LGPL-2.1-or-later


++++++ kimageformats-5.91.0.tar.xz -> kimageformats-5.92.0.tar.xz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/.gitlab-ci.yml 
new/kimageformats-5.92.0/.gitlab-ci.yml
--- old/kimageformats-5.91.0/.gitlab-ci.yml     2022-02-05 16:14:16.000000000 
+0100
+++ new/kimageformats-5.92.0/.gitlab-ci.yml     2022-03-05 12:15:00.000000000 
+0100
@@ -6,3 +6,4 @@
   - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android.yml
   - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/freebsd.yml
   - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/linux-qt6.yml
+  - 
https://invent.kde.org/sysadmin/ci-utilities/raw/master/gitlab-templates/android-qt6.yml
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/CMakeLists.txt 
new/kimageformats-5.92.0/CMakeLists.txt
--- old/kimageformats-5.91.0/CMakeLists.txt     2022-02-05 16:14:16.000000000 
+0100
+++ new/kimageformats-5.92.0/CMakeLists.txt     2022-03-05 12:15:00.000000000 
+0100
@@ -3,7 +3,7 @@
 project(KImageFormats)
 
 include(FeatureSummary)
-find_package(ECM 5.91.0  NO_MODULE)
+find_package(ECM 5.92.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)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/autotests/CMakeLists.txt 
new/kimageformats-5.92.0/autotests/CMakeLists.txt
--- old/kimageformats-5.91.0/autotests/CMakeLists.txt   2022-02-05 
16:14:16.000000000 +0100
+++ new/kimageformats-5.92.0/autotests/CMakeLists.txt   2022-03-05 
12:15:00.000000000 +0100
@@ -30,6 +30,12 @@
 endmacro()
 
 macro(kimageformats_write_tests)
+    cmake_parse_arguments(KIF_RT "" "FUZZ" "" ${ARGN})
+    set(_fuzzarg)
+    if (KIF_RT_FUZZ)
+        set(_fuzzarg -f ${KIF_RT_FUZZ})
+    endif()
+
     if (NOT TARGET writetest)
         add_executable(writetest writetest.cpp)
         target_link_libraries(writetest Qt${QT_MAJOR_VERSION}::Gui)
@@ -37,16 +43,22 @@
             PRIVATE IMAGEDIR="${CMAKE_CURRENT_SOURCE_DIR}/write")
         ecm_mark_as_test(writetest)
     endif()
-    foreach(_testname ${ARGN})
+    foreach(_testname ${KIF_RT_UNPARSED_ARGUMENTS})
         string(REGEX MATCH "-lossless$" _is_lossless "${_testname}")
+        string(REGEX MATCH "-nodatacheck" _is_no_data_check "${_testname}")
         unset(lossless_arg)
+        unset(no_data_check_arg)
         if (_is_lossless)
             set(lossless_arg "--lossless")
             string(REGEX REPLACE "-lossless$" "" _testname "${_testname}")
         endif()
+        if (_is_no_data_check)
+            set(no_data_check_arg "--no-data-check")
+            string(REGEX REPLACE "-nodatacheck$" "" _testname "${_testname}")
+        endif()
         add_test(
             NAME kimageformats-write-${_testname}
-            COMMAND writetest ${lossless_arg} ${_testname}
+            COMMAND writetest ${lossless_arg} ${no_data_check_arg} ${_fuzzarg} 
${_testname}
         )
     endforeach(_testname)
 endmacro()
@@ -74,18 +86,29 @@
     kimageformats_read_tests(
         avif
     )
+    # because the plug-ins use RGB->YUV conversion which sometimes results in 
1 value difference.
+    kimageformats_write_tests(FUZZ 1
+        avif-nodatacheck-lossless
+    )
 endif()
 
 if (LibHeif_FOUND)
     kimageformats_read_tests(
         heif
     )
+    # because the plug-ins use RGB->YUV conversion which sometimes results in 
1 value difference.
+    kimageformats_write_tests(FUZZ 1
+        heif-nodatacheck-lossless
+    )
 endif()
 
 if (LibJXL_FOUND AND LibJXLThreads_FOUND)
     kimageformats_read_tests(
         jxl
     )
+    kimageformats_write_tests(
+        jxl-nodatacheck-lossless
+    )
 endif()
 
 # Allow some fuzziness when reading this formats, to allow for
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/autotests/fuzzyeq.cpp 
new/kimageformats-5.92.0/autotests/fuzzyeq.cpp
--- old/kimageformats-5.91.0/autotests/fuzzyeq.cpp      1970-01-01 
01:00:00.000000000 +0100
+++ new/kimageformats-5.92.0/autotests/fuzzyeq.cpp      2022-03-05 
12:15:00.000000000 +0100
@@ -0,0 +1,37 @@
+/*
+    SPDX-FileCopyrightText: 2014 Alex Merry <[email protected]>
+
+    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR 
LicenseRef-KDE-Accepted-LGPL
+*/
+
+template<class Trait>
+static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
+{
+    Q_ASSERT(im1.format() == im2.format());
+    Q_ASSERT(im1.depth() == 24 || im1.depth() == 32 || im1.depth() == 64);
+
+    const int height = im1.height();
+    const int width = im1.width();
+    for (int i = 0; i < height; ++i) {
+        const Trait *line1 = reinterpret_cast<const Trait *>(im1.scanLine(i));
+        const Trait *line2 = reinterpret_cast<const Trait *>(im2.scanLine(i));
+        for (int j = 0; j < width; ++j) {
+            if (line1[j] > line2[j]) {
+                if (line1[j] - line2[j] > fuzziness) {
+                    return false;
+                }
+            } else {
+                if (line2[j] - line1[j] > fuzziness) {
+                    return false;
+                }
+            }
+        }
+    }
+    return true;
+}
+
+// allow each byte to be different by up to 1, to allow for rounding errors
+static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
+{
+    return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness) : 
fuzzyeq<quint8>(im1, im2, fuzziness);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/autotests/readtest.cpp 
new/kimageformats-5.92.0/autotests/readtest.cpp
--- old/kimageformats-5.91.0/autotests/readtest.cpp     2022-02-05 
16:14:16.000000000 +0100
+++ new/kimageformats-5.92.0/autotests/readtest.cpp     2022-03-05 
12:15:00.000000000 +0100
@@ -16,6 +16,8 @@
 
 #include "../tests/format-enum.h"
 
+#include "fuzzyeq.cpp"
+
 static void writeImageData(const char *name, const QString &filename, const 
QImage &image)
 {
     QFile file(filename);
@@ -31,38 +33,6 @@
     }
 }
 
-template<class Trait>
-static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
-{
-    Q_ASSERT(im1.format() == im2.format());
-    Q_ASSERT(im1.depth() == 24 || im1.depth() == 32 || im1.depth() == 64);
-
-    const int height = im1.height();
-    const int width = im1.width();
-    for (int i = 0; i < height; ++i) {
-        const Trait *line1 = reinterpret_cast<const Trait *>(im1.scanLine(i));
-        const Trait *line2 = reinterpret_cast<const Trait *>(im2.scanLine(i));
-        for (int j = 0; j < width; ++j) {
-            if (line1[j] > line2[j]) {
-                if (line1[j] - line2[j] > fuzziness) {
-                    return false;
-                }
-            } else {
-                if (line2[j] - line1[j] > fuzziness) {
-                    return false;
-                }
-            }
-        }
-    }
-    return true;
-}
-
-// allow each byte to be different by up to 1, to allow for rounding errors
-static bool fuzzyeq(const QImage &im1, const QImage &im2, uchar fuzziness)
-{
-    return (im1.depth() == 64) ? fuzzyeq<quint16>(im1, im2, fuzziness) : 
fuzzyeq<quint8>(im1, im2, fuzziness);
-}
-
 // Returns the original format if we support, or returns
 // format which we preferred to use for `fuzzyeq()`.
 // We do only support formats with 8-bits/16-bits pre pixel.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/autotests/writetest.cpp 
new/kimageformats-5.92.0/autotests/writetest.cpp
--- old/kimageformats-5.91.0/autotests/writetest.cpp    2022-02-05 
16:14:16.000000000 +0100
+++ new/kimageformats-5.92.0/autotests/writetest.cpp    2022-03-05 
12:15:00.000000000 +0100
@@ -16,6 +16,8 @@
 #include <QImageWriter>
 #include <QTextStream>
 
+#include "fuzzyeq.cpp"
+
 int main(int argc, char **argv)
 {
     QCoreApplication app(argc, argv);
@@ -31,7 +33,13 @@
     parser.addPositionalArgument(QStringLiteral("format"), 
QStringLiteral("format to test."));
     QCommandLineOption lossless(QStringList() << QStringLiteral("l") << 
QStringLiteral("lossless"),
                                 QStringLiteral("Check that reading back the 
data gives the same image."));
+    QCommandLineOption ignoreDataCheck({QStringLiteral("no-data-check")}, 
QStringLiteral("Don't check that write data is exactly the same."));
+    QCommandLineOption fuzz(QStringList() << QStringLiteral("f") << 
QStringLiteral("fuzz"),
+                            QStringLiteral("Allow for some deviation in ARGB 
data."),
+                            QStringLiteral("max"));
     parser.addOption(lossless);
+    parser.addOption(ignoreDataCheck);
+    parser.addOption(fuzz);
 
     parser.process(app);
 
@@ -44,11 +52,26 @@
         parser.showHelp(1);
     }
 
+    uchar fuzziness = 0;
+    if (parser.isSet(fuzz)) {
+        bool ok;
+        uint fuzzarg = parser.value(fuzz).toUInt(&ok);
+        if (!ok || fuzzarg > 255) {
+            QTextStream(stderr) << "Error: max fuzz argument must be a number 
between 0 and 255\n";
+            parser.showHelp(1);
+        }
+        fuzziness = uchar(fuzzarg);
+    }
+
     QString suffix = args.at(0);
     QByteArray format = suffix.toLatin1();
 
     QDir imgdir(QStringLiteral(IMAGEDIR));
-    imgdir.setNameFilters(QStringList(QLatin1String("*.") + suffix));
+    if (parser.isSet(ignoreDataCheck)) {
+        imgdir.setNameFilters({QLatin1String("*.png")});
+    } else {
+        imgdir.setNameFilters(QStringList(QLatin1String("*.") + suffix));
+    }
     imgdir.setFilter(QDir::Files);
 
     int passed = 0;
@@ -58,8 +81,13 @@
                         << "Starting basic write tests for " << suffix << " 
images *********\n";
     const QFileInfoList lstImgDir = imgdir.entryInfoList();
     for (const QFileInfo &fi : lstImgDir) {
-        int suffixPos = fi.filePath().count() - suffix.count();
-        QString pngfile = fi.filePath().replace(suffixPos, suffix.count(), 
QStringLiteral("png"));
+        QString pngfile;
+        if (parser.isSet(ignoreDataCheck)) {
+            pngfile = fi.filePath();
+        } else {
+            int suffixPos = fi.filePath().count() - suffix.count();
+            pngfile = fi.filePath().replace(suffixPos, suffix.count(), 
QStringLiteral("png"));
+        }
         QString pngfilename = QFileInfo(pngfile).fileName();
 
         QImageReader pngReader(pngfile, "png");
@@ -70,29 +98,13 @@
             continue;
         }
 
-        QFile expFile(fi.filePath());
-        if (!expFile.open(QIODevice::ReadOnly)) {
-            QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could not 
open " << fi.fileName() << ": " << expFile.errorString() << "\n";
-            ++failed;
-            continue;
-        }
-        QByteArray expData = expFile.readAll();
-        if (expData.isEmpty()) {
-            // check if there was actually anything to read
-            expFile.reset();
-            char buf[1];
-            qint64 result = expFile.read(buf, 1);
-            if (result < 0) {
-                QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could 
not load " << fi.fileName() << ": " << expFile.errorString() << "\n";
-                ++failed;
-                continue;
-            }
-        }
-
         QByteArray writtenData;
         {
             QBuffer buffer(&writtenData);
             QImageWriter imgWriter(&buffer, format.constData());
+            if (parser.isSet(lossless)) {
+                imgWriter.setQuality(100);
+            }
             if (!imgWriter.write(pngImage)) {
                 QTextStream(stdout) << "FAIL : " << fi.fileName() << ": failed 
to write image data\n";
                 ++failed;
@@ -100,10 +112,31 @@
             }
         }
 
-        if (expData != writtenData) {
-            QTextStream(stdout) << "FAIL : " << fi.fileName() << ": written 
data differs from " << fi.fileName() << "\n";
-            ++failed;
-            continue;
+        if (!parser.isSet(ignoreDataCheck)) {
+            QFile expFile(fi.filePath());
+            if (!expFile.open(QIODevice::ReadOnly)) {
+                QTextStream(stdout) << "ERROR: " << fi.fileName() << ": could 
not open " << fi.fileName() << ": " << expFile.errorString() << "\n";
+                ++failed;
+                continue;
+            }
+            QByteArray expData = expFile.readAll();
+            if (expData.isEmpty()) {
+                // check if there was actually anything to read
+                expFile.reset();
+                char buf[1];
+                qint64 result = expFile.read(buf, 1);
+                if (result < 0) {
+                    QTextStream(stdout) << "ERROR: " << fi.fileName() << ": 
could not load " << fi.fileName() << ": " << expFile.errorString() << "\n";
+                    ++failed;
+                    continue;
+                }
+            }
+
+            if (expData != writtenData) {
+                QTextStream(stdout) << "FAIL : " << fi.fileName() << ": 
written data differs from " << fi.fileName() << "\n";
+                ++failed;
+                continue;
+            }
         }
 
         QImage reReadImage;
@@ -119,8 +152,18 @@
         }
 
         if (parser.isSet(lossless)) {
-            if (pngImage != reReadImage) {
+            if (!fuzzyeq(pngImage, reReadImage, fuzziness)) {
                 QTextStream(stdout) << "FAIL : " << fi.fileName() << ": 
re-reading the data resulted in a different image\n";
+                if (pngImage.size() == reReadImage.size()) {
+                    for (int i = 0; i < pngImage.width(); ++i) {
+                        for (int j = 0; j < pngImage.height(); ++j) {
+                            if (pngImage.pixel(i, j) != reReadImage.pixel(i, 
j)) {
+                                QTextStream(stdout) << "Pixel is different " 
<< i << ',' << j << ' ' << pngImage.pixel(i, j) << ' ' << reReadImage.pixel(i, 
j)
+                                                    << '\n';
+                            }
+                        }
+                    }
+                }
                 ++failed;
                 continue;
             }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/src/imageformats/avif.cpp 
new/kimageformats-5.92.0/src/imageformats/avif.cpp
--- old/kimageformats-5.91.0/src/imageformats/avif.cpp  2022-02-05 
16:14:16.000000000 +0100
+++ new/kimageformats-5.92.0/src/imageformats/avif.cpp  2022-03-05 
12:15:00.000000000 +0100
@@ -133,7 +133,7 @@
         m_container_width = m_decoder->image->width;
         m_container_height = m_decoder->image->height;
 
-        if ((m_container_width > 32768) || (m_container_height > 32768)) {
+        if ((m_container_width > 65535) || (m_container_height > 65535)) {
             qWarning("AVIF image (%dx%d) is too large!", m_container_width, 
m_container_height);
             m_parseState = ParseAvifError;
             return false;
@@ -145,6 +145,12 @@
             return false;
         }
 
+        if (m_container_width > ((16384 * 16384) / m_container_height)) {
+            qWarning("AVIF image (%dx%d) has more than 256 megapixels!", 
m_container_width, m_container_height);
+            m_parseState = ParseAvifError;
+            return false;
+        }
+
         m_parseState = ParseAvifSuccess;
         if (decode_one_frame()) {
             return true;
@@ -417,12 +423,26 @@
 bool QAVIFHandler::write(const QImage &image)
 {
     if (image.format() == QImage::Format_Invalid) {
-        qWarning("No image data to save");
+        qWarning("No image data to save!");
         return false;
     }
 
-    if ((image.width() > 32768) || (image.height() > 32768)) {
-        qWarning("Image is too large");
+    if ((image.width() > 0) && (image.height() > 0)) {
+        if ((image.width() > 65535) || (image.height() > 65535)) {
+            qWarning("Image (%dx%d) is too large to save!", image.width(), 
image.height());
+            return false;
+        }
+
+        if (image.width() > ((16384 * 16384) / image.height())) {
+            qWarning("Image (%dx%d) will not be saved because it has more than 
256 megapixels!", image.width(), image.height());
+            return false;
+        }
+
+        if ((image.width() > 32768) || (image.height() > 32768)) {
+            qWarning("Image (%dx%d) has a dimension above 32768 pixels, saved 
AVIF may not work in other software!", image.width(), image.height());
+        }
+    } else {
+        qWarning("Image has zero dimension!");
         return false;
     }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kimageformats-5.91.0/src/imageformats/jxl.cpp 
new/kimageformats-5.92.0/src/imageformats/jxl.cpp
--- old/kimageformats-5.91.0/src/imageformats/jxl.cpp   2022-02-05 
16:14:16.000000000 +0100
+++ new/kimageformats-5.92.0/src/imageformats/jxl.cpp   2022-03-05 
12:15:00.000000000 +0100
@@ -12,6 +12,7 @@
 #include "jxl_p.h"
 #include <jxl/encode.h>
 #include <jxl/thread_parallel_runner.h>
+#include <string.h>
 
 QJpegXLHandler::QJpegXLHandler()
     : m_parseState(ParseJpegXLNotParsed)
@@ -174,19 +175,30 @@
         return false;
     }
 
-    if (m_basicinfo.xsize > 32768 || m_basicinfo.ysize > 32768) {
+    if (m_basicinfo.xsize > 65535 || m_basicinfo.ysize > 65535) {
         qWarning("JXL image (%dx%d) is too large", m_basicinfo.xsize, 
m_basicinfo.ysize);
         m_parseState = ParseJpegXLError;
         return false;
-    } else if (sizeof(void *) <= 4) {
+    }
+
+    if (sizeof(void *) <= 4) {
         /* On 32bit systems, there is limited address space.
          * We skip imagess bigger than 8192 x 8192 pixels.
          * If we don't do it, abort() in libjxl may close whole application */
-        if ((m_basicinfo.xsize * m_basicinfo.ysize) > 67108864) {
+        if (m_basicinfo.xsize > ((8192 * 8192) / m_basicinfo.ysize)) {
             qWarning("JXL image (%dx%d) is too large for 32bit build of the 
plug-in", m_basicinfo.xsize, m_basicinfo.ysize);
             m_parseState = ParseJpegXLError;
             return false;
         }
+    } else {
+        /* On 64bit systems
+         * We skip images bigger than 16384 x 16384 pixels.
+         * It is an artificial limit not to use extreme amount of memory */
+        if (m_basicinfo.xsize > ((16384 * 16384) / m_basicinfo.ysize)) {
+            qWarning("JXL image (%dx%d) is bigger than security limit 256 
megapixels", m_basicinfo.xsize, m_basicinfo.ysize);
+            m_parseState = ParseJpegXLError;
+            return false;
+        }
     }
 
     m_parseState = ParseJpegXLBasicInfoParsed;
@@ -411,11 +423,59 @@
         return false;
     }
 
-    if ((image.width() > 32768) || (image.height() > 32768)) {
-        qWarning("Image is too large");
+    if ((image.width() > 0) && (image.height() > 0)) {
+        if ((image.width() > 65535) || (image.height() > 65535)) {
+            qWarning("Image (%dx%d) is too large to save!", image.width(), 
image.height());
+            return false;
+        }
+
+        if (sizeof(void *) <= 4) {
+            if (image.width() > ((8192 * 8192) / image.height())) {
+                qWarning("Image (%dx%d) is too large save via 32bit build of 
JXL plug-in", image.width(), image.height());
+                return false;
+            }
+        } else {
+            if (image.width() > ((16384 * 16384) / image.height())) {
+                qWarning("Image (%dx%d) will not be saved because it has more 
than 256 megapixels", image.width(), image.height());
+                return false;
+            }
+        }
+    } else {
+        qWarning("Image has zero dimension!");
         return false;
     }
 
+    int save_depth = 8; // 8 or 16
+    // depth detection
+    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 = 16;
+        break;
+    case QImage::Format_RGB32:
+    case QImage::Format_ARGB32:
+    case QImage::Format_ARGB32_Premultiplied:
+    case QImage::Format_RGB888:
+    case QImage::Format_RGBX8888:
+    case QImage::Format_RGBA8888:
+    case QImage::Format_RGBA8888_Premultiplied:
+        save_depth = 8;
+        break;
+    default:
+        if (image.depth() > 32) {
+            save_depth = 16;
+        } else {
+            save_depth = 8;
+        }
+        break;
+    }
+
     JxlEncoder *encoder = JxlEncoderCreate(nullptr);
     if (!encoder) {
         qWarning("Failed to create Jxl encoder");
@@ -456,16 +516,16 @@
     bool convert_color_profile;
     QByteArray iccprofile;
 
-    if (image.colorSpace().isValid()) {
+    if (image.colorSpace().isValid() && (m_quality < 100)) {
         if (image.colorSpace().primaries() != QColorSpace::Primaries::SRgb || 
image.colorSpace().transferFunction() != QColorSpace::TransferFunction::SRgb) {
             convert_color_profile = true;
         } else {
             convert_color_profile = false;
         }
-    } else { // no profile or Qt-unsupported ICC profile
+    } else { // lossless or no profile or Qt-unsupported ICC profile
         convert_color_profile = false;
         iccprofile = image.colorSpace().iccProfile();
-        if (iccprofile.size() > 0) {
+        if (iccprofile.size() > 0 || m_quality == 100) {
             output_info.uses_original_profile = 1;
         }
     }
@@ -474,19 +534,45 @@
     QImage::Format tmpformat;
     JxlEncoderStatus status;
 
-    pixel_format.data_type = JXL_TYPE_UINT16;
     pixel_format.endianness = JXL_NATIVE_ENDIAN;
     pixel_format.align = 0;
 
-    if (image.hasAlphaChannel()) {
-        tmpformat = QImage::Format_RGBA64;
-        pixel_format.num_channels = 4;
-        output_info.alpha_bits = 16;
-        output_info.num_extra_channels = 1;
-    } else {
-        tmpformat = QImage::Format_RGBX64;
-        pixel_format.num_channels = 3;
-        output_info.alpha_bits = 0;
+    output_info.intensity_target = 255.0f;
+    output_info.orientation = JXL_ORIENT_IDENTITY;
+    output_info.num_color_channels = 3;
+    output_info.animation.tps_numerator = 10;
+    output_info.animation.tps_denominator = 1;
+
+    if (save_depth > 8) { // 16bit depth
+        pixel_format.data_type = JXL_TYPE_UINT16;
+
+        output_info.bits_per_sample = 16;
+
+        if (image.hasAlphaChannel()) {
+            tmpformat = QImage::Format_RGBA64;
+            pixel_format.num_channels = 4;
+            output_info.alpha_bits = 16;
+            output_info.num_extra_channels = 1;
+        } else {
+            tmpformat = QImage::Format_RGBX64;
+            pixel_format.num_channels = 3;
+            output_info.alpha_bits = 0;
+        }
+    } else { // 8bit depth
+        pixel_format.data_type = JXL_TYPE_UINT8;
+
+        output_info.bits_per_sample = 8;
+
+        if (image.hasAlphaChannel()) {
+            tmpformat = QImage::Format_RGBA8888;
+            pixel_format.num_channels = 4;
+            output_info.alpha_bits = 8;
+            output_info.num_extra_channels = 1;
+        } else {
+            tmpformat = QImage::Format_RGB888;
+            pixel_format.num_channels = 3;
+            output_info.alpha_bits = 0;
+        }
     }
 
     const QImage tmpimage =
@@ -494,7 +580,7 @@
 
     const size_t xsize = tmpimage.width();
     const size_t ysize = tmpimage.height();
-    const size_t buffer_size = 2 * pixel_format.num_channels * xsize * ysize;
+    const size_t buffer_size = (save_depth > 8) ? (2 * 
pixel_format.num_channels * xsize * ysize) : (pixel_format.num_channels * xsize 
* ysize);
 
     if (xsize == 0 || ysize == 0 || tmpimage.isNull()) {
         qWarning("Unable to allocate memory for output image");
@@ -507,12 +593,6 @@
 
     output_info.xsize = tmpimage.width();
     output_info.ysize = tmpimage.height();
-    output_info.bits_per_sample = 16;
-    output_info.intensity_target = 255.0f;
-    output_info.orientation = JXL_ORIENT_IDENTITY;
-    output_info.num_color_channels = 3;
-    output_info.animation.tps_numerator = 10;
-    output_info.animation.tps_denominator = 1;
 
     status = JxlEncoderSetBasicInfo(encoder, &output_info);
     if (status != JXL_ENC_SUCCESS) {
@@ -546,39 +626,60 @@
         }
     }
 
-    if (image.hasAlphaChannel()) {
+    if (image.hasAlphaChannel() || ((save_depth == 8) && (xsize % 4 == 0))) {
         status = JxlEncoderAddImageFrame(encoder_options, &pixel_format, (void 
*)tmpimage.constBits(), buffer_size);
     } else {
-        uint16_t *tmp_buffer = new (std::nothrow) uint16_t[3 * xsize * ysize];
-        if (!tmp_buffer) {
-            qWarning("Memory allocation error");
-            if (runner) {
-                JxlThreadParallelRunnerDestroy(runner);
+        if (save_depth > 8) { // 16bit depth without alpha channel
+            uint16_t *tmp_buffer = new (std::nothrow) uint16_t[3 * xsize * 
ysize];
+            if (!tmp_buffer) {
+                qWarning("Memory allocation error");
+                if (runner) {
+                    JxlThreadParallelRunnerDestroy(runner);
+                }
+                JxlEncoderDestroy(encoder);
+                return false;
+            }
+
+            uint16_t *dest_pixels = tmp_buffer;
+            for (int y = 0; y < tmpimage.height(); y++) {
+                const uint16_t *src_pixels = reinterpret_cast<const uint16_t 
*>(tmpimage.constScanLine(y));
+                for (int x = 0; x < tmpimage.width(); x++) {
+                    // R
+                    *dest_pixels = *src_pixels;
+                    dest_pixels++;
+                    src_pixels++;
+                    // G
+                    *dest_pixels = *src_pixels;
+                    dest_pixels++;
+                    src_pixels++;
+                    // B
+                    *dest_pixels = *src_pixels;
+                    dest_pixels++;
+                    src_pixels += 2; // skipalpha
+                }
+            }
+            status = JxlEncoderAddImageFrame(encoder_options, &pixel_format, 
(void *)tmp_buffer, buffer_size);
+            delete[] tmp_buffer;
+        } else { // 8bit depth without alpha channel
+            uchar *tmp_buffer8 = new (std::nothrow) uchar[3 * xsize * ysize];
+            if (!tmp_buffer8) {
+                qWarning("Memory allocation error");
+                if (runner) {
+                    JxlThreadParallelRunnerDestroy(runner);
+                }
+                JxlEncoderDestroy(encoder);
+                return false;
             }
-            JxlEncoderDestroy(encoder);
-            return false;
-        }
 
-        uint16_t *dest_pixels = tmp_buffer;
-        for (int y = 0; y < tmpimage.height(); y++) {
-            const uint16_t *src_pixels = reinterpret_cast<const uint16_t 
*>(tmpimage.constScanLine(y));
-            for (int x = 0; x < tmpimage.width(); x++) {
-                // R
-                *dest_pixels = *src_pixels;
-                dest_pixels++;
-                src_pixels++;
-                // G
-                *dest_pixels = *src_pixels;
-                dest_pixels++;
-                src_pixels++;
-                // B
-                *dest_pixels = *src_pixels;
-                dest_pixels++;
-                src_pixels += 2; // skipalpha
+            uchar *dest_pixels8 = tmp_buffer8;
+            const size_t rowbytes = 3 * xsize;
+            for (int y = 0; y < tmpimage.height(); y++) {
+                memcpy(dest_pixels8, tmpimage.constScanLine(y), rowbytes);
+                dest_pixels8 += rowbytes;
             }
+            status = JxlEncoderAddImageFrame(encoder_options, &pixel_format, 
(void *)tmp_buffer8, buffer_size);
+            delete[] tmp_buffer8;
         }
-        status = JxlEncoderAddImageFrame(encoder_options, &pixel_format, (void 
*)tmp_buffer, buffer_size);
-        delete[] tmp_buffer;
     }
 
     if (status == JXL_ENC_ERROR) {

Reply via email to