1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-26 04:00:49 +01:00

Some more exif parser improvements

This commit is contained in:
Martin Tůma 2019-03-14 18:52:15 +01:00
parent cb9606e057
commit 8a990d1b94
3 changed files with 66 additions and 49 deletions

View File

@ -18,13 +18,13 @@ QString WaypointItem::toolTip(Units units, CoordinatesFormat format)
tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name()); tt.insert(qApp->translate("WaypointItem", "Name"), _waypoint.name());
tt.insert(qApp->translate("WaypointItem", "Coordinates"), tt.insert(qApp->translate("WaypointItem", "Coordinates"),
Format::coordinates(_waypoint.coordinates(), format)); Format::coordinates(_waypoint.coordinates(), format));
if (!std::isnan(_waypoint.elevation())) if (_waypoint.hasElevation())
tt.insert(qApp->translate("WaypointItem", "Elevation"), tt.insert(qApp->translate("WaypointItem", "Elevation"),
Format::elevation(_waypoint.elevation(), units)); Format::elevation(_waypoint.elevation(), units));
if (!_waypoint.timestamp().isNull()) if (_waypoint.timestamp().isValid())
tt.insert(qApp->translate("WaypointItem", "Date"), tt.insert(qApp->translate("WaypointItem", "Date"),
_waypoint.timestamp().toString(Qt::SystemLocaleShortDate)); _waypoint.timestamp().toString(Qt::SystemLocaleShortDate));
if (!_waypoint.description().isNull()) if (!_waypoint.description().isEmpty())
tt.insert(qApp->translate("WaypointItem", "Description"), tt.insert(qApp->translate("WaypointItem", "Description"),
_waypoint.description()); _waypoint.description());
tt.setImage(_waypoint.image()); tt.setImage(_waypoint.image());

View File

@ -4,7 +4,12 @@
#include "exifparser.h" #include "exifparser.h"
#define SOI_MARKER 0xFFD8
#define APP1_MARKER 0xFFE1
#define GPSIFDTag 34853 #define GPSIFDTag 34853
#define ImageDescription 270
#define GPSLatitudeRef 1 #define GPSLatitudeRef 1
#define GPSLatitude 2 #define GPSLatitude 2
#define GPSLongitudeRef 3 #define GPSLongitudeRef 3
@ -14,6 +19,25 @@
#define GPSTimeStamp 7 #define GPSTimeStamp 7
#define GPSDateStamp 29 #define GPSDateStamp 29
QString EXIFParser::text(TIFFFile &file, const IFDEntry &e) const
{
if (e.type != TIFF_ASCII || !e.count)
return QString();
if (e.count <= sizeof(e.offset))
return QString(QByteArray((const char *)&e.offset, sizeof(e.offset)));
if (!file.seek(e.offset))
return QString();
QByteArray str(file.read(e.count));
if (str.size() < (int)e.count)
return QString();
return QString(str);
}
QTime EXIFParser::time(TIFFFile &file, const IFDEntry &ts) const QTime EXIFParser::time(TIFFFile &file, const IFDEntry &ts) const
{ {
if (!(ts.type == TIFF_RATIONAL && ts.count == 3)) if (!(ts.type == TIFF_RATIONAL && ts.count == 3))
@ -36,21 +60,6 @@ QTime EXIFParser::time(TIFFFile &file, const IFDEntry &ts) const
return QTime((int)hms[0], (int)hms[1], (int)hms[2]); return QTime((int)hms[0], (int)hms[1], (int)hms[2]);
} }
QDate EXIFParser::date(TIFFFile &file, const IFDEntry &ds) const
{
if (!(ds.type == TIFF_ASCII && ds.count == 11))
return QDate();
if (!file.seek(ds.offset))
return QDate();
QByteArray text(file.read(11));
if (text.size() < 11)
return QDate();
return QDate::fromString(text, "yyyy:MM:dd");
}
double EXIFParser::altitude(TIFFFile &file, const IFDEntry &alt, double EXIFParser::altitude(TIFFFile &file, const IFDEntry &alt,
const IFDEntry &altRef) const const IFDEntry &altRef) const
{ {
@ -157,34 +166,35 @@ bool EXIFParser::parseTIFF(QFile *file, QVector<Waypoint> &waypoints)
return false; return false;
} }
QSet<quint16> exifTags; QSet<quint16> IFD0Tags;
exifTags << GPSIFDTag; IFD0Tags << GPSIFDTag << ImageDescription;
QMap<quint16, IFDEntry> exif; QMap<quint16, IFDEntry> IFD0;
for (quint32 ifd = tiff.ifd(); ifd; ) { for (quint32 ifd = tiff.ifd(); ifd; ) {
if (!readIFD(tiff, ifd, exifTags, exif) || !tiff.readValue(ifd)) { if (!readIFD(tiff, ifd, IFD0Tags, IFD0) || !tiff.readValue(ifd)) {
_errorString = "Invalid EXIF IFD"; _errorString = "Invalid IFD0";
return false; return false;
} }
} }
if (!exif.contains(GPSIFDTag)) { if (!IFD0.contains(GPSIFDTag)) {
_errorString = "GPS IFD not found"; _errorString = "GPS IFD not found";
return false; return false;
} }
QSet<quint16> gpsTags; QSet<quint16> GPSIFDTags;
gpsTags << GPSLatitude << GPSLongitude << GPSLatitudeRef << GPSLongitudeRef GPSIFDTags << GPSLatitude << GPSLongitude << GPSLatitudeRef
<< GPSAltitude << GPSAltitudeRef << GPSDateStamp << GPSTimeStamp; << GPSLongitudeRef << GPSAltitude << GPSAltitudeRef << GPSDateStamp
QMap<quint16, IFDEntry> gps; << GPSTimeStamp;
for (quint32 ifd = exif.value(GPSIFDTag).offset; ifd; ) { QMap<quint16, IFDEntry> GPSIFD;
if (!readIFD(tiff, ifd, gpsTags, gps) || !tiff.readValue(ifd)) { for (quint32 ifd = IFD0.value(GPSIFDTag).offset; ifd; ) {
if (!readIFD(tiff, ifd, GPSIFDTags, GPSIFD) || !tiff.readValue(ifd)) {
_errorString = "Invalid GPS IFD"; _errorString = "Invalid GPS IFD";
return false; return false;
} }
} }
Coordinates c(coordinates(tiff, gps.value(GPSLongitude), Coordinates c(coordinates(tiff, GPSIFD.value(GPSLongitude),
gps.value(GPSLongitudeRef), gps.value(GPSLatitude), GPSIFD.value(GPSLongitudeRef), GPSIFD.value(GPSLatitude),
gps.value(GPSLatitudeRef))); GPSIFD.value(GPSLatitudeRef)));
if (!c.isValid()) { if (!c.isValid()) {
_errorString = "Invalid/missing GPS coordinates"; _errorString = "Invalid/missing GPS coordinates";
return false; return false;
@ -193,10 +203,12 @@ bool EXIFParser::parseTIFF(QFile *file, QVector<Waypoint> &waypoints)
Waypoint wp(c); Waypoint wp(c);
wp.setName(QFileInfo(file->fileName()).baseName()); wp.setName(QFileInfo(file->fileName()).baseName());
wp.setImage(file->fileName()); wp.setImage(file->fileName());
wp.setElevation(altitude(tiff, gps.value(GPSAltitude), wp.setElevation(altitude(tiff, GPSIFD.value(GPSAltitude),
gps.value(GPSAltitudeRef))); GPSIFD.value(GPSAltitudeRef)));
wp.setTimestamp(QDateTime(date(tiff, gps.value(GPSDateStamp)), wp.setTimestamp(QDateTime(QDate::fromString(text(tiff,
time(tiff, gps.value(GPSTimeStamp)), Qt::UTC)); GPSIFD.value(GPSDateStamp)), "yyyy:MM:dd"), time(tiff,
GPSIFD.value(GPSTimeStamp)), Qt::UTC));
wp.setDescription(text(tiff, IFD0.value(ImageDescription)).trimmed());
waypoints.append(wp); waypoints.append(wp);
@ -210,14 +222,19 @@ bool EXIFParser::parse(QFile *file, QList<TrackData> &tracks,
Q_UNUSED(tracks); Q_UNUSED(tracks);
Q_UNUSED(routes); Q_UNUSED(routes);
Q_UNUSED(polygons); Q_UNUSED(polygons);
quint16 marker;
QDataStream stream(file); QDataStream stream(file);
stream.setByteOrder(QDataStream::BigEndian); stream.setByteOrder(QDataStream::BigEndian);
stream >> marker;
if (marker != SOI_MARKER) {
_errorString = "Not a JPEG file";
return false;
}
quint16 marker;
while (!stream.atEnd()) { while (!stream.atEnd()) {
stream >> marker; stream >> marker;
if (marker == 0xFFE1) { if (marker == APP1_MARKER) {
quint16 size; quint16 size;
char magic[6]; char magic[6];
stream >> size; stream >> size;

View File

@ -34,8 +34,8 @@ private:
const IFDEntry &lonRef, const IFDEntry &lat, const IFDEntry &latRef) const; const IFDEntry &lonRef, const IFDEntry &lat, const IFDEntry &latRef) const;
double altitude(TIFFFile &file, const IFDEntry &alt, double altitude(TIFFFile &file, const IFDEntry &alt,
const IFDEntry &altRef) const; const IFDEntry &altRef) const;
QDate date(TIFFFile &file, const IFDEntry &ds) const;
QTime time(TIFFFile &file, const IFDEntry &ts) const; QTime time(TIFFFile &file, const IFDEntry &ts) const;
QString text(TIFFFile &file, const IFDEntry &e) const;
QString _errorString; QString _errorString;
}; };