OSDN Git Service

implement size option for QPngHandler spng
authorIvailo Monev <xakepa10@gmail.com>
Wed, 24 May 2023 03:13:20 +0000 (06:13 +0300)
committerIvailo Monev <xakepa10@gmail.com>
Wed, 24 May 2023 03:13:20 +0000 (06:13 +0300)
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
src/gui/image/qkathandler.cpp
src/gui/image/qpnghandler.cpp
src/gui/image/qpnghandler_p.h
src/gui/image/qppmhandler.cpp
src/gui/image/qxpmhandler.cpp

index a817951..d1e4237 100644 (file)
@@ -57,8 +57,9 @@ bool QKatHandler::canRead(QIODevice *device)
     }
 
     QSTACKARRAY(char, head, 5);
-    if (device->peek(head, sizeof(head)) != sizeof(head))
+    if (device->peek(head, sizeof(head)) != sizeof(head)) {
         return false;
+    }
 
     return (::memcmp(head, "KATIE", 5) == 0);
 }
index da2feb3..77cb3f9 100644 (file)
@@ -60,7 +60,7 @@ int spng_write_proc(spng_ctx *ctx, void *user, void *dst_src, size_t length)
 
 
 QPngHandler::QPngHandler()
-    : m_compression(1)
+    : m_complevel(1)
 {
 }
 
@@ -164,7 +164,7 @@ bool QPngHandler::write(const QImage &image)
         return false;
     }
 
-    spngresult = spng_set_option(spngctx, SPNG_IMG_COMPRESSION_LEVEL, m_compression);
+    spngresult = spng_set_option(spngctx, SPNG_IMG_COMPRESSION_LEVEL, m_complevel);
     if (Q_UNLIKELY(spngresult != SPNG_OK)) {
         qWarning("QPngHandler::write() Could not set image compression level: %s", spng_strerror(spngresult));
         spng_ctx_free(spngctx);
@@ -187,24 +187,71 @@ bool QPngHandler::write(const QImage &image)
     return true;
 }
 
-bool QPngHandler::supportsOption(QImageIOHandler::ImageOption option) const
+QVariant QPngHandler::option(QImageIOHandler::ImageOption option) const
 {
-    return (option == QImageIOHandler::CompressionLevel);
+    if (option == QImageIOHandler::Size) {
+        const qint64 devicepos = device()->pos();
+
+        spng_ctx *spngctx = spng_ctx_new(static_cast<spng_ctx_flags>(0));
+        if (Q_UNLIKELY(!spngctx)) {
+            qWarning("QPngHandler::option() Could not create context");
+            return false;
+        }
+
+        int spngresult = spng_set_png_stream(spngctx, spng_read_proc, device());
+        if (Q_UNLIKELY(spngresult != SPNG_OK)) {
+            qWarning("QPngHandler::option() Could not set stream: %s", spng_strerror(spngresult));
+            spng_ctx_free(spngctx);
+            return false;
+        }
+
+        struct spng_ihdr spngihdr;
+        ::memset(&spngihdr, 0, sizeof(struct spng_ihdr));
+        spngresult = spng_get_ihdr(spngctx, &spngihdr);
+        if (Q_UNLIKELY(spngresult != SPNG_OK)) {
+            qWarning("QPngHandler::option() Could not get IHDR: %s", spng_strerror(spngresult));
+            spng_ctx_free(spngctx);
+            device()->seek(devicepos);
+            return false;
+        }
+
+        spng_ctx_free(spngctx);
+        device()->seek(devicepos);
+        return QSize(spngihdr.width, spngihdr.height);
+    } else if (option == QImageIOHandler::CompressionLevel) {
+        return QVariant(m_complevel);
+    }
+    return QVariant();
 }
 
 void QPngHandler::setOption(QImageIOHandler::ImageOption option, const QVariant &value)
 {
     if (option == QImageIOHandler::CompressionLevel) {
-        const int newlevel = value.toInt();
-        if (Q_UNLIKELY(newlevel < 0 || newlevel > 9)) {
-            qWarning("QPngHandler::setOption() invalid compression level value");
-            m_compression = 1;
+        const int newcomplevel = value.toInt();
+        if (Q_UNLIKELY(newcomplevel < 0 || newcomplevel > 9)) {
+            qWarning("QPngHandler::setOption() Invalid compression level (%d)", newcomplevel);
+            m_complevel = 1;
         } else {
-            m_compression = newlevel;
+            m_complevel = newcomplevel;
         }
     }
 }
 
+bool QPngHandler::supportsOption(QImageIOHandler::ImageOption option) const
+{
+    switch (option) {
+        case QImageIOHandler::Size:
+        case QImageIOHandler::CompressionLevel: {
+            return true;
+        }
+        default: {
+            return false;
+        }
+    }
+    Q_UNREACHABLE();
+    return false;
+}
+
 QByteArray QPngHandler::name() const
 {
     return "png";
@@ -213,7 +260,7 @@ QByteArray QPngHandler::name() const
 bool QPngHandler::canRead(QIODevice *device)
 {
     if (Q_UNLIKELY(!device)) {
-        qWarning("QPngHandler::canRead() called with no device");
+        qWarning("QPngHandler::canRead() Called with no device");
         return false;
     }
 
@@ -222,8 +269,7 @@ bool QPngHandler::canRead(QIODevice *device)
         return false;
     }
 
-    static const uchar pngheader[]
-        = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
+    static const uchar pngheader[] = { 0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a };
     return (::memcmp(head, pngheader, 8) == 0);
 }
 
index da5654b..a93c36f 100644 (file)
@@ -1,7 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2016 Ivailo Monev
+** Copyright (C) 2023 Ivailo Monev
 **
 ** This file is part of the QtGui module of the Katie Toolkit.
 **
@@ -47,15 +46,16 @@ public:
     bool read(QImage *image) final;
     bool write(const QImage &image) final;
 
-    bool supportsOption(QImageIOHandler::ImageOption option) const final;
+    QVariant option(QImageIOHandler::ImageOption option) const final;
     void setOption(QImageIOHandler::ImageOption option, const QVariant &value) final;
+    bool supportsOption(QImageIOHandler::ImageOption option) const final;
 
     QByteArray name() const final;
 
     static bool canRead(QIODevice *device);
 
 private:
-    int m_compression;
+    int m_complevel;
 };
 
 QT_END_NAMESPACE
index dfb8fa7..e16a25a 100644 (file)
@@ -369,7 +369,7 @@ QByteArray QPpmHandler::name() const
 bool QPpmHandler::canRead(QIODevice *device, QByteArray *subType)
 {
     if (Q_UNLIKELY(!device)) {
-        qWarning("QPpmHandler::canRead() called with no device");
+        qWarning("QPpmHandler::canRead() Called with no device");
         return false;
     }
 
index a6d5876..744351e 100644 (file)
@@ -280,8 +280,9 @@ bool QXpmHandler::canRead(QIODevice *device)
     }
 
     QSTACKARRAY(char, head, 6);
-    if (device->peek(head, sizeof(head)) != sizeof(head))
+    if (device->peek(head, sizeof(head)) != sizeof(head)) {
         return false;
+    }
 
     return (::memcmp(head, "/* XPM", 6) == 0);
 }