File indexing completed on 2025-01-19 03:55:56
0001 /* ============================================================ 0002 * 0003 * This file is a part of digiKam project 0004 * https://www.digikam.org 0005 * 0006 * Date : 2006-02-23 0007 * Description : item metadata interface 0008 * 0009 * SPDX-FileCopyrightText: 2006-2024 by Gilles Caulier <caulier dot gilles at gmail dot com> 0010 * SPDX-FileCopyrightText: 2006-2013 by Marcel Wiesweg <marcel dot wiesweg at gmx dot de> 0011 * SPDX-FileCopyrightText: 2013 by Veaceslav Munteanu <veaceslav dot munteanu90 at gmail dot com> 0012 * 0013 * SPDX-License-Identifier: GPL-2.0-or-later 0014 * 0015 * ============================================================ */ 0016 0017 #ifndef DIGIKAM_DMETA_DATA_H 0018 #define DIGIKAM_DMETA_DATA_H 0019 0020 // Qt includes 0021 0022 #include <QByteArray> 0023 #include <QUrl> 0024 0025 // Local includes 0026 0027 #include "digikam_config.h" 0028 #include "digikam_export.h" 0029 #include "metaengine.h" 0030 #include "metaengine_data.h" 0031 #include "metaenginesettingscontainer.h" 0032 #include "metadatainfo.h" 0033 #include "captionvalues.h" 0034 #include "photoinfocontainer.h" 0035 #include "videoinfocontainer.h" 0036 #include "dmetadatasettings.h" 0037 0038 namespace Digikam 0039 { 0040 0041 class Template; 0042 class IccProfile; 0043 0044 // TODO: merge with MetaEngine class. 0045 0046 class DIGIKAM_EXPORT DMetadata : public MetaEngine 0047 { 0048 0049 public: 0050 0051 /** 0052 * Video color model reported by FFMPEG following XMP DM Spec from Adobe. 0053 * These values are stored in DB as Image color model properties (extension of DImg::ColorModel) 0054 */ 0055 enum VIDEOCOLORMODEL 0056 { 0057 VIDEOCOLORMODEL_UNKNOWN = 1000, 0058 VIDEOCOLORMODEL_OTHER, 0059 VIDEOCOLORMODEL_SRGB, 0060 VIDEOCOLORMODEL_BT709, 0061 VIDEOCOLORMODEL_BT601 0062 }; 0063 0064 public: 0065 0066 typedef QMap<QString, QString> CountryCodeMap; 0067 0068 public: 0069 0070 DMetadata(); 0071 explicit DMetadata(const QString& filePath); 0072 explicit DMetadata(const MetaEngineData& data); 0073 ~DMetadata(); 0074 0075 public: // Settings helpers 0076 0077 void registerMetadataSettings(); 0078 void setSettings(const MetaEngineSettingsContainer& settings); 0079 0080 public: // File I/O helpers 0081 0082 /** 0083 * Re-implemented from MetaEngine to use libraw identify, libheif, 0084 * ffmpeg probe, and ImageMAgick identify methods if Exiv2 failed. 0085 * If backend is non null, return the backend used to populate metadata (Exiv2). 0086 * See MetaEngine::Backend enum for details. 0087 */ 0088 bool load(const QString& filePath, Backend* backend = nullptr); 0089 bool save(const QString& filePath, bool setVersion = false) const; 0090 bool applyChanges(bool setVersion = false) const; 0091 0092 /** 0093 * Try to extract metadata using Raw Engine identify method (libraw). 0094 */ 0095 bool loadUsingRawEngine(const QString& filePath); 0096 0097 public: // History helpers 0098 0099 QString getItemHistory() const; 0100 bool setItemHistory(const QString& imageHistoryXml) const; 0101 bool hasItemHistoryTag() const; 0102 0103 QString getItemUniqueId() const; 0104 bool setItemUniqueId(const QString& uuid) const; 0105 0106 public: // Faces helpers 0107 0108 /** 0109 * Get Images Face Map based on tags stored in Picassa/Metadatagroup 0110 * format. 0111 */ 0112 bool getItemFacesMap(QMultiMap<QString, QVariant>& facesPath) const; 0113 0114 /** 0115 * Set Images Face Map tags in Picassa/Metadatagroup format. 0116 * 0117 * @param write : if true all faces will be written, else update mode: 0118 * search if at least a face tag exist and write if true. 0119 */ 0120 bool setItemFacesMap(const QMultiMap<QString, QVariant>& facesPath, bool write, const QSize& size = QSize()) const; 0121 0122 /** 0123 * Remove Images Face Map tags from Picassa/Metadatagroup format. 0124 */ 0125 bool removeItemFacesMap() const; 0126 0127 public: // Tags helpers 0128 0129 bool getItemTagsPath(QStringList& tagsPath, 0130 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0131 bool setItemTagsPath(const QStringList& tagsPath, 0132 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0133 0134 bool getACDSeeTagsPath(QStringList& tagsPath) const; 0135 0136 bool setACDSeeTagsPath(const QStringList& tagsPath) const; 0137 0138 public: // Comments helpers 0139 0140 CaptionsMap getItemComments(const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0141 bool setItemComments(const CaptionsMap& comments, 0142 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0143 0144 CaptionsMap getItemTitles(const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0145 bool setItemTitles(const CaptionsMap& title, 0146 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0147 0148 static MetaEngine::AltLangMap toAltLangMap(const QVariant& var); 0149 0150 public: // Labels helpers 0151 0152 int getItemRating(const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0153 bool setItemRating(int rating, 0154 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0155 0156 int getItemPickLabel() const; 0157 bool setItemPickLabel(int pickId) const; 0158 0159 int getItemColorLabel(const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0160 bool setItemColorLabel(int colorId, 0161 const DMetadataSettingsContainer& settings = DMetadataSettings::instance()->settings()) const; 0162 0163 public: // Template helpers 0164 0165 bool setMetadataTemplate(const Template& t) const; 0166 Template getMetadataTemplate() const; 0167 bool removeMetadataTemplate() const; 0168 0169 /** 0170 * Fills only the copyright values in the template. Use getMetadataTemplate() usually. 0171 * Returns true if valid fields were read. 0172 */ 0173 bool getCopyrightInformation(Template& t) const; 0174 0175 public: // EXIF helpers 0176 0177 /** 0178 * Reads an IccProfile that is described or embedded in the metadata. 0179 * This method does not retrieve profiles embedded in the image but from the Exif metadata, 0180 * e.g. embedded profiles in JPEG images. 0181 * Returns a null profile if no profile is found. 0182 */ 0183 IccProfile getIccProfile() const; 0184 0185 /** 0186 * Sets the IccProfile embedded in the Exif metadata. 0187 */ 0188 bool setIccProfile(const IccProfile& profile); 0189 0190 /** 0191 * Remove the Exif color space identification from the image. 0192 */ 0193 bool removeExifColorSpace() const; 0194 0195 /** 0196 * Returns millisecond time-stamp from Exif tags or 0 if not found. 0197 */ 0198 int getMSecsInfo() const; 0199 0200 /** 0201 * Extract milliseconds time-stamp of photo from an Exif tag and store it to 'ms'. 0202 * Returns true if data are extracted. 0203 */ 0204 bool mSecTimeStamp(const char* const exifTagName, int& ms) const; 0205 0206 bool removeExifTags(const QStringList& tagFilters); 0207 0208 private: 0209 0210 QString getExifTagStringFromTagsList(const QStringList& tagsList) const; 0211 0212 public: // IPTC helpers 0213 0214 IptcCoreContactInfo getCreatorContactInfo() const; 0215 bool setCreatorContactInfo(const IptcCoreContactInfo& info) const; 0216 0217 IptcCoreLocationInfo getIptcCoreLocation() const; 0218 bool setIptcCoreLocation(const IptcCoreLocationInfo& location) const; 0219 0220 QStringList getIptcCoreSubjects() const; 0221 0222 bool removeIptcTags(const QStringList& tagFilters); 0223 0224 /** 0225 * Return a map of ISO-639-1 2 letters country codes with country names. 0226 */ 0227 static CountryCodeMap countryCodeMap(); 0228 0229 /** 0230 * Return a map of ISO-639-2 3 letters country codes with country names. 0231 */ 0232 static CountryCodeMap countryCodeMap2(); 0233 0234 private: 0235 0236 bool setIptcTag(const QString& text, 0237 int maxLength, 0238 const char* const debugLabel, 0239 const char* const tagKey) const; 0240 0241 QVariant fromIptcEmulateList(const char* const iptcTagName) const; 0242 QVariant fromIptcEmulateLangAlt(const char* const iptcTagName) const; 0243 0244 public: // XMP helpers 0245 0246 /** 0247 * Set an Xmp tag content using a list of strings defined by the 'entriesToAdd' parameter. 0248 * The existing entries are preserved. The method will compare 0249 * all new with all already existing entries to prevent duplicates in the image. 0250 * Return true if the entries have been added to metadata. 0251 */ 0252 bool addToXmpTagStringBag(const char* const xmpTagName, const QStringList& entriesToAdd) const; 0253 0254 /** 0255 * Remove those Xmp tag entries that are listed in entriesToRemove from the entries in metadata. 0256 * Return true if tag entries are no longer contained in metadata. 0257 * All other entries are preserved. 0258 */ 0259 bool removeFromXmpTagStringBag(const char* const xmpTagName, const QStringList& entriesToRemove) const; 0260 0261 /** 0262 * Return a strings list of Xmp keywords from image. Return an empty list if no keyword are set. 0263 */ 0264 QStringList getXmpKeywords() const; 0265 0266 /** 0267 * Set Xmp keywords using a list of strings defined by 'newKeywords' parameter. 0268 * The existing keywords from image are preserved. The method will compare 0269 * all new keywords with all already existing keywords to prevent duplicate entries in image. 0270 * Return true if keywords have been changed in metadata. 0271 */ 0272 bool setXmpKeywords(const QStringList& newKeywords) const; 0273 0274 /** 0275 * Remove those Xmp keywords that are listed in keywordsToRemove from the keywords in metadata. 0276 * Return true if keywords are no longer contained in metadata. 0277 */ 0278 bool removeXmpKeywords(const QStringList& keywordsToRemove); 0279 0280 /** 0281 * Return a strings list of Xmp subjects from image. Return an empty list if no subject are set. 0282 */ 0283 QStringList getXmpSubjects() const; 0284 0285 /** 0286 * Set Xmp subjects using a list of strings defined by 'newSubjects' parameter. 0287 * The existing subjects from image are preserved. The method will compare 0288 * all new subject with all already existing subject to prevent duplicate entries in image. 0289 * Return true if subjects have been changed in metadata. 0290 */ 0291 bool setXmpSubjects(const QStringList& newSubjects) const; 0292 0293 /** 0294 * Remove those Xmp subjects that are listed in subjectsToRemove from the subjects in metadata. 0295 * Return true if subjects are no longer contained in metadata. 0296 */ 0297 bool removeXmpSubjects(const QStringList& subjectsToRemove); 0298 0299 /** 0300 * Return a strings list of Xmp sub-categories from image. Return an empty list if no sub-category 0301 * are set. 0302 */ 0303 QStringList getXmpSubCategories() const; 0304 0305 /** 0306 * Set Xmp sub-categories using a list of strings defined by 'newSubCategories' parameter. 0307 * The existing sub-categories from image are preserved. The method will compare 0308 * all new sub-categories with all already existing sub-categories to prevent duplicate entries in image. 0309 * Return true if sub-categories have been changed in metadata. 0310 */ 0311 bool setXmpSubCategories(const QStringList& newSubCategories) const; 0312 0313 /** 0314 * Remove those Xmp sub-categories that are listed in categoriesToRemove from the sub-categories in metadata. 0315 * Return true if subjects are no longer contained in metadata. 0316 */ 0317 bool removeXmpSubCategories(const QStringList& categoriesToRemove); 0318 0319 bool removeXmpTags(const QStringList& tagFilters); 0320 0321 private: 0322 0323 QVariant fromXmpList(const char* const xmpTagName) const; 0324 QVariant fromXmpLangAlt(const char* const xmpTagName) const; 0325 0326 public: // Video helpers 0327 0328 /** 0329 * Try to extract metadata using FFMpeg probe method (libav). 0330 */ 0331 bool loadUsingFFmpeg(const QString& filePath); 0332 0333 /** 0334 * Returns video metadata from Xmp tags. 0335 */ 0336 VideoInfoContainer getVideoInformation() const; 0337 0338 /** 0339 * Helper method to translate enum values to user presentable strings 0340 */ 0341 static QString videoColorModelToString(VIDEOCOLORMODEL videoColorModel); 0342 0343 public: // Photo helpers 0344 0345 /** 0346 * Return a string with Lens mounted on the front of camera. 0347 * There no standard Exif tag for Lens information. 0348 * Camera makernotes and Xmp tags are parsed. 0349 * Take a care : lens information are not standardized and string content is not homogeneous between 0350 * camera model/maker. 0351 */ 0352 QString getLensDescription() const; 0353 0354 /** 0355 * Return a string with Camera serial number. 0356 */ 0357 QString getCameraSerialNumber() const; 0358 0359 PhotoInfoContainer getPhotographInformation() const; 0360 0361 static double apexApertureToFNumber(double aperture); 0362 static double apexShutterSpeedToExposureTime(double shutterSpeed); 0363 0364 public: // Generic helpers 0365 0366 /** 0367 * Returns the requested metadata field as a QVariant. See metadatainfo.h for a specification 0368 * of the format of the QVariant. 0369 */ 0370 QVariant getMetadataField(MetadataInfo::Field field) const; 0371 QVariantList getMetadataFields(const MetadataFields& fields) const; 0372 0373 /** 0374 * Convert a QVariant value of the specified field to a user-presentable, i18n'ed string. 0375 * The QVariant must be of the type as specified in metadatainfo.h and as obtained by getMetadataField. 0376 */ 0377 static QString valueToString (const QVariant& value, MetadataInfo::Field field); 0378 static QStringList valuesToString(const QVariantList& list, const MetadataFields& fields); 0379 0380 /** 0381 * Returns a map of possible enum values and their user-presentable, i18n'ed representation. 0382 * Valid fields are those which are described as "enum from" or "bit mask from" in metadatainfo.h. 0383 */ 0384 static QMap<int, QString> possibleValuesForEnumField(MetadataInfo::Field field); 0385 0386 private: 0387 0388 QVariant fromExifOrXmp(const char* const exifTagName, const char* const xmpTagName) const; 0389 QVariant fromIptcOrXmp(const char* const iptcTagName, const char* const xmpTagName) const; 0390 QVariant fromExifOrXmpList(const QStringList& tagList) const; 0391 bool hasValidField(const QVariantList& list) const; 0392 QVariant toStringListVariant(const QStringList& list) const; 0393 0394 #ifdef HAVE_HEIF 0395 0396 private: 0397 0398 /** 0399 * Libheif helper methods. 0400 */ 0401 bool loadUsingLibheif(const QString& filePath); 0402 0403 #endif 0404 0405 private: 0406 0407 /** 0408 * ImageMagick helper methods. 0409 */ 0410 bool loadUsingImageMagick(const QString& filePath); 0411 0412 private: 0413 0414 /** 0415 * ExifTool helper methods. 0416 */ 0417 bool loadUsingExifTool(const QString& filePath, bool merge = false); 0418 bool saveUsingExifTool(const QString& filePath) const; 0419 }; 0420 0421 } // namespace Digikam 0422 0423 #endif // DIGIKAM_DMETA_DATA_H