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

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 - Exif helpers.
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: 2011      by Leif Huhn <leif at dkstat dot com>
0012  *
0013  * SPDX-License-Identifier: GPL-2.0-or-later
0014  *
0015  * ============================================================ */
0016 
0017 #include "dmetadata.h"
0018 
0019 // Qt includes
0020 
0021 #include <QLocale>
0022 
0023 // Local includes
0024 
0025 #include "metaenginesettings.h"
0026 #include "iccprofile.h"
0027 #include "digikam_version.h"
0028 #include "digikam_globals.h"
0029 #include "digikam_debug.h"
0030 
0031 namespace Digikam
0032 {
0033 
0034 int DMetadata::getMSecsInfo() const
0035 {
0036     int ms  = 0;
0037     bool ok = mSecTimeStamp("Exif.Photo.SubSecTime", ms);
0038     if (ok) return ms;
0039 
0040     ok      = mSecTimeStamp("Exif.Photo.SubSecTimeOriginal", ms);
0041     if (ok) return ms;
0042 
0043     ok      = mSecTimeStamp("Exif.Photo.SubSecTimeDigitized", ms);
0044     if (ok) return ms;
0045 
0046     return 0;
0047 }
0048 
0049 bool DMetadata::mSecTimeStamp(const char* const exifTagName, int& ms) const
0050 {
0051     bool ok     = false;
0052     QString val = getExifTagString(exifTagName);
0053 
0054     if (!val.isEmpty())
0055     {
0056         int sub = val.toUInt(&ok);
0057 
0058         if (ok)
0059         {
0060             int _ms = (int)(QString::fromLatin1("0.%1").arg(sub).toFloat(&ok) * 1000.0);
0061 
0062             if (ok)
0063             {
0064                 ms = _ms;
0065                 qCDebug(DIGIKAM_METAENGINE_LOG) << "msec timestamp: " << ms;
0066             }
0067         }
0068     }
0069 
0070     return ok;
0071 }
0072 
0073 IccProfile DMetadata::getIccProfile() const
0074 {
0075     // Check if Exif data contains an ICC color profile.
0076 
0077     QByteArray data = getExifTagData("Exif.Image.InterColorProfile");
0078 
0079     if (!data.isNull())
0080     {
0081         qCDebug(DIGIKAM_METAENGINE_LOG) << "Found an ICC profile in Exif metadata";
0082         return IccProfile(data);
0083     }
0084 
0085     // Else check the Exif color-space tag and use default profiles that we ship
0086 
0087     switch (getItemColorWorkSpace())
0088     {
0089         case DMetadata::WORKSPACE_SRGB:
0090         {
0091             qCDebug(DIGIKAM_METAENGINE_LOG) << "Exif color-space tag is sRGB. Using default sRGB ICC profile.";
0092             return IccProfile::sRGB();
0093         }
0094 
0095         case DMetadata::WORKSPACE_ADOBERGB:
0096         {
0097             qCDebug(DIGIKAM_METAENGINE_LOG) << "Exif color-space tag is AdobeRGB. Using default AdobeRGB ICC profile.";
0098             return IccProfile::adobeRGB();
0099         }
0100 
0101         default:
0102         {
0103             break;
0104         }
0105     }
0106 
0107     return IccProfile();
0108 }
0109 
0110 bool DMetadata::setIccProfile(const IccProfile& profile)
0111 {
0112     if (profile.isNull())
0113     {
0114         removeExifTag("Exif.Image.InterColorProfile");
0115     }
0116     else
0117     {
0118         QByteArray data = IccProfile(profile).data();
0119 
0120         if (!setExifTagData("Exif.Image.InterColorProfile", data))
0121         {
0122             return false;
0123         }
0124     }
0125 
0126     removeExifColorSpace();
0127 
0128     return true;
0129 }
0130 
0131 bool DMetadata::removeExifColorSpace() const
0132 {
0133     bool ret =  true;
0134     ret     &= removeExifTag("Exif.Photo.ColorSpace");
0135     ret     &= removeXmpTag("Xmp.exif.ColorSpace");
0136 
0137     return ret;
0138 }
0139 
0140 QString DMetadata::getExifTagStringFromTagsList(const QStringList& tagsList) const
0141 {
0142     QString val;
0143 
0144     Q_FOREACH (const QString& tag, tagsList)
0145     {
0146         val = getExifTagString(tag.toLatin1().constData());
0147 
0148         if (!val.isEmpty())
0149         {
0150             return val;
0151         }
0152     }
0153 
0154     return QString();
0155 }
0156 
0157 bool DMetadata::removeExifTags(const QStringList& tagFilters)
0158 {
0159     MetaDataMap m = getExifTagsDataList(tagFilters);
0160 
0161     if (m.isEmpty())
0162     {
0163         return false;
0164     }
0165 
0166     for (MetaDataMap::iterator it = m.begin() ; it != m.end() ; ++it)
0167     {
0168         removeExifTag(it.key().toLatin1().constData());
0169     }
0170 
0171     return true;
0172 }
0173 
0174 } // namespace Digikam