File indexing completed on 2025-01-19 03:54:50

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2005-06-14
0007  * Description : digiKam 8/16 bits image management API
0008  *               Files input output
0009  *
0010  * SPDX-FileCopyrightText: 2005-2024 by Gilles Caulier <caulier dot gilles at gmail dot com>
0011  * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "dimg_p.h"
0018 
0019 namespace Digikam
0020 {
0021 
0022 bool DImg::loadItemInfo(const QString& filePath, bool loadMetadata, bool loadICCData, bool loadUniqueHash, bool loadImageHistory)
0023 {
0024     DImgLoader::LoadFlags loadFlags = DImgLoader::LoadItemInfo;
0025 
0026     if (loadMetadata)
0027     {
0028         loadFlags |= DImgLoader::LoadMetadata;
0029     }
0030 
0031     if (loadICCData)
0032     {
0033         loadFlags |= DImgLoader::LoadICCData;
0034     }
0035 
0036     if (loadUniqueHash)
0037     {
0038         loadFlags |= DImgLoader::LoadUniqueHash;
0039     }
0040 
0041     if (loadImageHistory)
0042     {
0043         loadFlags |= DImgLoader::LoadImageHistory;
0044     }
0045 
0046     return load(filePath, loadFlags, nullptr, DRawDecoding());
0047 }
0048 
0049 bool DImg::load(const QString& filePath,
0050                 DImgLoaderObserver* const observer,
0051                 const DRawDecoding& rawDecodingSettings)
0052 {
0053     return load(filePath, DImgLoader::LoadAll, observer, rawDecodingSettings);
0054 }
0055 
0056 bool DImg::load(const QString& filePath,
0057                 bool loadMetadata,
0058                 bool loadICCData,
0059                 bool loadUniqueHash,
0060                 bool loadImageHistory,
0061                 DImgLoaderObserver* const observer,
0062                 const DRawDecoding& rawDecodingSettings)
0063 {
0064     DImgLoader::LoadFlags loadFlags = DImgLoader::LoadItemInfo | DImgLoader::LoadImageData;
0065 
0066     if (loadMetadata)
0067     {
0068         loadFlags |= DImgLoader::LoadMetadata;
0069     }
0070 
0071     if (loadICCData)
0072     {
0073         loadFlags |= DImgLoader::LoadICCData;
0074     }
0075 
0076     if (loadUniqueHash)
0077     {
0078         loadFlags |= DImgLoader::LoadUniqueHash;
0079     }
0080 
0081     if (loadImageHistory)
0082     {
0083         loadFlags |= DImgLoader::LoadImageHistory;
0084     }
0085 
0086     return load(filePath, loadFlags, observer, rawDecodingSettings);
0087 }
0088 
0089 bool DImg::load(const QString& filePath,
0090                 int loadFlagsInt,
0091                 DImgLoaderObserver* const observer,
0092                 const DRawDecoding& rawDecodingSettings)
0093 {
0094     QFileInfo fileInfo(filePath);
0095 
0096     if (!fileInfo.exists() || !fileInfo.isReadable())
0097     {
0098         qCDebug(DIGIKAM_DIMG_LOG) << "File" << filePath << "does not exist";
0099         return false;
0100     }
0101 
0102     DPluginDImg* plugin             = DImgStaticPriv::pluginForFile(fileInfo, false);
0103     DImgLoader::LoadFlags loadFlags = (DImgLoader::LoadFlags)loadFlagsInt;
0104     setAttribute(QLatin1String("originalFilePath"), filePath);
0105 
0106     FileReadLocker lock(filePath);
0107 
0108     // First step we check the file extension to find the right loader.
0109 
0110     if (observer && !observer->continueQuery())
0111     {
0112         return false;
0113     }
0114 
0115     if (plugin && (!(loadFlags & DImgLoader::LoadPreview) || plugin->previewSupported()))
0116     {
0117         qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plugin->loaderName() << "file identified";
0118         FORMAT format            = DImgStaticPriv::loaderNameToFormat(plugin->loaderName());
0119         DImgLoader* const loader = plugin->loader(this, rawDecodingSettings);
0120         setAttribute(QLatin1String("detectedFileFormat"), format);
0121         loader->setLoadFlags(loadFlags);
0122 
0123         if (loader->load(filePath, observer))
0124         {
0125             m_priv->null       = !loader->hasLoadedData();
0126             m_priv->alpha      = loader->hasAlpha();
0127             m_priv->sixteenBit = loader->sixteenBit();
0128             setAttribute(QLatin1String("isReadOnly"), loader->isReadOnly());
0129             delete loader;
0130 
0131             return true;
0132         }
0133 
0134         delete loader;
0135     }
0136 
0137     // In the second step we check the magic bytes to find the right loader.
0138 
0139     plugin = DImgStaticPriv::pluginForFile(fileInfo, true);
0140 
0141     if (observer && !observer->continueQuery())
0142     {
0143         return false;
0144     }
0145 
0146     if (plugin && (!(loadFlags & DImgLoader::LoadPreview) || plugin->previewSupported()))
0147     {
0148         qCDebug(DIGIKAM_DIMG_LOG) << filePath << ":" << plugin->loaderName() << "file identified (magic)";
0149         FORMAT format            = DImgStaticPriv::loaderNameToFormat(plugin->loaderName());
0150         DImgLoader* const loader = plugin->loader(this, rawDecodingSettings);
0151         setAttribute(QLatin1String("detectedFileFormat"), format);
0152         loader->setLoadFlags(loadFlags);
0153 
0154         if (loader->load(filePath, observer))
0155         {
0156             m_priv->null       = !loader->hasLoadedData();
0157             m_priv->alpha      = loader->hasAlpha();
0158             m_priv->sixteenBit = loader->sixteenBit();
0159             setAttribute(QLatin1String("isReadOnly"), loader->isReadOnly());
0160             delete loader;
0161 
0162             return true;
0163         }
0164 
0165         delete loader;
0166     }
0167 
0168     if (!plugin && !(loadFlags & DImgLoader::LoadPreview))
0169     {
0170         qCDebug(DIGIKAM_DIMG_LOG) << filePath << ": Unknown image format !!!";
0171         return false;
0172     }
0173 
0174     if (observer                  &&
0175         observer->continueQuery() &&
0176         !(loadFlags & DImgLoader::LoadPreview))
0177     {
0178         qCWarning(DIGIKAM_DIMG_LOG) << filePath << ": Cannot load file !!!";
0179     }
0180 
0181     return false;
0182 }
0183 
0184 QString DImg::formatToMimeType(FORMAT frm)
0185 {
0186     QString format;
0187 
0188     switch (frm)
0189     {
0190         case (NONE):
0191         {
0192             return format;
0193         }
0194 
0195         case (JPEG):
0196         {
0197             format = QLatin1String("JPG");
0198             break;
0199         }
0200 
0201         case (TIFF):
0202         {
0203             format = QLatin1String("TIF");
0204             break;
0205         }
0206 
0207         case (PNG):
0208         {
0209             format = QLatin1String("PNG");
0210             break;
0211         }
0212 
0213         case (JP2K):
0214         {
0215             format = QLatin1String("JP2");
0216             break;
0217         }
0218 
0219         case (PGF):
0220         {
0221             format = QLatin1String("PGF");
0222             break;
0223         }
0224 
0225         default:
0226         {
0227             // For QImage or ImageMagick based.
0228             break;
0229         }
0230     }
0231 
0232     return format;
0233 }
0234 
0235 bool DImg::save(const QString& filePath, FORMAT frm, DImgLoaderObserver* const observer)
0236 {
0237     if (isNull())
0238     {
0239         return false;
0240     }
0241 
0242     return(save(filePath, formatToMimeType(frm), observer));
0243 }
0244 
0245 bool DImg::save(const QString& filePath, const QString& format, DImgLoaderObserver* const observer)
0246 {
0247     qCDebug(DIGIKAM_DIMG_LOG) << "Saving to " << filePath << " with format: " << format;
0248 
0249     if (isNull())
0250     {
0251         return false;
0252     }
0253 
0254     if (format.isEmpty())
0255     {
0256         return false;
0257     }
0258 
0259     QString frm = format.toUpper();
0260     setAttribute(QLatin1String("savedFilePath"), filePath);
0261     setAttribute(QLatin1String("savedFormat"),   frm);
0262 
0263     FileWriteLocker lock(filePath);
0264 
0265     DPluginDImg* const plug = DImgStaticPriv::pluginForFormat(frm);
0266     DImg copyForSave        = copy();
0267 
0268     if ((frm == QLatin1String("JPEG")) || (frm == QLatin1String("JPG")) || (frm == QLatin1String("JPE")))
0269     {
0270         // JPEG does not support transparency, so we shall provide an image without alpha channel.
0271         // This is only necessary if the image has an alpha channel, and there are actually transparent pixels
0272 
0273         if (hasTransparentPixels())
0274         {
0275             copyForSave.removeAlphaChannel();
0276         }
0277     }
0278 
0279     if (plug)
0280     {
0281         DImgLoader* const loader = plug->loader(&copyForSave);
0282         copyForSave.setAttribute(QLatin1String("format"), frm);
0283         copyForSave.setAttribute(QLatin1String("savedFormat-isReadOnly"), loader->isReadOnly());
0284         bool ret                 = loader->save(filePath, observer);
0285         delete loader;
0286 
0287         return ret;
0288     }
0289 
0290     qCWarning(DIGIKAM_DIMG_LOG) << filePath << " : Unknown save format !!!";
0291 
0292     return false;
0293 }
0294 
0295 DImg::FORMAT DImg::fileFormat(const QString& filePath)
0296 {
0297     FORMAT format = DImg::NONE;
0298 
0299     if (filePath.isEmpty())
0300     {
0301         return format;
0302     }
0303 
0304     QFileInfo fileInfo(filePath);
0305 
0306     if (!fileInfo.exists() || !fileInfo.isReadable())
0307     {
0308         return format;
0309     }
0310 
0311     DPluginDImg* const plugin = DImgStaticPriv::pluginForFile(fileInfo, false);
0312 
0313     if (plugin)
0314     {
0315         QString name = plugin->loaderName();
0316         format       = DImgStaticPriv::loaderNameToFormat(name);
0317     }
0318 
0319     return format;
0320 }
0321 
0322 QDateTime DImg::creationDateFromFilesystem(const QFileInfo& fileInfo) const
0323 {
0324     // creation date is not what it seems on Unix
0325 
0326     QDateTime ctime = fileInfo.birthTime();
0327     QDateTime mtime = fileInfo.lastModified();
0328 
0329     if (ctime.isValid())
0330     {
0331         ctime.setTimeSpec(Qt::UTC);
0332 
0333         return ctime;
0334     }
0335 
0336     if (mtime.isValid())
0337     {
0338         mtime.setTimeSpec(Qt::UTC);
0339 
0340         return mtime;
0341     }
0342 
0343     QDateTime dateTime = QDateTime::currentDateTime();
0344     dateTime.setTimeSpec(Qt::UTC);
0345 
0346     return dateTime;
0347 }
0348 
0349 } // namespace Digikam