File indexing completed on 2024-05-12 15:55:36
0001 // SPDX-FileCopyrightText: 2003-2010 Jesper K. Pedersen <blackie@kde.org> 0002 // SPDX-FileCopyrightText: 2023 Tobias Leupold <tl at stonemx dot de> 0003 // 0004 // SPDX-License-Identifier: GPL-2.0-or-later 0005 0006 #include "DatabaseElement.h" 0007 0008 #include <kpabase/Logging.h> 0009 0010 #include <QVariant> 0011 #include <exiv2/exif.hpp> 0012 #include <exiv2/version.hpp> 0013 0014 static QString replaceDotWithUnderscore(const char *cstr) 0015 { 0016 QString str(QString::fromLatin1(cstr)); 0017 return str.replace(QString::fromLatin1("."), QString::fromLatin1("_")); 0018 } 0019 0020 Exif::DatabaseElement::DatabaseElement() 0021 : m_value() 0022 { 0023 } 0024 0025 QVariant Exif::DatabaseElement::value() const 0026 { 0027 return m_value; 0028 } 0029 void Exif::DatabaseElement::setValue(QVariant val) 0030 { 0031 m_value = val; 0032 } 0033 0034 Exif::StringExifElement::StringExifElement(const char *tag) 0035 : m_tag(tag) 0036 { 0037 } 0038 0039 QString Exif::StringExifElement::columnName() const 0040 { 0041 return replaceDotWithUnderscore(m_tag); 0042 } 0043 0044 QString Exif::StringExifElement::createString() const 0045 { 0046 return QString::fromLatin1("%1 string").arg(replaceDotWithUnderscore(m_tag)); 0047 } 0048 0049 QString Exif::StringExifElement::queryString() const 0050 { 0051 return QString::fromLatin1("?"); 0052 } 0053 0054 QVariant Exif::StringExifElement::valueFromExif(Exiv2::ExifData &data) const 0055 { 0056 return QVariant { QLatin1String(data[m_tag].toString().c_str()) }; 0057 } 0058 0059 Exif::IntExifElement::IntExifElement(const char *tag) 0060 : m_tag(tag) 0061 { 0062 } 0063 0064 QString Exif::IntExifElement::columnName() const 0065 { 0066 return replaceDotWithUnderscore(m_tag); 0067 } 0068 0069 QString Exif::IntExifElement::createString() const 0070 { 0071 return QString::fromLatin1("%1 int").arg(replaceDotWithUnderscore(m_tag)); 0072 } 0073 0074 QString Exif::IntExifElement::queryString() const 0075 { 0076 return QString::fromLatin1("?"); 0077 } 0078 0079 QVariant Exif::IntExifElement::valueFromExif(Exiv2::ExifData &data) const 0080 { 0081 if (data[m_tag].count() > 0) { 0082 #if EXIV2_TEST_VERSION(0, 28, 0) 0083 return QVariant((int) data[m_tag].toInt64()); 0084 #else 0085 return QVariant((int) data[m_tag].toLong()); 0086 #endif 0087 } else { 0088 return QVariant(0); 0089 } 0090 } 0091 0092 Exif::RationalExifElement::RationalExifElement(const char *tag) 0093 : m_tag(tag) 0094 { 0095 } 0096 0097 QString Exif::RationalExifElement::columnName() const 0098 { 0099 return replaceDotWithUnderscore(m_tag); 0100 } 0101 0102 QString Exif::RationalExifElement::createString() const 0103 { 0104 return QString::fromLatin1("%1 float").arg(replaceDotWithUnderscore(m_tag)); 0105 } 0106 0107 QString Exif::RationalExifElement::queryString() const 0108 { 0109 return QString::fromLatin1("?"); 0110 } 0111 0112 QVariant Exif::RationalExifElement::valueFromExif(Exiv2::ExifData &data) const 0113 { 0114 double value; 0115 Exiv2::Exifdatum &tagDatum = data[m_tag]; 0116 switch (tagDatum.count()) { 0117 case 0: // empty 0118 value = -1.0; 0119 break; 0120 case 1: // "normal" rational 0121 value = 1.0 * tagDatum.toRational().first / tagDatum.toRational().second; 0122 break; 0123 case 3: // GPS lat/lon data: 0124 { 0125 value = 0.0; 0126 double divisor = 1.0; 0127 // degree / minute / second: 0128 for (int i = 0; i < 3; i++) { 0129 double nom = tagDatum.toRational(i).first; 0130 double denom = tagDatum.toRational(i).second; 0131 if (denom != 0) 0132 value += (nom / denom) / divisor; 0133 divisor *= 60.0; 0134 } 0135 } break; 0136 default: 0137 // FIXME: there are at least the following other rational types: 0138 // whitepoints -> 2 components 0139 // YCbCrCoefficients -> 3 components (Coefficients for transformation from RGB to YCbCr image data. ) 0140 // chromaticities -> 6 components 0141 qCWarning(ExifLog) << "Exif rational data with " << tagDatum.count() << " components is not handled, yet!"; 0142 return QVariant {}; 0143 } 0144 return QVariant { value }; 0145 } 0146 0147 Exif::LensExifElement::LensExifElement() 0148 : m_tag("Exif.Photo.LensModel") 0149 { 0150 } 0151 0152 QString Exif::LensExifElement::columnName() const 0153 { 0154 return replaceDotWithUnderscore(m_tag); 0155 } 0156 0157 QString Exif::LensExifElement::createString() const 0158 { 0159 return QString::fromLatin1("%1 string").arg(replaceDotWithUnderscore(m_tag)); 0160 } 0161 0162 QString Exif::LensExifElement::queryString() const 0163 { 0164 return QString::fromLatin1("?"); 0165 } 0166 0167 QVariant Exif::LensExifElement::valueFromExif(Exiv2::ExifData &data) const 0168 { 0169 QString value; 0170 bool canonHack = false; 0171 for (Exiv2::ExifData::const_iterator it = data.begin(); it != data.end(); ++it) { 0172 const QString datum = QString::fromLatin1(it->key().c_str()); 0173 0174 // Exif.Photo.LensModel [Ascii] 0175 // Exif.Canon.LensModel [Ascii] 0176 // Exif.OlympusEq.LensModel [Ascii] 0177 if (datum.endsWith(QString::fromLatin1(".LensModel"))) { 0178 qCDebug(ExifLog) << datum << ": " << it->toString().c_str(); 0179 canonHack = false; 0180 value = QString::fromUtf8(it->toString().c_str()); 0181 // we can break here since Exif.Photo.LensModel should be bound first 0182 break; 0183 } 0184 0185 // Exif.NikonLd3.LensIDNumber [Byte] 0186 // on Nikon cameras, this seems to provide better results than .Lens and .LensType 0187 // (i.e. it includes the lens manufacturer). 0188 if (datum.endsWith(QString::fromLatin1(".LensIDNumber"))) { 0189 // ExifDatum::print() returns the interpreted value 0190 qCDebug(ExifLog) << datum << ": " << it->print(&data).c_str(); 0191 canonHack = false; 0192 value = QString::fromUtf8(it->print(&data).c_str()); 0193 continue; 0194 } 0195 0196 // Exif.Nikon3.LensType [Byte] 0197 // Exif.OlympusEq.LensType [Byte] 0198 // Exif.Panasonic.LensType [Ascii] 0199 // Exif.Pentax.LensType [Byte] 0200 // Exif.Samsung2.LensType [Short] 0201 if (datum.endsWith(QString::fromLatin1(".LensType"))) { 0202 // ExifDatum::print() returns the interpreted value 0203 qCDebug(ExifLog) << datum << ": " << it->print(&data).c_str(); 0204 // make sure this cannot overwrite LensIDNumber 0205 if (value.isEmpty()) { 0206 canonHack = (datum == QString::fromLatin1("Exif.CanonCs.LensType")); 0207 value = QString::fromUtf8(it->print(&data).c_str()); 0208 } 0209 } 0210 } 0211 0212 // some canon lenses have a dummy value as LensType: 0213 if (canonHack && value == QString::fromLatin1("(65535)")) { 0214 value = QString::fromLatin1("Canon generic"); 0215 const auto datum = data.findKey(Exiv2::ExifKey("Exif.CanonCs.Lens")); 0216 if (datum != data.end()) { 0217 value += QString::fromLatin1(" "); 0218 value += QString::fromUtf8(datum->print(&data).c_str()); 0219 } 0220 } 0221 qCDebug(ExifLog) << "final lens value " << value; 0222 return QVariant { value }; 0223 } 0224 0225 // vi:expandtab:tabstop=4 shiftwidth=4: