File indexing completed on 2024-12-22 04:15:57

0001 /*
0002  *  SPDX-FileCopyrightText: 2005 Cyrille Berger <cberger@cberger.net>
0003  *  SPDX-FileCopyrightText: 2022 L. E. Segovia <amy@amyspark.me>
0004  *
0005  *  SPDX-License-Identifier: GPL-2.0-or-later
0006  */
0007 
0008 #include "kis_tiff_import.h"
0009 #include "KisImportExportErrorCode.h"
0010 #include "kis_assert.h"
0011 
0012 #include <QBuffer>
0013 #include <QFileInfo>
0014 #include <QPair>
0015 #include <QSharedPointer>
0016 #include <QStack>
0017 
0018 #include <array>
0019 
0020 #include <exiv2/exiv2.hpp>
0021 #include <kpluginfactory.h>
0022 #ifdef Q_OS_WIN
0023 #include <io.h>
0024 #endif
0025 #include <tiffio.h>
0026 
0027 #include <KisDocument.h>
0028 #include <KisImportExportAdditionalChecks.h>
0029 #include <KisViewManager.h>
0030 #include <KoColorProfile.h>
0031 #include <KoDocumentInfo.h>
0032 #include <KoUnit.h>
0033 #include <KisExiv2IODevice.h>
0034 #include <kis_group_layer.h>
0035 #include <kis_image.h>
0036 #include <kis_meta_data_backend_registry.h>
0037 #include <kis_meta_data_tags.h>
0038 #include <kis_paint_layer.h>
0039 #include <kis_transform_worker.h>
0040 #include <kis_transparency_mask.h>
0041 
0042 #ifdef TIFF_HAS_PSD_TAGS
0043 #include <psd_resource_block.h>
0044 
0045 #include "kis_tiff_psd_layer_record.h"
0046 #include "kis_tiff_psd_resource_record.h"
0047 
0048 #include <KisImportUserFeedbackInterface.h>
0049 #include <QMessageBox>
0050 #endif /* TIFF_HAS_PSD_TAGS */
0051 
0052 #ifdef HAVE_JPEG_TURBO
0053 #include <turbojpeg.h>
0054 #endif
0055 
0056 #include "kis_buffer_stream.h"
0057 #include "kis_tiff_logger.h"
0058 #include "kis_tiff_reader.h"
0059 #include "kis_tiff_ycbcr_reader.h"
0060 
0061 enum class TiffResolution : quint8 {
0062     NONE = RESUNIT_NONE,
0063     INCH = RESUNIT_INCH,
0064     CM = RESUNIT_CENTIMETER,
0065 };
0066 
0067 struct KisTiffBasicInfo {
0068     uint32_t width{};
0069     uint32_t height{};
0070     float x{};
0071     float y{};
0072     float xres{};
0073     float yres{};
0074     uint16_t depth{};
0075     uint16_t sampletype{};
0076     uint16_t nbchannels{};
0077     uint16_t color_type{};
0078     uint16_t *sampleinfo = nullptr;
0079     uint16_t extrasamplescount = 0;
0080     const KoColorSpace *cs = nullptr;
0081     QPair<QString, QString> colorSpaceIdTag;
0082     KoColorTransformation *transform = nullptr;
0083     uint8_t dstDepth{};
0084     TiffResolution resolution = TiffResolution::NONE;
0085 };
0086 
0087 K_PLUGIN_FACTORY_WITH_JSON(TIFFImportFactory,
0088                            "krita_tiff_import.json",
0089                            registerPlugin<KisTIFFImport>();)
0090 
0091 QPair<QString, QString> getColorSpaceForColorType(uint16_t sampletype,
0092                                                   uint16_t color_type,
0093                                                   uint16_t color_nb_bits,
0094                                                   TIFF *image,
0095                                                   uint16_t &nbchannels,
0096                                                   uint16_t &extrasamplescount,
0097                                                   uint8_t &destDepth)
0098 {
0099     const int bits32 = 32;
0100     const int bits16 = 16;
0101     const int bits8 = 8;
0102 
0103     if (sampletype == SAMPLEFORMAT_INT) {
0104         dbgFile << "Detected signed TIFF image" << color_type << color_nb_bits;
0105     }
0106 
0107     if (color_type == PHOTOMETRIC_MINISWHITE
0108         || color_type == PHOTOMETRIC_MINISBLACK) {
0109         if (nbchannels == 0)
0110             nbchannels = 1;
0111         extrasamplescount =
0112             nbchannels - 1; // FIX the extrasamples count in case of
0113         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0114             if (color_nb_bits == 16) {
0115 #ifdef HAVE_OPENEXR
0116                 destDepth = 16;
0117                 return {GrayAColorModelID.id(), Float16BitsColorDepthID.id()};
0118 #endif
0119             } else if (color_nb_bits == 32) {
0120                 destDepth = 32;
0121                 return {GrayAColorModelID.id(), Float32BitsColorDepthID.id()};
0122             }
0123             return {}; // sanity check; no support for float of
0124                        // higher or lower bit depth
0125         }
0126         if (color_nb_bits <= 8) {
0127             destDepth = 8;
0128             return {GrayAColorModelID.id(), Integer8BitsColorDepthID.id()};
0129         } else /* if (color_nb_bits == bits16) */ {
0130             destDepth = 16;
0131             return {GrayAColorModelID.id(), Integer16BitsColorDepthID.id()};
0132         }
0133 
0134     } else if (color_type == PHOTOMETRIC_RGB /*|| color_type == */) {
0135         if (nbchannels == 0)
0136             nbchannels = 3;
0137         extrasamplescount =
0138             nbchannels - 3; // FIX the extrasamples count in case of
0139         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0140             if (color_nb_bits == 16) {
0141 #ifdef HAVE_OPENEXR
0142                 destDepth = 16;
0143                 return {RGBAColorModelID.id(), Float16BitsColorDepthID.id()};
0144 #endif
0145             } else if (color_nb_bits == 32) {
0146                 destDepth = 32;
0147                 return {RGBAColorModelID.id(), Float32BitsColorDepthID.id()};
0148             }
0149             return {}; // sanity check; no support for float of
0150                        // higher or lower bit depth
0151         } else {
0152             if (color_nb_bits <= 8) {
0153                 destDepth = 8;
0154                 return {RGBAColorModelID.id(), Integer8BitsColorDepthID.id()};
0155             } else /* if (color_nb_bits == bits16) */ {
0156                 destDepth = 16;
0157                 return {RGBAColorModelID.id(), Integer16BitsColorDepthID.id()};
0158             }
0159         }
0160     } else if (color_type == PHOTOMETRIC_YCBCR) {
0161         if (nbchannels == 0)
0162             nbchannels = 3;
0163         extrasamplescount =
0164             nbchannels - 3; // FIX the extrasamples count in case of
0165         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0166             if (color_nb_bits == 16) {
0167 #ifdef HAVE_OPENEXR
0168                 destDepth = 16;
0169                 return {YCbCrAColorModelID.id(), Float16BitsColorDepthID.id()};
0170 #endif
0171             } else if (color_nb_bits == 32) {
0172                 destDepth = 32;
0173                 return {YCbCrAColorModelID.id(), Float32BitsColorDepthID.id()};
0174             }
0175             return {}; // sanity check; no support for float of
0176                        // higher or lower bit depth
0177         } else {
0178             if (color_nb_bits <= 8) {
0179                 destDepth = 8;
0180                 return {YCbCrAColorModelID.id(), Integer8BitsColorDepthID.id()};
0181             } else /* if (color_nb_bits == bits16) */ {
0182                 destDepth = 16;
0183                 return {YCbCrAColorModelID.id(),
0184                         Integer16BitsColorDepthID.id()};
0185             }
0186         }
0187         if (color_nb_bits <= 8) {
0188             destDepth = 8;
0189             return {YCbCrAColorModelID.id(), Integer8BitsColorDepthID.id()};
0190         } else if (color_nb_bits == bits16) {
0191             destDepth = 16;
0192             return {YCbCrAColorModelID.id(), Integer16BitsColorDepthID.id()};
0193         } else {
0194             return {}; // sanity check; no support
0195                        // integers of higher bit depth
0196         }
0197     } else if (color_type == PHOTOMETRIC_SEPARATED) {
0198         if (nbchannels == 0)
0199             nbchannels = 4;
0200         // SEPARATED is in general CMYK but not always, so we check
0201         uint16_t inkset = 0;
0202         if ((TIFFGetField(image, TIFFTAG_INKSET, &inkset) == 0)) {
0203             dbgFile << "Image does not define the inkset.";
0204             inkset = 2;
0205         }
0206         if (inkset != INKSET_CMYK) {
0207             dbgFile << "Unsupported inkset (right now, only CMYK is supported)";
0208             char **ink_names = nullptr;
0209             uint16_t numberofinks = 0;
0210             if (TIFFGetField(image, TIFFTAG_INKNAMES, &ink_names) == 1
0211                 && TIFFGetField(image, TIFFTAG_NUMBEROFINKS, &numberofinks)
0212                     == 1) {
0213                 dbgFile << "Inks are :";
0214                 for (uint32_t i = 0; i < numberofinks; i++) {
0215                     dbgFile << ink_names[i];
0216                 }
0217             } else {
0218                 dbgFile << "inknames are not defined !";
0219                 // To be able to read stupid adobe files, if there are no
0220                 // information about inks and four channels, then it's a CMYK
0221                 // file :
0222                 if (nbchannels - extrasamplescount != 4) {
0223                     return {};
0224                 }
0225                 // else - assume it's CMYK and proceed
0226             }
0227         }
0228         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0229             if (color_nb_bits == 16) {
0230 #ifdef HAVE_OPENEXR
0231                 destDepth = 16;
0232                 return {CMYKAColorModelID.id(), Float16BitsColorDepthID.id()};
0233 #endif
0234             } else if (color_nb_bits == 32) {
0235                 destDepth = 32;
0236                 return {CMYKAColorModelID.id(), Float32BitsColorDepthID.id()};
0237             }
0238             return {}; // sanity check; no support for float of
0239                        // higher or lower bit depth
0240         }
0241         if (color_nb_bits <= 8) {
0242             destDepth = 8;
0243             return {CMYKAColorModelID.id(), Integer8BitsColorDepthID.id()};
0244         } else if (color_nb_bits == 16) {
0245             destDepth = 16;
0246             return {CMYKAColorModelID.id(), Integer16BitsColorDepthID.id()};
0247         } else {
0248             return {}; // no support for other bit depths
0249         }
0250     } else if (color_type == PHOTOMETRIC_CIELAB
0251                || color_type == PHOTOMETRIC_ICCLAB) {
0252         if (nbchannels == 0)
0253             nbchannels = 3;
0254         extrasamplescount = nbchannels - 3; // FIX the extrasamples count
0255 
0256         switch (color_nb_bits) {
0257         case bits32: {
0258             destDepth = bits32;
0259             if (sampletype == SAMPLEFORMAT_IEEEFP) {
0260                 return {LABAColorModelID.id(), Float32BitsColorDepthID.id()};
0261             } else {
0262                 return {}; // no support for other bit depths
0263             }
0264         }
0265         case bits16: {
0266             destDepth = bits16;
0267             if (sampletype == SAMPLEFORMAT_IEEEFP) {
0268 #ifdef HAVE_OPENEXR
0269                 return {LABAColorModelID.id(), Float16BitsColorDepthID.id()};
0270 #endif
0271             } else {
0272                 return {LABAColorModelID.id(), Integer16BitsColorDepthID.id()};
0273             }
0274             return {}; // no support for other bit depths
0275         }
0276         case bits8: {
0277             destDepth = bits8;
0278             return {LABAColorModelID.id(), Integer8BitsColorDepthID.id()};
0279         }
0280         default: {
0281             return {};
0282         }
0283         }
0284     } else if (color_type == PHOTOMETRIC_PALETTE) {
0285         destDepth = 16;
0286         if (nbchannels == 0)
0287             nbchannels = 2;
0288         extrasamplescount = nbchannels - 2; // FIX the extrasamples count
0289         // <-- we will convert the index image to RGBA16 as the palette is
0290         // always on 16bits colors
0291         return {RGBAColorModelID.id(), Integer16BitsColorDepthID.id()};
0292     }
0293     return {};
0294 }
0295 
0296 template<template<typename> class T>
0297 QSharedPointer<KisTIFFPostProcessor>
0298 makePostProcessor(uint32_t nbsamples, const QPair<QString, QString> &id)
0299 {
0300     if (id.second == Integer8BitsColorDepthID.id()) {
0301         return QSharedPointer<T<uint8_t>>::create(nbsamples);
0302     } else if (id.second == Integer16BitsColorDepthID.id()) {
0303         return QSharedPointer<T<uint16_t>>::create(nbsamples);
0304 #ifdef HAVE_OPENEXR
0305     } else if (id.second == Float16BitsColorDepthID.id()) {
0306         return QSharedPointer<T<half>>::create(nbsamples);
0307 #endif
0308     } else if (id.second == Float32BitsColorDepthID.id()) {
0309         return QSharedPointer<T<float>>::create(nbsamples);
0310     } else {
0311         KIS_ASSERT(false && "TIFF does not support this bit depth!");
0312         return {};
0313     }
0314 }
0315 
0316 KisTIFFImport::KisTIFFImport(QObject *parent, const QVariantList &)
0317     : KisImportExportFilter(parent)
0318     , m_image(nullptr)
0319     , oldErrHandler(TIFFSetErrorHandler(&KisTiffErrorHandler))
0320     , oldWarnHandler(TIFFSetWarningHandler(&KisTiffWarningHandler))
0321 {
0322 }
0323 
0324 KisTIFFImport::~KisTIFFImport()
0325 {
0326     TIFFSetErrorHandler(oldErrHandler);
0327     TIFFSetWarningHandler(oldWarnHandler);
0328 }
0329 
0330 template<typename T, typename Deleter>
0331 auto make_unique_with_deleter(T *data, Deleter d)
0332 {
0333     return std::unique_ptr<T, Deleter>(data, d);
0334 }
0335 
0336 #ifdef TIFF_HAS_PSD_TAGS
0337 KisImportExportErrorCode KisTIFFImport::readImageFromPsdRecords(
0338     KisDocument *m_doc,
0339     const KisTiffPsdLayerRecord &photoshopLayerRecord,
0340     KisTiffPsdResourceRecord &photoshopImageResourceRecord,
0341     QBuffer &photoshopLayerData,
0342     const KisTiffBasicInfo &basicInfo)
0343 {
0344     QMap<KisTiffPsdResourceRecord::PSDResourceID, PSDResourceBlock *>
0345         &resources = photoshopImageResourceRecord.resources;
0346 
0347     const KoColorSpace *cs = basicInfo.cs;
0348 
0349     // Attempt to get the ICC profile from the image resource section
0350     if (resources.contains(KisTiffPsdResourceRecord::ICC_PROFILE)) {
0351         const KoColorProfile *profile = nullptr;
0352 
0353         // Use the color mode from the synthetic PSD header
0354         QPair<QString, QString> colorSpaceId =
0355             psd_colormode_to_colormodelid(photoshopLayerRecord.colorMode(),
0356                                           photoshopLayerRecord.channelDepth());
0357 
0358         if (colorSpaceId.first.isNull()) {
0359             dbgFile << "Inconsistent PSD metadata, the color space"
0360                     << photoshopLayerRecord.colorMode()
0361                     << photoshopLayerRecord.channelDepth()
0362                     << "does not exist; falling back to the synthetic header "
0363                        "information";
0364             colorSpaceId = basicInfo.colorSpaceIdTag;
0365         }
0366 
0367         ICC_PROFILE_1039 *iccProfileData = dynamic_cast<ICC_PROFILE_1039 *>(
0368             resources[KisTiffPsdResourceRecord::ICC_PROFILE]->resource);
0369         if (iccProfileData) {
0370             profile = KoColorSpaceRegistry::instance()->createColorProfile(
0371                 colorSpaceId.first,
0372                 colorSpaceId.second,
0373                 iccProfileData->icc);
0374             dbgFile << "Loaded ICC profile from PSD" << profile->name();
0375             delete resources.take(KisTiffPsdResourceRecord::ICC_PROFILE);
0376         }
0377 
0378         if (profile) {
0379             const KoColorSpace *tempCs =
0380                 KoColorSpaceRegistry::instance()->colorSpace(
0381                     colorSpaceId.first,
0382                     colorSpaceId.second,
0383                     profile);
0384             if (tempCs) {
0385                 // Profile found, override the colorspace
0386                 dbgFile << "TIFF: PSD metadata overrides the color space!"
0387                         << cs->name() << cs->profile()->name();
0388                 cs = tempCs;
0389             }
0390         }
0391     }
0392 
0393     KisImageSP psdImage = new KisImage(m_doc->createUndoStore(),
0394                                        static_cast<qint32>(basicInfo.width),
0395                                        static_cast<qint32>(basicInfo.height),
0396                                        cs,
0397                                        "built image");
0398     KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(psdImage,
0399                                          ImportExportCodes::InsufficientMemory);
0400 
0401     psdImage->setResolution(
0402         POINT_TO_INCH(static_cast<qreal>(basicInfo.xres)),
0403         POINT_TO_INCH(static_cast<qreal>(
0404             basicInfo.yres))); // It is the "invert" macro because we convert
0405                                // from pointer-per-inch to points
0406 
0407     // set the correct resolution
0408     if (resources.contains(KisTiffPsdResourceRecord::RESN_INFO)) {
0409         RESN_INFO_1005 *resInfo = dynamic_cast<RESN_INFO_1005 *>(
0410             resources[KisTiffPsdResourceRecord::RESN_INFO]->resource);
0411         if (resInfo) {
0412             // check resolution size is not zero
0413             if (resInfo->hRes * resInfo->vRes > 0)
0414                 psdImage->setResolution(POINT_TO_INCH(resInfo->hRes),
0415                                         POINT_TO_INCH(resInfo->vRes));
0416             // let's skip the unit for now; we can only set that on the
0417             // KisDocument, and krita doesn't use it.
0418             delete resources.take(KisTiffPsdResourceRecord::RESN_INFO);
0419         }
0420     }
0421 
0422     // Preserve all the annotations
0423     for (const auto &resourceBlock : resources.values()) {
0424         psdImage->addAnnotation(resourceBlock);
0425     }
0426 
0427     dbgFile << "Loading Photoshop layers";
0428 
0429     QStack<KisGroupLayerSP> groupStack;
0430 
0431     groupStack << psdImage->rootLayer().data();
0432 
0433     /**
0434      * PSD has a weird "optimization": if a group layer has only one
0435      * child layer, it omits it's 'psd_bounding_divider' section. So
0436      * fi you ever see an unbalanced layers group in PSD, most
0437      * probably, it is just a single layered group.
0438      */
0439     KisNodeSP lastAddedLayer;
0440 
0441     using LayerStyleMapping = QPair<QDomDocument, KisLayerSP>;
0442     QVector<LayerStyleMapping> allStylesXml;
0443 
0444     const std::shared_ptr<PSDLayerMaskSection> &layerSection =
0445         photoshopLayerRecord.record();
0446 
0447     KIS_SAFE_ASSERT_RECOVER(layerSection->nLayers != 0)
0448     {
0449         return ImportExportCodes::FileFormatIncorrect;
0450     }
0451 
0452     for (int i = 0; i != layerSection->nLayers; i++) {
0453         PSDLayerRecord *layerRecord = layerSection->layers.at(i);
0454         dbgFile << "Going to read channels for layer" << i
0455                 << layerRecord->layerName;
0456         KisLayerSP newLayer;
0457         if (layerRecord->infoBlocks.keys.contains("lsct")
0458             && layerRecord->infoBlocks.sectionDividerType != psd_other) {
0459             if (layerRecord->infoBlocks.sectionDividerType
0460                     == psd_bounding_divider
0461                 && !groupStack.isEmpty()) {
0462                 KisGroupLayerSP groupLayer =
0463                     new KisGroupLayer(psdImage, "temp", OPACITY_OPAQUE_U8);
0464                 psdImage->addNode(groupLayer, groupStack.top());
0465                 groupStack.push(groupLayer);
0466                 newLayer = groupLayer;
0467             } else if ((layerRecord->infoBlocks.sectionDividerType
0468                             == psd_open_folder
0469                         || layerRecord->infoBlocks.sectionDividerType
0470                             == psd_closed_folder)
0471                        && (groupStack.size() > 1
0472                            || (lastAddedLayer && !groupStack.isEmpty()))) {
0473                 KisGroupLayerSP groupLayer;
0474 
0475                 if (groupStack.size() <= 1) {
0476                     groupLayer =
0477                         new KisGroupLayer(psdImage, "temp", OPACITY_OPAQUE_U8);
0478                     psdImage->addNode(groupLayer, groupStack.top());
0479                     psdImage->moveNode(lastAddedLayer, groupLayer, KisNodeSP());
0480                 } else {
0481                     groupLayer = groupStack.pop();
0482                 }
0483 
0484                 const QDomDocument &styleXml =
0485                     layerRecord->infoBlocks.layerStyleXml;
0486 
0487                 if (!styleXml.isNull()) {
0488                     allStylesXml << LayerStyleMapping(styleXml, groupLayer);
0489                 }
0490 
0491                 groupLayer->setName(layerRecord->layerName);
0492                 groupLayer->setVisible(layerRecord->visible);
0493 
0494                 QString compositeOp = psd_blendmode_to_composite_op(
0495                     layerRecord->infoBlocks.sectionDividerBlendMode);
0496 
0497                 // Krita doesn't support pass-through blend
0498                 // mode. Instead it is just a property of a group
0499                 // layer, so flip it
0500                 if (compositeOp == COMPOSITE_PASS_THROUGH) {
0501                     compositeOp = COMPOSITE_OVER;
0502                     groupLayer->setPassThroughMode(true);
0503                 }
0504 
0505                 groupLayer->setCompositeOpId(compositeOp);
0506 
0507                 newLayer = groupLayer;
0508             } else {
0509                 /**
0510                  * In some files saved by PS CS6 the group layer sections seem
0511                  * to be unbalanced.  I don't know why it happens because the
0512                  * reporter didn't provide us an example file. So here we just
0513                  * check if the new layer was created, and if not, skip the
0514                  * initialization of masks.
0515                  *
0516                  * See bug: 357559
0517                  */
0518 
0519                 warnKrita << "WARNING: Provided PSD has unbalanced group "
0520                           << "layer markers. Some masks and/or layers can "
0521                           << "be lost while loading this file. Please "
0522                           << "report a bug to Krita developers and attach "
0523                           << "this file to the bugreport\n"
0524                           << "    " << ppVar(layerRecord->layerName) << "\n"
0525                           << "    "
0526                           << ppVar(layerRecord->infoBlocks.sectionDividerType)
0527                           << "\n"
0528                           << "    " << ppVar(groupStack.size());
0529                 continue;
0530             }
0531         } else {
0532             KisPaintLayerSP layer = new KisPaintLayer(psdImage,
0533                                                       layerRecord->layerName,
0534                                                       layerRecord->opacity);
0535             layer->setCompositeOpId(
0536                 psd_blendmode_to_composite_op(layerRecord->blendModeKey));
0537 
0538             const QDomDocument &styleXml =
0539                 layerRecord->infoBlocks.layerStyleXml;
0540 
0541             if (!styleXml.isNull()) {
0542                 allStylesXml << LayerStyleMapping(styleXml, layer);
0543             }
0544 
0545             // XXX: does this require endianness handling?
0546             if (!layerRecord->readPixelData(photoshopLayerData,
0547                                             layer->paintDevice())) {
0548                 dbgFile << "failed reading channels for layer: "
0549                         << layerRecord->layerName << layerRecord->error;
0550                 return ImportExportCodes::FileFormatIncorrect;
0551             }
0552 
0553             if (!groupStack.isEmpty()) {
0554                 psdImage->addNode(layer, groupStack.top());
0555             } else {
0556                 psdImage->addNode(layer, psdImage->root());
0557             }
0558             layer->setVisible(layerRecord->visible);
0559             newLayer = layer;
0560         }
0561 
0562         for (ChannelInfo *channelInfo : layerRecord->channelInfoRecords) {
0563             if (channelInfo->channelId < -1) {
0564                 KisTransparencyMaskSP mask =
0565                     new KisTransparencyMask(psdImage,
0566                                             i18n("Transparency Mask"));
0567                 mask->initSelection(newLayer);
0568                 if (!layerRecord->readMask(photoshopLayerData,
0569                                            mask->paintDevice(),
0570                                            channelInfo)) {
0571                     dbgFile << "failed reading masks for layer: "
0572                             << layerRecord->layerName << layerRecord->error;
0573                 }
0574                 psdImage->addNode(mask, newLayer);
0575             }
0576         }
0577 
0578         lastAddedLayer = newLayer;
0579     }
0580 
0581     // Only assign the image if the parsing was successful (for fallback
0582     // purposes)
0583     this->m_image = psdImage;
0584     // Photoshop images only have one IFD plus the layer blob
0585     // Ward off inconsistencies by blocking future attempts to parse them
0586     this->m_photoshopBlockParsed = true;
0587 
0588     return ImportExportCodes::OK;
0589 }
0590 #endif
0591 
0592 KisImportExportErrorCode
0593 KisTIFFImport::readImageFromTiff(KisDocument *m_doc,
0594                                  TIFF *image,
0595                                  KisTiffBasicInfo &basicInfo)
0596 {
0597     uint32_t &width = basicInfo.width;
0598     uint32_t &height = basicInfo.height;
0599     float &xres = basicInfo.xres;
0600     float &yres = basicInfo.yres;
0601     uint16_t &depth = basicInfo.depth;
0602     uint16_t &sampletype = basicInfo.sampletype;
0603     uint16_t &nbchannels = basicInfo.nbchannels;
0604     uint16_t &color_type = basicInfo.color_type;
0605     uint16_t *&sampleinfo = basicInfo.sampleinfo;
0606     uint16_t &extrasamplescount = basicInfo.extrasamplescount;
0607     const KoColorSpace *&cs = basicInfo.cs;
0608     QPair<QString, QString> &colorSpaceIdTag = basicInfo.colorSpaceIdTag;
0609     KoColorTransformation *&transform = basicInfo.transform;
0610     uint8_t &dstDepth = basicInfo.dstDepth;
0611 
0612     // Check if there is an alpha channel
0613     int32_t alphapos = -1; // <- no alpha
0614     bool hasPremultipliedAlpha = false;
0615     // Check which extra is alpha if any
0616     dbgFile << "There are" << nbchannels << " channels and" << extrasamplescount
0617             << " extra channels";
0618     if (sampleinfo) { // index images don't have any sampleinfo, and therefore
0619                       // sampleinfo == 0
0620         for (uint16_t i = 0; i < extrasamplescount; i++) {
0621             dbgFile << "sample" << i << "extra sample count"
0622                     << extrasamplescount << "color channel count"
0623                     << (cs->colorChannelCount()) << "Number of channels"
0624                     << nbchannels << "sample info" << sampleinfo[i];
0625             switch (sampleinfo[i]) {
0626             case EXTRASAMPLE_ASSOCALPHA:
0627                 // The color values are already multiplied with the alpha value.
0628                 // This is reversed in the postprocessor.
0629                 dbgPlugins << "Detected associated alpha @ " << i;
0630                 hasPremultipliedAlpha = true;
0631                 alphapos = static_cast<int32_t>(extrasamplescount
0632                                                 - 1U); // nbsamples - 1
0633                 break;
0634             case EXTRASAMPLE_UNASSALPHA:
0635                 // color values are not premultiplied with alpha, and can be
0636                 // used as they are.
0637                 alphapos = i;
0638                 break;
0639             case EXTRASAMPLE_UNSPECIFIED:
0640             default:
0641                 qWarning() << "Extra sample type not defined for this file, "
0642                               "assuming unassociated alpha.";
0643                 alphapos = i;
0644                 break;
0645             }
0646 
0647             if (sampleinfo[i] == EXTRASAMPLE_UNASSALPHA) {
0648                 // color values are not premultiplied with alpha, and can be
0649                 // used as they are.
0650                 alphapos = i;
0651             }
0652         }
0653     }
0654 
0655     dbgFile << "Alpha pos:" << alphapos;
0656 
0657     // Read META Information
0658     KoDocumentInfo *info = m_doc->documentInfo();
0659     char *text = nullptr;
0660     if (TIFFGetField(image, TIFFTAG_ARTIST, &text) == 1) {
0661         info->setAuthorInfo("creator", text);
0662     }
0663     if (TIFFGetField(image, TIFFTAG_DOCUMENTNAME, &text) == 1) {
0664         info->setAboutInfo("title", text);
0665     }
0666     if (TIFFGetField(image, TIFFTAG_IMAGEDESCRIPTION, &text) == 1) {
0667         info->setAboutInfo("description", text);
0668     }
0669 
0670     uint16_t orientation = ORIENTATION_TOPLEFT;
0671     if (TIFFGetField(image, TIFFTAG_ORIENTATION, &orientation) == 0) {
0672         dbgFile << "Orientation not defined, assuming top left";
0673     }
0674 
0675     dbgFile << "Orientation:" << orientation;
0676 
0677     // Try to get IPTC metadata
0678     uint32_t iptc_profile_size = 0;
0679     uint32_t *iptc_profile_data = nullptr;
0680     if (TIFFGetField(image,
0681                      TIFFTAG_RICHTIFFIPTC,
0682                      &iptc_profile_size,
0683                      &iptc_profile_data)
0684         == 0) {
0685         dbgFile << "IPTC metadata not found!";
0686     }
0687 
0688     // Try to get XMP metadata
0689     uint32_t xmp_size = 0;
0690     uint8_t *xmp_data = nullptr;
0691     if (TIFFGetField(image, TIFFTAG_XMLPACKET, &xmp_size, &xmp_data) == 0) {
0692         dbgFile << "XML metadata not found!";
0693     }
0694 
0695     // Get the planar configuration
0696     uint16_t planarconfig = PLANARCONFIG_CONTIG;
0697     if (TIFFGetField(image, TIFFTAG_PLANARCONFIG, &planarconfig) == 0) {
0698         dbgFile << "Planar configuration is not defined";
0699         return ImportExportCodes::FileFormatIncorrect;
0700     }
0701     // Creating the KisImageSP
0702     if (!m_image) {
0703         m_image = new KisImage(m_doc->createUndoStore(),
0704                                static_cast<qint32>(width),
0705                                static_cast<qint32>(height),
0706                                cs,
0707                                "built image");
0708         KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(
0709             m_image,
0710             ImportExportCodes::InsufficientMemory);
0711         // It is the "invert" macro because we
0712         // convert from pointer-per-unit to points
0713         if (basicInfo.resolution == TiffResolution::INCH) {
0714             m_image->setResolution(POINT_TO_INCH(static_cast<qreal>(xres)), POINT_TO_INCH(static_cast<qreal>(yres)));
0715         } else {
0716             m_image->setResolution(POINT_TO_CM(static_cast<qreal>(xres)), POINT_TO_CM(static_cast<qreal>(yres)));
0717         }
0718     } else {
0719         if (m_image->width() < static_cast<qint32>(width)
0720             || m_image->height() < static_cast<qint32>(height)) {
0721             qint32 newwidth = (m_image->width() < static_cast<qint32>(width))
0722                 ? static_cast<qint32>(width)
0723                 : m_image->width();
0724             qint32 newheight = (m_image->height() < static_cast<qint32>(height))
0725                 ? static_cast<qint32>(height)
0726                 : m_image->height();
0727             m_image->resizeImage(QRect(0, 0, newwidth, newheight));
0728         }
0729     }
0730     KisPaintLayer *layer =
0731         new KisPaintLayer(m_image, m_image->nextLayerName(), quint8_MAX, cs);
0732     std::unique_ptr<std::remove_pointer_t<tdata_t>, decltype(&_TIFFfree)> buf(
0733         nullptr,
0734         &_TIFFfree);
0735     // used only for planar configuration separated
0736     auto ps_buf = make_unique_with_deleter(new QVector<uint8_t *>(),
0737                                            [](QVector<uint8_t *> *buf) {
0738                                                for (uint8_t *p : *buf)
0739                                                    _TIFFfree(p);
0740                                                delete buf;
0741                                            });
0742 
0743     QSharedPointer<KisBufferStreamBase> tiffstream = nullptr;
0744     QSharedPointer<KisTIFFReaderBase> tiffReader = nullptr;
0745 
0746     // Configure poses
0747     uint16_t nbcolorsamples = nbchannels - extrasamplescount;
0748     const auto poses = [&]() -> std::array<quint8, 5> {
0749         switch (color_type) {
0750         case PHOTOMETRIC_MINISWHITE:
0751         case PHOTOMETRIC_MINISBLACK:
0752             return {0, 1};
0753         case PHOTOMETRIC_CIELAB:
0754         case PHOTOMETRIC_ICCLAB:
0755             return {0, 1, 2, 3};
0756         case PHOTOMETRIC_RGB:
0757             if (sampletype == SAMPLEFORMAT_IEEEFP) {
0758                 return {0, 1, 2, 3};
0759             } else {
0760                 return {2, 1, 0, 3};
0761             }
0762         case PHOTOMETRIC_SEPARATED:
0763             return {0, 1, 2, 3, 4};
0764         default:
0765             return {};
0766         }
0767     }();
0768 
0769     auto postprocessor = [&]() -> QSharedPointer<KisTIFFPostProcessor> {
0770         switch (color_type) {
0771         case PHOTOMETRIC_MINISWHITE:
0772             return makePostProcessor<KisTIFFPostProcessorInvert>(
0773                 nbcolorsamples,
0774                 colorSpaceIdTag);
0775         case PHOTOMETRIC_MINISBLACK:
0776             return makePostProcessor<KisTIFFPostProcessorDummy>(
0777                 nbcolorsamples,
0778                 colorSpaceIdTag);
0779         case PHOTOMETRIC_CIELAB:
0780             return makePostProcessor<KisTIFFPostProcessorCIELABtoICCLAB>(
0781                 nbcolorsamples,
0782                 colorSpaceIdTag);
0783         case PHOTOMETRIC_ICCLAB:
0784         case PHOTOMETRIC_RGB:
0785         case PHOTOMETRIC_SEPARATED:
0786             return makePostProcessor<KisTIFFPostProcessorDummy>(
0787                 nbcolorsamples,
0788                 colorSpaceIdTag);
0789         default:
0790             return {};
0791         }
0792     }();
0793 
0794     // Initialize tiffReader
0795     QVector<uint16_t> lineSizeCoeffs(nbchannels, 1);
0796     uint16_t vsubsampling = 1;
0797     uint16_t hsubsampling = 1;
0798     if (color_type == PHOTOMETRIC_PALETTE) {
0799         uint16_t *red =
0800             nullptr; // No need to free them they are free by libtiff
0801         uint16_t *green = nullptr;
0802         uint16_t *blue = nullptr;
0803         if ((TIFFGetField(image, TIFFTAG_COLORMAP, &red, &green, &blue)) == 0) {
0804             dbgFile << "Indexed image does not define a palette";
0805             return ImportExportCodes::FileFormatIncorrect;
0806         }
0807 
0808         tiffReader =
0809             QSharedPointer<KisTIFFReaderFromPalette>::create(layer->paintDevice(),
0810                                                        red,
0811                                                        green,
0812                                                        blue,
0813                                                        poses,
0814                                                        alphapos,
0815                                                        depth,
0816                                                        sampletype,
0817                                                        nbcolorsamples,
0818                                                        extrasamplescount,
0819                                                        hasPremultipliedAlpha,
0820                                                        transform,
0821                                                        postprocessor);
0822     } else if (color_type == PHOTOMETRIC_YCBCR) {
0823         TIFFGetFieldDefaulted(image,
0824                               TIFFTAG_YCBCRSUBSAMPLING,
0825                               &hsubsampling,
0826                               &vsubsampling);
0827         lineSizeCoeffs[1] = hsubsampling;
0828         lineSizeCoeffs[2] = hsubsampling;
0829         dbgFile << "Subsampling" << 4 << hsubsampling << vsubsampling;
0830         if (dstDepth == 8) {
0831             tiffReader = QSharedPointer<KisTIFFYCbCrReader<uint8_t>>::create(
0832                 layer->paintDevice(),
0833                 static_cast<quint32>(layer->image()->width()),
0834                 static_cast<quint32>(layer->image()->height()),
0835                 poses,
0836                 alphapos,
0837                 depth,
0838                 sampletype,
0839                 nbcolorsamples,
0840                 extrasamplescount,
0841                 hasPremultipliedAlpha,
0842                 transform,
0843                 postprocessor,
0844                 hsubsampling,
0845                 vsubsampling);
0846         } else if (dstDepth == 16) {
0847             if (sampletype == SAMPLEFORMAT_IEEEFP) {
0848 #ifdef HAVE_OPENEXR
0849                 tiffReader = QSharedPointer<KisTIFFYCbCrReader<half>>::create(
0850                     layer->paintDevice(),
0851                     static_cast<quint32>(layer->image()->width()),
0852                     static_cast<quint32>(layer->image()->height()),
0853                     poses,
0854                     alphapos,
0855                     depth,
0856                     sampletype,
0857                     nbcolorsamples,
0858                     extrasamplescount,
0859                     hasPremultipliedAlpha,
0860                     transform,
0861                     postprocessor,
0862                     hsubsampling,
0863                     vsubsampling);
0864 #endif
0865             } else {
0866                 tiffReader =
0867                     QSharedPointer<KisTIFFYCbCrReader<uint16_t>>::create(
0868                     layer->paintDevice(),
0869                     static_cast<quint32>(layer->image()->width()),
0870                     static_cast<quint32>(layer->image()->height()),
0871                     poses,
0872                     alphapos,
0873                     depth,
0874                     sampletype,
0875                     nbcolorsamples,
0876                     extrasamplescount,
0877                     hasPremultipliedAlpha,
0878                     transform,
0879                     postprocessor,
0880                     hsubsampling,
0881                     vsubsampling);
0882             }
0883         } else if (dstDepth == 32) {
0884             if (sampletype == SAMPLEFORMAT_IEEEFP) {
0885                 tiffReader = QSharedPointer<KisTIFFYCbCrReader<float>>::create(
0886                     layer->paintDevice(),
0887                     static_cast<quint32>(layer->image()->width()),
0888                     static_cast<quint32>(layer->image()->height()),
0889                     poses,
0890                     alphapos,
0891                     depth,
0892                     sampletype,
0893                     nbcolorsamples,
0894                     extrasamplescount,
0895                     hasPremultipliedAlpha,
0896                     transform,
0897                     postprocessor,
0898                     hsubsampling,
0899                     vsubsampling);
0900             } else {
0901                 tiffReader =
0902                     QSharedPointer<KisTIFFYCbCrReader<uint32_t>>::create(
0903                     layer->paintDevice(),
0904                     static_cast<quint32>(layer->image()->width()),
0905                     static_cast<quint32>(layer->image()->height()),
0906                     poses,
0907                     alphapos,
0908                     depth,
0909                     sampletype,
0910                     nbcolorsamples,
0911                     extrasamplescount,
0912                     hasPremultipliedAlpha,
0913                     transform,
0914                     postprocessor,
0915                     hsubsampling,
0916                     vsubsampling);
0917             }
0918         }
0919     } else if (dstDepth == 8) {
0920         tiffReader = QSharedPointer<KisTIFFReaderTarget<uint8_t>>::create(
0921             layer->paintDevice(),
0922             poses,
0923             alphapos,
0924             depth,
0925             sampletype,
0926             nbcolorsamples,
0927             extrasamplescount,
0928             hasPremultipliedAlpha,
0929             transform,
0930             postprocessor,
0931             quint8_MAX);
0932     } else if (dstDepth == 16) {
0933         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0934 #ifdef HAVE_OPENEXR
0935             tiffReader = QSharedPointer<KisTIFFReaderTarget<half>>::create(
0936                 layer->paintDevice(),
0937                 poses,
0938                 alphapos,
0939                 depth,
0940                 sampletype,
0941                 nbcolorsamples,
0942                 extrasamplescount,
0943                 hasPremultipliedAlpha,
0944                 transform,
0945                 postprocessor,
0946                 1.0);
0947 #endif
0948         } else {
0949             tiffReader = QSharedPointer<KisTIFFReaderTarget<uint16_t>>::create(
0950                 layer->paintDevice(),
0951                 poses,
0952                 alphapos,
0953                 depth,
0954                 sampletype,
0955                 nbcolorsamples,
0956                 extrasamplescount,
0957                 hasPremultipliedAlpha,
0958                 transform,
0959                 postprocessor,
0960                 quint16_MAX);
0961         }
0962     } else if (dstDepth == 32) {
0963         if (sampletype == SAMPLEFORMAT_IEEEFP) {
0964             tiffReader = QSharedPointer<KisTIFFReaderTarget<float>>::create(
0965                 layer->paintDevice(),
0966                 poses,
0967                 alphapos,
0968                 depth,
0969                 sampletype,
0970                 nbcolorsamples,
0971                 extrasamplescount,
0972                 hasPremultipliedAlpha,
0973                 transform,
0974                 postprocessor,
0975                 1.0f);
0976         } else {
0977             tiffReader = QSharedPointer<KisTIFFReaderTarget<uint32_t>>::create(
0978                 layer->paintDevice(),
0979                 poses,
0980                 alphapos,
0981                 depth,
0982                 sampletype,
0983                 nbcolorsamples,
0984                 extrasamplescount,
0985                 hasPremultipliedAlpha,
0986                 transform,
0987                 postprocessor,
0988                 std::numeric_limits<uint32_t>::max());
0989         }
0990     }
0991 
0992     if (!tiffReader) {
0993         dbgFile << "Image has an invalid/unsupported color type: "
0994                 << color_type;
0995         return ImportExportCodes::FileFormatIncorrect;
0996     }
0997 
0998     uint32_t compression = COMPRESSION_NONE;
0999     TIFFGetFieldDefaulted(image, TIFFTAG_COMPRESSION, &compression, COMPRESSION_NONE);
1000 
1001 #ifdef HAVE_JPEG_TURBO
1002     uint32_t hasSplitTables = 0;
1003     uint8_t *tables = nullptr;
1004     uint32_t sz = 0;
1005     QVector<unsigned char> jpegBuf;
1006 
1007     auto handle = [&]() -> std::unique_ptr<void, decltype(&tjDestroy)> {
1008         if (planarconfig == PLANARCONFIG_CONTIG
1009             && color_type == PHOTOMETRIC_YCBCR
1010             && compression == COMPRESSION_JPEG) {
1011             return {tjInitDecompress(), &tjDestroy};
1012         } else {
1013             return {nullptr, &tjDestroy};
1014         }
1015     }();
1016 
1017     if (color_type == PHOTOMETRIC_YCBCR && compression == COMPRESSION_JPEG
1018         && hsubsampling != 1 && vsubsampling != 1) {
1019         dbgFile << "Setting up libjpeg-turbo for handling subsampled JPEG...";
1020         if (!TIFFGetFieldDefaulted(image,
1021                                    TIFFTAG_JPEGTABLESMODE,
1022                                    &hasSplitTables)) {
1023             errFile << "Error when detecting the JPEG coefficient "
1024                        "table mode";
1025             return ImportExportCodes::FileFormatIncorrect;
1026         }
1027         if (hasSplitTables) {
1028             if (!TIFFGetField(image, TIFFTAG_JPEGTABLES, &sz, &tables)) {
1029                 errFile << "Unable to retrieve the JPEG abbreviated datastream";
1030                 return ImportExportCodes::FileFormatIncorrect;
1031             }
1032         }
1033 
1034         {
1035             int width = 0;
1036             int height = 0;
1037 
1038             if (hasSplitTables
1039                 && tjDecompressHeader(handle.get(), tables, sz, &width, &height)
1040                     != 0) {
1041                 errFile << tjGetErrorStr2(handle.get());
1042                 m_doc->setErrorMessage(
1043                     i18nc("TIFF errors",
1044                           "This TIFF file is compressed with JPEG, but "
1045                           "libjpeg-turbo could not load its coefficient "
1046                           "quantization and/or Huffman coding tables. "
1047                           "Please upgrade your version of libjpeg-turbo "
1048                           "and try again."));
1049                 return ImportExportCodes::FileFormatIncorrect;
1050             }
1051         }
1052     }
1053 #endif
1054 
1055     if (TIFFIsTiled(image)) {
1056         dbgFile << "tiled image";
1057         uint32_t tileWidth = 0;
1058         uint32_t tileHeight = 0;
1059         uint32_t x = 0;
1060         uint32_t y = 0;
1061         TIFFGetField(image, TIFFTAG_TILEWIDTH, &tileWidth);
1062         TIFFGetField(image, TIFFTAG_TILELENGTH, &tileHeight);
1063         tmsize_t tileSize = TIFFTileSize(image);
1064 
1065         if (planarconfig == PLANARCONFIG_CONTIG
1066             && !(color_type == PHOTOMETRIC_YCBCR
1067                  && compression == COMPRESSION_JPEG && hsubsampling != 1
1068                  && vsubsampling != 1)) {
1069             buf.reset(_TIFFmalloc(tileSize));
1070             if (depth < 16) {
1071                 tiffstream =
1072                     QSharedPointer<KisBufferStreamContigBelow16>::create(
1073                         static_cast<uint8_t *>(buf.get()),
1074                         depth,
1075                         tileSize / tileHeight);
1076             } else if (depth >= 16 && depth < 32) {
1077                 tiffstream =
1078                     QSharedPointer<KisBufferStreamContigBelow32>::create(
1079                         static_cast<uint8_t *>(buf.get()),
1080                         depth,
1081                         tileSize / tileHeight);
1082             } else {
1083                 tiffstream =
1084                     QSharedPointer<KisBufferStreamContigAbove32>::create(
1085                         static_cast<uint8_t *>(buf.get()),
1086                         depth,
1087                         tileSize / tileHeight);
1088             }
1089         } else if (planarconfig == PLANARCONFIG_CONTIG
1090                    && color_type == PHOTOMETRIC_YCBCR
1091                    && compression == COMPRESSION_JPEG) {
1092 #ifdef HAVE_JPEG_TURBO
1093             jpegBuf.resize(tileSize);
1094             ps_buf->resize(nbchannels);
1095             TIFFReadRawTile(image, 0, jpegBuf.data(), tileSize);
1096 
1097             int width = tileWidth;
1098             int height = tileHeight;
1099             int jpegSubsamp = TJ_444;
1100             int jpegColorspace = TJCS_YCbCr;
1101 
1102             if (tjDecompressHeader3(handle.get(),
1103                                     jpegBuf.data(),
1104                                     tileSize,
1105                                     &width,
1106                                     &height,
1107                                     &jpegSubsamp,
1108                                     &jpegColorspace)
1109                 != 0) {
1110                 errFile << tjGetErrorStr2(handle.get());
1111                 return ImportExportCodes::FileFormatIncorrect;
1112             }
1113 
1114             QVector<tsize_t> lineSizes(nbchannels);
1115             for (uint32_t i = 0; i < nbchannels; i++) {
1116                 const unsigned long uncompressedTileSize =
1117                     tjPlaneSizeYUV(i, width, 0, height, jpegColorspace);
1118                 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(
1119                     uncompressedTileSize != (unsigned long)-1,
1120                     ImportExportCodes::FileFormatIncorrect);
1121                 dbgFile << QString("Uncompressed tile size (plane %1): %2")
1122                                .arg(i)
1123                                .arg(uncompressedTileSize)
1124                                .toStdString()
1125                                .c_str();
1126                 tsize_t scanLineSize = uncompressedTileSize / tileHeight;
1127                 dbgFile << QString("scan line size (plane %1): %2")
1128                                .arg(i)
1129                                .arg(scanLineSize)
1130                                .toStdString()
1131                                .c_str();
1132                 (*ps_buf)[i] =
1133                     static_cast<uint8_t *>(_TIFFmalloc(uncompressedTileSize));
1134                 lineSizes[i] = scanLineSize;
1135             }
1136             tiffstream =
1137                 QSharedPointer<KisBufferStreamInterleaveUpsample>::create(
1138                     ps_buf->data(),
1139                     nbchannels,
1140                     depth,
1141                     lineSizes.data(),
1142                     hsubsampling,
1143                     vsubsampling);
1144 #else
1145             m_doc->setErrorMessage(
1146                 i18nc("TIFF",
1147                       "Subsampled YCbCr TIFF files compressed with JPEG cannot "
1148                       "be loaded."));
1149             return ImportExportCodes::FileFormatIncorrect;
1150 #endif
1151         } else {
1152             ps_buf->resize(nbchannels);
1153             tsize_t scanLineSize = tileSize / tileHeight;
1154             dbgFile << " scanLineSize for each plan =" << scanLineSize;
1155             QVector<tsize_t> lineSizes(nbchannels);
1156             for (uint32_t i = 0; i < nbchannels; i++) {
1157                 (*ps_buf)[i] = static_cast<uint8_t *>(_TIFFmalloc(tileSize));
1158                 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
1159             }
1160             tiffstream = QSharedPointer<KisBufferStreamSeparate>::create(
1161                 ps_buf->data(),
1162                 nbchannels,
1163                 depth,
1164                 lineSizes.data());
1165         }
1166         dbgFile << "Scanline size =" << TIFFRasterScanlineSize(image)
1167                 << " / tile size =" << TIFFTileSize(image)
1168                 << " / tile width =" << tileWidth
1169                 << " tileSize/tileHeight =" << tileSize / tileHeight;
1170 
1171         dbgFile << " NbOfTiles =" << TIFFNumberOfTiles(image)
1172                 << " tileWidth =" << tileWidth << " tileSize =" << tileSize;
1173 
1174         for (y = 0; y < height; y += tileHeight) {
1175             for (x = 0; x < width; x += tileWidth) {
1176                 dbgFile << "Reading tile x =" << x << " y =" << y;
1177 #ifdef HAVE_JPEG_TURBO
1178                 if (planarconfig == PLANARCONFIG_CONTIG
1179                     && !(color_type == PHOTOMETRIC_YCBCR
1180                          && compression == COMPRESSION_JPEG && hsubsampling != 1
1181                          && vsubsampling != 1)) {
1182 #else
1183                 if (planarconfig == PLANARCONFIG_CONTIG) {
1184 #endif
1185                     TIFFReadTile(image, buf.get(), x, y, 0, (tsample_t)-1);
1186 #ifdef HAVE_JPEG_TURBO
1187                 } else if (planarconfig == PLANARCONFIG_CONTIG
1188                            && (color_type == PHOTOMETRIC_YCBCR
1189                                && compression == COMPRESSION_JPEG)) {
1190                     uint32_t tile =
1191                         TIFFComputeTile(image, x, y, 0, (tsample_t)-1);
1192                     TIFFReadRawTile(image, tile, jpegBuf.data(), tileSize);
1193 
1194                     int width = tileWidth;
1195                     int height = tileHeight;
1196                     int jpegSubsamp = TJ_444;
1197                     int jpegColorspace = TJCS_YCbCr;
1198 
1199                     if (tjDecompressHeader3(handle.get(),
1200                                             jpegBuf.data(),
1201                                             tileSize,
1202                                             &width,
1203                                             &height,
1204                                             &jpegSubsamp,
1205                                             &jpegColorspace)
1206                         != 0) {
1207                         errFile << tjGetErrorStr2(handle.get());
1208                         return ImportExportCodes::FileFormatIncorrect;
1209                     }
1210 
1211                     if (tjDecompressToYUVPlanes(handle.get(),
1212                                                 jpegBuf.data(),
1213                                                 tileSize,
1214                                                 ps_buf->data(),
1215                                                 width,
1216                                                 nullptr,
1217                                                 height,
1218                                                 0)
1219                         != 0) {
1220                         errFile << tjGetErrorStr2(handle.get());
1221                         return ImportExportCodes::FileFormatIncorrect;
1222                     }
1223 #endif
1224                 } else {
1225                     for (uint16_t i = 0; i < nbchannels; i++) {
1226                         TIFFReadTile(image, (*ps_buf)[i], x, y, 0, i);
1227                     }
1228                 }
1229                 uint32_t realTileWidth =
1230                     (x + tileWidth) < width ? tileWidth : width - x;
1231                 for (uint32_t yintile = 0;
1232                      yintile < tileHeight && y + yintile < height;) {
1233                     uint32_t linesread =
1234                         tiffReader->copyDataToChannels(x,
1235                                                        y + yintile,
1236                                                        realTileWidth,
1237                                                        tiffstream);
1238                     yintile += linesread;
1239                     tiffstream->moveToLine(yintile);
1240                 }
1241                 tiffstream->restart();
1242             }
1243         }
1244     } else {
1245         dbgFile << "striped image";
1246         tsize_t stripsize = TIFFStripSize(image);
1247         uint32_t rowsPerStrip = 0;
1248         TIFFGetFieldDefaulted(image, TIFFTAG_ROWSPERSTRIP, &rowsPerStrip);
1249         dbgFile << rowsPerStrip << "" << height;
1250         rowsPerStrip =
1251             qMin(rowsPerStrip,
1252                  height); // when TIFFNumberOfStrips(image) == 1 it might happen
1253                           // that rowsPerStrip is incorrectly set
1254         if (planarconfig == PLANARCONFIG_CONTIG
1255             && !(color_type == PHOTOMETRIC_YCBCR
1256                  && compression == COMPRESSION_JPEG && hsubsampling != 1
1257                  && vsubsampling != 1)) {
1258             buf.reset(_TIFFmalloc(stripsize));
1259             if (depth < 16) {
1260                 tiffstream =
1261                     QSharedPointer<KisBufferStreamContigBelow16>::create(
1262                     static_cast<uint8_t *>(buf.get()),
1263                     depth,
1264                     stripsize / rowsPerStrip);
1265             } else if (depth < 32) {
1266                 tiffstream =
1267                     QSharedPointer<KisBufferStreamContigBelow32>::create(
1268                     static_cast<uint8_t *>(buf.get()),
1269                     depth,
1270                     stripsize / rowsPerStrip);
1271             } else {
1272                 tiffstream =
1273                     QSharedPointer<KisBufferStreamContigAbove32>::create(
1274                     static_cast<uint8_t *>(buf.get()),
1275                     depth,
1276                     stripsize / rowsPerStrip);
1277             }
1278         } else if (planarconfig == PLANARCONFIG_CONTIG
1279                    && color_type == PHOTOMETRIC_YCBCR
1280                    && compression == COMPRESSION_JPEG) {
1281 #ifdef HAVE_JPEG_TURBO
1282             jpegBuf.resize(stripsize);
1283             ps_buf->resize(nbchannels);
1284             TIFFReadRawStrip(image, 0, jpegBuf.data(), stripsize);
1285 
1286             int width = basicInfo.width;
1287             int height = rowsPerStrip;
1288             int jpegSubsamp = TJ_444;
1289             int jpegColorspace = TJCS_YCbCr;
1290 
1291             if (tjDecompressHeader3(handle.get(),
1292                                     jpegBuf.data(),
1293                                     stripsize,
1294                                     &width,
1295                                     &height,
1296                                     &jpegSubsamp,
1297                                     &jpegColorspace)
1298                 != 0) {
1299                 errFile << tjGetErrorStr2(handle.get());
1300                 return ImportExportCodes::FileFormatIncorrect;
1301             }
1302 
1303             QVector<tsize_t> lineSizes(nbchannels);
1304             for (uint32_t i = 0; i < nbchannels; i++) {
1305                 const unsigned long uncompressedStripsize =
1306                     tjPlaneSizeYUV(i, width, 0, height, jpegColorspace);
1307                 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(
1308                     uncompressedStripsize != (unsigned long)-1,
1309                     ImportExportCodes::FileFormatIncorrect);
1310                 dbgFile << QString("Uncompressed strip size (plane %1): %2")
1311                                .arg(i)
1312                                .arg(uncompressedStripsize);
1313                 tsize_t scanLineSize = uncompressedStripsize / rowsPerStrip;
1314                 dbgFile << QString("scan line size (plane %1): %2")
1315                                .arg(i)
1316                                .arg(scanLineSize);
1317                 (*ps_buf)[i] = static_cast<uint8_t*>(_TIFFmalloc(uncompressedStripsize));
1318                 lineSizes[i] = scanLineSize;
1319             }
1320             tiffstream = QSharedPointer<KisBufferStreamInterleaveUpsample>::create(
1321                 ps_buf->data(),
1322                 nbchannels,
1323                 depth,
1324                 lineSizes.data(),
1325                 hsubsampling,
1326                 vsubsampling);
1327 #else
1328             m_doc->setErrorMessage(
1329                 i18nc("TIFF",
1330                       "Subsampled YCbCr TIFF files compressed with JPEG cannot "
1331                       "be loaded."));
1332             return ImportExportCodes::FileFormatIncorrect;
1333 #endif
1334         } else {
1335             ps_buf->resize(nbchannels);
1336             tsize_t scanLineSize = stripsize / rowsPerStrip;
1337             dbgFile << " scanLineSize for each plan =" << scanLineSize;
1338             QVector<tsize_t> lineSizes(nbchannels);
1339             for (uint32_t i = 0; i < nbchannels; i++) {
1340                 (*ps_buf)[i] = static_cast<uint8_t*>(_TIFFmalloc(stripsize));
1341                 lineSizes[i] = scanLineSize / lineSizeCoeffs[i];
1342             }
1343             tiffstream = QSharedPointer<KisBufferStreamSeparate>::create(
1344                 ps_buf->data(),
1345                 nbchannels,
1346                 depth,
1347                 lineSizes.data());
1348         }
1349 
1350         dbgFile << "Scanline size =" << TIFFRasterScanlineSize(image)
1351                 << " / strip size =" << TIFFStripSize(image)
1352                 << " / rowsPerStrip =" << rowsPerStrip
1353                 << " stripsize/rowsPerStrip =" << stripsize / rowsPerStrip;
1354         uint32_t y = 0;
1355         dbgFile << " NbOfStrips =" << TIFFNumberOfStrips(image)
1356                 << " rowsPerStrip =" << rowsPerStrip
1357                 << " stripsize =" << stripsize;
1358 
1359         for (uint32_t strip = 0; y < height; strip++) {
1360 #ifdef HAVE_JPEG_TURBO
1361             if (planarconfig == PLANARCONFIG_CONTIG
1362                 && !(color_type == PHOTOMETRIC_YCBCR
1363                      && compression == COMPRESSION_JPEG && hsubsampling != 1
1364                      && vsubsampling != 1)) {
1365 #else
1366             if (planarconfig == PLANARCONFIG_CONTIG) {
1367 #endif
1368                 TIFFReadEncodedStrip(image,
1369                                      TIFFComputeStrip(image, y, 0),
1370                                      buf.get(),
1371                                      (tsize_t)-1);
1372 #ifdef HAVE_JPEG_TURBO
1373             } else if (planarconfig == PLANARCONFIG_CONTIG
1374                        && (color_type == PHOTOMETRIC_YCBCR
1375                            && compression == COMPRESSION_JPEG)) {
1376                 TIFFReadRawStrip(image, strip, jpegBuf.data(), stripsize);
1377 
1378                 int width = basicInfo.width;
1379                 int height = rowsPerStrip;
1380                 int jpegSubsamp = TJ_444;
1381                 int jpegColorspace = TJCS_YCbCr;
1382 
1383                 if (tjDecompressHeader3(handle.get(),
1384                                         jpegBuf.data(),
1385                                         stripsize,
1386                                         &width,
1387                                         &height,
1388                                         &jpegSubsamp,
1389                                         &jpegColorspace)
1390                     != 0) {
1391                     errFile << tjGetErrorStr2(handle.get());
1392                     return ImportExportCodes::FileFormatIncorrect;
1393                 }
1394 
1395                 if (tjDecompressToYUVPlanes(
1396                         handle.get(),
1397                         jpegBuf.data(),
1398                         stripsize,
1399                         ps_buf->data(),
1400                         width,
1401                         nullptr,
1402                         height,
1403                         0)
1404                     != 0) {
1405                     errFile << tjGetErrorStr2(handle.get());
1406                     return ImportExportCodes::FileFormatIncorrect;
1407                 }
1408 #endif
1409             } else {
1410                 for (uint16_t i = 0; i < nbchannels; i++) {
1411                     TIFFReadEncodedStrip(image,
1412                                          TIFFComputeStrip(image, y, i),
1413                                          (*ps_buf)[i],
1414                                          (tsize_t)-1);
1415                 }
1416             }
1417             for (uint32_t yinstrip = 0;
1418                  yinstrip < rowsPerStrip && y < height;) {
1419                 uint32_t linesread =
1420                     tiffReader->copyDataToChannels(0, y, width, tiffstream);
1421                 y += linesread;
1422                 yinstrip += linesread;
1423                 tiffstream->moveToLine(yinstrip);
1424             }
1425             tiffstream->restart();
1426         }
1427     }
1428     tiffReader->finalize();
1429     tiffReader.reset();
1430     tiffstream.reset();
1431     ps_buf.reset();
1432 
1433     m_image->addNode(KisNodeSP(layer), m_image->rootLayer().data());
1434 
1435     layer->paintDevice()->setX(static_cast<int>(basicInfo.x * basicInfo.xres));
1436     layer->paintDevice()->setY(static_cast<int>(basicInfo.y * basicInfo.yres));
1437 
1438     // Process rotation before handing image over
1439     // https://developer.apple.com/documentation/imageio/cgimagepropertyorientation
1440     switch (orientation) {
1441     case ORIENTATION_TOPRIGHT:
1442         KisTransformWorker::mirrorX(layer->paintDevice());
1443         break;
1444     case ORIENTATION_BOTRIGHT:
1445         m_image->rotateImage(M_PI);
1446         break;
1447     case ORIENTATION_BOTLEFT:
1448         KisTransformWorker::mirrorY(layer->paintDevice());
1449         break;
1450     case ORIENTATION_LEFTTOP:
1451         m_image->rotateImage(M_PI / 2);
1452         KisTransformWorker::mirrorY(layer->paintDevice());
1453         break;
1454     case ORIENTATION_RIGHTTOP:
1455         m_image->rotateImage(M_PI / 2);
1456         break;
1457     case ORIENTATION_RIGHTBOT:
1458         m_image->rotateImage(M_PI / 2);
1459         KisTransformWorker::mirrorX(layer->paintDevice());
1460         break;
1461     case ORIENTATION_LEFTBOT:
1462         m_image->rotateImage(-M_PI / 2 + M_PI * 2);
1463         break;
1464     default:
1465         break;
1466     }
1467 
1468     // Process IPTC metadata
1469     if (iptc_profile_size > 0 && iptc_profile_data != nullptr) {
1470         dbgFile << "Loading IPTC profile. Size: "
1471                 << sizeof(uint32_t) * iptc_profile_size;
1472 
1473         // warning: profile is an array of uint32_t's
1474         if (TIFFIsByteSwapped(image) != 0) {
1475             TIFFSwabArrayOfLong(iptc_profile_data,
1476                                 iptc_profile_size / sizeof(uint32_t));
1477         }
1478 
1479         KisMetaData::IOBackend *iptcIO =
1480             KisMetadataBackendRegistry::instance()->value("iptc");
1481 
1482         // Copy the xmp data into the byte array
1483         QByteArray ba(reinterpret_cast<const char *>(iptc_profile_data),
1484                       static_cast<int>(iptc_profile_size));
1485         QBuffer buf(&ba);
1486         iptcIO->loadFrom(layer->metaData(), &buf);
1487     }
1488 
1489     // Process XMP metadata
1490     if (xmp_size > 0 && xmp_data != nullptr) {
1491         dbgFile << "Loading XMP data. Size: " << xmp_size;
1492 
1493         KisMetaData::IOBackend *xmpIO =
1494             KisMetadataBackendRegistry::instance()->value("xmp");
1495 
1496         // Copy the xmp data into the byte array
1497         QByteArray ba(reinterpret_cast<char *>(xmp_data),
1498                       static_cast<int>(xmp_size));
1499         QBuffer buf(&ba);
1500         xmpIO->loadFrom(layer->metaData(), &buf);
1501     }
1502 
1503     return ImportExportCodes::OK;
1504 }
1505 
1506 KisImportExportErrorCode KisTIFFImport::readImageFromPsd(KisDocument *m_doc, TIFF *image, KisTiffBasicInfo &basicInfo)
1507 {
1508 #ifdef TIFF_HAS_PSD_TAGS
1509   // Attempt to parse Photoshop metadata
1510     // if it succeeds, divert and load as PSD
1511 
1512     if (!m_photoshopBlockParsed) {
1513         QBuffer photoshopLayerData;
1514 
1515         KisTiffPsdLayerRecord photoshopLayerRecord(TIFFIsBigEndian(image),
1516                                                    basicInfo.width,
1517                                                    basicInfo.height,
1518                                                    basicInfo.depth,
1519                                                    basicInfo.nbchannels,
1520                                                    basicInfo.color_type);
1521 
1522         KisTiffPsdResourceRecord photoshopImageResourceRecord;
1523 
1524         {
1525             // Determine if we have Photoshop metadata
1526             uint32_t length{0};
1527             uint8_t *data{nullptr};
1528 
1529             if (TIFFGetField(image, TIFFTAG_IMAGESOURCEDATA, &length, &data)
1530                 == 1) {
1531                 dbgFile << "There are Photoshop layers, processing them now. "
1532                            "Section size: "
1533                         << length;
1534 
1535                 QByteArray buf(reinterpret_cast<char *>(data),
1536                                static_cast<int>(length));
1537                 photoshopLayerData.setData(buf);
1538                 photoshopLayerData.open(QIODevice::ReadOnly);
1539 
1540                 if (!photoshopLayerRecord.read(photoshopLayerData)) {
1541                     dbgFile << "TIFF: failed reading Photoshop layer metadata: "
1542                             << photoshopLayerRecord.record()->error;
1543                 }
1544             }
1545         }
1546 
1547         {
1548             // Determine if we have Photoshop metadata
1549             uint32_t length{0};
1550             uint8_t *data{nullptr};
1551 
1552             if (TIFFGetField(image, TIFFTAG_PHOTOSHOP, &length, &data) == 1
1553                 && data != nullptr) {
1554                 dbgFile << "There is Photoshop metadata, processing it now. "
1555                            "Section size: "
1556                         << length;
1557 
1558                 QByteArray photoshopImageResourceData(
1559                     reinterpret_cast<char *>(data),
1560                     static_cast<int>(length));
1561 
1562                 QBuffer buf(&photoshopImageResourceData);
1563                 buf.open(QIODevice::ReadOnly);
1564 
1565                 if (!photoshopImageResourceRecord.read(buf)) {
1566                     dbgFile << "TIFF: failed reading Photoshop image metadata: "
1567                             << photoshopImageResourceRecord.error;
1568                 }
1569             }
1570         }
1571 
1572 
1573         if (importUserFeedBackInterface()) {
1574 
1575             bool usePsd = true;
1576             importUserFeedBackInterface()->askUser([&] (QWidget *parent) {
1577                 usePsd = QMessageBox::question(parent, i18nc("@title:window", "TIFF image with PSD data"),
1578                                       i18nc("the choice for the user on loading a TIFF file",
1579                                             "The TIFF image contains valid PSD data embedded. "
1580                                             "Would you like to use PSD data instead of normal TIFF data?"))
1581                     == QMessageBox::Yes;
1582 
1583                 return true;
1584             });
1585 
1586             if (!usePsd) {
1587                 return ImportExportCodes::Cancelled;
1588             }
1589         }
1590 
1591         if (photoshopLayerRecord.valid()
1592             && photoshopImageResourceRecord.valid()) {
1593             KisImportExportErrorCode result =
1594                 readImageFromPsdRecords(m_doc,
1595                                         photoshopLayerRecord,
1596                                         photoshopImageResourceRecord,
1597                                         photoshopLayerData,
1598                                         basicInfo);
1599 
1600             if (!result.isOk()) {
1601                 dbgFile << "Photoshop import failed";
1602             }
1603             return result;
1604         }
1605     }
1606 
1607     return ImportExportCodes::FormatFeaturesUnsupported;
1608 
1609 #else
1610     return ImportExportCodes::FormatFeaturesUnsupported;
1611 #endif
1612 }
1613 
1614 KisImportExportErrorCode KisTIFFImport::readTIFFDirectory(KisDocument *m_doc,
1615                                                           TIFF *image)
1616 {
1617     // Read information about the tiff
1618 
1619     KisTiffBasicInfo basicInfo;
1620 
1621     if (TIFFGetField(image, TIFFTAG_IMAGEWIDTH, &basicInfo.width) == 0) {
1622         dbgFile << "Image does not define its width";
1623         return ImportExportCodes::FileFormatIncorrect;
1624     }
1625 
1626     if (TIFFGetField(image, TIFFTAG_IMAGELENGTH, &basicInfo.height) == 0) {
1627         dbgFile << "Image does not define its height";
1628         return ImportExportCodes::FileFormatIncorrect;
1629     }
1630 
1631     if (TIFFGetField(image, TIFFTAG_XRESOLUTION, &basicInfo.xres) == 0) {
1632         dbgFile << "Image does not define x resolution";
1633         // but we don't stop
1634         basicInfo.xres = 100;
1635     }
1636 
1637     if (TIFFGetField(image, TIFFTAG_YRESOLUTION, &basicInfo.yres) == 0) {
1638         dbgFile << "Image does not define y resolution";
1639         // but we don't stop
1640         basicInfo.yres = 100;
1641     }
1642 
1643     if (TIFFGetField(image, TIFFTAG_RESOLUTIONUNIT, &basicInfo.resolution) == 0) {
1644         dbgFile << "Image does not define resolution unit";
1645         // but we don't stop
1646         basicInfo.resolution = TiffResolution::INCH;
1647     }
1648 
1649     if (TIFFGetField(image, TIFFTAG_XPOSITION, &basicInfo.x) == 0) {
1650         dbgFile << "Image does not define a horizontal offset";
1651         basicInfo.x = 0;
1652     }
1653 
1654     if (TIFFGetField(image, TIFFTAG_YPOSITION, &basicInfo.y) == 0) {
1655         dbgFile << "Image does not define a vertical offset";
1656         basicInfo.y = 0;
1657     }
1658 
1659     if ((TIFFGetField(image, TIFFTAG_BITSPERSAMPLE, &basicInfo.depth) == 0)) {
1660         dbgFile << "Image does not define its depth";
1661         basicInfo.depth = 1;
1662     }
1663 
1664     if ((TIFFGetField(image, TIFFTAG_SAMPLEFORMAT, &basicInfo.sampletype)
1665          == 0)) {
1666         dbgFile << "Image does not define its sample type";
1667         basicInfo.sampletype = SAMPLEFORMAT_UINT;
1668     }
1669 
1670     // Determine the number of channels (useful to know if a file has an alpha
1671     // or not
1672     if (TIFFGetField(image, TIFFTAG_SAMPLESPERPIXEL, &basicInfo.nbchannels)
1673         == 0) {
1674         dbgFile << "Image has an undefined number of samples per pixel";
1675         basicInfo.nbchannels = 0;
1676     }
1677 
1678     // Get the number of extrasamples and information about them
1679     if (TIFFGetField(image,
1680                      TIFFTAG_EXTRASAMPLES,
1681                      &basicInfo.extrasamplescount,
1682                      &basicInfo.sampleinfo)
1683         == 0) {
1684         basicInfo.extrasamplescount = 0;
1685     }
1686 
1687     // Determine the colorspace
1688     if (TIFFGetField(image, TIFFTAG_PHOTOMETRIC, &basicInfo.color_type) == 0) {
1689         dbgFile << "Image has an undefined photometric interpretation";
1690         basicInfo.color_type = PHOTOMETRIC_MINISWHITE;
1691     }
1692 
1693     basicInfo.colorSpaceIdTag =
1694         getColorSpaceForColorType(basicInfo.sampletype,
1695                                   basicInfo.color_type,
1696                                   basicInfo.depth,
1697                                   image,
1698                                   basicInfo.nbchannels,
1699                                   basicInfo.extrasamplescount,
1700                                   basicInfo.dstDepth);
1701 
1702     if (basicInfo.colorSpaceIdTag.first.isEmpty()) {
1703         dbgFile << "Image has an unsupported colorspace :"
1704                 << basicInfo.color_type
1705                 << " for this depth :" << basicInfo.depth;
1706         return ImportExportCodes::FormatColorSpaceUnsupported;
1707     }
1708     dbgFile << "Color space is :" << basicInfo.colorSpaceIdTag.first
1709             << basicInfo.colorSpaceIdTag.second << " with a depth of"
1710             << basicInfo.depth << " and with a nb of channels of"
1711             << basicInfo.nbchannels;
1712 
1713     // Read image profile
1714     dbgFile << "Reading profile";
1715     const KoColorProfile *profile = nullptr;
1716     quint32 EmbedLen = 0;
1717     uint8_t *EmbedBuffer = nullptr;
1718 
1719     if (TIFFGetField(image, TIFFTAG_ICCPROFILE, &EmbedLen, &EmbedBuffer) == 1) {
1720         dbgFile << "Profile found";
1721         QByteArray rawdata(reinterpret_cast<char *>(EmbedBuffer),
1722                            static_cast<int>(EmbedLen));
1723         profile = KoColorSpaceRegistry::instance()->createColorProfile(
1724             basicInfo.colorSpaceIdTag.first,
1725             basicInfo.colorSpaceIdTag.second,
1726             rawdata);
1727     }
1728 
1729     const QString colorSpaceId = KoColorSpaceRegistry::instance()->colorSpaceId(
1730         basicInfo.colorSpaceIdTag.first,
1731         basicInfo.colorSpaceIdTag.second);
1732 
1733     // Check that the profile is used by the color space
1734     if (profile
1735         && !KoColorSpaceRegistry::instance()->profileIsCompatible(
1736             profile,
1737             colorSpaceId)) {
1738         dbgFile << "The profile " << profile->name()
1739                 << " is not compatible with the color space model "
1740                 << basicInfo.colorSpaceIdTag.first << " "
1741                 << basicInfo.colorSpaceIdTag.second;
1742         profile = nullptr;
1743     }
1744 
1745     // Do not use the linear gamma profile for 16 bits/channel by default, tiff
1746     // files are usually created with gamma correction. XXX: Should we ask the
1747     // user?
1748     if (!profile) {
1749         dbgFile << "No profile found; trying to assign a default one.";
1750         if (basicInfo.colorSpaceIdTag.first == RGBAColorModelID.id()) {
1751             profile = KoColorSpaceRegistry::instance()->profileByName(
1752                 "sRGB-elle-V2-srgbtrc.icc");
1753         } else if (basicInfo.colorSpaceIdTag.first == GrayAColorModelID.id()) {
1754             profile = KoColorSpaceRegistry::instance()->profileByName(
1755                 "Gray-D50-elle-V2-srgbtrc.icc");
1756         } else if (basicInfo.colorSpaceIdTag.first == CMYKAColorModelID.id()) {
1757             profile = KoColorSpaceRegistry::instance()->profileByName(
1758                 "Chemical proof");
1759         } else if (basicInfo.colorSpaceIdTag.first == LABAColorModelID.id()) {
1760             profile = KoColorSpaceRegistry::instance()->profileByName(
1761                 "Lab identity built-in");
1762         } else if (basicInfo.colorSpaceIdTag.first == YCbCrAColorModelID.id()) {
1763             profile = KoColorSpaceRegistry::instance()->profileByName(
1764                 "ITU-R BT.709-6 YCbCr ICC V4 profile");
1765         }
1766         if (!profile) {
1767             dbgFile << "No suitable default profile found.";
1768         }
1769     }
1770 
1771     // Retrieve a pointer to the colorspace
1772     if (profile && profile->isSuitableForOutput()) {
1773         dbgFile << "image has embedded profile:" << profile->name() << "";
1774         basicInfo.cs = KoColorSpaceRegistry::instance()->colorSpace(
1775             basicInfo.colorSpaceIdTag.first,
1776             basicInfo.colorSpaceIdTag.second,
1777             profile);
1778     } else {
1779         // Ensure an empty profile name is supplied so that the fallback logic
1780         // in KoColorSpaceRegistry is triggered. BUG:464848
1781         basicInfo.cs = KoColorSpaceRegistry::instance()->colorSpace(basicInfo.colorSpaceIdTag.first,
1782                                                                     basicInfo.colorSpaceIdTag.second,
1783                                                                     "");
1784     }
1785 
1786     if (basicInfo.cs == nullptr) {
1787         dbgFile << "Color space" << basicInfo.colorSpaceIdTag.first
1788                 << basicInfo.colorSpaceIdTag.second
1789                 << " is not available, please check your installation.";
1790         return ImportExportCodes::FormatColorSpaceUnsupported;
1791     }
1792 
1793     // Create the cmsTransform if needed
1794     if (profile && !profile->isSuitableForOutput()) {
1795         dbgFile << "The profile can't be used in krita, need conversion";
1796         basicInfo.transform =
1797             KoColorSpaceRegistry::instance()
1798                 ->colorSpace(basicInfo.colorSpaceIdTag.first,
1799                              basicInfo.colorSpaceIdTag.second,
1800                              profile)
1801                 ->createColorConverter(
1802                     basicInfo.cs,
1803                     KoColorConversionTransformation::internalRenderingIntent(),
1804                     KoColorConversionTransformation::internalConversionFlags());
1805     }
1806 
1807     KisImportExportErrorCode result = readImageFromPsd(m_doc, image, basicInfo);
1808     if (!result.isOk()) {
1809         result = readImageFromTiff(m_doc, image, basicInfo);
1810     }
1811 
1812     return result;
1813 }
1814 
1815 KisImportExportErrorCode
1816 KisTIFFImport::convert(KisDocument *document,
1817                        QIODevice * /*io*/,
1818                        KisPropertiesConfigurationSP /*configuration*/)
1819 {
1820     dbgFile << "Start decoding TIFF File";
1821 
1822     if (!KisImportExportAdditionalChecks::doesFileExist(filename())) {
1823         return ImportExportCodes::FileNotExist;
1824     }
1825     if (!KisImportExportAdditionalChecks::isFileReadable(filename())) {
1826         return ImportExportCodes::NoAccessToRead;
1827     }
1828 
1829     QFile file(filename());
1830     if (!file.open(QFile::ReadOnly)) {
1831         return KisImportExportErrorCode(KisImportExportErrorCannotRead(file.error()));
1832     }
1833 
1834     // Open the TIFF file
1835     const QByteArray encodedFilename = QFile::encodeName(filename());
1836 
1837     // https://gitlab.com/libtiff/libtiff/-/issues/173
1838 #ifdef Q_OS_WIN
1839     const intptr_t handle = _get_osfhandle(file.handle());
1840 #else
1841     const int handle = file.handle();
1842 #endif
1843 
1844     std::unique_ptr<TIFF, decltype(&TIFFCleanup)> image(TIFFFdOpen(handle, encodedFilename.data(), "r"), &TIFFCleanup);
1845 
1846     if (!image) {
1847         dbgFile << "Could not open the file, either it does not exist, either "
1848                    "it is not a TIFF :"
1849                 << filename();
1850         return (ImportExportCodes::FileFormatIncorrect);
1851     }
1852     dbgFile << "Reading first image descriptor";
1853     KisImportExportErrorCode result = readTIFFDirectory(document, image.get());
1854     if (!result.isOk()) {
1855         return result;
1856     }
1857 
1858     if (!m_photoshopBlockParsed) {
1859         // Photoshop images only have one IFD plus the layer blob
1860         // Ward off inconsistencies by blocking future attempts to parse them
1861         m_photoshopBlockParsed = true;
1862         while (TIFFReadDirectory(image.get())) {
1863             result = readTIFFDirectory(document, image.get());
1864             if (!result.isOk()) {
1865                 return result;
1866             }
1867         }
1868     }
1869     // Freeing memory
1870     image.reset();
1871     file.close();
1872 
1873     {
1874         // HACK!! Externally parse the Exif metadata
1875         // libtiff has no way to access the fields wholesale
1876         try {
1877             KisExiv2IODevice::ptr_type basicIoDevice(new KisExiv2IODevice(filename()));
1878 
1879 #if EXIV2_TEST_VERSION(0,28,0)
1880             const std::unique_ptr<Exiv2::Image> readImg = Exiv2::ImageFactory::open(std::move(basicIoDevice));
1881 #else
1882             const std::unique_ptr<Exiv2::Image> readImg(Exiv2::ImageFactory::open(basicIoDevice).release());
1883 #endif
1884 
1885             readImg->readMetadata();
1886 
1887             const KisMetaData::IOBackend *io =
1888                 KisMetadataBackendRegistry::instance()->value("exif");
1889 
1890             // All IFDs are paint layer children of root
1891             KisNodeSP node = m_image->rootLayer()->firstChild();
1892 
1893             QBuffer ioDevice;
1894 
1895             {
1896                 // Synthesize the Exif blob
1897                 Exiv2::ExifData tempData;
1898                 Exiv2::Blob tempBlob;
1899 
1900                 // NOTE: do not use std::copy_if, auto_ptrs beware
1901                 for (const Exiv2::Exifdatum &i : readImg->exifData()) {
1902                     const uint16_t tag = i.tag();
1903 
1904                     if (tag == Exif::Image::ImageWidth
1905                         || tag == Exif::Image::ImageLength
1906                         || tag == Exif::Image::BitsPerSample
1907                         || tag == Exif::Image::Compression
1908                         || tag == Exif::Image::PhotometricInterpretation
1909                         || tag == Exif::Image::Orientation
1910                         || tag == Exif::Image::SamplesPerPixel
1911                         || tag == Exif::Image::PlanarConfiguration
1912                         || tag == Exif::Image::YCbCrSubSampling
1913                         || tag == Exif::Image::YCbCrPositioning
1914                         || tag == Exif::Image::XResolution
1915                         || tag == Exif::Image::YResolution
1916                         || tag == Exif::Image::ResolutionUnit
1917                         || tag == Exif::Image::TransferFunction
1918                         || tag == Exif::Image::WhitePoint
1919                         || tag == Exif::Image::PrimaryChromaticities
1920                         || tag == Exif::Image::YCbCrCoefficients
1921                         || tag == Exif::Image::ReferenceBlackWhite
1922                         || tag == Exif::Image::InterColorProfile) {
1923                         dbgMetaData << "Ignoring TIFF-specific"
1924                                     << i.key().c_str();
1925                         continue;
1926                     }
1927 
1928                     tempData.add(i);
1929                 }
1930 
1931                 // Encode into temporary blob
1932                 Exiv2::ExifParser::encode(tempBlob,
1933                                           Exiv2::littleEndian,
1934                                           tempData);
1935 
1936                 // Reencode into Qt land
1937                 ioDevice.setData(reinterpret_cast<char *>(tempBlob.data()),
1938                                  static_cast<int>(tempBlob.size()));
1939             }
1940 
1941             // Get layer
1942             KisLayer *layer = qobject_cast<KisLayer *>(node.data());
1943             KIS_ASSERT_RECOVER(layer)
1944             {
1945                 errFile << "Attempted to import metadata on an empty document";
1946                 return ImportExportCodes::InternalError;
1947             }
1948 
1949             // Inject the data as any other IOBackend
1950             io->loadFrom(layer->metaData(), &ioDevice);
1951 #if EXIV2_TEST_VERSION(0,28,0)
1952         } catch (Exiv2::Error &e) {
1953             errFile << "Failed metadata import:" << Exiv2::Error(e.code()).what();
1954 #else
1955         } catch (Exiv2::AnyError &e) {
1956             errFile << "Failed metadata import:" << e.code() << e.what();
1957 #endif
1958         }
1959     }
1960 
1961     document->setCurrentImage(m_image);
1962 
1963     m_image = nullptr;
1964     m_photoshopBlockParsed = false;
1965 
1966     return ImportExportCodes::OK;
1967 }
1968 
1969 #include <kis_tiff_import.moc>