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