Skip to content

Commit

Permalink
Define ReadExifDate in terms of ReadExifData
Browse files Browse the repository at this point in the history
This reduces code duplication.
  • Loading branch information
dfandrich committed Dec 8, 2024
1 parent bd0e3de commit 052cb64
Showing 1 changed file with 77 additions and 120 deletions.
197 changes: 77 additions & 120 deletions exif-gps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand All @@ -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.
Expand Down

0 comments on commit 052cb64

Please sign in to comment.