QString exifDataToString(Exiv2::ExifData exifData) { if (exifData.empty()) { return QString(QObject::tr("No EXIF found")); } try { Exiv2::ExifData::const_iterator end = exifData.end(); QString tmpExif, final; for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { const char* tn = i->typeName(); /*std::string str = i->key() << " "; << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << (tn ? tn : "Unknown") << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n";*/ tmpExif = "<span style='color:#1cb495;'>" + QString::fromStdString(i->key()).split(".").at(2) + "</span> " + //QString::number(i->tag()) + "\t" + //(tn ? tn : "Unknown") + "\t" + //QString::number(i->count()) + "\t" + QString::fromStdString(i->value().toString()) + "<br />"; final.append(tmpExif); } return final; } catch(Exiv2::Error& e) {
bool NegativeProcessor::getRawExifTag(const char* exifTagName, dng_string* value) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if (it == m_RawExif.end()) return false; value->Set_ASCII((it->print(&m_RawExif)).c_str()); value->TrimLeadingBlanks(); value->TrimTrailingBlanks(); return true; }
bool NegativeProcessor::getRawExifTag(const char* exifTagName, dng_date_time_info* value) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if (it == m_RawExif.end()) return false; dng_date_time dt; dt.Parse((it->print(&m_RawExif)).c_str()); value->SetDateTime(dt); return true; }
Profile::Ptr Profile::loadFromExiv2Image(const Exiv2::Image* image) { Profile::Ptr ptr; cmsHPROFILE hProfile = 0; const Exiv2::ExifData& exifData = image->exifData(); Exiv2::ExifKey key("Exif.Image.InterColorProfile"); Exiv2::ExifData::const_iterator it = exifData.findKey(key); if (it == exifData.end()) { LOG("No profile found"); return ptr; } int size = it->size(); LOG("size:" << size); QByteArray data; data.resize(size); it->copy(reinterpret_cast<Exiv2::byte*>(data.data()), Exiv2::invalidByteOrder); hProfile = cmsOpenProfileFromMem(data, size); if (hProfile) { ptr = new Profile(hProfile); } return ptr; }
bool NegativeProcessor::getRawExifTag(const char* exifTagName, int32 component, uint32* value) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if ((it == m_RawExif.end()) || (it->count() < (component + 1))) return false; *value = static_cast<uint32>(it->toLong(component)); return true; }
int RafImage::pixelWidth() const { Exiv2::ExifData::const_iterator widthIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelXDimension")); if (widthIter != exifData_.end() && widthIter->count() > 0) { return widthIter->toLong(); } return 0; }
int RafImage::pixelHeight() const { Exiv2::ExifData::const_iterator heightIter = exifData_.findKey(Exiv2::ExifKey("Exif.Photo.PixelYDimension")); if (heightIter != exifData_.end() && heightIter->count() > 0) { return heightIter->toLong(); } return 0; }
const double getExiv2ValueDouble(Exiv2::ExifData& exifData, Exiv2::ExifData::const_iterator it) { if(it!=exifData.end() && it->count()) { return it->toFloat(); } return 0; };
const std::string getExiv2ValueString(Exiv2::ExifData& exifData,Exiv2::ExifData::const_iterator it) { if(it!=exifData.end() && it->count()) { return hugin_utils::StrTrim(it->toString()); }; return std::string(""); };
const long getExiv2ValueLong(Exiv2::ExifData& exifData, Exiv2::ExifData::const_iterator it) { if(it!=exifData.end() && it->count()) { return it->toLong(); } return 0; };
bool NegativeProcessor::getRawExifTag(const char* exifTagName, int32 component, dng_urational* rational) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if ((it == m_RawExif.end()) || (it->count() < (component + 1))) return false; Exiv2::URational exiv2Rational = (*it).toRational(component); *rational = dng_urational(exiv2Rational.first, exiv2Rational.second); return true; }
int NegativeProcessor::getRawExifTag(const char* exifTagName, int16* valueArray, int32 maxFill) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if (it == m_RawExif.end()) return 0; int lengthToFill = std::min(maxFill, static_cast<int32>(it->count())); for (int i = 0; i < lengthToFill; i++) valueArray[i] = static_cast<int16>(it->toLong(i)); return lengthToFill; }
int NegativeProcessor::getRawExifTag(const char* exifTagName, dng_urational* valueArray, int32 maxFill) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if (it == m_RawExif.end()) return 0; int lengthToFill = std::min(maxFill, static_cast<int32>(it->count())); for (int i = 0; i < lengthToFill; i++) { Exiv2::URational exiv2Rational = (*it).toRational(i); valueArray[i] = dng_urational(exiv2Rational.first, exiv2Rational.second); } return lengthToFill; }
bool NegativeProcessor::getInterpretedRawExifTag(const char* exifTagName, int32 component, uint32* value) { Exiv2::ExifData::const_iterator it = m_RawExif.findKey(Exiv2::ExifKey(exifTagName)); if (it == m_RawExif.end()) return false; std::stringstream interpretedValue; it->write(interpretedValue, &m_RawExif); uint32 tmp; for (int i = 0; (i <= component) && !interpretedValue.fail(); i++) interpretedValue >> tmp; if (interpretedValue.fail()) return false; *value = tmp; return true; }
// uses the exiv2 class to readout the exifdata from images int ExifScout::showExifData(std::string a){ try { Ui_MainWindow::textEdit->clear(); std::cerr << "ImageFactory::open "; Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(a); std::cerr << "DONE\n"; assert(image.get() != 0); std::cerr << "image->readMetadata() "; image->readMetadata(); std::cerr << "DONE\n"; std::cerr << "Exiv2::ExifData& exifData = image->exifData() "; Exiv2::ExifData exifData = image->exifData(); std::cerr << "DONE\n"; cout << "Number of found exiv2 data: " << exifData.count() << endl; if (exifData.empty()) { Ui_MainWindow::textEdit->setPlainText("No Exif data found in file"); return 1; } Exiv2::ExifData::const_iterator end = exifData.end(); std::cerr << "Generate the exif-output "; QString output; for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { std::string tagname = i->tagName(); if(tagname != std::string("MakerNote") and tagname.substr(0,2) != "0x"){ // Print out the exif-data in the QtextEdit Field std::ostringstream oss; oss << i->tagName() << ":\n " << i->value() << "\n"; output = output+(QString)oss.str().c_str(); } } std::cerr << "Done\n"; Ui_MainWindow::textEdit->setPlainText(output); return 0; } //catch (std::exception& e) { //catch (Exiv2::AnyError& e) { catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e.what() << "'\n"; return -1; } }
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 print(const std::string& file) { Exiv2::ExifData ed; int rc = ed.read(file); if (rc) { std::string error = Exiv2::ExifData::strError(rc, file); throw Exiv2::Error(error); } Exiv2::ExifData::const_iterator end = ed.end(); for (Exiv2::ExifData::const_iterator i = ed.begin(); i != end; ++i) { std::cout << std::setw(45) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(12) << std::setfill(' ') << std::left << i->ifdName() << " " << std::setw(9) << std::setfill(' ') << std::left << i->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; } }
void print(const std::string& file) { Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(file); assert(image.get() != 0); image->readMetadata(); Exiv2::ExifData &ed = image->exifData(); Exiv2::ExifData::const_iterator end = ed.end(); for (Exiv2::ExifData::const_iterator i = ed.begin(); i != end; ++i) { std::cout << std::setw(45) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(12) << std::setfill(' ') << std::left << i->ifdName() << " " << std::setw(9) << std::setfill(' ') << std::left << i->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; } }
// This is weird because iptc and exif have not been "unified". Once // they are unified, this DLL should not have to know // about either... just generic images, keys, values, etc. // // buffsize should be the total size of *buff (including space for null) // Note that if there is more than one entry (for some IPTC datasets) this // returns the first one found. Currently no way to get the others. // Returns 0 on success EXIVSIMPLE_API int ReadMeta(HIMAGE img, const char *key, char *buff, int buffsize) { assert(img && key && buff); if (img==0 || key==0 || buff==0 || buffsize==0) return -1; ImageWrapper *imgWrap = (ImageWrapper*)img; int rc = 2; Exiv2::IptcData &iptcData = imgWrap->image->iptcData(); Exiv2::ExifData &exifData = imgWrap->image->exifData(); try { // First try iptc Exiv2::IptcKey iptcKey(key); rc = 1; Exiv2::IptcData::const_iterator iter = iptcData.findKey(iptcKey); if (iter != iptcData.end()) { strncpy(buff, iter->value().toString().c_str(), buffsize); buff[buffsize-1] = 0; rc = 0; } } catch(const Exiv2::AnyError&) { } if (rc) { // No iptc value, so try exif try { Exiv2::ExifKey exifKey(key); rc = 1; Exiv2::ExifData::const_iterator iter = exifData.findKey(exifKey); if (iter != exifData.end()) { strncpy(buff, iter->value().toString().c_str(), buffsize); buff[buffsize-1] = 0; rc = 0; } } catch(const Exiv2::AnyError&) { } } return rc; }
// tries to find a specified exif tag in a specified file QString ExifScout::getExifData(QString fname, QString etag){ std::string filename = fname.toAscii().data(); std::string exiftag = etag.toAscii().data(); Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(filename); assert(image.get() != 0); image->readMetadata(); Exiv2::ExifData exifData = image->exifData(); if (!exifData.empty()) { Exiv2::ExifData::const_iterator end = exifData.end(); QString output; for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { if(i->tagName()==exiftag){ std::ostringstream oss; oss << i->value(); return (QString)oss.str().c_str(); } } } return NULL; }
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]); if (image.get() == 0) { std::string error(argv[1]); error += " : Could not read file or unknown image type"; throw Exiv2::Error(error); } // Load existing metadata int rc = image->readMetadata(); if (rc) { std::string error = Exiv2::Image::strError(rc, argv[1]); throw Exiv2::Error(error); } Exiv2::ExifData &exifData = image->exifData(); Exiv2::ExifData::const_iterator end = exifData.end(); for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { std::cout << std::setw(53) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::dec << i->value() << "\n"; } return rc; } catch (Exiv2::Error& e) { std::cout << "Caught Exiv2 exception '" << e << "'\n"; return -1; }
bool ExtendedPhoto::findExifKey(const std::string& key, String& value) const { const Exiv2::ExifData& exifData = pImage->exifData(); try { Exiv2::ExifKey exifKey(key); Exiv2::ExifData::const_iterator citer = exifData.findKey(exifKey); if (citer != exifData.end()) { value = citer->value().toString(); value.trim(); return true; } return false; } catch (...) { return false; } }
EXIVSIMPLE_API int EnumMeta(HIMAGE img, METAENUMPROC proc, void *user) { assert(img && proc); if (img==0 || proc==0) return -1; ImageWrapper *imgWrap = (ImageWrapper*)img; bool more = true; Exiv2::IptcData &iptcData = imgWrap->image->iptcData(); Exiv2::ExifData &exifData = imgWrap->image->exifData(); Exiv2::IptcData::const_iterator iend = iptcData.end(); for (Exiv2::IptcData::const_iterator i = iptcData.begin(); i != iend && more; ++i) { more = proc(i->key().c_str(), i->value().toString().c_str(), user); } Exiv2::ExifData::const_iterator eend = exifData.end(); for (Exiv2::ExifData::const_iterator e = exifData.begin(); e != eend && more; ++e) { more = proc(e->key().c_str(), e->value().toString().c_str(), user); } return 0; }
void ImageResolution::readexiv(char const *fn) { Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(fn); if (!image.get()) return; image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (exifData.empty()) return; Exiv2::ExifData::const_iterator end = exifData.end(); bool havex = false; bool havey = false; bool haveunit = false; int unit; for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { if (ok_) break; if (i->tag()==0x011a) { // X Resolution x_ = i->toFloat(); havex = true; } else if (i->tag()==0x011b) { // Y Resolution y_ = i->toFloat(); havey = true; } else if (i->tag()==0x0128) { unit = i->toLong(); } ok_ = havex && havey && haveunit; } if (haveunit) { if (unit==3) { x_ *= 2.54; y_ *= 2.54; } } ok_ = havex && havey; }
void exiv2_dump_tags(const ExifData& exif) { cout << "exiv2_dump_tags: " << endl; Exiv2::ExifData::const_iterator end = exif.end(); for (Exiv2::ExifData::const_iterator i = exif.begin(); i != end; ++i) { std::cout << std::setw(44) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << i->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; } }
void print(const ExifData& exifData) { if (exifData.empty()) { std::string error("No Exif data found in the file"); throw Exiv2::Error(1, error); } Exiv2::ExifData::const_iterator end = exifData.end(); for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != end; ++i) { std::cout << std::setw(44) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << i->typeName() << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; } }
void Tag_Handler::parseTag() { if(!gps_from_filename) gps_found = false; Exiv2::ExifData::const_iterator end = exif_data->end(); for(Exiv2::ExifData::const_iterator i = exif_data->begin(); i != end; ++i) { if(0)//(dumpAllExif) { const char* tn = i->typeName(); std::cout << std::setw(44) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << (tn ? tn : "Unknown") << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; } if(i->key() == "Exif.GPSInfo.GPSLatitude" && !gps_from_filename) { gps.lat_ratio = QString::fromStdString(i->value().toString()); convert_degMinSec(gps.lat_ratio, gps.lat_coord); gps.lat_coord.dec_form = getDecForm(gps.lat_coord, gps.lat_coord.ref); gps_found = true; } else if(i->key() == "Exif.GPSInfo.GPSLongitude" && !gps_from_filename) { gps.long_ratio = QString::fromStdString(i->value().toString()); convert_degMinSec(gps.long_ratio, gps.long_coord); gps.long_coord.dec_form = getDecForm(gps.long_coord, gps.long_coord.ref); gps_found = true; } else if(i->key() == "Exif.GPSInfo.GPSLatitudeRef" && !gps_from_filename) { gps.lat_coord.ref = QString::fromStdString(i->value().toString()); } else if(i->key() == "Exif.GPSInfo.GPSLongitudeRef" && !gps_from_filename) { gps.long_coord.ref = QString::fromStdString(i->value().toString()); } else if(i->key() == "Exif.Photo.UserComment") { const char* tn = i->typeName(); std::cout << std::setw(44) << std::setfill(' ') << std::left << i->key() << " " << "0x" << std::setw(4) << std::setfill('0') << std::right << std::hex << i->tag() << " " << std::setw(9) << std::setfill(' ') << std::left << (tn ? tn : "Unknown") << " " << std::dec << std::setw(3) << std::setfill(' ') << std::right << i->count() << " " << std::dec << i->value() << "\n"; //need to reset user comment if hasn't been set before if(i->count() == 264) { (*exif_data)["Exif.Photo.UserComment"] = ""; image->writeMetadata(); } } } if(!gps_found) { clearGPSdata(gps); } }
JSONNODE *ImgTagJson::genLitExif(const Exiv2::Image::AutoPtr & image) { //const Exiv2::ExifData &data = image->exifData(); Exiv2::ExifData &data = image->exifData(); data.sortByKey(); if (data.empty()) return NULL; Exiv2::ExifData::const_iterator end = data.end(); JMAP *grpmap = new JMAP(); JSONNODE *tree = json_new(JSON_NODE); json_set_name(tree, "exif"); for (Exiv2::ExifData::const_iterator i = data.begin(); i != end; i++) { JSONNODE *grp; if (grpmap->find(i->groupName()) == grpmap->end()) { grp = json_new(JSON_NODE); json_set_name(grp, i->groupName().c_str()); grpmap->insert(JMAP::value_type(i->groupName(), grp)); } else grp = (grpmap->find(i->groupName()))->second; Exiv2::ExifData::const_iterator nxt = i; nxt++; if ((nxt != data.end()) && (i->key() == nxt->key())) { //cout << "Array Elem! " << i->key() << endl; JSONNODE *arr = json_new(JSON_ARRAY); json_set_name(arr, i->tagName().c_str()); json_push_back(arr, json_new_a((i->tagName()).c_str(), (i->print()).c_str())); while ((nxt != data.end()) && (nxt->key() == i->key())) { json_push_back(arr, json_new_a((nxt->tagName()).c_str(), (nxt->print()).c_str())); nxt++; } json_push_back(grp, arr); if (nxt == data.end()) break; nxt--; i = nxt; } else { json_push_back(grp, json_new_a((i->tagName()).c_str(), (i->print()).c_str())); } } JMAP::iterator it; for(it = grpmap->begin(); it != grpmap->end(); it++) { json_push_back(tree, it->second); grpmap->erase(it); } //cout << it->first << endl; delete grpmap; //cout << json_write_formatted(tree) << endl; return tree; }
/** \fn ImageUtils::GetAllExifValues(const QString &) * \brief Reads and returns all non empty tags from the given file * \param fileName The filename that holds the exif data * \return The list of exif tag names and values */ QList<QStringList> ImageUtils::GetAllExifValues(const QString &fileName) { // default value, an empty list means no // exif tags were found or an error occured QList<QStringList> valueList; try { Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(fileName.toLocal8Bit().constData()); if (image.get()) { image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (!exifData.empty()) { LOG(VB_GENERAL, LOG_DEBUG, QString("Found %1 tag(s) for file %2") .arg(exifData.count()) .arg(fileName)); Exiv2::ExifData::const_iterator end = exifData.end(); Exiv2::ExifData::const_iterator i = exifData.begin(); for (; i != end; ++i) { QString value = QString::fromStdString(i->value().toString()); // Do not add empty tags to the list if (!value.isEmpty()) { QStringList values; // These three are the same as i->key() values.append(QString::fromStdString(i->familyName())); values.append(QString::fromStdString(i->groupName())); values.append(QString::fromStdString(i->tagName())); values.append(QString::fromStdString(i->key())); values.append(QString::fromStdString(i->tagLabel())); values.append(QString::fromStdString(i->value().toString())); // Add the exif information to the list valueList.append(values); } } } else { LOG(VB_GENERAL, LOG_ERR, QString("Exiv2 error: No header, file %1") .arg(fileName)); } } else { LOG(VB_GENERAL, LOG_ERR, QString("Exiv2 error: Could not open file, file %1") .arg(fileName)); } } catch (Exiv2::Error& e) { LOG(VB_GENERAL, LOG_ERR, QString("Exiv2 exception %1, file %2") .arg(e.what()).arg(fileName)); } return valueList; }
void scan_exiv2(const class scanner_params &sp,const recursion_control_block &rcb) { assert(sp.sp_version==scanner_params::CURRENT_SP_VERSION); if(sp.phase==scanner_params::PHASE_STARTUP){ assert(sp.info->si_version==scanner_info::CURRENT_SI_VERSION); sp.info->name = "exiv2"; sp.info->author = "Simson L. Garfinkel"; sp.info->description = "Searches for EXIF information using exiv2"; sp.info->scanner_version= "1.0"; sp.info->feature_names.insert("exif"); sp.info->feature_names.insert("gps"); sp.info->flags = scanner_info::SCANNER_DISABLED; // disabled because we have be_exif return; } if(sp.phase==scanner_params::PHASE_SHUTDOWN) return; if(sp.phase==scanner_params::PHASE_SCAN){ const sbuf_t &sbuf = sp.sbuf; feature_recorder *exif_recorder = sp.fs.get_name("exif"); feature_recorder *gps_recorder = sp.fs.get_name("gps"); #ifdef HAVE_EXIV2__LOGMSG__SETLEVEL /* New form to suppress error messages on exiv2 */ Exiv2::LogMsg::setLevel(Exiv2::LogMsg::mute); #endif size_t pos_max = 1; // by default, just scan 1 byte if(sbuf.bufsize > min_exif_size){ pos_max = sbuf.bufsize - min_exif_size; // we can scan more! } /* Loop through all possible locations in the buffer */ for(size_t pos=0;pos<pos_max;pos++){ size_t count = exif_gulp_size; count = min(count,sbuf.bufsize-pos); //size_t count = sbuf.bufsize-pos; // use all to end /* Explore the beginning of each 512-byte block as well as the starting location * of any JPEG on any boundary. This will cause processing of any multimedia file * that Exiv2 recognizes (for which I do not know all the headers. */ if(pos%512==0 || jpeg_start(sbuf+pos)){ try { Exiv2::Image::AutoPtr image = Exiv2::ImageFactory::open(sbuf.buf+pos,count); if(image->good()){ image->readMetadata(); Exiv2::ExifData &exifData = image->exifData(); if (exifData.empty()) continue; /* * Create the MD5 of the first 4K to use as a unique identifier. */ sbuf_t tohash(sbuf,0,4096); string md5_hex = exif_recorder->fs.hasher.func(tohash.buf,tohash.bufsize); char xmlbuf[1024]; snprintf(xmlbuf,sizeof(xmlbuf), "<exiv2><width>%d</width><height>%d</height>", image->pixelWidth(),image->pixelHeight()); /* Scan through the fields reported by exiv2. * Create XML for each and extract GPS information if present. */ string photo_time; // use this when gps_time is not available string gps_time; string gps_date; string gps_lat_ref; string gps_lat; string gps_lon_ref; string gps_lon; string gps_ele; string gps_speed; string gps_course; bool has_gps = false; bool has_gps_date = false; string xml = xmlbuf; for (Exiv2::ExifData::const_iterator i = exifData.begin(); i != exifData.end(); ++i) { if(i->count()>1000) continue; // ignore long ones string key = string(i->key()); xml.append("<"+key+">"+dfxml_writer::xmlescape(i->value().toString())+"</"+key+">"); // use Date from Photo unless date from GPS is available if(key=="Exif.Photo.DateTimeOriginal"){ photo_time = i->value().toString(); /* change "2011/06/25 12:20:11" to "2011-06-25 12:20:11" */ std::transform(photo_time.begin(),photo_time.end(),photo_time.begin(),slash_to_dash); /* change "2011:06:25 12:20:11" to "2011-06-25 12:20:11" */ if (photo_time[4] == ':') { photo_time[4] = '-'; } if (photo_time[7] == ':') { photo_time[7] = '-'; } /* Change "2011-06-25 12:20:11" to "2011-06-25T12:20:11" */ size_t first_space = photo_time.find(' '); if(first_space!=string::npos) { photo_time.replace(first_space,1,"T"); } } else if(key=="Exif.GPSInfo.GPSTimeStamp") { has_gps = true; has_gps_date = true; gps_time = i->value().toString(); // reformat timestamp to standard ISO8601 // change "12 20 11" to "12:20:11" if (gps_time.length() == 8) { if (gps_time[4] == ' ') { gps_time[4] = ':'; } if (gps_time[7] == ' ') { gps_time[7] = ':'; } } } else if(key=="Exif.GPSInfo.GPSDateStamp") { has_gps = true; has_gps_date = true; gps_date = i->value().toString(); // reformat timestamp to standard ISO8601 // change "2011:06:25" to "2011-06-25" if (gps_date.length() == 10) { if (gps_date[4] == ':') { gps_date[4] = '-'; } if (gps_date[7] == ':') { gps_date[7] = '-'; } } } else if(key=="Exif.GPSInfo.GPSLongitudeRef"){ has_gps = true; gps_lon_ref = fix_gps_ref(i->value().toString()); } else if(key=="Exif.GPSInfo.GPSLongitude"){ has_gps = true; gps_lon = fix_gps(i->value().toString()); } else if(key=="Exif.GPSInfo.GPSLatitudeRef"){ has_gps = true; gps_lat_ref = fix_gps_ref(i->value().toString()); } else if(key=="Exif.GPSInfo.GPSLatitude"){ has_gps = true; gps_lat = fix_gps(i->value().toString()); } else if(key=="Exif.GPSInfo.GPSAltitude"){ has_gps = true; gps_ele = dtos(rational(i->value().toString())); } else if(key=="Exif.GPSInfo.GPSSpeed"){ has_gps = true; gps_speed = dtos(rational(i->value().toString())); } else if(key=="Exif.GPSInfo.GPSTrack"){ has_gps = true; gps_course = i->value().toString(); } } xml.append("</exiv2>"); // record EXIF exif_recorder->write(sp.sbuf.pos0+pos,md5_hex,xml); // record GPS if (has_gps) { if (has_gps_date) { // record the GPS entry using the GPS date gps_recorder->write(sp.sbuf.pos0+pos,md5_hex, gps_date+"T"+gps_time+","+gps_lat_ref+gps_lat+"," +gps_lon_ref+gps_lon+"," +gps_ele+","+gps_speed+","+gps_course); } else { // record the GPS entry using the date obtained from Photo gps_recorder->write(sp.sbuf.pos0+pos,md5_hex, photo_time+","+gps_lat_ref+gps_lat+"," +gps_lon_ref+gps_lon+"," +gps_ele+","+gps_speed+","+gps_course); } } } } catch (Exiv2::AnyError &e) { } catch (std::exception &e) { } } } } }