File indexing completed on 2024-04-21 16:32:30

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