QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
ExifParser.cc
Go to the documentation of this file.
1#include "ExifParser.h"
2#include "ExifUtility.h"
4
5#include <QtCore/QByteArray>
6#include <QtCore/QDateTime>
7
8QGC_LOGGING_CATEGORY(ExifParserLog, "AnalyzeView.ExifParser")
9
10namespace ExifParser
11{
12
13QDateTime readTime(const QByteArray &buffer)
14{
15 ExifData *data = ExifUtility::loadFromBuffer(buffer);
16 if (!data) {
17 qCWarning(ExifParserLog) << "Failed to parse EXIF data";
18 return QDateTime();
19 }
20
21 const QString dateTimeDigitized = ExifUtility::readString(data, EXIF_TAG_DATE_TIME_DIGITIZED, EXIF_IFD_EXIF);
22 exif_data_unref(data);
23
24 if (dateTimeDigitized.isEmpty()) {
25 qCWarning(ExifParserLog) << "DateTimeDigitized tag not found";
26 return QDateTime();
27 }
28
29 return QDateTime::fromString(dateTimeDigitized, QStringLiteral("yyyy:MM:dd HH:mm:ss"));
30}
31
32bool write(QByteArray &buffer, const GeoTagData &geotag)
33{
34 ExifData *data = ExifUtility::loadFromBuffer(buffer);
35 if (!data) {
37 if (!data) {
38 qCWarning(ExifParserLog) << "Failed to create EXIF data";
39 return false;
40 }
41 }
42
43 const ExifByteOrder order = exif_data_get_byte_order(data);
44
45 // Helper to get existing or create new GPS entry
46 auto getOrCreateEntry = [&](ExifTag tag, ExifFormat format, unsigned long components) -> ExifEntry* {
47 ExifEntry *entry = exif_content_get_entry(data->ifd[EXIF_IFD_GPS], tag);
48 if (!entry) {
49 entry = ExifUtility::createTag(data, EXIF_IFD_GPS, tag, format, components);
50 }
51 return entry;
52 };
53
54 // GPS Version ID (2.3.0.0)
55 ExifEntry *versionEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_VERSION_ID), EXIF_FORMAT_BYTE, 4);
56 if (versionEntry && versionEntry->data) {
57 versionEntry->data[0] = 2;
58 versionEntry->data[1] = 3;
59 versionEntry->data[2] = 0;
60 versionEntry->data[3] = 0;
61 }
62
63 // Latitude
64 ExifEntry *latRefEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE_REF), EXIF_FORMAT_ASCII, 2);
65 ExifUtility::writeGpsRef(latRefEntry, geotag.coordinate.latitude() >= 0 ? 'N' : 'S');
66
67 ExifEntry *latEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_LATITUDE), EXIF_FORMAT_RATIONAL, 3);
68 ExifUtility::writeGpsCoordinate(latEntry, order, geotag.coordinate.latitude());
69
70 // Longitude
71 ExifEntry *lonRefEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE_REF), EXIF_FORMAT_ASCII, 2);
72 ExifUtility::writeGpsRef(lonRefEntry, geotag.coordinate.longitude() >= 0 ? 'E' : 'W');
73
74 ExifEntry *lonEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_LONGITUDE), EXIF_FORMAT_RATIONAL, 3);
75 ExifUtility::writeGpsCoordinate(lonEntry, order, geotag.coordinate.longitude());
76
77 // Altitude
78 ExifEntry *altRefEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE_REF), EXIF_FORMAT_BYTE, 1);
79 ExifUtility::writeGpsAltRef(altRefEntry, geotag.coordinate.altitude() < 0 ? 1 : 0);
80
81 ExifEntry *altEntry = getOrCreateEntry(static_cast<ExifTag>(EXIF_TAG_GPS_ALTITUDE), EXIF_FORMAT_RATIONAL, 1);
82 ExifUtility::writeRational(altEntry, order, geotag.coordinate.altitude(), 100);
83
84 // Save back to buffer
85 const bool success = ExifUtility::saveToBuffer(data, buffer);
86 exif_data_unref(data);
87
88 return success;
89}
90
91} // namespace ExifParser
#define QGC_LOGGING_CATEGORY(name, categoryStr)
QDateTime readTime(const QByteArray &buffer)
Definition ExifParser.cc:13
bool write(QByteArray &buffer, const GeoTagData &geotag)
Definition ExifParser.cc:32
void writeGpsAltRef(ExifEntry *entry, unsigned char value)
Write a byte value to a GPS altitude reference entry (0=above, 1=below sea level)
ExifEntry * createTag(ExifData *data, ExifIfd ifd, ExifTag tag, ExifFormat format, unsigned long components)
ExifData * loadFromBuffer(const QByteArray &buffer)
void writeGpsCoordinate(ExifEntry *entry, ExifByteOrder order, double value)
Write GPS coordinate as EXIF rationals (degrees, minutes, seconds)
void writeRational(ExifEntry *entry, ExifByteOrder order, double value, int denominator)
Write a single rational value to an entry.
QString readString(ExifData *data, ExifTag tag, ExifIfd ifd)
Read a string value from an EXIF tag.
bool saveToBuffer(ExifData *data, QByteArray &buffer)
ExifData * createNew()
void writeGpsRef(ExifEntry *entry, char value)
Write an ASCII character to a GPS reference entry (N/S/E/W)
QGeoCoordinate coordinate
Definition GeoTagData.h:17