commit 091a4f7d
Add geo location and an openstreetmaps link
Changed files
| M | src/exifreader.cpp before |
| M | src/exifreader.h before |
| M | test/test_exifreader.cpp before |
diff --git a/src/exifreader.cpp b/src/exifreader.cpp
index 48ab6d6..deaf876 100644
--- a/src/exifreader.cpp
+++ b/src/exifreader.cpp
@@ -34,6 +34,20 @@ static void addField(QList<QPair<QString, QString>> &result, const char *label,
result.append({QString::fromLatin1(label), value});
}
+static double parseGpsCoordinate(const Exiv2::ExifData &exif, const std::string &key)
+{
+ try {
+ Exiv2::ExifData::const_iterator it = exif.findKey(Exiv2::ExifKey(key));
+ if (it != exif.end() && it->count() >= 3) {
+ double d = it->toRational(0).first / static_cast<double>(it->toRational(0).second);
+ double m = it->toRational(1).first / static_cast<double>(it->toRational(1).second);
+ double s = it->toRational(2).first / static_cast<double>(it->toRational(2).second);
+ return d + m / 60.0 + s / 3600.0;
+ }
+ } catch (...) {}
+ return 0.0;
+}
+
// EXIF orientation values run 1-8 and may encode mirroring. A 90-degree
// rotation maps each value to another; the tables below cover all eight so
// mirrored images stay correct. Unknown values are treated as 1 (normal).
@@ -73,7 +87,9 @@ bool ExifData::isEmpty() const
&& dateTime.isEmpty() && make.isEmpty() && model.isEmpty()
&& exposureTime.isEmpty() && fNumber.isEmpty() && iso.isEmpty()
&& focalLength.isEmpty() && flash.isEmpty()
- && filename.isEmpty() && dimensions.isEmpty() && fileSize.isEmpty();
+ && filename.isEmpty() && dimensions.isEmpty() && fileSize.isEmpty()
+ && orientation.isEmpty() && latitude.isEmpty() && longitude.isEmpty()
+ && osmLink.isEmpty();
}
QList<QPair<QString, QString>> ExifData::toList() const
@@ -92,6 +108,10 @@ QList<QPair<QString, QString>> ExifData::toList() const
addField(result, "Filename", filename);
addField(result, "Dimensions", dimensions);
addField(result, "File Size", fileSize);
+ addField(result, "Orientation", orientation);
+ addField(result, "Latitude", latitude);
+ addField(result, "Longitude", longitude);
+ addField(result, "OpenStreetMap", osmLink);
return result;
}
@@ -158,6 +178,29 @@ ExifData ExifReader::read(const QByteArray &path)
data.focalLength = findTag(exif, "Exif.Photo.FocalLength");
data.flash = findTag(exif, "Exif.Photo.Flash");
data.description = findTag(exif, "Exif.Image.ImageDescription");
+ data.orientation = findTag(exif, "Exif.Image.Orientation");
+
+ // GPS
+ QString latStr = findTag(exif, "Exif.GPSInfo.GPSLatitude");
+ QString latRef = findTag(exif, "Exif.GPSInfo.GPSLatitudeRef");
+ if (!latStr.isEmpty() && !latRef.isEmpty()) {
+ data.latitude = latStr + u" " + latRef;
+ }
+
+ QString lonStr = findTag(exif, "Exif.GPSInfo.GPSLongitude");
+ QString lonRef = findTag(exif, "Exif.GPSInfo.GPSLongitudeRef");
+ if (!lonStr.isEmpty() && !lonRef.isEmpty()) {
+ data.longitude = lonStr + u" " + lonRef;
+ }
+
+ if (!data.latitude.isEmpty() && !data.longitude.isEmpty()) {
+ double lat = parseGpsCoordinate(exif, "Exif.GPSInfo.GPSLatitude");
+ if (latRef == u"S") lat = -lat;
+ double lon = parseGpsCoordinate(exif, "Exif.GPSInfo.GPSLongitude");
+ if (lonRef == u"W") lon = -lon;
+ data.osmLink = QString::fromLatin1("https://www.openstreetmap.org/?mlat=%1&mlon=%2#map=16/%1/%2")
+ .arg(lat, 0, 'f', 6).arg(lon, 0, 'f', 6);
+ }
// IPTC Caption-Abstract
const Exiv2::IptcData &iptc = image->iptcData();
diff --git a/src/exifreader.h b/src/exifreader.h
index bdd6632..51aad51 100644
--- a/src/exifreader.h
+++ b/src/exifreader.h
@@ -19,6 +19,10 @@ struct ExifData {
QString filename;
QString dimensions;
QString fileSize;
+ QString orientation;
+ QString latitude;
+ QString longitude;
+ QString osmLink;
bool isEmpty() const;
QList<QPair<QString, QString>> toList() const;
diff --git a/test/test_exifreader.cpp b/test/test_exifreader.cpp
index a135a68..74eae7b 100644
--- a/test/test_exifreader.cpp
+++ b/test/test_exifreader.cpp
@@ -19,15 +19,31 @@ int main(int argc, char *argv[]) {
// Test ExifData::toList()
data.fileSize = "1.2 MiB";
+ data.orientation = "1 (top, left)";
+ data.latitude = "55deg 40' 32.12\" N";
+ data.longitude = "12deg 34' 11.23\" E";
+ data.osmLink = "https://www.openstreetmap.org/?mlat=55.675589&mlon=12.569786#map=16/55.675589/12.569786";
auto list = data.toList();
bool foundFilename = false;
bool foundSize = false;
+ bool foundOrientation = false;
+ bool foundLat = false;
+ bool foundLon = false;
+ bool foundOsm = false;
for (const auto &pair : list) {
if (pair.first == "Filename" && pair.second == "test.jpg") foundFilename = true;
if (pair.first == "File Size" && pair.second == "1.2 MiB") foundSize = true;
+ if (pair.first == "Orientation" && pair.second == "1 (top, left)") foundOrientation = true;
+ if (pair.first == "Latitude" && pair.second == "55deg 40' 32.12\" N") foundLat = true;
+ if (pair.first == "Longitude" && pair.second == "12deg 34' 11.23\" E") foundLon = true;
+ if (pair.first == "OpenStreetMap" && pair.second == "https://www.openstreetmap.org/?mlat=55.675589&mlon=12.569786#map=16/55.675589/12.569786") foundOsm = true;
}
assert(foundFilename);
assert(foundSize);
+ assert(foundOrientation);
+ assert(foundLat);
+ assert(foundLon);
+ assert(foundOsm);
qDebug() << "ExifData::toList() passed.";
qDebug() << "All ExifReader tests passed!";