File indexing completed on 2025-01-19 03:51:02

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-06-14
0007  * Description : A QImage loader for DImg framework - load method.
0008  *
0009  * SPDX-FileCopyrightText: 2005      by Renchi Raju <renchi dot raju at gmail dot com>
0010  * SPDX-FileCopyrightText: 2006-2021 by Caulier Gilles <caulier dot gilles at gmail dot com>
0011  *
0012  * SPDX-License-Identifier: GPL-2.0-or-later
0013  *
0014  * ============================================================ */
0015 
0016 #include "dimgqimageloader.h"
0017 
0018 // Qt includes
0019 
0020 #include <QImage>
0021 #include <QByteArray>
0022 #include <QColorSpace>
0023 #include <QImageReader>
0024 
0025 // Local includes
0026 
0027 #include "digikam_debug.h"
0028 #include "dimgloaderobserver.h"
0029 
0030 namespace DigikamQImageDImgPlugin
0031 {
0032 
0033 bool DImgQImageLoader::load(const QString& filePath, DImgLoaderObserver* const observer)
0034 {
0035     readMetadata(filePath);
0036 
0037     // Loading is opaque to us. No support for stopping from observer,
0038     // progress info are only pseudo values
0039 
0040     QImageReader reader(filePath);
0041     reader.setDecideFormatFromContent(true);
0042 
0043     QByteArray readFormat = reader.format();
0044     QImage image          = reader.read();
0045 
0046     if (observer)
0047     {
0048         observer->progressInfo(0.9F);
0049     }
0050 
0051     if (image.isNull())
0052     {
0053         qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Can not load \"" << filePath << "\" using DImg::DImgQImageLoader!";
0054         qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Error message from loader:" << reader.errorString();
0055         loadingFailed();
0056         return false;
0057     }
0058 
0059     int colorModel    = DImg::COLORMODELUNKNOWN;
0060     int originalDepth = 0;
0061 
0062     switch (image.format())
0063     {
0064         case QImage::Format_Invalid:
0065         default:
0066         {
0067             colorModel    = DImg::COLORMODELUNKNOWN;
0068             originalDepth = 0;
0069             break;
0070         }
0071 
0072         case QImage::Format_Mono:
0073         case QImage::Format_MonoLSB:
0074         {
0075             colorModel    = DImg::MONOCHROME;
0076             originalDepth = 1;
0077             break;
0078         }
0079 
0080         case QImage::Format_Indexed8:
0081         {
0082             colorModel    = DImg::INDEXED;
0083             originalDepth = 0;
0084             break;
0085         }
0086 
0087         case QImage::Format_RGB32:
0088         {
0089             colorModel    = DImg::RGB;
0090             originalDepth = 8;
0091             break;
0092         }
0093 
0094         case QImage::Format_ARGB32:
0095         case QImage::Format_ARGB32_Premultiplied:
0096         {
0097             colorModel    = DImg::RGB;
0098             originalDepth = 8;
0099             break;
0100         }
0101 
0102         case QImage::Format_RGBX64:
0103         case QImage::Format_RGBA64:
0104         case QImage::Format_RGBA64_Premultiplied:
0105         {
0106             colorModel    = DImg::RGB;
0107             m_sixteenBit  = true;
0108             originalDepth = 16;
0109             break;
0110         }
0111     }
0112 
0113     QImage target;
0114     uint w      = 0;
0115     uint h      = 0;
0116     uchar* data = nullptr;
0117 
0118     if (!m_sixteenBit)
0119     {
0120         qCDebug(DIGIKAM_DIMG_LOG_QIMAGE) << filePath << "is a 8 bits per color per pixels QImage";
0121 
0122         m_hasAlpha    = (image.hasAlphaChannel() && (readFormat != "psd"));
0123         target        = image.convertToFormat(QImage::Format_ARGB32);
0124         w             = target.width();
0125         h             = target.height();
0126         data          = new_failureTolerant(w, h, 4);
0127 
0128         if (!data)
0129         {
0130             qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Failed to allocate memory for loading" << filePath;
0131             loadingFailed();
0132             return false;
0133         }
0134 
0135         const QRgb* sptr = reinterpret_cast<const QRgb*>(target.constBits());
0136         uchar*      dptr = data;
0137 
0138         for (uint i = 0 ; i < w * h ; ++i)
0139         {
0140             QColor color(*sptr);
0141             dptr[0] = color.blue();
0142             dptr[1] = color.green();
0143             dptr[2] = color.red();
0144             dptr[3] = m_hasAlpha ? color.alpha() : 255;
0145 
0146             dptr   += 4;
0147             sptr++;
0148         }
0149     }
0150     else
0151     {
0152         qCDebug(DIGIKAM_DIMG_LOG_QIMAGE) << filePath << "is a 16 bits per color per pixels QImage";
0153 
0154         m_hasAlpha    = (image.hasAlphaChannel() && (readFormat != "psd"));
0155         target        = image.convertToFormat(QImage::Format_RGBA64);
0156         w             = target.width();
0157         h             = target.height();
0158         data          = new_failureTolerant(w, h, 8);
0159 
0160         if (!data)
0161         {
0162             qCWarning(DIGIKAM_DIMG_LOG_QIMAGE) << "Failed to allocate memory for loading" << filePath;
0163             loadingFailed();
0164             return false;
0165         }
0166 
0167         const QRgba64* sptr = reinterpret_cast<const QRgba64*>(target.constBits());
0168         ushort*        dptr = reinterpret_cast<ushort*>(data);
0169 
0170         for (uint i = 0 ; i < w * h ; ++i)
0171         {
0172             dptr[0] = (*sptr).blue();
0173             dptr[1] = (*sptr).green();
0174             dptr[2] = (*sptr).red();
0175             dptr[3] = m_hasAlpha ? (*sptr).alpha() : 65535;
0176 
0177             dptr   += 4;
0178             sptr++;
0179         }
0180     }
0181 
0182     if (m_loadFlags & LoadICCData)
0183     {
0184         QByteArray iccRawProfile(target.colorSpace().iccProfile());
0185 
0186         if (!iccRawProfile.isEmpty())
0187         {
0188             imageSetIccProfile(IccProfile(iccRawProfile));
0189         }
0190     }
0191 
0192     if (observer)
0193     {
0194         observer->progressInfo(1.0F);
0195     }
0196 
0197     imageWidth()  = w;
0198     imageHeight() = h;
0199     imageData()   = data;
0200 
0201     QStringList noRotate({QLatin1String("JXL"),
0202                           QLatin1String("AVIF"),
0203                           QLatin1String("HEIF")});
0204 
0205     QString format(QString::fromLatin1(readFormat).toUpper());
0206 
0207     imageSetAttribute(QLatin1String("format"),             format);
0208     imageSetAttribute(QLatin1String("originalColorModel"), colorModel);
0209     imageSetAttribute(QLatin1String("originalSize"),       QSize(w, h));
0210     imageSetAttribute(QLatin1String("originalBitDepth"),   originalDepth);
0211     imageSetAttribute(QLatin1String("exifRotated"),        noRotate.contains(format));
0212 
0213     return true;
0214 }
0215 
0216 } // namespace DigikamQImageDImgPlugin