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 #ifndef DIGIKAM_DIMG_LOADER_H
0017 #define DIGIKAM_DIMG_LOADER_H
0018 
0019 // C++ includes
0020 
0021 #include <limits>
0022 
0023 // Qt includes
0024 
0025 #include <QMap>
0026 #include <QString>
0027 #include <QVariant>
0028 
0029 // Local includes
0030 
0031 #include "digikam_debug.h"
0032 #include "digikam_export.h"
0033 #include "dimg.h"
0034 
0035 namespace Digikam
0036 {
0037 
0038 class DImgLoaderObserver;
0039 class DMetadata;
0040 
0041 class DIGIKAM_EXPORT DImgLoader
0042 {
0043 public:
0044 
0045     /**
0046      * This is the list of loading modes usable by DImg image plugins
0047      */
0048     enum LoadFlag
0049     {
0050         /// Load image information without image data
0051 
0052         LoadItemInfo     = 1,           ///< Image info as width and height
0053         LoadMetadata     = 2,           ///< Image metadata
0054         LoadICCData      = 4,           ///< Image color profile
0055 
0056         LoadImageData    = 8,           ///< Full image data
0057         LoadUniqueHash   = 16,          ///< Image unique hash
0058         LoadImageHistory = 32,          ///< Image version history
0059 
0060         /// Special mode to load reduced image data
0061 
0062         LoadPreview      = 64,          ///< Load embedded preview image instead full size image
0063 
0064         /// Helper to load all information, metadata and full image.
0065 
0066         LoadAll          = LoadItemInfo | LoadMetadata | LoadICCData | LoadImageData | LoadUniqueHash | LoadImageHistory
0067     };
0068     Q_DECLARE_FLAGS(LoadFlags, LoadFlag)
0069 
0070 public:
0071 
0072     void setLoadFlags(LoadFlags flags);
0073 
0074     virtual ~DImgLoader();
0075 
0076     virtual bool load(const QString& filePath, DImgLoaderObserver* const observer)        = 0;
0077     virtual bool save(const QString& filePath, DImgLoaderObserver* const observer)        = 0;
0078 
0079     virtual bool hasLoadedData()                                                    const;
0080     virtual bool hasAlpha()                                                         const = 0;
0081     virtual bool sixteenBit()                                                       const = 0;
0082     virtual bool isReadOnly()                                                       const = 0;
0083 
0084     static unsigned char*  new_failureTolerant(size_t unsecureSize);
0085     static unsigned char*  new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel);
0086     static unsigned short* new_short_failureTolerant(size_t unsecureSize);
0087     static unsigned short* new_short_failureTolerant(quint64 w, quint64 h, uint typesPerPixel);
0088 
0089     static int convertCompressionForLibPng(int value);
0090     static int convertCompressionForLibJpeg(int value);
0091 
0092     /**
0093      * Value returned : -1 : unsupported platform
0094      *                   0 : parse failure from supported platform
0095      *                   1 : parse done with success from supported platform
0096      */
0097     static qint64 checkAllocation(qint64 fullSize);
0098 
0099     template <typename Type> static Type* new_failureTolerant(size_t unsecureSize);
0100     template <typename Type> static Type* new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel);
0101 
0102 protected:
0103 
0104     explicit DImgLoader(DImg* const image);
0105 
0106     unsigned char*&         imageData();
0107     unsigned int&           imageWidth();
0108     unsigned int&           imageHeight();
0109 
0110     bool                    imageHasAlpha()                                         const;
0111     bool                    imageSixteenBit()                                       const;
0112 
0113     quint64                 imageNumBytes()                                         const;
0114     int                     imageBitsDepth()                                        const;
0115     int                     imageBytesDepth()                                       const;
0116 
0117     void                    imageSetIccProfile(const IccProfile& profile);
0118     QVariant                imageGetAttribute(const QString& key)                   const;
0119     void                    imageSetAttribute(const QString& key,
0120                                               const QVariant& value);
0121 
0122     QMap<QString, QString>& imageEmbeddedText()                                     const;
0123     QString                 imageGetEmbbededText(const QString& key)                const;
0124     void                    imageSetEmbbededText(const QString& key,
0125                                                  const QString& text);
0126 
0127     void                    loadingFailed();
0128     bool                    checkExifWorkingColorSpace()                            const;
0129     void                    purgeExifWorkingColorSpace();
0130     void                    storeColorProfileInMetadata();
0131 
0132     virtual bool            readMetadata(const QString& filePath);
0133     virtual bool            saveMetadata(const QString& filePath);
0134     virtual int             granularity(DImgLoaderObserver* const observer, int total, float progressSlice = 1.0F);
0135 
0136 protected:
0137 
0138     DImg*     m_image;
0139     LoadFlags m_loadFlags;
0140 
0141 private:
0142 
0143     // Disable
0144     DImgLoader() = delete;
0145 
0146 private:
0147 
0148     Q_DISABLE_COPY(DImgLoader)
0149 };
0150 
0151 // ---------------------------------------------------------------------------------------------------
0152 
0153 /**
0154  * Allows safe multiplication of requested pixel number and bytes per pixel, avoiding particularly
0155  * 32 bits overflow and exceeding the size_t type
0156  */
0157 template <typename Type>
0158 Q_INLINE_TEMPLATE Type* DImgLoader::new_failureTolerant(quint64 w, quint64 h, uint typesPerPixel)
0159 {
0160     quint64 requested = w * h * (quint64)typesPerPixel;
0161 
0162     if (requested >= std::numeric_limits<size_t>::max())
0163     {
0164         qCCritical(DIGIKAM_DIMG_LOG) << "Requested memory of" << requested * quint64(sizeof(Type))
0165                                      << "is larger than size_t supported by platform.";
0166         return nullptr;
0167     }
0168 
0169     return new_failureTolerant<Type>(requested);
0170 }
0171 
0172 template <typename Type>
0173 Q_INLINE_TEMPLATE Type* DImgLoader::new_failureTolerant(size_t size)
0174 {
0175     qint64 res = checkAllocation(size);
0176 
0177     switch (res)
0178     {
0179         case 0:       // parse failure from supported platform
0180         {
0181             return nullptr;
0182         }
0183 
0184         case -1:      // unsupported platform
0185         {
0186             // We will try to continue to allocate
0187             break;
0188         }
0189 
0190         default:     // parse done with success from supported platform
0191         {
0192             break;
0193         }
0194     }
0195 
0196     Type* const reserved = new (std::nothrow) Type[size];
0197 
0198     if (!reserved)
0199     {
0200         qCCritical(DIGIKAM_DIMG_LOG) << "Failed to allocate chunk of memory of size" << size;
0201     }
0202 
0203     return reserved;
0204 }
0205 
0206 Q_DECLARE_OPERATORS_FOR_FLAGS(DImgLoader::LoadFlags)
0207 
0208 } // namespace Digikam
0209 
0210 #endif // DIGIKAM_DIMG_LOADER_H