try recover missing EXIF filds from XMP

This commit is contained in:
cDc
2017-12-09 11:59:09 +02:00
parent 0aeb65dcd2
commit 36f7056799
4 changed files with 89 additions and 43 deletions

View File

@@ -38,3 +38,25 @@ int main(int argc, const char** argv) {
} }
``` ```
See `main.cpp` for more details. See `main.cpp` for more details.
## Copyright
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
NO EVENT SHALL THE FREEBSD PROJECT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@@ -13,9 +13,9 @@
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
-- Redistributions of source code must retain the above copyright notice, - Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright notice, - Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
@@ -637,19 +637,19 @@ int EXIFInfo::parseFrom(const uint8_t* buf, unsigned len) {
inline operator uint32_t& () { return val; } inline operator uint32_t& () { return val; }
inline int operator () (int code=PARSE_ABSENT_DATA) const { return val&FIELD_ALL ? (int)PARSE_SUCCESS : code; } inline int operator () (int code=PARSE_ABSENT_DATA) const { return val&FIELD_ALL ? (int)PARSE_SUCCESS : code; }
} app1s(Fields); } app1s(Fields);
for (unsigned pos=2; pos<len; ) { for (unsigned pos=2; pos+2<=len; ) {
// find next marker // find next marker;
uint8_t marker, prev(0); // in cases of markers appended after the compressed data,
do { // optional JM_START fill bytes may precede the marker
marker = buf[pos++]; if (buf[pos++] != JM_START)
if (marker != JM_START && prev == JM_START)
break; break;
prev = marker; uint8_t marker;
} while (pos<len); while ((marker=buf[pos++]) == JM_START && pos<len);
// select marker // select marker
switch (marker) { switch (marker) {
case 0x00: case 0x00:
case 0x01: case 0x01:
case JM_START:
case JM_RST0: case JM_RST0:
case JM_RST1: case JM_RST1:
case JM_RST2: case JM_RST2:
@@ -851,7 +851,7 @@ int EXIFInfo::parseFromXMPSegment(const uint8_t* buf, unsigned len) {
if ((strEnd=Tools::strrnstr(strXMP, "<?xpacket end=", len)) != NULL) if ((strEnd=Tools::strrnstr(strXMP, "<?xpacket end=", len)) != NULL)
len = (unsigned)(strEnd - strXMP); len = (unsigned)(strEnd - strXMP);
// Now try parsing the XML packet. // Try parsing the XML packet.
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
const tinyxml2::XMLElement* document; const tinyxml2::XMLElement* document;
if (doc.Parse(strXMP, len) != tinyxml2::XML_SUCCESS || if (doc.Parse(strXMP, len) != tinyxml2::XML_SUCCESS ||
@@ -860,7 +860,26 @@ int EXIFInfo::parseFromXMPSegment(const uint8_t* buf, unsigned len) {
(document=document->FirstChildElement("rdf:Description")) == NULL) (document=document->FirstChildElement("rdf:Description")) == NULL)
return PARSE_ABSENT_DATA; return PARSE_ABSENT_DATA;
// Now try parsing the XMP content for projection type. // Try parsing the XMP content for tiff details.
if (Orientation == 0) {
uint32_t _Orientation(0);
document->QueryUnsignedAttribute("tiff:Orientation", &_Orientation);
Orientation = (uint16_t)_Orientation;
}
if (ImageWidth == 0 && ImageHeight == 0) {
document->QueryUnsignedAttribute("tiff:ImageWidth", &ImageWidth);
if (document->QueryUnsignedAttribute("tiff:ImageHeight", &ImageHeight) != tinyxml2::XML_SUCCESS)
document->QueryUnsignedAttribute("tiff:ImageLength", &ImageHeight) ;
}
if (XResolution == 0 && YResolution == 0 && ResolutionUnit == 0) {
document->QueryDoubleAttribute("tiff:XResolution", &XResolution);
document->QueryDoubleAttribute("tiff:YResolution", &YResolution);
uint32_t _ResolutionUnit(0);
document->QueryUnsignedAttribute("tiff:ResolutionUnit", &_ResolutionUnit);
ResolutionUnit = (uint16_t)_ResolutionUnit;
}
// Try parsing the XMP content for projection type.
{ {
const tinyxml2::XMLElement* const element(document->FirstChildElement("GPano:ProjectionType")); const tinyxml2::XMLElement* const element(document->FirstChildElement("GPano:ProjectionType"));
if (element != NULL) { if (element != NULL) {
@@ -875,7 +894,7 @@ int EXIFInfo::parseFromXMPSegment(const uint8_t* buf, unsigned len) {
} }
} }
// Now try parsing the XMP content for DJI info. // Try parsing the XMP content for DJI info.
document->QueryDoubleAttribute("drone-dji:AbsoluteAltitude", &GeoLocation.Altitude); document->QueryDoubleAttribute("drone-dji:AbsoluteAltitude", &GeoLocation.Altitude);
document->QueryDoubleAttribute("drone-dji:RelativeAltitude", &GeoLocation.RelativeAltitude); document->QueryDoubleAttribute("drone-dji:RelativeAltitude", &GeoLocation.RelativeAltitude);
document->QueryDoubleAttribute("drone-dji:GimbalRollDegree", &GeoLocation.RollDegree); document->QueryDoubleAttribute("drone-dji:GimbalRollDegree", &GeoLocation.RollDegree);
@@ -887,7 +906,7 @@ int EXIFInfo::parseFromXMPSegment(const uint8_t* buf, unsigned len) {
void EXIFInfo::Geolocation_t::parseCoords() { void EXIFInfo::Geolocation_t::parseCoords() {
// convert GPS latitude // Convert GPS latitude
if (LatComponents.degrees != DBL_MAX || if (LatComponents.degrees != DBL_MAX ||
LatComponents.minutes != 0 || LatComponents.minutes != 0 ||
LatComponents.seconds != 0) { LatComponents.seconds != 0) {
@@ -898,7 +917,7 @@ void EXIFInfo::Geolocation_t::parseCoords() {
if ('S' == LatComponents.direction) if ('S' == LatComponents.direction)
Latitude = -Latitude; Latitude = -Latitude;
} }
// convert GPS longitude // Convert GPS longitude
if (LonComponents.degrees != DBL_MAX || if (LonComponents.degrees != DBL_MAX ||
LonComponents.minutes != 0 || LonComponents.minutes != 0 ||
LonComponents.seconds != 0) { LonComponents.seconds != 0) {
@@ -909,7 +928,7 @@ void EXIFInfo::Geolocation_t::parseCoords() {
if ('W' == LonComponents.direction) if ('W' == LonComponents.direction)
Longitude = -Longitude; Longitude = -Longitude;
} }
// convert GPS altitude // Convert GPS altitude
if (hasAltitude() && if (hasAltitude() &&
AltitudeRef == 1) { AltitudeRef == 1) {
Altitude = -Altitude; Altitude = -Altitude;
@@ -951,6 +970,9 @@ void EXIFInfo::clear() {
RelatedImageWidth = 0; RelatedImageWidth = 0;
RelatedImageHeight= 0; RelatedImageHeight= 0;
Orientation = 0; Orientation = 0;
XResolution = 0;
YResolution = 0;
ResolutionUnit = 0;
BitsPerSample = 0; BitsPerSample = 0;
ExposureTime = 0; ExposureTime = 0;
FNumber = 0; FNumber = 0;

View File

@@ -13,9 +13,9 @@
Redistribution and use in source and binary forms, with or without Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met: modification, are permitted provided that the following conditions are met:
-- Redistributions of source code must retain the above copyright notice, - Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer. this list of conditions and the following disclaimer.
-- Redistributions in binary form must reproduce the above copyright notice, - Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.

View File

@@ -41,9 +41,11 @@ int main(int argc, const char** argv)
std::cout << "CameraModel " << imageEXIF.Make << " - " << imageEXIF.Model << "\n"; std::cout << "CameraModel " << imageEXIF.Make << " - " << imageEXIF.Model << "\n";
if (!imageEXIF.SerialNumber.empty()) if (!imageEXIF.SerialNumber.empty())
std::cout << "SerialNumber " << imageEXIF.SerialNumber << "\n"; std::cout << "SerialNumber " << imageEXIF.SerialNumber << "\n";
if (imageEXIF.Orientation)
std::cout << "Orientation " << imageEXIF.Orientation << "\n"; std::cout << "Orientation " << imageEXIF.Orientation << "\n";
std::cout << "Resolution " << imageEXIF.XResolution << "x" << imageEXIF.YResolution << "\n"; if (imageEXIF.XResolution || imageEXIF.YResolution || imageEXIF.ResolutionUnit)
std::cout << "ResolutionUnit " << imageEXIF.ResolutionUnit << "\n"; std::cout << "Resolution " << imageEXIF.XResolution << "x" << imageEXIF.YResolution << " (" << imageEXIF.ResolutionUnit << ")\n";
if (imageEXIF.BitsPerSample)
std::cout << "BitsPerSample " << imageEXIF.BitsPerSample << "\n"; std::cout << "BitsPerSample " << imageEXIF.BitsPerSample << "\n";
if (!imageEXIF.Software.empty()) if (!imageEXIF.Software.empty())
std::cout << "Software " << imageEXIF.Software << "\n"; std::cout << "Software " << imageEXIF.Software << "\n";