File indexing completed on 2025-01-05 03:56:29

0001 /* ============================================================
0002  *
0003  * This file is a part of digiKam project
0004  * https://www.digikam.org
0005  *
0006  * Date        : 2006-09-15
0007  * Description : Exiv2 library interface.
0008  *               Internal private container.
0009  *
0010  * SPDX-FileCopyrightText: 2006-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 #ifndef DIGIKAM_META_ENGINE_PRIVATE_H
0018 #define DIGIKAM_META_ENGINE_PRIVATE_H
0019 
0020 #include "metaengine.h"
0021 
0022  // C++ includes
0023 
0024 #include <cstdlib>
0025 #include <cstdio>
0026 #include <cmath>
0027 #include <cfloat>
0028 #include <iostream>
0029 #include <iomanip>
0030 #include <string>
0031 #include <memory>
0032 
0033 // Qt includes
0034 
0035 #include <QDir>
0036 #include <QFile>
0037 #include <QSize>
0038 #include <QLatin1String>
0039 #include <QFileInfo>
0040 #include <QSharedData>
0041 #include <QMutexLocker>
0042 #include <QRecursiveMutex>
0043 #include <QMimeDatabase>
0044 
0045 // Exiv2 includes -------------------------------------------------------
0046 
0047 // NOTE: All Exiv2 headers must be stay there to not expose external source code to Exiv2 API
0048 //       and reduce Exiv2 dependency to client code.
0049 
0050 #if defined(Q_CC_CLANG)
0051 #   pragma clang diagnostic push
0052 #   pragma clang diagnostic ignored "-Wdeprecated-declarations"
0053 #endif
0054 
0055 // The pragmas are required to be able to catch exceptions thrown by libexiv2:
0056 // See gcc.gnu.org/wiki/Visibility, the section about c++ exceptions.
0057 // They are needed for all libexiv2 versions that do not care about visibility.
0058 
0059 #ifdef Q_CC_GNU
0060 #   pragma GCC visibility push(default)
0061 #endif
0062 
0063 #include <exiv2/exv_conf.h>
0064 #include <exiv2/error.hpp>
0065 #include <exiv2/convert.hpp>
0066 #include <exiv2/image.hpp>
0067 #include <exiv2/jpgimage.hpp>
0068 #include <exiv2/datasets.hpp>
0069 #include <exiv2/tags.hpp>
0070 #include <exiv2/preview.hpp>
0071 #include <exiv2/properties.hpp>
0072 #include <exiv2/types.hpp>
0073 #include <exiv2/exif.hpp>
0074 #include <exiv2/xmpsidecar.hpp>
0075 #include <exiv2/version.hpp>
0076 
0077 // Check if Exiv2 support XMP
0078 
0079 #ifdef EXV_HAVE_XMP_TOOLKIT
0080 #   define _XMP_SUPPORT_ 1
0081 #endif
0082 
0083 #ifndef EXIV2_TEST_VERSION
0084 #    define EXIV2_TEST_VERSION(major,minor,patch) \
0085          ( EXIV2_VERSION >= EXIV2_MAKE_VERSION(major,minor,patch) )
0086 #endif
0087 
0088 #if EXIV2_TEST_VERSION(0,27,99)
0089 #   define AutoPtr UniquePtr
0090 #   define AnyError Error
0091 #   define kerErrorMessage ErrorCode::kerErrorMessage
0092 #   include <exiv2/photoshop.hpp>
0093 #endif
0094 
0095 #if EXIV2_TEST_VERSION(0,27,4)
0096 #   include <exiv2/bmffimage.hpp>
0097 #endif
0098 
0099 // With exiv2 > 0.20.0, all makernote header files have been removed to increase binary compatibility.
0100 // See Exiv2 bugzilla entry dev.exiv2.org/issues/719
0101 // and wiki topic           dev.exiv2.org/boards/3/topics/583
0102 
0103 #ifdef Q_CC_GNU
0104 #   pragma GCC visibility pop
0105 #endif
0106 
0107 // End of Exiv2 headers ------------------------------------------------------
0108 
0109 // Local includes
0110 
0111 #include "metaengine_mergehelper.h"
0112 #include "metaenginesettings.h"
0113 
0114 namespace Digikam
0115 {
0116 
0117 extern QRecursiveMutex s_metaEngineMutex;            ///< Mutex to fix no re-entrancy from Exiv2.
0118 extern bool            s_metaEngineSupportBmff;      ///< Flag for Exiv2 Base Media File Format support.
0119 extern bool            s_metaEngineWarnOrError;      ///< Flag for Exiv2 has printed a warning or error.
0120 
0121 // --------------------------------------------------------------------------
0122 
0123 class Q_DECL_HIDDEN MetaEngine::Private
0124 {
0125 public:
0126 
0127     explicit Private(MetaEngine* const q);
0128     ~Private();
0129 
0130     void copyPrivateData(const Private* const other);
0131 
0132     bool saveToXMPSidecar(const QFileInfo& finfo)                                 const;
0133     bool saveToFile(const QFileInfo& finfo)                                       const;
0134     bool saveUsingExiv2(const QFileInfo& finfo,
0135                         const QDateTime& modTime,
0136                         Exiv2::Image::AutoPtr image)                              const;
0137     bool saveUsingExifTool(const QFileInfo& finfo,
0138                            const QDateTime& modTime)                              const;
0139 
0140     bool exportChanges(const QString& exvTmpFile)                                 const;
0141 
0142     /**
0143      * Wrapper method to convert a Comments content to a QString.
0144      */
0145     QString convertCommentValue(const Exiv2::Exifdatum& exifDatum)                const;
0146 
0147     /**
0148      * Charset autodetection to convert a string to a QString.
0149      */
0150     QString detectEncodingAndDecode(const std::string& value)                     const;
0151 
0152     /**
0153      * UTF8 autodetection from a string.
0154      */
0155     bool isUtf8(const char* const buffer)                                         const;
0156 
0157     /**
0158      * Decodes Latitude or Longitude from EXIF tag name.
0159      */
0160     bool decodeGPSCoordinate(const char* exifTagName, double* const coordinate)   const;
0161 
0162     int getXMPTagsListFromPrefix(const QString& pf, MetaEngine::TagsMap& tagsMap) const;
0163 
0164     const Exiv2::ExifData& exifMetadata()                                         const;
0165     const Exiv2::IptcData& iptcMetadata()                                         const;
0166     const std::string&     itemComments()                                         const;
0167 
0168     Exiv2::ExifData&       exifMetadata();
0169     Exiv2::IptcData&       iptcMetadata();
0170     std::string&           itemComments();
0171 
0172 public:
0173 
0174 #ifdef _XMP_SUPPORT_
0175 
0176     const Exiv2::XmpData&  xmpMetadata()                                          const;
0177     Exiv2::XmpData&        xmpMetadata();
0178 
0179     void loadSidecarData(Exiv2::Image::AutoPtr xmpsidecar);
0180 
0181 #endif
0182 
0183 public:
0184 
0185     /**
0186      * Helper method to decode IPTC tag string contents following characters encoding preset.
0187      */
0188     QString extractIptcTagString(const Exiv2::IptcData& iptcData, const Exiv2::Iptcdatum& iptcTag) const;
0189 
0190 public:
0191 
0192     /**
0193      * Generic method to print the Exiv2 C++ Exception error message from 'e'.
0194      * 'msg' string is printed using qDebug rules.
0195      */
0196     static void printExiv2ExceptionError(const QString& msg, Exiv2::AnyError& e);
0197 
0198     /**
0199      * Generic method to print debug message from Exiv2.
0200      * 'msg' string is printed using qDebug rules. 'lvl' is the debug level of Exiv2 message.
0201      */
0202     static void printExiv2MessageHandler(int lvl, const char* msg);
0203 
0204 public:
0205 
0206     bool                                                  writeWithExifTool;
0207     bool                                                  writeRawFiles;
0208     bool                                                  writeDngFiles;
0209     bool                                                  updateFileTimeStamp;
0210 
0211     bool                                                  useXMPSidecar4Reading;
0212     bool                                                  useCompatibleFileName;
0213 
0214     /// A mode from #MetadataWritingMode enum.
0215     int                                                   metadataWritingMode;
0216 
0217     /// XMP, and parts of EXIF/IPTC, were loaded from an XMP sidecar file
0218     bool                                                  loadedFromSidecar;
0219 
0220     QString                                               filePath;
0221     QSize                                                 pixelSize;
0222     QString                                               mimeType;
0223 
0224     MetaEngine*                                           parent;
0225 
0226     QExplicitlySharedDataPointer<MetaEngineData::Private> data;
0227 };
0228 
0229 } // namespace Digikam
0230 
0231 #if defined(Q_CC_CLANG)
0232 #   pragma clang diagnostic pop
0233 #endif
0234 
0235 #endif // DIGIKAM_META_ENGINE_PRIVATE_H