diff --git a/exif-gps.cpp b/exif-gps.cpp index a76cdc2..f6f68a3 100644 --- a/exif-gps.cpp +++ b/exif-gps.cpp @@ -105,56 +105,8 @@ int main(int argc, char* argv[]) char* ReadExifDate(const char* File, int* IncludesGPS) { - // Open and read the file. - Exiv2::Image::UNIQUEPTR 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.GPSLatitude"]; - - if (GPSData.count() < 3) - { - // No valid GPS data. - *IncludesGPS = 0; - } else { - // Seems to include GPS data... - *IncludesGPS = 1; - } - - // Now return, passing a pointer to the date string. - return Copy; // It's up to the caller to free this. + // It's up to the caller to free this. + return ReadExifData(File, NULL, NULL, NULL, IncludesGPS); } char* ReadExifData(const char* File, double* Lat, double* Long, double* Elev, int* IncludesGPS) @@ -196,7 +148,7 @@ char* ReadExifData(const char* File, double* Lat, double* Long, double* Elev, in } // Copy the tag and return that. - char* Copy = strdup(Value.c_str()); + char* DateTime = strdup(Value.c_str()); // Check if we have GPS tags. *IncludesGPS = 0; @@ -213,84 +165,89 @@ char* ReadExifData(const char* File, double* Lat, double* Long, double* Elev, in // exists, but some cameras skip it anyway. } - // 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 { - // This is enough to say it includes GPS data... - *IncludesGPS = 1; - - 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; + *IncludesGPS = GPSData.count() == 3; + + // Skip Lat/Long/Elev reading if the caller doesn't need it + if (Lat) { + // 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; + + if (GPSData.count() < 3) + *Lat = nan("invalid"); + else { + // This is enough to say it includes GPS data... + *IncludesGPS = 1; + + 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; + 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 && (int) GPSData.TOINTEGER() == 1) - { - // Negate the elevation. - *Elev = -*Elev; + // 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 && (int) GPSData.TOINTEGER() == 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. + return DateTime; // It's up to the caller to free this. } // This function is for the --fix-datestamp option.