void ExifTransfer::copyIPTC() { const Exiv2::IptcData & srcIptc = src->iptcData(); Exiv2::IptcData & dstIptc = dst->iptcData(); for (const auto & datum : srcIptc) { if (dstIptc.findKey(Exiv2::IptcKey(datum.key())) == dstIptc.end()) { dstIptc.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); } } }
void ExifTools::copyExif(const QString &sourceStr, const QString &destStr) { Exiv2::Image::AutoPtr sourceImageData = Exiv2::ImageFactory::open(QFile::encodeName(sourceStr).data()); sourceImageData->readMetadata(); Exiv2::ExifData exifData = sourceImageData->exifData(); Exiv2::IptcData iptcData = sourceImageData->iptcData(); Exiv2::ExifThumb exifThumb(exifData); exifThumb.erase(); Exiv2::Image::AutoPtr destImageData = Exiv2::ImageFactory::open(QFile::encodeName(destStr).data()); destImageData->setExifData(exifData); destImageData->setIptcData(iptcData); destImageData->writeMetadata(); }
bool ImageTags::writeTagsToImage(QString &imageFileName, QSet<QString> &newTags) { QSet<QString> imageTags; Exiv2::Image::AutoPtr exifImage; try { exifImage = Exiv2::ImageFactory::open(imageFileName.toStdString()); exifImage->readMetadata(); Exiv2::IptcData newIptcData; /* copy existing data */ Exiv2::IptcData &iptcData = exifImage->iptcData(); if (!iptcData.empty()) { QString key; Exiv2::IptcData::iterator end = iptcData.end(); for (Exiv2::IptcData::iterator iptcIt = iptcData.begin(); iptcIt != end; ++iptcIt) { if (iptcIt->tagName() != "Keywords") { newIptcData.add(*iptcIt); } } } /* add new tags */ QSetIterator<QString> newTagsIt(newTags); while (newTagsIt.hasNext()) { QString tag = newTagsIt.next(); Exiv2::Value::AutoPtr value = Exiv2::Value::create(Exiv2::string); value->read(tag.toStdString()); Exiv2::IptcKey key("Iptc.Application2.Keywords"); newIptcData.add(key, value.get()); } exifImage->setIptcData(newIptcData); exifImage->writeMetadata(); } catch (Exiv2::Error &error) { QMessageBox msgBox; msgBox.critical(this, tr("Error"), tr("Failed to save tags to ") + imageFileName); return false; } return true; }
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; }
int main(int argc, char* const argv[]) try { if (argc != 2) { std::cout << "Usage: " << argv[0] << " file\n"; return 1; } Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(argv[1]); assert (image.get() != 0); image->readMetadata(); Exiv2::IptcData &iptcData = image->iptcData(); if (iptcData.empty()) { std::string error(argv[1]); error += ": No IPTC data found in the file"; throw Exiv2::Error(1, error); } Exiv2::IptcData::iterator end = iptcData.end(); for (Exiv2::IptcData::iterator md = iptcData.begin(); md != end; ++md) { std::cout << std::setw(44) << std::setfill(' ') << std::left << md->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << md->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << md->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << md->count() << " " << std::dec << md->value() << std::endl; } return 0; } catch (Exiv2::AnyError& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; return -1; }
int main(int argc, char* const argv[]) try { if (argc != 3) { std::cout << "Usage: " << argv[0] << " image datafile\n"; return 1; } std::string file(argv[1]); std::string data(argv[2]); // Read data file into data buffer Exiv2::FileIo io(data); if (io.open() != 0) { throw Exiv2::Error(Exiv2::kerDataSourceOpenFailed, io.path(), Exiv2::strError()); } Exiv2::DataBuf buf((long)io.size()); std::cout << "Reading " << buf.size_ << " bytes from " << data << "\n"; io.read(buf.pData_, buf.size_); if (io.error() || !io.eof()) throw Exiv2::Error(Exiv2::kerFailedToReadImageData); // Read metadata from file Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file); assert(image.get() != 0); image->readMetadata(); // Set Preview field to the content of the data file Exiv2::DataValue value; value.read(buf.pData_, buf.size_); Exiv2::IptcData& iptcData = image->iptcData(); std::cout << "IPTC fields: " << iptcData.size() << "\n"; iptcData["Iptc.Application2.Preview"] = value; std::cout << "IPTC fields: " << iptcData.size() << "\n"; // Set IRB, compare with IPTC raw data Exiv2::DataBuf irb = Exiv2::Photoshop::setIptcIrb(0, 0, iptcData); std::cout << "IRB buffer : " << irb.size_ << "\n"; const Exiv2::byte* record; uint32_t sizeHdr; uint32_t sizeData; Exiv2::Photoshop::locateIptcIrb(irb.pData_, irb.size_, &record, &sizeHdr, &sizeData); Exiv2::DataBuf rawIptc = Exiv2::IptcParser::encode(iptcData); std::cout << "Comparing IPTC and IRB size... "; if (static_cast<uint32_t>(rawIptc.size_) != sizeData) { std::cout << "not "; } std::cout << "ok\n"; std::cout << "Comparing IPTC and IRB data... "; if (0 != memcmp(rawIptc.pData_, record + sizeHdr, sizeData)) { std::cout << "not "; } std::cout << "ok\n"; // Set Iptc data and write it to the file image->writeMetadata(); return 0; } catch (Exiv2::AnyError& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; return -1; }
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; }
SlideShowWindow::SlideShowWindow(QWidget *parent) : QWidget(parent) , m_group(0) , m_scene(0) , m_oldScene(0) , m_useGLWidget(true) , m_glWidget(0) , m_graphicsView(0) , m_xfadeSpeed(300) { QVBoxLayout *layout = new QVBoxLayout(this); layout->setContentsMargins(0,0,0,0); bool verbose = true; QString configFile = "player.ini"; if(verbose) qDebug() << "SlideShowWindow: Reading settings from "<<configFile; QSettings settings(configFile,QSettings::IniFormat); QString str; QStringList parts; QPoint point; QString activeGroup = settings.value("config").toString(); str = settings.value("verbose").toString(); if(!str.isEmpty()) verbose = str == "true"; if(verbose && !activeGroup.isEmpty()) qDebug() << "SlideShowWindow: Using config:"<<activeGroup; #define READ_STRING(key,default) \ (!activeGroup.isEmpty() ? \ (!(str = settings.value(QString("%1/%2").arg(activeGroup).arg(key)).toString()).isEmpty() ? str : \ settings.value(key,default).toString()) : \ settings.value(key,default).toString()) #define READ_POINT(key,default) \ str = READ_STRING(key,default); \ parts = str.split("x"); \ point = QPoint(parts[0].toInt(),parts[1].toInt()); \ if(verbose) qDebug() << "SlideShowWindow: " key ": " << point; m_useGLWidget = READ_STRING("compat","false") == "false"; if(m_useGLWidget) { m_glWidget = new GLWidget(this); layout->addWidget(m_glWidget); qDebug() << "SlideShowWindow: Using OpenGL to provide high-quality graphics."; m_glWidget->setCursor(Qt::BlankCursor); } else { m_graphicsView = new ScaledGraphicsView(); m_graphicsScene = new QGraphicsScene(); m_graphicsView->setScene(m_graphicsScene); m_graphicsView->setViewport(new QGLWidget(QGLFormat(QGL::SampleBuffers))); m_graphicsScene->setSceneRect(QRectF(0,0,1000.,750.)); m_graphicsView->setBackgroundBrush(Qt::black); layout->addWidget(m_graphicsView); qDebug() << "SlideShowWindow: Using vendor-provided stock graphics engine for compatibility with older hardware."; m_graphicsView->setCursor(Qt::BlankCursor); } // Window position and size READ_POINT("window-pos","10x10"); QPoint windowPos = point; READ_POINT("window-size","640x480"); QPoint windowSize = point; //windowSize = QPoint(3120,1050); if(verbose) qDebug() << "SlideShowWindow: pos:"<<windowPos<<", size:"<<windowSize; resize(windowSize.x(),windowSize.y()); move(windowPos.x(),windowPos.y()); bool frameless = READ_STRING("frameless","true") == "true"; if(frameless) setWindowFlags(Qt::FramelessWindowHint);// | Qt::ToolTip); if(m_useGLWidget) { // Keystoning / Corner Translations READ_POINT("key-tl","0x0"); m_glWidget->setTopLeftTranslation(point); READ_POINT("key-tr","0x0"); m_glWidget->setTopRightTranslation(point); READ_POINT("key-bl","0x0"); m_glWidget->setBottomLeftTranslation(point); READ_POINT("key-br","0x0"); m_glWidget->setBottomRightTranslation(point); // Brightness/Contrast, Hue/Sat m_glWidget->setBrightness(READ_STRING("brightness","0").toInt()); m_glWidget->setContrast(READ_STRING("contrast","0").toInt()); m_glWidget->setHue(READ_STRING("hue","0").toInt()); m_glWidget->setSaturation(READ_STRING("saturation","0").toInt()); // Flip H/V bool fliph = READ_STRING("flip-h","false") == "true"; if(verbose) qDebug() << "SlideShowWindow: flip-h: "<<fliph; m_glWidget->setFlipHorizontal(fliph); bool flipv = READ_STRING("flip-v","false") == "true"; if(verbose) qDebug() << "SlideShowWindow: flip-v: "<<flipv; m_glWidget->setFlipVertical(flipv); // Rotate int rv = READ_STRING("rotate","0").toInt(); if(verbose) qDebug() << "SlideShowWindow: rotate: "<<rv; if(rv != 0) m_glWidget->setCornerRotation(rv == -1 ? GLRotateLeft : rv == 1 ? GLRotateRight : GLRotateNone); // Aspet Ratio Mode m_glWidget->setAspectRatioMode(READ_STRING("ignore-ar","false") == "true" ? Qt::IgnoreAspectRatio : Qt::KeepAspectRatio); // Alpha Mask QString alphaFile = READ_STRING("alphamask",""); if(!alphaFile.isEmpty()) { QImage alphamask(alphaFile); if(alphamask.isNull()) qDebug() << "SlideShowWindow: Error loading alphamask "<<alphaFile; else m_glWidget->setAlphaMask(alphamask); } // GLWidgetSubview *sub1 = m_glWidget->defaultSubview(); // sub1->setRight(1680./3120.); // // GLWidgetSubview *sub2 = new GLWidgetSubview(); // sub2->setLeft(sub1->right()); // sub2->setBrightness(75); // sub2->setFlipVertical(true); // sub2->setFlipHorizontal(true); // // m_glWidget->addSubview(sub2); } // Canvas Size READ_POINT("canvas-size","1000x750"); QSizeF canvasSize((qreal)point.x(),(qreal)point.y()); //canvasSize = QSizeF(2000,750); canvasSize = QSizeF(3120,1050); if(m_useGLWidget) { m_glWidget->setCanvasSize(canvasSize); } else { m_graphicsScene->setSceneRect(QRectF(QPointF(0,0),canvasSize)); } m_xfadeSpeed = READ_STRING("xfade-speed",300).toInt(); //qDebug() << "SlideShowWindow: Crossfade speed: "<<m_xfadeSpeed; // QString loadGroup = READ_STRING("load-group",""); // if(!loadGroup.isEmpty()) // { // QFile file(loadGroup); // if (!file.open(QIODevice::ReadOnly)) // { // qDebug() << "SlideShowWindow: Unable to read group file: "<<loadGroup; // } // else // { // QByteArray array = file.readAll(); // // GLSceneGroup *group = new GLSceneGroup(); // group->fromByteArray(array); // setGroup(group); // // GLScene *scene = group->at(0); // if(scene) // { // //scene->setGLWidget(this); // setScene(scene); // qDebug() << "SlideShowWindow: [DEBUG]: Loaded File: "<<loadGroup<<", GroupID: "<<group->groupId()<<", SceneID: "<< scene->sceneId(); // // if(m_outputEncoder && // !m_outputEncoder->encodingStarted()) // m_outputEncoder->startEncoder(); // // } // else // { // qDebug() << "SlideShowWindow: [DEBUG]: Loaded File: "<<loadGroup<<", GroupID: "<<group->groupId()<<" - no scenes found at index 0"; // } // } // } // else // { // QString loadGroup = READ_STRING("collection",""); // if(!loadGroup.isEmpty()) // { // QFile file(loadGroup); // if (!file.open(QIODevice::ReadOnly)) // { // qDebug() << "SlideShowWindow: Unable to read group file: "<<loadGroup; // } // else // { // QByteArray array = file.readAll(); // // GLSceneGroupCollection *collection = new GLSceneGroupCollection(); // collection->fromByteArray(array); // setGroup(collection->at(0)); // // if(m_group) // { // GLScene *scene = m_group->at(0); // if(scene) // { // //scene->setGLWidget(this); // setScene(scene); // qDebug() << "SlideShowWindow: [DEBUG]: Loaded File: "<<loadGroup<<", GroupID: "<<m_group->groupId()<<", SceneID: "<< scene->sceneId(); // // GLDrawableList list = scene->drawableList(); // foreach(GLDrawable *gld, list) // if(gld->playlist()->size() > 0) // gld->playlist()->play(); // // if(m_outputEncoder && // !m_outputEncoder->encodingStarted()) // m_outputEncoder->startEncoder(); // // } // else // { // qDebug() << "SlideShowWindow: [DEBUG]: Loaded File: "<<loadGroup<<", GroupID: "<<m_group->groupId()<<" - no scenes found at index 0"; // } // } // } // } // } QStringList argList = qApp->arguments(); if(argList.size() > 1) { QString dirName = argList.at(1); QDir dir(dirName); dir.setNameFilters(QStringList() << "*.jpg" << "*.JPG" << "*.jpeg" << "*.png" << "*.PNG"); QFileInfoList list = dir.entryInfoList(QDir::Files, QDir::Name); if(m_glWidget) m_glWidget->setFboEnabled(false); int spinSize = 28; //QStringList list = dir.entryList(); //foreach(QString file, list) foreach(QFileInfo info, list) { //QFileInfo info(QString("%1/%2").arg(dirName,file)); //if(!info.isFile()) // continue; //QString ext = info.suffix().toLower(); //if(ext != "jpg" || ext != "png" || ext != "jpeg") // continue; bool flipText = true; QString fullFile = info.absoluteFilePath(); qDebug() << "SlideShowWindow: Loading "<<fullFile;//<<" (ext:"<<ext<<")"; GLScene *scene = new GLScene(); { QString comment = ""; QString datetime = ""; try { Exiv2::Image::AutoPtr exiv = Exiv2::ImageFactory::open(fullFile.toStdString()); if(exiv.get() != 0) { exiv->readMetadata(); Exiv2::ExifData& exifData = exiv->exifData(); if (exifData.empty()) { qDebug() << fullFile << ": No Exif data found in the file"; } comment = exifData["Exif.Image.ImageDescription"].toString().c_str(); comment = GLTextDrawable::htmlToPlainText(comment); datetime = exifData["Exif.Photo.DateTimeOriginal"].toString().c_str(); if(comment.trimmed().isEmpty()) { Exiv2::IptcData& iptcData = exiv->iptcData(); comment = iptcData["Iptc.Application2.Caption"].toString().c_str(); comment = GLTextDrawable::htmlToPlainText(comment); if (exifData.empty()) { qDebug() << fullFile << ": No IPTC data found in the file"; } else { qDebug() << "SlideShowWindow: IPTC Caption:"<<comment; } } else { qDebug() << "SlideShowWindow: EXIF Caption:"<<comment; } } } catch (Exiv2::AnyError& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; //return -1; } GLImageDrawable *image = new GLImageDrawable(fullFile); if(canvasSize.width() > 1000) { image->setRect(QRectF(QPointF(0,0),QSize(1680,canvasSize.height()))); } else { image->setRect(QRectF(QPointF(0,0),canvasSize)); } //image->setCrossFadeMode(GLVideoDrawable::JustFront); scene->addDrawable(image); if(!comment.isEmpty()) { comment = comment.replace(QRegExp("^\\s*\"([^\"]+)\"\\s*-\\s*"), "<center>\"\\1\"</center><br>"); GLTextDrawable *text = new GLTextDrawable(); QString ptSize = "36"; QString html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd\">" "<html><head><meta name=\"qrichtext\" content=\"1\"/>" "<style type=\"text/css\">p, li { white-space: pre-wrap; }</style>" "</head>" "<body style=\"font-family:'Sans Serif'; font-size:" + ptSize +"pt; font-weight:600; font-style:normal;\">" "<table style=\"-qt-table-type: root; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;\">" "<tr><td style=\"border: none;\">" "<p style=\"margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">" "<span style=\"font-size:" + ptSize + "pt; font-weight:600; color:#ffffff;\">" + comment + "</span></p></td></tr></table></body></html>"; text->setText(html); //qDebug() << "File # text size:"<<size<<" @ width:"<<w<<", html:"<<html; if(canvasSize.width() > 1000) { QSize size = text->findNaturalSize(1400); QRectF targetRect = QRectF(0, 0, size.width(), size.height()); targetRect.moveCenter(QRectF(1680,0,1440,900).center()); text->setRect(targetRect); if(flipText) { text->setFlipVertical(true); text->setFlipHorizontal(true); } } else { int w = (int)canvasSize.width(); QSize size = text->findNaturalSize(w); double x = (canvasSize.width() - size.width()) / 2; double y = canvasSize.height() - size.height() - 2; text->setRect(QRectF(QPointF(x,y),size)); } text->setZIndex(5.); scene->addDrawable(text); qDebug() << "Loaded caption:"<<comment; } QFileInfo fileInfo(fullFile); QString fileName = fileInfo.baseName().toLower(); fileName = fileName.replace(QRegExp("\\d{2,6}-\\{\\d\\}"),""); fileName = fileName.replace(QRegExp("(dsc_|sdc)"), ""); if(!fileName.isEmpty()) { GLTextDrawable *text = new GLTextDrawable(); //QString html = QString("<span style='font-color:white;font-size:20px'>%1</font>").arg(fileName); QString ptSize = "24"; QString html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd\">" "<html><head><meta name=\"qrichtext\" content=\"1\"/>" "<style type=\"text/css\">p, li { white-space: pre-wrap; }</style>" "</head>" "<body style=\"font-family:'Sans Serif'; font-size:" + ptSize +"pt; font-weight:600; font-style:normal;\">" "<table style=\"-qt-table-type: root; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;\">" "<tr><td style=\"border: none;\">" "<p style=\"margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">" "<span style=\"font-size:" + ptSize + "pt; font-weight:600; color:#ffffff;\">" "Photograph # "+ fileName + "</span></p></td></tr></table></body></html>"; text->setText(html); int w = (int)canvasSize.width(); QSize size = text->findNaturalSize(w); //qDebug() << "File # text size:"<<size<<" @ width:"<<w<<", html:"<<html; if(flipText) { if(canvasSize.width() > 1000) { int spinSpace = spinSize + 10; size = text->findNaturalSize(1440); //QRectF targetRect = QRectF(0, 0, size.width(), size.height()); //targetRect.moveCenter(QRectF(1680,0,1440,900).center()); double x = 1680 + 10 + spinSpace; double y = 900 - 10 - size.height(); QRectF rect(QPointF(x,y),size); //qDebug() << "Rect: "<<rect; text->setRect(rect); text->setFlipVertical(true); text->setFlipHorizontal(true); } else { // TODO flip here too double x = canvasSize.width() - size.width() - 2; double y = 2; text->setRect(QRectF(QPointF(x,y),size)); } } else { double x = canvasSize.width() - size.width() - 2; double y = 2; text->setRect(QRectF(QPointF(x,y),size)); } text->setZIndex(5.); scene->addDrawable(text); } if(!datetime.isEmpty()) { GLTextDrawable *text = new GLTextDrawable(); //QString html = QString("<span style='font-color:white;font-size:20px'>%1</font>").arg(fileName); // 2009:10:25 12:13:34 QDateTime parsedDate = QDateTime::fromString(datetime, "yyyy:MM:dd hh:mm:ss"); QString dateString = "Photographed " + parsedDate.toString("dddd, MMMM d, yyyy"); QString ptSize = "24"; QString html = "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd\">" "<html><head><meta name=\"qrichtext\" content=\"1\"/>" "<style type=\"text/css\">p, li { white-space: pre-wrap; }</style>" "</head>" "<body style=\"font-family:'Sans Serif'; font-size:" + ptSize +"pt; font-weight:600; font-style:normal;\">" "<table style=\"-qt-table-type: root; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px;\">" "<tr><td style=\"border: none;\">" "<p style=\"margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">" "<span style=\"font-size:" + ptSize + "pt; font-weight:600; color:#ffffff;\">" + dateString + "</span></p></td></tr></table></body></html>"; text->setText(html); int w = (int)canvasSize.width(); QSize size = text->findNaturalSize(w); //qDebug() << "File # text size:"<<size<<" @ width:"<<w<<", html:"<<html; if(flipText) { if(canvasSize.width() > 1000) { //int spinSpace = spinSize + 10; size = text->findNaturalSize(1440); //QRectF targetRect = QRectF(0, 0, size.width(), size.height()); //targetRect.moveCenter(QRectF(1680,0,1440,900).center()); double x = 1680 + (1440 - size.width()) / 2; double y = 10; //900 - 10 - size.height(); QRectF rect(QPointF(x,y),size); //qDebug() << "Rect: "<<rect; text->setRect(rect); text->setFlipVertical(true); text->setFlipHorizontal(true); } else { // TODO // double x = canvasSize.width() - size.width() - 2; // double y = 2; // text->setRect(QRectF(QPointF(x,y),size)); } } else { // TODO // double x = canvasSize.width() - size.width() - 2; // double y = 2; // text->setRect(QRectF(QPointF(x,y),size)); } text->setZIndex(5.); scene->addDrawable(text); } } m_scenes << scene; }
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) */ }