File indexing completed on 2024-04-28 15:39:55

0001 // SPDX-FileCopyrightText: 2003-2010 Jesper K. Pedersen <blackie@kde.org>
0002 // SPDX-FileCopyrightText: 2021-2023 Johannes Zarl-Zierl <johannes@zarl-zierl.at>
0003 // SPDX-FileCopyrightText: 2023 Tobias Leupold <tl at stonemx dot de>
0004 //
0005 // SPDX-License-Identifier: GPL-2.0-or-later
0006 
0007 #include "FileInfo.h"
0008 
0009 #include <kpabase/FileExtensions.h>
0010 #include <kpabase/SettingsData.h>
0011 #include <kpaexif/Info.h>
0012 
0013 #include <Utilities/FastDateTime.h>
0014 #include <QFileInfo>
0015 #include <QRegularExpression>
0016 
0017 #include <exiv2/version.hpp>
0018 
0019 using namespace DB;
0020 
0021 FileInfo FileInfo::read(const DB::FileName &fileName, DB::ExifMode mode)
0022 {
0023     return FileInfo(fileName, mode);
0024 }
0025 
0026 DB::FileInfo::FileInfo(const DB::FileName &fileName, DB::ExifMode mode)
0027     : m_angle(0)
0028     , m_fileName(fileName)
0029 {
0030     parseEXIV2(fileName);
0031 
0032     if (updateDataFromFileTimeStamp(fileName, mode))
0033         m_date = QFileInfo(fileName.absolute()).lastModified();
0034 }
0035 
0036 Exiv2::ExifData &DB::FileInfo::getExifData()
0037 {
0038     return m_exifMap;
0039 }
0040 
0041 const DB::FileName &DB::FileInfo::getFileName() const
0042 {
0043     return m_fileName;
0044 }
0045 
0046 bool DB::FileInfo::updateDataFromFileTimeStamp(const DB::FileName &fileName, DB::ExifMode mode)
0047 {
0048     // If the date is valid from Exif reading, then we should not use the time stamp from the file.
0049     if (m_date.isValid())
0050         return false;
0051 
0052     // If we are not setting date, then we should of course not set the date
0053     if ((mode & EXIFMODE_DATE) == 0)
0054         return false;
0055 
0056     // If we are we already have specifies that we want to sent the date (from the ReReadExif dialog), then we of course should.
0057     if ((mode & EXIFMODE_USE_IMAGE_DATE_IF_INVALID_EXIF_DATE) != 0)
0058         return true;
0059 
0060     // Always trust for videos (this is a way to say that we should not trust for scaned in images - which makes no sense for videos)
0061     if (KPABase::isVideo(fileName))
0062         return true;
0063 
0064     // Finally use the info from the settings dialog
0065     return Settings::SettingsData::instance()->trustTimeStamps();
0066 }
0067 
0068 void DB::FileInfo::parseEXIV2(const DB::FileName &fileName)
0069 {
0070     m_exifMap = Exif::Info::instance()->metadata(fileName).exif;
0071 
0072     // Date
0073     m_date = fetchEXIV2Date(m_exifMap, "Exif.Photo.DateTimeOriginal");
0074     if (!m_date.isValid()) {
0075         m_date = fetchEXIV2Date(m_exifMap, "Exif.Photo.DateTimeDigitized");
0076         if (!m_date.isValid())
0077             m_date = fetchEXIV2Date(m_exifMap, "Exif.Image.DateTime");
0078     }
0079 
0080     // Angle
0081     if (m_exifMap.findKey(Exiv2::ExifKey("Exif.Image.Orientation")) != m_exifMap.end()) {
0082         const Exiv2::Exifdatum &datum = m_exifMap["Exif.Image.Orientation"];
0083 
0084         int orientation = 0;
0085         if (datum.count() > 0) {
0086 #if EXIV2_TEST_VERSION(0, 28, 0)
0087             orientation = datum.toInt64();
0088 #else
0089             orientation = datum.toLong();
0090 #endif
0091         }
0092 
0093         m_angle = orientationToAngle(orientation);
0094     }
0095 
0096     // Description
0097     if (m_exifMap.findKey(Exiv2::ExifKey("Exif.Image.ImageDescription")) != m_exifMap.end()) {
0098         const Exiv2::Exifdatum &datum = m_exifMap["Exif.Image.ImageDescription"];
0099         m_description = QString::fromLocal8Bit(datum.toString().c_str()).trimmed();
0100         // some cameras seem to add control characters. Remove them:
0101         m_description.remove(QRegularExpression(QString::fromLatin1("\\p{Cc}")));
0102     }
0103 }
0104 
0105 Utilities::FastDateTime FileInfo::fetchEXIV2Date(Exiv2::ExifData &map, const char *key)
0106 {
0107     try {
0108         if (map.findKey(Exiv2::ExifKey(key)) != map.end()) {
0109             const Exiv2::Exifdatum &datum = map[key];
0110             return Utilities::FastDateTime::fromString(QString::fromLatin1(datum.toString().c_str()), Qt::ISODate);
0111         }
0112     } catch (...) {
0113     }
0114 
0115     return Utilities::FastDateTime();
0116 }
0117 
0118 int DB::FileInfo::orientationToAngle(int orientation)
0119 {
0120     if (orientation == 1 || orientation == 2)
0121         return 0;
0122     else if (orientation == 3 || orientation == 4)
0123         return 180;
0124     else if (orientation == 5 || orientation == 8)
0125         return 270;
0126     else if (orientation == 6 || orientation == 7)
0127         return 90;
0128 
0129     return 0;
0130 }
0131 
0132 // vi:expandtab:tabstop=4 shiftwidth=4: