[graphics/krita] plugins/impex/tiff: [string-freeze exception] Fix loading TIFF images with embedded PSD data

Dmitry Kazakov null at kde.org
Wed Jul 26 11:22:29 BST 2023


Git commit 89ccdfb467fe0d68c26b9cc54dde272b66967253 by Dmitry Kazakov.
Committed on 26/07/2023 at 12:22.
Pushed by dkazakov into branch 'master'.

[string-freeze exception] Fix loading TIFF images with embedded PSD data

In some cases the embedded PSD data may be loaded incorrectly into
Krita, in such cases we should let the user to choose, which form
he/she wants to load.

The patch breaks the string freeze, since it adds a dialog allowing
the user to choose between the two options.

BUG:376950
CC:kimageshop at kde.org
CC:kde-i18n-doc at kde.org

M  +118  -84   plugins/impex/tiff/kis_tiff_import.cc
M  +9    -1    plugins/impex/tiff/kis_tiff_import.h

https://invent.kde.org/graphics/krita/-/commit/89ccdfb467fe0d68c26b9cc54dde272b66967253

diff --git a/plugins/impex/tiff/kis_tiff_import.cc b/plugins/impex/tiff/kis_tiff_import.cc
index 60110ba0eef..c77905ceed3 100644
--- a/plugins/impex/tiff/kis_tiff_import.cc
+++ b/plugins/impex/tiff/kis_tiff_import.cc
@@ -44,7 +44,10 @@
 
 #include "kis_tiff_psd_layer_record.h"
 #include "kis_tiff_psd_resource_record.h"
-#endif
+
+#include <KisImportUserFeedbackInterface.h>
+#include <QMessageBox>
+#endif /* TIFF_HAS_PSD_TAGS */
 
 #ifdef HAVE_JPEG_TURBO
 #include <turbojpeg.h>
@@ -331,7 +334,7 @@ auto make_unique_with_deleter(T *data, Deleter d)
 }
 
 #ifdef TIFF_HAS_PSD_TAGS
-KisImportExportErrorCode KisTIFFImport::readImageFromPsd(
+KisImportExportErrorCode KisTIFFImport::readImageFromPsdRecords(
     KisDocument *m_doc,
     const KisTiffPsdLayerRecord &photoshopLayerRecord,
     KisTiffPsdResourceRecord &photoshopImageResourceRecord,
@@ -546,6 +549,7 @@ KisImportExportErrorCode KisTIFFImport::readImageFromPsd(
                         << layerRecord->layerName << layerRecord->error;
                 return ImportExportCodes::FileFormatIncorrect;
             }
+
             if (!groupStack.isEmpty()) {
                 psdImage->addNode(layer, groupStack.top());
             } else {
@@ -1499,6 +1503,114 @@ KisTIFFImport::readImageFromTiff(KisDocument *m_doc,
     return ImportExportCodes::OK;
 }
 
+KisImportExportErrorCode KisTIFFImport::readImageFromPsd(KisDocument *m_doc, TIFF *image, KisTiffBasicInfo &basicInfo)
+{
+#ifdef TIFF_HAS_PSD_TAGS
+  // Attempt to parse Photoshop metadata
+    // if it succeeds, divert and load as PSD
+
+    if (!m_photoshopBlockParsed) {
+        QBuffer photoshopLayerData;
+
+        KisTiffPsdLayerRecord photoshopLayerRecord(TIFFIsBigEndian(image),
+                                                   basicInfo.width,
+                                                   basicInfo.height,
+                                                   basicInfo.depth,
+                                                   basicInfo.nbchannels,
+                                                   basicInfo.color_type);
+
+        KisTiffPsdResourceRecord photoshopImageResourceRecord;
+
+        {
+            // Determine if we have Photoshop metadata
+            uint32_t length{0};
+            uint8_t *data{nullptr};
+
+            if (TIFFGetField(image, TIFFTAG_IMAGESOURCEDATA, &length, &data)
+                == 1) {
+                dbgFile << "There are Photoshop layers, processing them now. "
+                           "Section size: "
+                        << length;
+
+                QByteArray buf(reinterpret_cast<char *>(data),
+                               static_cast<int>(length));
+                photoshopLayerData.setData(buf);
+                photoshopLayerData.open(QIODevice::ReadOnly);
+
+                if (!photoshopLayerRecord.read(photoshopLayerData)) {
+                    dbgFile << "TIFF: failed reading Photoshop layer metadata: "
+                            << photoshopLayerRecord.record()->error;
+                }
+            }
+        }
+
+        {
+            // Determine if we have Photoshop metadata
+            uint32_t length{0};
+            uint8_t *data{nullptr};
+
+            if (TIFFGetField(image, TIFFTAG_PHOTOSHOP, &length, &data) == 1
+                && data != nullptr) {
+                dbgFile << "There is Photoshop metadata, processing it now. "
+                           "Section size: "
+                        << length;
+
+                QByteArray photoshopImageResourceData(
+                    reinterpret_cast<char *>(data),
+                    static_cast<int>(length));
+
+                QBuffer buf(&photoshopImageResourceData);
+                buf.open(QIODevice::ReadOnly);
+
+                if (!photoshopImageResourceRecord.read(buf)) {
+                    dbgFile << "TIFF: failed reading Photoshop image metadata: "
+                            << photoshopImageResourceRecord.error;
+                }
+            }
+        }
+
+
+        if (importUserFeedBackInterface()) {
+
+            bool usePsd = true;
+            importUserFeedBackInterface()->askUser([&] (QWidget *parent) {
+                usePsd = QMessageBox::question(parent, i18nc("@title:window", "TIFF image with PSD data"),
+                                      i18nc("the choice for the user on loading a TIFF file",
+                                            "The TIFF image contains valid PSD data embedded. "
+                                            "Would you like to use PSD data instead of normal TIFF data?"))
+                    == QMessageBox::Yes;
+
+                return true;
+            });
+
+            if (!usePsd) {
+                return ImportExportCodes::Cancelled;
+            }
+        }
+
+        if (photoshopLayerRecord.valid()
+            && photoshopImageResourceRecord.valid()) {
+            KisImportExportErrorCode result =
+                readImageFromPsdRecords(m_doc,
+                                        photoshopLayerRecord,
+                                        photoshopImageResourceRecord,
+                                        photoshopLayerData,
+                                        basicInfo);
+
+            if (!result.isOk()) {
+                dbgFile << "Photoshop import failed";
+            }
+            return result;
+        }
+    }
+
+    return ImportExportCodes::FormatFeaturesUnsupported;
+
+#else
+    return ImportExportCodes::FormatFeaturesUnsupported;
+#endif
+}
+
 KisImportExportErrorCode KisTIFFImport::readTIFFDirectory(KisDocument *m_doc,
                                                           TIFF *image)
 {
@@ -1692,90 +1804,12 @@ KisImportExportErrorCode KisTIFFImport::readTIFFDirectory(KisDocument *m_doc,
                     KoColorConversionTransformation::internalConversionFlags());
     }
 
-#ifdef TIFF_HAS_PSD_TAGS
-    // Attempt to parse Photoshop metadata
-    // if it succeeds, divert and load as PSD
-
-    if (!m_photoshopBlockParsed) {
-        QBuffer photoshopLayerData;
-
-        KisTiffPsdLayerRecord photoshopLayerRecord(TIFFIsBigEndian(image),
-                                                   basicInfo.width,
-                                                   basicInfo.height,
-                                                   basicInfo.depth,
-                                                   basicInfo.nbchannels,
-                                                   basicInfo.color_type);
-
-        KisTiffPsdResourceRecord photoshopImageResourceRecord;
-
-        {
-            // Determine if we have Photoshop metadata
-            uint32_t length{0};
-            uint8_t *data{nullptr};
-
-            if (TIFFGetField(image, TIFFTAG_IMAGESOURCEDATA, &length, &data)
-                == 1) {
-                dbgFile << "There are Photoshop layers, processing them now. "
-                           "Section size: "
-                        << length;
-
-                QByteArray buf(reinterpret_cast<char *>(data),
-                               static_cast<int>(length));
-                photoshopLayerData.setData(buf);
-                photoshopLayerData.open(QIODevice::ReadOnly);
-
-                if (!photoshopLayerRecord.read(photoshopLayerData)) {
-                    dbgFile << "TIFF: failed reading Photoshop layer metadata: "
-                            << photoshopLayerRecord.record()->error;
-                }
-            }
-        }
-
-        {
-            // Determine if we have Photoshop metadata
-            uint32_t length{0};
-            uint8_t *data{nullptr};
-
-            if (TIFFGetField(image, TIFFTAG_PHOTOSHOP, &length, &data) == 1
-                && data != nullptr) {
-                dbgFile << "There is Photoshop metadata, processing it now. "
-                           "Section size: "
-                        << length;
-
-                QByteArray photoshopImageResourceData(
-                    reinterpret_cast<char *>(data),
-                    static_cast<int>(length));
-
-                QBuffer buf(&photoshopImageResourceData);
-                buf.open(QIODevice::ReadOnly);
-
-                if (!photoshopImageResourceRecord.read(buf)) {
-                    dbgFile << "TIFF: failed reading Photoshop image metadata: "
-                            << photoshopImageResourceRecord.error;
-                }
-            }
-        }
-
-        if (photoshopLayerRecord.valid()
-            && photoshopImageResourceRecord.valid()) {
-            KisImportExportErrorCode result =
-                readImageFromPsd(m_doc,
-                                 photoshopLayerRecord,
-                                 photoshopImageResourceRecord,
-                                 photoshopLayerData,
-                                 basicInfo);
-
-            if (result.isOk()) {
-                return result;
-            } else {
-                dbgFile << "Photoshop import failed, falling back to TIFF "
-                           "image data";
-            }
-        }
+    KisImportExportErrorCode result = readImageFromPsd(m_doc, image, basicInfo);
+    if (!result.isOk()) {
+        result = readImageFromTiff(m_doc, image, basicInfo);
     }
-#endif
 
-    return readImageFromTiff(m_doc, image, basicInfo);
+    return result;
 }
 
 KisImportExportErrorCode
diff --git a/plugins/impex/tiff/kis_tiff_import.h b/plugins/impex/tiff/kis_tiff_import.h
index 0b09d7e9c3a..0eff7074a43 100644
--- a/plugins/impex/tiff/kis_tiff_import.h
+++ b/plugins/impex/tiff/kis_tiff_import.h
@@ -41,6 +41,14 @@ private:
     KisImportExportErrorCode readImageFromTiff(KisDocument *m_doc,
                                                TIFF *image,
                                                KisTiffBasicInfo &basicInfo);
+
+    /**
+     * Imports the image from the PSD descriptor.
+     */
+    KisImportExportErrorCode readImageFromPsd(KisDocument *m_doc,
+                                              TIFF *image,
+                                              KisTiffBasicInfo &basicInfo);
+
 #ifdef TIFF_HAS_PSD_TAGS
     /**
      * Imports the image from the PSD descriptor attached.
@@ -48,7 +56,7 @@ private:
      * parse the first image descriptor.
      */
     KisImportExportErrorCode
-    readImageFromPsd(KisDocument *m_doc,
+    readImageFromPsdRecords(KisDocument *m_doc,
                      const KisTiffPsdLayerRecord &photoshopLayerRecord,
                      KisTiffPsdResourceRecord &photoshopImageResourceRecord,
                      QBuffer &photoshopLayerData,


More information about the kimageshop mailing list