QString MetaEngine::Private::convertCommentValue(const Exiv2::Exifdatum& exifDatum) const { try { std::string comment; std::string charset; comment = exifDatum.toString(); // libexiv2 will prepend "charset=\"SomeCharset\" " if charset is specified // Before conversion to QString, we must know the charset, so we stay with std::string for a while if (comment.length() > 8 && comment.substr(0, 8) == "charset=") { // the prepended charset specification is followed by a blank std::string::size_type pos = comment.find_first_of(' '); if (pos != std::string::npos) { // extract string between the = and the blank charset = comment.substr(8, pos-8); // get the rest of the string after the charset specification comment = comment.substr(pos+1); } } if (charset == "\"Unicode\"") { return QString::fromUtf8(comment.data()); } else if (charset == "\"Jis\"") { QTextCodec* const codec = QTextCodec::codecForName("JIS7"); return codec->toUnicode(comment.c_str()); } else if (charset == "\"Ascii\"") { return QString::fromLatin1(comment.c_str()); } else { return detectEncodingAndDecode(comment); } } catch( Exiv2::Error& e ) { printExiv2ExceptionError(QString::fromLatin1("Cannot convert Comment using Exiv2 "), e); } catch(...) { qCCritical(DIGIKAM_METAENGINE_LOG) << "Default exception from Exiv2"; } return QString(); }
char* ReadExifData(const char* File, double* Lat, double* Long, double* Elev, int* IncludesGPS) { // This function varies in that it reads // much more data than the last, specifically // for display purposes. For the GUI version. // Open and read the file. Exiv2::Image::AutoPtr Image; try { Image = Exiv2::ImageFactory::open(File); } catch (Exiv2::Error e) { DEBUGLOG("Failed to open file %s.\n", File); return NULL; } Image->readMetadata(); if (Image.get() == NULL) { DEBUGLOG("Failed to read file %s %s.\n", File, Exiv2::strError().c_str()); return NULL; } Exiv2::ExifData &ExifRead = Image->exifData(); // Read the tag out. Exiv2::Exifdatum& Tag = ExifRead["Exif.Photo.DateTimeOriginal"]; // Check that the tag is not blank. std::string Value = Tag.toString(); if (Value.length() == 0) { // No date/time stamp. // Not good. // Just return - above us will handle it. return NULL; } // Copy the tag and return that. char* Copy = strdup(Value.c_str()); // Check if we have GPS tags. Exiv2::Exifdatum GPSData = ExifRead["Exif.GPSInfo.GPSVersionID"]; Value = GPSData.toString(); if (Value.length() == 0) { // No GPS data. // Just return. *IncludesGPS = 0; } else { // Seems to include GPS data... *IncludesGPS = 1; // Read it out and send it up! // What we are trying to do here is convert the // three rationals: // dd/v mm/v ss/v // To a decimal // dd.dddddd... // dd/v is easy: result = dd/v. // mm/v is harder: // mm // -- / 60 = result. // v // ss/v is sorta easy. // ss // -- / 3600 = result // v // Each part is added to the final number. Exiv2::URational RatNum; GPSData = ExifRead["Exif.GPSInfo.GPSLatitude"]; if (GPSData.count() < 3) *Lat = nan("invalid"); else { RatNum = GPSData.toRational(0); *Lat = (double)RatNum.first / (double)RatNum.second; RatNum = GPSData.toRational(1); *Lat = *Lat + (((double)RatNum.first / (double)RatNum.second) / 60); RatNum = GPSData.toRational(2); *Lat = *Lat + (((double)RatNum.first / (double)RatNum.second) / 3600); GPSData = ExifRead["Exif.GPSInfo.GPSLatitudeRef"]; if (strcmp(GPSData.toString().c_str(), "S") == 0) { // Negate the value - Western Hemisphere. *Lat = -*Lat; } } GPSData = ExifRead["Exif.GPSInfo.GPSLongitude"]; if (GPSData.count() < 3) *Long = nan("invalid"); else { RatNum = GPSData.toRational(0); *Long = (double)RatNum.first / (double)RatNum.second; RatNum = GPSData.toRational(1); *Long = *Long + (((double)RatNum.first / (double)RatNum.second) / 60); RatNum = GPSData.toRational(2); *Long = *Long + (((double)RatNum.first / (double)RatNum.second) / 3600); GPSData = ExifRead["Exif.GPSInfo.GPSLongitudeRef"]; if (strcmp(GPSData.toString().c_str(), "W") == 0) { // Negate the value - Western Hemisphere. *Long = -*Long; } } // Finally, read elevation out. This one is simple. GPSData = ExifRead["Exif.GPSInfo.GPSAltitude"]; if (GPSData.count() < 1) *Elev = nan("invalid"); else { RatNum = GPSData.toRational(0); *Elev = (double)RatNum.first / (double)RatNum.second; } // Is the altitude below sea level? If so, negate the value. GPSData = ExifRead["Exif.GPSInfo.GPSAltitudeRef"]; if (GPSData.count() >= 1 && GPSData.toLong() == 1) { // Negate the elevation. *Elev = -*Elev; } } // Now return, passing a pointer to the date string. return Copy; // It's up to the caller to free this. }
//! Returns true if IFD id matches. bool operator()(const Exiv2::Exifdatum& md) const { return ifdId_ == md.ifdId(); }