add MakerNote support for DJI
This commit is contained in:
102
TinyEXIF.cpp
102
TinyEXIF.cpp
@@ -145,6 +145,10 @@ public:
|
||||
length = parse32(buf + offs + 4, alignIntel);
|
||||
}
|
||||
|
||||
const uint8_t* GetBuffer() const { return buf; }
|
||||
unsigned GetOffset() const { return offs; }
|
||||
bool IsIntelAligned() const { return alignIntel; }
|
||||
|
||||
uint16_t GetTag() const { return tag; }
|
||||
uint32_t GetLength() const { return length; }
|
||||
uint32_t GetData() const { return parse32(buf + offs + 8, alignIntel); }
|
||||
@@ -153,11 +157,12 @@ public:
|
||||
bool IsShort() const { return format == 3; }
|
||||
bool IsLong() const { return format == 4; }
|
||||
bool IsRational() const { return format == 5 || format == 10; }
|
||||
bool IsFloat() const { return format == 11; }
|
||||
|
||||
bool Fetch(std::string& val) const {
|
||||
if (format != 2 || length == 0)
|
||||
return false;
|
||||
val = parseEXIFString(buf, length, GetData(), tiff_header_start, len, alignIntel);
|
||||
val = parseString(buf, length, GetData(), tiff_header_start, len, alignIntel);
|
||||
return true;
|
||||
}
|
||||
bool Fetch(uint8_t& val) const {
|
||||
@@ -184,16 +189,30 @@ public:
|
||||
val = parse32(buf + offs + 8, alignIntel);
|
||||
return true;
|
||||
}
|
||||
bool Fetch(float& val) const {
|
||||
if (!IsFloat() || length == 0)
|
||||
return false;
|
||||
val = parseFloat(buf + offs + 8, alignIntel);
|
||||
return true;
|
||||
}
|
||||
bool Fetch(double& val) const {
|
||||
if (!IsRational() || length == 0)
|
||||
return false;
|
||||
val = parseEXIFRational(buf + GetSubIFD(), alignIntel);
|
||||
val = parseRational(buf + GetSubIFD(), alignIntel);
|
||||
return true;
|
||||
}
|
||||
bool Fetch(double& val, uint32_t idx) const {
|
||||
if (!IsRational() || length <= idx)
|
||||
return false;
|
||||
val = parseEXIFRational(buf + GetSubIFD() + idx*8, alignIntel);
|
||||
val = parseRational(buf + GetSubIFD() + idx*8, alignIntel);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FetchFloat(double& val) const {
|
||||
float _val;
|
||||
if (!Fetch(_val))
|
||||
return false;
|
||||
val = _val;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,14 +236,22 @@ public:
|
||||
((uint32_t)buf[2]<<8) |
|
||||
buf[3];
|
||||
}
|
||||
static double parseEXIFRational(const uint8_t* buf, bool intel) {
|
||||
static float parseFloat(const uint8_t* buf, bool intel) {
|
||||
union {
|
||||
uint32_t i;
|
||||
float f;
|
||||
} i2f;
|
||||
i2f.i = parse32(buf, intel);
|
||||
return i2f.f;
|
||||
}
|
||||
static double parseRational(const uint8_t* buf, bool intel) {
|
||||
const uint32_t denominator = parse32(buf+4, intel);
|
||||
if (denominator == 0)
|
||||
return 0.0;
|
||||
const uint32_t numerator = parse32(buf, intel);
|
||||
return (double)(int32_t)numerator/(double)(int32_t)denominator;
|
||||
}
|
||||
static std::string parseEXIFString(const uint8_t* buf,
|
||||
static std::string parseString(const uint8_t* buf,
|
||||
unsigned num_components,
|
||||
unsigned data,
|
||||
unsigned base,
|
||||
@@ -448,6 +475,11 @@ void EXIFInfo::parseIFDExif(EntryParser& parser) {
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x927c:
|
||||
// MakerNote
|
||||
parseIFDMakerNote(parser);
|
||||
break;
|
||||
|
||||
case 0x9291:
|
||||
// Fractions of seconds for DateTimeOriginal
|
||||
parser.Fetch(SubSecTimeOriginal);
|
||||
@@ -534,6 +566,60 @@ void EXIFInfo::parseIFDExif(EntryParser& parser) {
|
||||
}
|
||||
}
|
||||
|
||||
// Parse tag as MakerNote IFD
|
||||
void EXIFInfo::parseIFDMakerNote(EntryParser& parser) {
|
||||
const unsigned startOff = parser.GetOffset();
|
||||
const uint32_t off = parser.GetSubIFD();
|
||||
if (0 != _tcsicmp(Make.c_str(), "DJI"))
|
||||
return;
|
||||
int num_entries = EntryParser::parse16(parser.GetBuffer()+off, parser.IsIntelAligned());
|
||||
if (uint32_t(2 + 12 * num_entries) > parser.GetLength())
|
||||
return;
|
||||
parser.Init(off+2);
|
||||
parser.ParseTag();
|
||||
--num_entries;
|
||||
std::string maker;
|
||||
if (parser.GetTag() == 1 && parser.Fetch(maker)) {
|
||||
if (0 == _tcsicmp(maker.c_str(), "DJI")) {
|
||||
while (--num_entries >= 0) {
|
||||
parser.ParseTag();
|
||||
switch (parser.GetTag()) {
|
||||
case 3:
|
||||
// SpeedX
|
||||
parser.FetchFloat(GeoLocation.SpeedX);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
// SpeedY
|
||||
parser.FetchFloat(GeoLocation.SpeedY);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
// SpeedZ
|
||||
parser.FetchFloat(GeoLocation.SpeedZ);
|
||||
break;
|
||||
|
||||
case 9:
|
||||
// Camera Pitch
|
||||
parser.FetchFloat(GeoLocation.PitchDegree);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
// Camera Yaw
|
||||
parser.FetchFloat(GeoLocation.YawDegree);
|
||||
break;
|
||||
|
||||
case 11:
|
||||
// Camera Roll
|
||||
parser.FetchFloat(GeoLocation.RollDegree);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
parser.Init(startOff+12);
|
||||
}
|
||||
|
||||
// Parse tag as GPS IFD
|
||||
void EXIFInfo::parseIFDGPS(EntryParser& parser) {
|
||||
switch (parser.GetTag()) {
|
||||
@@ -985,6 +1071,9 @@ bool EXIFInfo::Geolocation_t::hasRelativeAltitude() const {
|
||||
bool EXIFInfo::Geolocation_t::hasOrientation() const {
|
||||
return RollDegree != DBL_MAX && PitchDegree != DBL_MAX && YawDegree != DBL_MAX;
|
||||
}
|
||||
bool EXIFInfo::Geolocation_t::hasSpeed() const {
|
||||
return SpeedX != DBL_MAX && SpeedY != DBL_MAX && SpeedZ != DBL_MAX;
|
||||
}
|
||||
|
||||
|
||||
void EXIFInfo::clear() {
|
||||
@@ -1055,6 +1144,9 @@ void EXIFInfo::clear() {
|
||||
GeoLocation.RollDegree = DBL_MAX;
|
||||
GeoLocation.PitchDegree = DBL_MAX;
|
||||
GeoLocation.YawDegree = DBL_MAX;
|
||||
GeoLocation.SpeedX = DBL_MAX;
|
||||
GeoLocation.SpeedY = DBL_MAX;
|
||||
GeoLocation.SpeedZ = DBL_MAX;
|
||||
GeoLocation.GPSDOP = 0;
|
||||
GeoLocation.GPSDifferential = 0;
|
||||
GeoLocation.GPSMapDatum = "";
|
||||
|
||||
@@ -133,6 +133,8 @@ private:
|
||||
void parseIFDExif(EntryParser&);
|
||||
// Parse tag as GPS IFD.
|
||||
void parseIFDGPS(EntryParser&);
|
||||
// Parse tag as MakerNote IFD.
|
||||
void parseIFDMakerNote(EntryParser&);
|
||||
|
||||
public:
|
||||
// Data fields
|
||||
@@ -270,6 +272,9 @@ public:
|
||||
double RollDegree; // Flight roll in degrees
|
||||
double PitchDegree; // Flight pitch in degrees
|
||||
double YawDegree; // Flight yaw in degrees
|
||||
double SpeedX; // Flight speed on X in meters/second
|
||||
double SpeedY; // Flight speed on Y in meters/second
|
||||
double SpeedZ; // Flight speed on Z in meters/second
|
||||
double GPSDOP; // GPS DOP (data degree of precision)
|
||||
uint16_t GPSDifferential; // Differential correction applied to the GPS receiver (may not exist)
|
||||
// 0: measurement without differential correction
|
||||
@@ -288,6 +293,7 @@ public:
|
||||
bool hasAltitude() const; // Return true if (alt) is available
|
||||
bool hasRelativeAltitude()const;// Return true if (rel_alt) is available
|
||||
bool hasOrientation() const; // Return true if (roll,yaw,pitch) is available
|
||||
bool hasSpeed() const; // Return true if (speedX,speedY,speedZ) is available
|
||||
} GeoLocation;
|
||||
};
|
||||
|
||||
|
||||
5
main.cpp
5
main.cpp
@@ -132,6 +132,11 @@ int main(int argc, const char** argv)
|
||||
std::cout << "GeoLocation.PitchDegree " << imageEXIF.GeoLocation.PitchDegree << "\n";
|
||||
std::cout << "GeoLocation.YawDegree " << imageEXIF.GeoLocation.YawDegree << "\n";
|
||||
}
|
||||
if (imageEXIF.GeoLocation.hasSpeed()) {
|
||||
std::cout << "GeoLocation.SpeedX " << imageEXIF.GeoLocation.SpeedX << "\n";
|
||||
std::cout << "GeoLocation.SpeedY " << imageEXIF.GeoLocation.SpeedY << "\n";
|
||||
std::cout << "GeoLocation.SpeedZ " << imageEXIF.GeoLocation.SpeedZ << "\n";
|
||||
}
|
||||
std::cout << "GeoLocation.GPSDOP " << imageEXIF.GeoLocation.GPSDOP << "\n";
|
||||
std::cout << "GeoLocation.GPSDifferential " << imageEXIF.GeoLocation.GPSDifferential << "\n";
|
||||
if (!imageEXIF.GeoLocation.GPSMapDatum.empty())
|
||||
|
||||
Reference in New Issue
Block a user