void ExifTransfer::copyXMP() { const Exiv2::XmpData & srcXmp = src->xmpData(); Exiv2::XmpData & dstXmp = dst->xmpData(); for (const auto & datum : srcXmp) { if (datum.groupName() != "tiff" && dstXmp.findKey(Exiv2::XmpKey(datum.key())) == dstXmp.end()) { dstXmp.add(datum); } } }
int main(int argc, char* const argv[]) try { if (argc != 2) { std::cout << "Usage: " << argv[0] << " file\n"; return 1; } const char* path=argv[1]; Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(path); assert(image.get() != 0); image->readMetadata(); Jzon::Object root; const char* FS="FS"; Jzon::Object fs ; root.Add (FS,fs) ; fileSystemPush(path,root.Get(FS)); Exiv2::ExifData &exifData = image->exifData(); for ( ExifData::const_iterator i = exifData.begin(); i != exifData.end() ; ++i ) { std::string key ; push(objectForKey(i->key(),key,root),key,i); } Exiv2::IptcData &iptcData = image->iptcData(); for (Exiv2::IptcData::const_iterator i = iptcData.begin(); i != iptcData.end(); ++i) { std::string key ; push(objectForKey(i->key(),key,root),key,i); } Exiv2::XmpData &xmpData = image->xmpData(); for (Exiv2::XmpData::const_iterator i = xmpData.begin(); i != xmpData.end(); ++i) { std::string key ; push(objectForKey(i->key(),key,root),key,i); } /* This is only for testing long paths { ExifData::const_iterator i = exifData.begin(); std::string key; push(objectForKey("This.Is.A.Rather.Long.Path.Key",key,root),key,i); } */ Jzon::Writer writer(root,Jzon::StandardFormat); writer.Write(); std::cout << writer.GetResult() << std::endl; return 0; } //catch (std::exception& e) { //catch (Exiv2::AnyError& e) { catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e.what() << "'\n"; return -1; }
// ***************************************************************************** // Main int main(int argc, char* const argv[]) { try { // Handle command line arguments Params params; if (params.getopt(argc, argv)) { params.usage(); return 1; } if (params.help_) { params.help(); return 2; } // Use MemIo to increase test coverage. Exiv2::BasicIo::AutoPtr fileIo(new Exiv2::FileIo(params.read_)); Exiv2::BasicIo::AutoPtr memIo(new Exiv2::MemIo); memIo->transfer(*fileIo); Exiv2::Image::AutoPtr readImg = Exiv2::ImageFactory::open(memIo); assert(readImg.get() != 0); readImg->readMetadata(); Exiv2::Image::AutoPtr writeImg = Exiv2::ImageFactory::open(params.write_); assert(writeImg.get() != 0); if (params.preserve_) writeImg->readMetadata(); if (params.iptc_) { writeImg->setIptcData(readImg->iptcData()); } if (params.exif_) { writeImg->setExifData(readImg->exifData()); } if (params.comment_) { writeImg->setComment(readImg->comment()); } if (params.xmp_) { writeImg->setXmpData(readImg->xmpData()); } try { writeImg->writeMetadata(); } catch (const Exiv2::AnyError&) { std::cerr << params.progname() << ": Could not write metadata to (" << params.write_ << ")\n"; return 8; } return 0; } catch (Exiv2::AnyError& e) { std::cerr << "Caught Exiv2 exception '" << e << "'\n"; return 10; } }
bool KExiv2::loadFromData(const QByteArray& imgData) const { if (imgData.isEmpty()) return false; try { Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open((Exiv2::byte*)imgData.data(), imgData.size()); d->filePath.clear(); image->readMetadata(); // Size and mimetype --------------------------------- d->pixelSize = QSize(image->pixelWidth(), image->pixelHeight()); d->mimeType = QString::fromLatin1(image->mimeType().c_str()); // Image comments --------------------------------- d->imageComments() = image->comment(); // Exif metadata ---------------------------------- d->exifMetadata() = image->exifData(); // Iptc metadata ---------------------------------- d->iptcMetadata() = image->iptcData(); #ifdef _XMP_SUPPORT_ // Xmp metadata ----------------------------------- d->xmpMetadata() = image->xmpData(); #endif // _XMP_SUPPORT_ return true; } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError(QString::fromLatin1("Cannot load metadata using Exiv2 "), e); } catch(...) { qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; } return false; }
void ThumbView::updateExifInfo(QString imageFullPath) { Exiv2::Image::AutoPtr exifImage; QString key; QString val; try { exifImage = Exiv2::ImageFactory::open(imageFullPath.toStdString()); exifImage->readMetadata(); } catch (Exiv2::Error &error) { return; } Exiv2::ExifData &exifData = exifImage->exifData(); if (!exifData.empty()) { Exiv2::ExifData::const_iterator end = exifData.end(); infoView->addTitleEntry("Exif"); for (Exiv2::ExifData::const_iterator md = exifData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } Exiv2::IptcData &iptcData = exifImage->iptcData(); if (!iptcData.empty()) { Exiv2::IptcData::iterator end = iptcData.end(); infoView->addTitleEntry("IPTC"); for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } Exiv2::XmpData &xmpData = exifImage->xmpData(); if (!xmpData.empty()) { Exiv2::XmpData::iterator end = xmpData.end(); infoView->addTitleEntry("XMP"); for (Exiv2::XmpData::iterator md = xmpData.begin(); md != end; ++md) { key = QString::fromUtf8(md->tagName().c_str()); val = QString::fromUtf8(md->print().c_str()); infoView->addEntry(key, val); } } }
bool Exiv2ReadingWorker::readMetadata(Models::ArtworkMetadata *artwork, ImportDataResult &importResult) { const QString &filepath = artwork->getFilepath(); #if defined(Q_OS_WIN) Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filepath.toStdWString()); #else Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filepath.toStdString()); #endif Q_ASSERT(image.get() != NULL); image->readMetadata(); Exiv2::XmpData &xmpData = image->xmpData(); Exiv2::ExifData &exifData = image->exifData(); Exiv2::IptcData &iptcData = image->iptcData(); QString iptcEncoding = getIptcCharset(iptcData).toUpper(); bool isIptcUtf8 = (iptcEncoding == QLatin1String("UTF-8")) || (iptcEncoding == QLatin1String("UTF8")); importResult.FilePath = filepath; importResult.Description = retrieveDescription(xmpData, exifData, iptcData, isIptcUtf8); importResult.Title = retrieveTitle(xmpData, exifData, iptcData, isIptcUtf8); importResult.Keywords = retrieveKeywords(xmpData, exifData, iptcData, isIptcUtf8); importResult.DateTimeOriginal = retrieveDateTime(xmpData, exifData, iptcData, isIptcUtf8); MetadataSavingCopy copy; if (copy.readFromFile(filepath)) { importResult.BackupDict = copy.getInfo(); } QFileInfo fi(filepath); importResult.FileSize = fi.size(); Models::ImageArtwork *imageArtwork = dynamic_cast<Models::ImageArtwork*>(artwork); if (imageArtwork != NULL) { QImageReader reader(filepath); importResult.ImageSize = reader.size(); } return true; }
bool KExiv2::load(const QString& filePath) const { if (filePath.isEmpty()) { return false; } d->filePath = filePath; bool hasLoaded = false; try { Exiv2::Image::AutoPtr image; image = Exiv2::ImageFactory::open((const char*)(QFile::encodeName(filePath)).constData()); image->readMetadata(); // Size and mimetype --------------------------------- d->pixelSize = QSize(image->pixelWidth(), image->pixelHeight()); d->mimeType = QString::fromLatin1(image->mimeType().c_str()); // Image comments --------------------------------- d->imageComments() = image->comment(); // Exif metadata ---------------------------------- d->exifMetadata() = image->exifData(); // Iptc metadata ---------------------------------- d->iptcMetadata() = image->iptcData(); #ifdef _XMP_SUPPORT_ // Xmp metadata ----------------------------------- d->xmpMetadata() = image->xmpData(); #endif // _XMP_SUPPORT_ hasLoaded = true; } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError(QString::fromLatin1("Cannot load metadata from file "), e); } catch(...) { qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; } #ifdef _XMP_SUPPORT_ try { if (d->useXMPSidecar4Reading) { QString xmpSidecarPath = sidecarFilePathForFile(filePath); QFileInfo xmpSidecarFileInfo(xmpSidecarPath); Exiv2::Image::AutoPtr xmpsidecar; if (xmpSidecarFileInfo.exists() && xmpSidecarFileInfo.isReadable()) { // Read sidecar data xmpsidecar = Exiv2::ImageFactory::open(QFile::encodeName(xmpSidecarPath).constData()); xmpsidecar->readMetadata(); // Merge d->loadSidecarData(xmpsidecar); hasLoaded = true; } } } catch( Exiv2::Error& e ) { d->printExiv2ExceptionError(QString::fromLatin1("Cannot load XMP sidecar"), e); } catch(...) { qCCritical(LIBKEXIV2_LOG) << "Default exception from Exiv2"; } #endif // _XMP_SUPPORT_ return hasLoaded; }
void MetaEngine::Private::loadSidecarData(Exiv2::Image::AutoPtr xmpsidecar) { // Having a sidecar is a special situation. // The sidecar data often "dominates", see in particular bug 309058 for important aspects: // If a field is removed from the sidecar, we must ignore (older) data for this field in the file. // First: Ignore file XMP, only use sidecar XMP xmpMetadata() = xmpsidecar->xmpData(); loadedFromSidecar = true; // EXIF // Four groups of properties are mapped between EXIF and XMP: // Date/Time, Description, Copyright, Creator // A few more tags are defined "writeback" tags in the XMP specification, the sidecar value therefore overrides the Exif value. // The rest is kept side-by-side. // (to understand, remember that the xmpsidecar's Exif data is actually XMP data mapped back to Exif) // Description, Copyright and Creator is dominated by the sidecar: Remove file Exif fields, if field not in XMP. ExifMergeHelper exifDominatedHelper; exifDominatedHelper << QLatin1String("Exif.Image.ImageDescription") << QLatin1String("Exif.Photo.UserComment") << QLatin1String("Exif.Image.Copyright") << QLatin1String("Exif.Image.Artist"); exifDominatedHelper.exclusiveMerge(xmpsidecar->exifData(), exifMetadata()); // Date/Time and "the few more" from the XMP spec are handled as writeback // Note that Date/Time mapping is slightly contradictory in latest specs. ExifMergeHelper exifWritebackHelper; exifWritebackHelper << QLatin1String("Exif.Image.DateTime") << QLatin1String("Exif.Image.DateTime") << QLatin1String("Exif.Photo.DateTimeOriginal") << QLatin1String("Exif.Photo.DateTimeDigitized") << QLatin1String("Exif.Image.Orientation") << QLatin1String("Exif.Image.XResolution") << QLatin1String("Exif.Image.YResolution") << QLatin1String("Exif.Image.ResolutionUnit") << QLatin1String("Exif.Image.Software") << QLatin1String("Exif.Photo.RelatedSoundFile"); exifWritebackHelper.mergeFields(xmpsidecar->exifData(), exifMetadata()); // IPTC // These fields cover almost all relevant IPTC data and are defined in the XMP specification for reconciliation. IptcMergeHelper iptcDominatedHelper; iptcDominatedHelper << QLatin1String("Iptc.Application2.ObjectName") << QLatin1String("Iptc.Application2.Urgency") << QLatin1String("Iptc.Application2.Category") << QLatin1String("Iptc.Application2.SuppCategory") << QLatin1String("Iptc.Application2.Keywords") << QLatin1String("Iptc.Application2.SubLocation") << QLatin1String("Iptc.Application2.SpecialInstructions") << QLatin1String("Iptc.Application2.Byline") << QLatin1String("Iptc.Application2.BylineTitle") << QLatin1String("Iptc.Application2.City") << QLatin1String("Iptc.Application2.ProvinceState") << QLatin1String("Iptc.Application2.CountryCode") << QLatin1String("Iptc.Application2.CountryName") << QLatin1String("Iptc.Application2.TransmissionReference") << QLatin1String("Iptc.Application2.Headline") << QLatin1String("Iptc.Application2.Credit") << QLatin1String("Iptc.Application2.Source") << QLatin1String("Iptc.Application2.Copyright") << QLatin1String("Iptc.Application2.Caption") << QLatin1String("Iptc.Application2.Writer"); iptcDominatedHelper.exclusiveMerge(xmpsidecar->iptcData(), iptcMetadata()); IptcMergeHelper iptcWritebackHelper; iptcWritebackHelper << QLatin1String("Iptc.Application2.DateCreated") << QLatin1String("Iptc.Application2.TimeCreated") << QLatin1String("Iptc.Application2.DigitizationDate") << QLatin1String("Iptc.Application2.DigitizationTime"); iptcWritebackHelper.mergeFields(xmpsidecar->iptcData(), iptcMetadata()); /* * TODO: Exiv2 (referring to 0.23) does not correctly synchronize all times values as given below. * Time values and their synchronization: * Original Date/Time – Creation date of the intellectual content (e.g. the photograph), rather than the creatio*n date of the content being shown Exif DateTimeOriginal (36867, 0x9003) and SubSecTimeOriginal (37521, 0x9291) IPTC DateCreated (IIM 2:55, 0x0237) and TimeCreated (IIM 2:60, 0x023C) XMP (photoshop:DateCreated) * Digitized Date/Time – Creation date of the digital representation Exif DateTimeDigitized (36868, 0x9004) and SubSecTimeDigitized (37522, 0x9292) IPTC DigitalCreationDate (IIM 2:62, 0x023E) and DigitalCreationTime (IIM 2:63, 0x023F) XMP (xmp:CreateDate) * Modification Date/Time – Modification date of the digital image file Exif DateTime (306, 0x132) and SubSecTime (37520, 0x9290) XMP (xmp:ModifyDate) */ }