File indexing completed on 2025-01-19 03:54:49
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2005-06-14 0007 * Description : DImg image loader interface 0008 * 0009 * SPDX-FileCopyrightText: 2005 by Renchi Raju <renchi dot raju at gmail dot com> 0010 * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0011 * 0012 * SPDX-License-Identifier: GPL-2.0-or-later 0013 * 0014 * ============================================================ */ 0015 0016 #include "dimgloader.h" 0017 0018 // C++ includes 0019 0020 #include <new> 0021 #include <cstddef> 0022 0023 // Qt includes 0024 0025 #include <QScopedPointer> 0026 0027 // KDE includes 0028 0029 #include <kmemoryinfo.h> 0030 0031 // Local includes 0032 0033 #include "dimg_p.h" 0034 #include "dmetadata.h" 0035 #include "dimgloaderobserver.h" 0036 0037 namespace Digikam 0038 { 0039 0040 DImgLoader::DImgLoader(DImg* const image) 0041 : m_image (image), 0042 m_loadFlags(LoadAll) 0043 { 0044 } 0045 0046 DImgLoader::~DImgLoader() 0047 { 0048 } 0049 0050 void DImgLoader::setLoadFlags(LoadFlags flags) 0051 { 0052 m_loadFlags = flags; 0053 } 0054 0055 bool DImgLoader::hasLoadedData() const 0056 { 0057 return ((m_loadFlags & (LoadImageData | LoadPreview)) && m_image->m_priv->data); 0058 } 0059 0060 int DImgLoader::granularity(DImgLoaderObserver* const observer, int total, float progressSlice) 0061 { 0062 // Splits expect total value into the chunks where checks shall occur 0063 // and combines this with a possible correction factor from observer. 0064 // Progress slice is the part of 100% concerned with the current granularity 0065 // (E.g. in a loop only the values from 10% to 90% are used, then progressSlice is 0.8) 0066 // Current default is 1/20, that is progress info every 5% 0067 0068 int granularity = 0; 0069 0070 if (observer) 0071 { 0072 granularity = (int)((total / (20 * progressSlice)) / observer->granularity()); 0073 } 0074 0075 return (granularity ? granularity : 1); 0076 } 0077 0078 unsigned char*& DImgLoader::imageData() 0079 { 0080 return m_image->m_priv->data; 0081 } 0082 0083 quint64 DImgLoader::imageNumBytes() const 0084 { 0085 return m_image->numBytes(); 0086 } 0087 0088 unsigned int& DImgLoader::imageWidth() 0089 { 0090 return m_image->m_priv->width; 0091 } 0092 0093 unsigned int& DImgLoader::imageHeight() 0094 { 0095 return m_image->m_priv->height; 0096 } 0097 0098 bool DImgLoader::imageHasAlpha() const 0099 { 0100 return m_image->hasAlpha(); 0101 } 0102 0103 bool DImgLoader::imageSixteenBit() const 0104 { 0105 return m_image->sixteenBit(); 0106 } 0107 0108 int DImgLoader::imageBitsDepth() const 0109 { 0110 return m_image->bitsDepth(); 0111 } 0112 0113 int DImgLoader::imageBytesDepth() const 0114 { 0115 return m_image->bytesDepth(); 0116 } 0117 0118 void DImgLoader::imageSetIccProfile(const IccProfile& profile) 0119 { 0120 m_image->setIccProfile(profile); 0121 } 0122 0123 QVariant DImgLoader::imageGetAttribute(const QString& key) const 0124 { 0125 return m_image->attribute(key); 0126 } 0127 0128 QString DImgLoader::imageGetEmbbededText(const QString& key) const 0129 { 0130 return m_image->embeddedText(key); 0131 } 0132 0133 void DImgLoader::imageSetAttribute(const QString& key, const QVariant& value) 0134 { 0135 m_image->setAttribute(key, value); 0136 } 0137 0138 QMap<QString, QString>& DImgLoader::imageEmbeddedText() const 0139 { 0140 return m_image->m_priv->embeddedText; 0141 } 0142 0143 void DImgLoader::imageSetEmbbededText(const QString& key, const QString& text) 0144 { 0145 m_image->setEmbeddedText(key, text); 0146 } 0147 0148 void DImgLoader::loadingFailed() 0149 { 0150 if (m_image->m_priv->data) 0151 { 0152 delete [] m_image->m_priv->data; 0153 } 0154 0155 m_image->m_priv->data = nullptr; 0156 m_image->m_priv->width = 0; 0157 m_image->m_priv->height = 0; 0158 } 0159 0160 qint64 DImgLoader::checkAllocation(qint64 fullSize) 0161 { 0162 if ((quint64)fullSize >= std::numeric_limits<size_t>::max()) 0163 { 0164 qCWarning(DIGIKAM_DIMG_LOG) << "Cannot allocate buffer of size" << fullSize; 0165 return 0; 0166 } 0167 0168 // Do extra check if allocating serious amounts of memory. 0169 // At the time of writing (2011), I consider 100 MB as "serious". 0170 0171 if (fullSize > (qint64)(100 * 1024 * 1024)) 0172 { 0173 KMemoryInfo memInfo; 0174 0175 if (memInfo.isNull()) 0176 { 0177 qCWarning(DIGIKAM_DIMG_LOG) << "Not a recognized platform to get memory information"; 0178 0179 return -1; 0180 } 0181 0182 qint64 available = memInfo.availablePhysical(); 0183 0184 if (available == 0) 0185 { 0186 qCWarning(DIGIKAM_DIMG_LOG) << "Error to get physical memory information form a recognized platform"; 0187 0188 return 0; 0189 } 0190 0191 if (fullSize > available) 0192 { 0193 qCWarning(DIGIKAM_DIMG_LOG) << "Not enough memory to allocate buffer of size " << fullSize; 0194 qCWarning(DIGIKAM_DIMG_LOG) << "Available memory size is " << available; 0195 0196 return 0; 0197 } 0198 } 0199 0200 return fullSize; 0201 } 0202 0203 bool DImgLoader::readMetadata(const QString& filePath) 0204 { 0205 if (!((m_loadFlags & LoadMetadata) || (m_loadFlags & LoadUniqueHash) || (m_loadFlags & LoadImageHistory))) 0206 { 0207 return false; 0208 } 0209 0210 QScopedPointer<DMetadata> metaDataFromFile(new DMetadata); 0211 0212 if (!metaDataFromFile->load(filePath)) 0213 { 0214 m_image->setMetadata(MetaEngineData()); 0215 return false; 0216 } 0217 0218 m_image->setMetadata(metaDataFromFile->data()); 0219 0220 if (m_loadFlags & LoadImageHistory) 0221 { 0222 DImageHistory history = DImageHistory::fromXml(metaDataFromFile->getItemHistory()); 0223 HistoryImageId id = m_image->createHistoryImageId(filePath, HistoryImageId::Current); 0224 history << id; 0225 0226 m_image->setItemHistory(history); 0227 imageSetAttribute(QLatin1String("originalImageHistory"), QVariant::fromValue(history)); 0228 } 0229 0230 return true; 0231 } 0232 0233 bool DImgLoader::saveMetadata(const QString& filePath) 0234 { 0235 QScopedPointer<DMetadata> metaDataToFile(new DMetadata(filePath)); 0236 metaDataToFile->setData(m_image->getMetadata()); 0237 0238 QVariant writingMode = imageGetAttribute(QLatin1String("metadataWritingMode")); 0239 0240 if (writingMode.isValid()) 0241 { 0242 metaDataToFile->setMetadataWritingMode(writingMode.toInt()); 0243 } 0244 else if (metaDataToFile->metadataWritingMode() == (int)DMetadata::WRITE_TO_SIDECAR_ONLY) 0245 { 0246 metaDataToFile->setMetadataWritingMode((int)DMetadata::WRITE_TO_SIDECAR_AND_FILE); 0247 } 0248 0249 return metaDataToFile->applyChanges(true); 0250 } 0251 0252 bool DImgLoader::checkExifWorkingColorSpace() const 0253 { 0254 QScopedPointer<DMetadata> metaData(new DMetadata(m_image->getMetadata())); 0255 IccProfile profile = metaData->getIccProfile(); 0256 0257 if (!profile.isNull()) 0258 { 0259 m_image->setIccProfile(profile); 0260 return true; 0261 } 0262 0263 return false; 0264 } 0265 0266 void DImgLoader::storeColorProfileInMetadata() 0267 { 0268 IccProfile profile = m_image->getIccProfile(); 0269 0270 if (profile.isNull()) 0271 { 0272 return; 0273 } 0274 0275 QScopedPointer<DMetadata> metaData(new DMetadata(m_image->getMetadata())); 0276 metaData->setIccProfile(profile); 0277 m_image->setMetadata(metaData->data()); 0278 } 0279 0280 void DImgLoader::purgeExifWorkingColorSpace() 0281 { 0282 QScopedPointer<DMetadata> meta(new DMetadata(m_image->getMetadata())); 0283 meta->removeExifColorSpace(); 0284 m_image->setMetadata(meta->data()); 0285 } 0286 0287 unsigned char* DImgLoader::new_failureTolerant(size_t unsecureSize) 0288 { 0289 return new_failureTolerant<unsigned char>(unsecureSize); 0290 } 0291 0292 unsigned char* DImgLoader::new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel) 0293 { 0294 return new_failureTolerant<unsigned char>(w, h, typesPerPixel); 0295 } 0296 0297 unsigned short* DImgLoader::new_short_failureTolerant(size_t unsecureSize) 0298 { 0299 return new_failureTolerant<unsigned short>(unsecureSize); 0300 } 0301 0302 unsigned short* DImgLoader::new_short_failureTolerant(quint64 w, quint64 h, uint typesPerPixel) 0303 { 0304 return new_failureTolerant<unsigned short>(w, h, typesPerPixel); 0305 } 0306 0307 int DImgLoader::convertCompressionForLibPng(int value) 0308 { 0309 // PNG compression slider settings : 1 - 9 ==> libpng settings : 100 - 1. 0310 0311 return ((int)(((1.0 - 100.0) / 8.0) * (float)value + 100.0 - ((1.0 - 100.0) / 8.0))); 0312 } 0313 0314 int DImgLoader::convertCompressionForLibJpeg(int value) 0315 { 0316 // JPEG quality slider settings : 1 - 100 ==> libjpeg settings : 25 - 100. 0317 0318 return ((int)((75.0 / 100.0) * (float)value + 26.0 - (75.0 / 100.0))); 0319 } 0320 0321 } // namespace Digikam