File indexing completed on 2024-09-08 05:15:32
0001 // SPDX-License-Identifier: GPL-2.0-or-later 0002 // SPDX-FileCopyrightText: 2008 Dominik Seichter <domseichter@web.de> 0003 0004 #include "exiv2plugin.h" 0005 0006 #include <KLocalizedString> 0007 0008 #include <exiv2/exiv2.hpp> 0009 0010 #include "batchrenamer.h" 0011 #include "tokenhelpdialog.h" 0012 0013 using namespace Exiv2; 0014 0015 static const char *exifTags[] = { 0016 "Exif.Image.ImageWidth", 0017 "Exif.Image.ImageLength", 0018 "Exif.Image.BitsPerSample", 0019 "Exif.Image.Compression", 0020 "Exif.Image.PhotometricInterpretation", 0021 "Exif.Image.Orientation", 0022 "Exif.Image.SamplesPerPixel", 0023 "Exif.Image.PlanarConfiguration", 0024 "Exif.Image.YCbCrSubSampling", 0025 "Exif.Image.YCbCrPositioning", 0026 "Exif.Image.XResolution", 0027 "Exif.Image.YResolution", 0028 "Exif.Image.ResolutionUnit", 0029 "Exif.Image.TransferFunction", 0030 "Exif.Image.WhitePoint", 0031 "Exif.Image.PrimaryChromaticities", 0032 "Exif.Image.YCbCrCoefficients", 0033 "Exif.Image.ReferenceBlackWhite", 0034 "Exif.Image.DateTime", 0035 "Exif.Image.ImageDescription", 0036 "Exif.Image.Make", 0037 "Exif.Image.Model", 0038 "Exif.Image.Software", 0039 "Exif.Image.Artist", 0040 "Exif.Image.Copyright", 0041 "Exif.Photo.ExifVersion", 0042 "Exif.Photo.FlashpixVersion", 0043 "Exif.Photo.ColorSpace", 0044 "Exif.Photo.ComponentsConfiguration", 0045 "Exif.Photo.CompressedBitsPerPixel", 0046 "Exif.Photo.PixelXDimension", 0047 "Exif.Photo.PixelYDimension", 0048 "Exif.Photo.UserComment", 0049 "Exif.Photo.RelatedSoundFile", 0050 "Exif.Photo.DateTimeOriginal", 0051 "Exif.Photo.DateTimeDigitized", 0052 "Exif.Photo.ExposureTime", 0053 "Exif.Photo.FNumber", 0054 "Exif.Photo.ExposureProgram", 0055 "Exif.Photo.SpectralSensitivity", 0056 "Exif.Photo.ISOSpeedRatings", 0057 "Exif.Photo.OECF", 0058 "Exif.Photo.ShutterSpeedValue", 0059 "Exif.Photo.ApertureValue", 0060 "Exif.Photo.BrightnessValue", 0061 "Exif.Photo.ExposureBiasValue", 0062 "Exif.Photo.MaxApertureValue", 0063 "Exif.Photo.SubjectDistance", 0064 "Exif.Photo.MeteringMode", 0065 "Exif.Photo.LightSource", 0066 "Exif.Photo.Flash", 0067 "Exif.Photo.FocalLength", 0068 "Exif.Photo.SubjectArea", 0069 "Exif.Photo.FlashEnergy", 0070 "Exif.Photo.SpatialFrequencyResponse", 0071 "Exif.Photo.FocalPlaneXResolution", 0072 "Exif.Photo.FocalPlaneYResolution", 0073 "Exif.Photo.FocalPlaneResolutionUnit", 0074 "Exif.Photo.SubjectLocation", 0075 "Exif.Photo.ExposureIndex", 0076 "Exif.Photo.SensingMethod", 0077 "Exif.Photo.FileSource", 0078 "Exif.Photo.SceneType", 0079 "Exif.Photo.CFAPattern", 0080 "Exif.Photo.CustomRendered", 0081 "Exif.Photo.ExposureMode", 0082 "Exif.Photo.WhiteBalance", 0083 "Exif.Photo.DigitalZoomRatio", 0084 "Exif.Photo.FocalLengthIn35mmFilm", 0085 "Exif.Photo.SceneCaptureType", 0086 "Exif.Photo.GainControl", 0087 "Exif.Photo.Contrast", 0088 "Exif.Photo.Saturation", 0089 "Exif.Photo.Sharpness", 0090 "Exif.Photo.DeviceSettingDescription", 0091 "Exif.Photo.SubjectDistanceRange", 0092 "Exif.Photo.ImageUniqueID", 0093 "Exif.GPSInfo.GPSVersionID", 0094 "Exif.GPSInfo.GPSLatitude", 0095 "Exif.GPSInfo.GPSLongitude", 0096 "Exif.GPSInfo.GPSAltitudeRef", 0097 "Exif.GPSInfo.GPSAltitude", 0098 "Exif.GPSInfo.GPSTimeStamp", 0099 "Exif.GPSInfo.GPSSatellites", 0100 "Exif.GPSInfo.GPSStatus", 0101 "Exif.GPSInfo.GPSMeasureMode", 0102 "Exif.GPSInfo.GPSDOP", 0103 "Exif.GPSInfo.GPSSpeedRef", 0104 "Exif.GPSInfo.GPSSpeed", 0105 "Exif.GPSInfo.GPSTrackRef", 0106 "Exif.GPSInfo.GPSTrack", 0107 "Exif.GPSInfo.GPSImgDirectionRef", 0108 "Exif.GPSInfo.GPSImgDirection", 0109 "Exif.GPSInfo.GPSMapDatum", 0110 "Exif.GPSInfo.GPSDestLatitude", 0111 "Exif.GPSInfo.GPSDestLongitude", 0112 "Exif.GPSInfo.GPSDestBearingRef", 0113 "Exif.GPSInfo.GPSDestBearing", 0114 "Exif.GPSInfo.GPSDestDistanceRef", 0115 "Exif.GPSInfo.GPSDestDistance", 0116 "Exif.GPSInfo.GPSProcessingMethod", 0117 "Exif.GPSInfo.GPSAreaInformation", 0118 "Exif.GPSInfo.GPSDifferential", 0119 nullptr 0120 }; 0121 0122 static const char *xmpTags[] = { 0123 "Xmp.tiff.ImageWidth", 0124 "Xmp.tiff.ImageLength", 0125 "Xmp.tiff.BitsPerSample", 0126 "Xmp.tiff.Compression", 0127 "Xmp.tiff.PhotometricInterpretation", 0128 "Xmp.tiff.Orientation", 0129 "Xmp.tiff.SamplesPerPixe", 0130 "Xmp.tiff.PlanarConfiguration", 0131 "Xmp.tiff.YCbCrSubSampling", 0132 "Xmp.tiff.YCbCrPositioning", 0133 "Xmp.tiff.XResolution", 0134 "Xmp.tiff.YResolution", 0135 "Xmp.tiff.ResolutionUnit", 0136 "Xmp.tiff.TransferFunction", 0137 "Xmp.tiff.WhitePoint", 0138 "Xmp.tiff.PrimaryChromaticities", 0139 "Xmp.tiff.YCbCrCoefficients", 0140 "Xmp.tiff.ReferenceBlackWhite", 0141 "Xmp.tiff.DateTime", 0142 "Xmp.dc.description", 0143 "Xmp.tiff.Make", 0144 "Xmp.tiff.Model", 0145 "Xmp.tiff.Software", 0146 "Xmp.dc.creator", 0147 "Xmp.dc.rights", 0148 "Xmp.exif.ExifVersion", 0149 "Xmp.exif.FlashpixVersion", 0150 "Xmp.exif.ColorSpace", 0151 "Xmp.exif.ComponentsConfiguration", 0152 "Xmp.exif.CompressedBitsPerPixel", 0153 "Xmp.exif.PixelXDimension", 0154 "Xmp.exif.PixelYDimension", 0155 "Xmp.exif.UserComment", 0156 "Xmp.exif.RelatedSoundFile", 0157 "Xmp.exif.DateTimeOriginal", 0158 "Xmp.exif.DateTimeDigitized", 0159 "Xmp.exif.ExposureTime", 0160 "Xmp.exif.FNumber", 0161 "Xmp.exif.ExposureProgram", 0162 "Xmp.exif.SpectralSensitivity", 0163 "Xmp.exif.ISOSpeedRatings", 0164 "Xmp.exif.OECF", 0165 "Xmp.exif.ShutterSpeedValue", 0166 "Xmp.exif.ApertureValue", 0167 "Xmp.exif.BrightnessValue", 0168 "Xmp.exif.ExposureBiasValue", 0169 "Xmp.exif.MaxApertureValue", 0170 "Xmp.exif.SubjectDistance", 0171 "Xmp.exif.MeteringMode", 0172 "Xmp.exif.LightSource", 0173 "Xmp.exif.Flash", 0174 "Xmp.exif.FocalLength", 0175 "Xmp.exif.SubjectArea", 0176 "Xmp.exif.FlashEnergy", 0177 "Xmp.exif.SpatialFrequencyResponse", 0178 "Xmp.exif.FocalPlaneXResolution", 0179 "Xmp.exif.FocalPlaneYResolution", 0180 "Xmp.exif.FocalPlaneResolutionUnit", 0181 "Xmp.exif.SubjectLocation", 0182 "Xmp.exif.ExposureIndex", 0183 "Xmp.exif.SensingMethod", 0184 "Xmp.exif.FileSource", 0185 "Xmp.exif.SceneType", 0186 "Xmp.exif.CFAPattern", 0187 "Xmp.exif.CustomRendered", 0188 "Xmp.exif.ExposureMode", 0189 "Xmp.exif.WhiteBalance", 0190 "Xmp.exif.DigitalZoomRatio", 0191 "Xmp.exif.FocalLengthIn35mmFilm", 0192 "Xmp.exif.SceneCaptureType", 0193 "Xmp.exif.GainControl", 0194 "Xmp.exif.Contrast", 0195 "Xmp.exif.Saturation", 0196 "Xmp.exif.Sharpness", 0197 "Xmp.exif.DeviceSettingDescription", 0198 "Xmp.exif.SubjectDistanceRange", 0199 "Xmp.exif.ImageUniqueID", 0200 "Xmp.exif.GPSVersionID", 0201 "Xmp.exif.GPSLatitude", 0202 "Xmp.exif.GPSLongitude", 0203 "Xmp.exif.GPSAltitudeRef", 0204 "Xmp.exif.GPSAltitude", 0205 "Xmp.exif.GPSTimeStamp", 0206 "Xmp.exif.GPSSatellites", 0207 "Xmp.exif.GPSStatus", 0208 "Xmp.exif.GPSMeasureMode", 0209 "Xmp.exif.GPSDOP", 0210 "Xmp.exif.GPSSpeedRef", 0211 "Xmp.exif.GPSSpeed", 0212 "Xmp.exif.GPSTrackRef", 0213 "Xmp.exif.GPSTrack", 0214 "Xmp.exif.GPSImgDirectionRef", 0215 "Xmp.exif.GPSImgDirection", 0216 "Xmp.exif.GPSMapDatum", 0217 "Xmp.exif.GPSDestLatitude", 0218 "Xmp.exif.GPSDestLongitude", 0219 "Xmp.exif.GPSDestBearingRef", 0220 "Xmp.exif.GPSDestBearing", 0221 "Xmp.exif.GPSDestDistanceRef", 0222 "Xmp.exif.GPSDestDistance", 0223 "Xmp.exif.GPSProcessingMethod", 0224 "Xmp.exif.GPSAreaInformation", 0225 "Xmp.exif.GPSDifferential", 0226 "Xmp.dc.title", 0227 "Xmp.photoshop.Urgency", 0228 "Xmp.photoshop.Category", 0229 "Xmp.photoshop.SupplementalCategory", 0230 "Xmp.dc.subject", 0231 "Xmp.iptc.Location", 0232 "Xmp.photoshop.Instruction", 0233 "Xmp.photoshop.DateCreated", 0234 "Xmp.dc.creator", 0235 "Xmp.photoshop.AuthorsPosition", 0236 "Xmp.photoshop.City", 0237 "Xmp.photoshop.State", 0238 "Xmp.iptc.CountryCode", 0239 "Xmp.photoshop.Country", 0240 "Xmp.photoshop.TransmissionReference", 0241 "Xmp.photoshop.Headline", 0242 "Xmp.photoshop.Credit", 0243 "Xmp.photoshop.Source", 0244 "Xmp.dc.rights", 0245 "Xmp.dc.description", 0246 "Xmp.photoshop.CaptionWriter", 0247 nullptr 0248 }; 0249 0250 static const char *iptcTags[] = { 0251 "Iptc.Application2.ObjectName", 0252 "Iptc.Application2.Urgency", 0253 "Iptc.Application2.Category", 0254 "Iptc.Application2.SuppCategory", 0255 "Iptc.Application2.Keywords", 0256 "Iptc.Application2.LocationName", 0257 "Iptc.Application2.SpecialInstructions", 0258 "Iptc.Application2.DateCreated", 0259 "Iptc.Application2.Byline", 0260 "Iptc.Application2.BylineTitle", 0261 "Iptc.Application2.City", 0262 "Iptc.Application2.ProvinceState", 0263 "Iptc.Application2.CountryCode", 0264 "Iptc.Application2.CountryName", 0265 "Iptc.Application2.TransmissionReference", 0266 "Iptc.Application2.Headline", 0267 "Iptc.Application2.Credit", 0268 "Iptc.Application2.Source", 0269 "Iptc.Application2.Copyright", 0270 "Iptc.Application2.Caption", 0271 "Iptc.Application2.Writer", 0272 nullptr 0273 }; 0274 0275 Exiv2Plugin::Exiv2Plugin(PluginLoader *loader) 0276 : FilePlugin(loader) 0277 { 0278 const QString prefix("exif"); 0279 const char **token; 0280 0281 this->addSupportedToken("exifComment"); 0282 //this->addSupportedToken("exifWidth"); 0283 //this->addSupportedToken("exifHeight"); 0284 m_help.append("[exifComment]" + TokenHelpDialog::getTokenSeparator() + i18n("Insert the comment of an image")); 0285 //m_help.append( "[exifWidth]" + TokenHelpDialog::getTokenSeparator() + i18n("Insert the width in pixel of an image") ); 0286 //m_help.append( "[exifHeight]" + TokenHelpDialog::getTokenSeparator() + i18n("Insert the height in pixel of an image") ); 0287 0288 // Add exif taks 0289 token = exifTags; 0290 while (*token) { 0291 ExifKey key(*token); 0292 QString help; 0293 try { 0294 help = QString::fromUtf8(key.tagLabel().c_str()); 0295 } catch (const std::exception &e) { 0296 help = ""; 0297 // exiv2 throws sometimes exceptions 0298 // because it tries to create std::string from NULL pointers 0299 } 0300 0301 QString cur(*token); 0302 this->addSupportedToken(prefix + cur); 0303 m_help.append(QString("[") + prefix + cur + QString("]") + TokenHelpDialog::getTokenSeparator() + help); 0304 0305 m_mapRealKeys[QString(prefix + cur).toLower()] = cur; 0306 ++token; 0307 } 0308 0309 // Add exif taks 0310 token = xmpTags; 0311 while (*token) { 0312 XmpKey key(*token); 0313 QString help; 0314 try { 0315 help = QString::fromUtf8(key.tagLabel().c_str()); 0316 } catch (const std::exception &e) { 0317 help = ""; 0318 // exiv2 throws sometimes exceptions 0319 // because it tries to create std::string from NULL pointers 0320 } 0321 0322 QString cur(*token); 0323 this->addSupportedToken(prefix + cur); 0324 m_help.append(QString("[") + prefix + cur + QString("]") + TokenHelpDialog::getTokenSeparator() + help); 0325 0326 m_mapRealKeys[QString(prefix + cur).toLower()] = cur; 0327 ++token; 0328 } 0329 0330 // Add exif taks 0331 token = iptcTags; 0332 while (*token) { 0333 IptcKey key(*token); 0334 QString help; 0335 try { 0336 help = QString::fromUtf8(key.tagLabel().c_str()); 0337 } catch (const std::exception &e) { 0338 help = ""; 0339 // exiv2 throws sometimes exceptions 0340 // because it tries to create std::string from NULL pointers 0341 } 0342 0343 QString cur(*token); 0344 this->addSupportedToken(prefix + cur); 0345 m_help.append(QString("[") + prefix + cur + QString("]") + TokenHelpDialog::getTokenSeparator() + help); 0346 0347 m_mapRealKeys[QString(prefix + cur).toLower()] = cur; 0348 ++token; 0349 } 0350 0351 m_name = i18n("Exiv2 (JPEG/TIFF Exif) Plugin"); 0352 m_comment = i18n("<qt>This plugin supports reading tags from " 0353 "JPEG and TIFF files.</qt>"); 0354 0355 m_icon = "image-x-generic"; 0356 } 0357 0358 QString Exiv2Plugin::processFile(BatchRenamer *b, int index, const QString &filenameOrToken, EPluginType) 0359 { 0360 QString token(filenameOrToken.toLower()); 0361 QString filename = (*b->files())[index].srcUrl().path(); 0362 0363 if (!this->supports(token)) { 0364 return QString(""); 0365 } 0366 0367 //const QByteArray asc = filename.toAscii(); 0368 // Use toUtf8 so that unicode filenames will work 0369 const QByteArray asc = filename.toUtf8(); 0370 std::string strFilename(asc.constData(), asc.length()); 0371 0372 try { 0373 #if EXIV2_TEST_VERSION(0,28,0) 0374 Image::UniquePtr image = Exiv2::ImageFactory::open(strFilename); 0375 #else 0376 Image::AutoPtr image = Exiv2::ImageFactory::open(strFilename); 0377 #endif 0378 if (image.get() != nullptr && image->good()) { 0379 image->readMetadata(); 0380 0381 if (token == "exifcomment") { 0382 return QString::fromUtf8(image->comment().c_str()); 0383 } 0384 /* 0385 else if( token =="exifwidth" ) 0386 return QString::number( image->pixelWidth() ); 0387 else if( token =="exifheight" ) 0388 return QString::number( image->pixelHeight() ); 0389 */ 0390 if (token.startsWith(QLatin1String("exifexif."))) { 0391 ExifKey key(m_mapRealKeys[token].toLatin1().data()); 0392 ExifData::const_iterator it = image->exifData().findKey(key); 0393 if (it != image->exifData().end()) { 0394 std::string val = (*it).toString(); 0395 return QString::fromUtf8(val.c_str()); 0396 } 0397 } else if (token.startsWith(QLatin1String("exifxmp."))) { 0398 XmpKey key(m_mapRealKeys[token].toLatin1().data()); 0399 XmpData::const_iterator it = image->xmpData().findKey(key); 0400 if (it != image->xmpData().end()) { 0401 std::string val = (*it).toString(); 0402 return QString::fromUtf8(val.c_str()); 0403 } 0404 } else if (token.startsWith(QLatin1String("exifiptc."))) { 0405 IptcKey key(m_mapRealKeys[token].toLatin1().data()); 0406 IptcData::const_iterator it = image->iptcData().findKey(key); 0407 if (it != image->iptcData().end()) { 0408 std::string val = (*it).toString(); 0409 return QString::fromUtf8(val.c_str()); 0410 } 0411 } 0412 } 0413 } catch (const std::exception &err) { 0414 return QString::fromUtf8(err.what()); 0415 } 0416 0417 return QString(""); 0418 }