Huge refactor
I did my best...
This commit is contained in:
@@ -199,6 +199,54 @@ namespace
|
||||
*ptr += valueToAdd;
|
||||
*ptr = EndianSwap(*ptr);
|
||||
}
|
||||
|
||||
int AppendTagValueTypeAndString(std::vector<uint8_t>& array, IFDTag tag, std::vector<uint8_t> &otherArray, const std::string& str)
|
||||
{
|
||||
AppendTagAndValueType(array, (uint16_t) tag, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(array, str.size() + 1);
|
||||
int offset = AppendU32(array, otherArray.size() + 1);
|
||||
int offsetInData = AppendVector(otherArray, (char*) str.c_str(), str.size() + 1);
|
||||
uint32_t* ptr = (uint32_t*) (array.data() + offset);
|
||||
*ptr = offsetInData;
|
||||
return offset;
|
||||
}
|
||||
|
||||
int AppendTagValueTypeAndRational(std::vector<uint8_t>& array, IFDTag tag, std::vector<uint8_t> &otherArray, const OpenVulkano::Image::RationalValue& value)
|
||||
{
|
||||
AppendTagAndValueType(array, (uint16_t) tag, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(array, 1); // number of components
|
||||
int offset = AppendU32(array, otherArray.size());
|
||||
int offsetInData = AppendRational(otherArray, value);
|
||||
uint32_t* ptr = (uint32_t*) (array.data() + offset);
|
||||
*ptr = offsetInData;
|
||||
return offset;
|
||||
}
|
||||
|
||||
void AppendTagValueTypeAndShort(std::vector<uint8_t>& array, IFDTag tag, uint16_t value)
|
||||
{
|
||||
AppendTagAndValueType(array, (uint16_t ) tag, (uint16_t) IFDValueType::SHORT);
|
||||
AppendU32(array, 1);
|
||||
AppendU16(array, value);
|
||||
AppendU16(array, 0); // padding
|
||||
}
|
||||
|
||||
void AppendTagValueTypeAndByte(std::vector<uint8_t>& array, IFDGPSTag tag, IFDValueType valueType, uint16_t byte)
|
||||
{
|
||||
AppendTagAndValueType(array, (uint16_t) tag, (uint16_t) valueType);
|
||||
AppendU32(array, (valueType == IFDValueType::BYTE) ? 1 : 2); // 2 for N/S/E/W + \0, 1 for a single byte
|
||||
AppendU8(array, byte);
|
||||
AppendU8(array, 0); // padding
|
||||
AppendU8(array, 0); // padding
|
||||
AppendU8(array, 0); // padding
|
||||
}
|
||||
|
||||
int AppendTagValueTypeAndGPSRational(std::vector<uint8_t>& array, IFDGPSTag tag, int numberOfComponents, int initialOffsetValue)
|
||||
{
|
||||
AppendTagAndValueType(array, (uint16_t) tag, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(array, numberOfComponents); // number of components
|
||||
int offset = AppendU32NES(array, initialOffsetValue);
|
||||
return offset;
|
||||
}
|
||||
}
|
||||
|
||||
namespace OpenVulkano::Image
|
||||
@@ -283,163 +331,89 @@ namespace OpenVulkano::Image
|
||||
AppendU32(result, 8); // Append offset to the ifd
|
||||
AppendU16(result, numberOfMainTags);
|
||||
|
||||
// offsets in result array where the offset to the data should be stored
|
||||
int makeOffset = 0;
|
||||
int modelOffset = 0;
|
||||
int dateTakenOffset = 0;
|
||||
int softwareUsedOffset = 0;
|
||||
std::vector<int> offsets;
|
||||
int gpsInfoOffset = 0;
|
||||
|
||||
// Make
|
||||
if (!make.empty())
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::MAKE, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, make.size() + 1);
|
||||
makeOffset = AppendU32(result, data.size() + 1);
|
||||
int offsetInData = AppendVector(data, (char *)make.c_str(), make.size() + 1);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + makeOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndString(result, IFDTag::MAKE, data, make));
|
||||
}
|
||||
|
||||
// Model
|
||||
if (!model.empty())
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::MODEL, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, model.size() + 1);
|
||||
modelOffset = AppendU32(result, data.size() + 1);
|
||||
int offsetInData = AppendVector(data, (char *)model.c_str(), model.size() + 1);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + modelOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndString(result, IFDTag::MODEL, data, model));
|
||||
}
|
||||
|
||||
// Orientation
|
||||
if (orientation != 0)
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::ORIENTATION, (uint16_t) IFDValueType::SHORT);
|
||||
AppendU32(result, 1);
|
||||
AppendU16(result, (uint16_t)orientation);
|
||||
AppendU16(result, 0); // padding
|
||||
AppendTagValueTypeAndShort(result, IFDTag::ORIENTATION, orientation);
|
||||
}
|
||||
|
||||
// xResolution
|
||||
int xResolutionOffset = 0;
|
||||
if (xResolution.nominator || xResolution.denominator)
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::X_RESOLUTION, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 1); // number of components
|
||||
xResolutionOffset = AppendU32(result, data.size());
|
||||
int offsetInData = AppendRational(data, xResolution);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + xResolutionOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndRational(result, IFDTag::X_RESOLUTION, data, xResolution));
|
||||
}
|
||||
|
||||
// yResolution
|
||||
int yResolutionOffset = 0;
|
||||
if (yResolution.nominator || yResolution.denominator)
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::Y_RESOLUTION, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 1); // number of components
|
||||
yResolutionOffset = AppendU32(result, data.size());
|
||||
int offsetInData = AppendRational(data, yResolution);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + yResolutionOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndRational(result, IFDTag::Y_RESOLUTION, data, yResolution));
|
||||
}
|
||||
|
||||
// Exposure Time
|
||||
int exposureTimeOffset = 0;
|
||||
if (exposureTime.nominator || exposureTime.denominator)
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::EXPOSURE_TIME, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 1); // number of components
|
||||
exposureTimeOffset = AppendU32(result, data.size());
|
||||
int offsetInData = AppendRational(data, exposureTime);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + exposureTimeOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndRational(result, IFDTag::EXPOSURE_TIME, data, exposureTime));
|
||||
}
|
||||
|
||||
// ResolutionUnit
|
||||
if (resolutionUnit != 0)
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::RESOLUTION_UNIT, (uint16_t) IFDValueType::SHORT);
|
||||
AppendU32(result, 1); // number of components
|
||||
AppendU16(result, resolutionUnit);
|
||||
AppendU16(result, 0); // padding
|
||||
AppendTagValueTypeAndShort(result, IFDTag::RESOLUTION_UNIT, resolutionUnit);
|
||||
}
|
||||
|
||||
// Software Used
|
||||
if (!softwareUsed.empty())
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::SOFTWARE_USED, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, softwareUsed.size() + 1);
|
||||
softwareUsedOffset = AppendU32(result, data.size() + 1);
|
||||
int offsetInData = AppendVector(data, (char *)softwareUsed.c_str(), softwareUsed.size() + 1);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + softwareUsedOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndString(result, IFDTag::SOFTWARE_USED, data, softwareUsed));
|
||||
}
|
||||
|
||||
// Date Taken
|
||||
// NOTE(vb): For some reason windows file properties doesn't print date taken field!
|
||||
// Even though other software does provide this information without a problem
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::DATE_TAKEN, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, dateTaken.size() + 1);
|
||||
dateTakenOffset = AppendU32(result, data.size() + 1);
|
||||
int offsetInData = AppendVector(data, (char *)dateTaken.c_str(), dateTaken.size() + 1);
|
||||
uint32_t* ptr = (uint32_t *)(result.data() + dateTakenOffset);
|
||||
*ptr = offsetInData;
|
||||
offsets.push_back(AppendTagValueTypeAndString(result, IFDTag::DATE_TAKEN, data, dateTaken));
|
||||
}
|
||||
|
||||
// GPS Info offset
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::GPS_INFO_OFFSET, (uint16_t) IFDValueType::LONG_);
|
||||
AppendU32(result, 1); // num components
|
||||
gpsInfoOffset = AppendU32(result, 0); // to be filled
|
||||
{
|
||||
AppendTagAndValueType(result, (uint16_t) IFDTag::GPS_INFO_OFFSET, (uint16_t) IFDValueType::LONG_);
|
||||
AppendU32(result, 1); // num components
|
||||
gpsInfoOffset = AppendU32(result, 0);
|
||||
}
|
||||
|
||||
// next ifd offset
|
||||
AppendU32(result, 0);
|
||||
|
||||
int resultSize = result.size();
|
||||
AppendVector(result, data);
|
||||
int ifdAndSubdataSize = result.size();
|
||||
|
||||
// Resolve offsets
|
||||
{
|
||||
const int valueToAdd = resultSize - EXIF_HEADER_SIZE;
|
||||
if (!model.empty())
|
||||
for (const auto& offset: offsets)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + modelOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (!make.empty())
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + makeOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (xResolutionOffset)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + xResolutionOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (yResolutionOffset)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + yResolutionOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (exposureTimeOffset)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + exposureTimeOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (dateTakenOffset)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + dateTakenOffset, valueToAdd);
|
||||
}
|
||||
|
||||
if (softwareUsedOffset)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + softwareUsedOffset, valueToAdd);
|
||||
AddValueToU32AndEndianSwap(result.data() + offset, valueToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve GPS info offset
|
||||
{
|
||||
int ifdAndSubdataSize = result.size();
|
||||
uint32_t *ptr = (uint32_t *) (result.data() + gpsInfoOffset);
|
||||
*ptr = EndianSwap((uint32_t)(ifdAndSubdataSize - EXIF_HEADER_SIZE));
|
||||
}
|
||||
@@ -447,82 +421,40 @@ namespace OpenVulkano::Image
|
||||
// Writing GPS Info structure
|
||||
int numberOfGPSInfoTags = 8;
|
||||
AppendU16(result, numberOfGPSInfoTags);
|
||||
offsets.resize(0);
|
||||
|
||||
// Latitude Ref
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::LATITUDE_REF, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, 2); // 2 for N/S + \0
|
||||
AppendU8(result, latitude.latitudeRef == LatitudeRef::NORTH ? 'N' : 'S');
|
||||
AppendU8(result, 0);
|
||||
AppendU8(result, 0); // padding
|
||||
AppendU8(result, 0); // padding
|
||||
AppendTagValueTypeAndByte(result, IFDGPSTag::LATITUDE_REF, IFDValueType::ASCII, (latitude.latitudeRef == LatitudeRef::NORTH) ? 'N' : 'S');
|
||||
|
||||
// Latitude
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::LATITUDE, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 3); // number of components
|
||||
int latitudeOffset = AppendU32NES(result, 0); // 0 * sizeof(RationalValue)
|
||||
offsets.push_back(AppendTagValueTypeAndGPSRational(result, IFDGPSTag::LATITUDE, 3, 0)); // 0 * sizeof(RationalValue)
|
||||
|
||||
// Longitude Ref
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::LONGITUDE_REF, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, 2); // 2 for E/W + \0
|
||||
AppendU8(result, longitude.longitudeRef == LongitudeRef::EAST ? 'E' : 'W');
|
||||
AppendU8(result, 0);
|
||||
AppendU8(result, 0); // padding
|
||||
AppendU8(result, 0); // padding
|
||||
AppendTagValueTypeAndByte(result, IFDGPSTag::LONGITUDE_REF, IFDValueType::ASCII, (longitude.longitudeRef == LongitudeRef::EAST) ? 'E' : 'W');
|
||||
|
||||
// Longitude
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::LONGITUDE, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 3); // number of components
|
||||
int longitudeOffset = AppendU32NES(result, 24); // 3 * sizeof(RationalValue)
|
||||
offsets.push_back(AppendTagValueTypeAndGPSRational(result, IFDGPSTag::LONGITUDE, 3, 24)); // 3 * sizeof(RationalValue)
|
||||
|
||||
// Altitude Ref
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::ALTITUDE_REF, (uint16_t) IFDValueType::BYTE);
|
||||
AppendU32(result, 1); // number of components
|
||||
AppendU8(result, altitudeIsAboveSeaLevel ? 0 : 1);
|
||||
AppendU8(result, 0); // padding
|
||||
AppendU8(result, 0); // padding
|
||||
AppendU8(result, 0); // padding
|
||||
AppendTagValueTypeAndByte(result, IFDGPSTag::ALTITUDE_REF, IFDValueType::BYTE, altitudeIsAboveSeaLevel ? 0 : 1);
|
||||
|
||||
// Altitude
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::ALTITUDE, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 1); // number of components
|
||||
int altitudeOffset = AppendU32NES(result, 48); // 6 * sizeof(RationalValue)
|
||||
offsets.push_back(AppendTagValueTypeAndGPSRational(result, IFDGPSTag::ALTITUDE, 1, 48)); // 6 * sizeof(RationalValue)
|
||||
|
||||
// Track Ref
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::TRACK_REF, (uint16_t) IFDValueType::ASCII);
|
||||
AppendU32(result, 2); // 2 for T/M + \0
|
||||
AppendU8(result, trackRef == GPSTrackRef::TRUE_NORTH ? 'T' : 'M');
|
||||
AppendU8(result, 0);
|
||||
AppendU8(result, 0); // padding
|
||||
AppendU8(result, 0); // padding
|
||||
AppendTagValueTypeAndByte(result, IFDGPSTag::TRACK_REF, IFDValueType::ASCII, (trackRef == GPSTrackRef::TRUE_NORTH) ? 'T' : 'M');
|
||||
|
||||
// Track
|
||||
AppendTagAndValueType(result, (uint16_t) IFDGPSTag::TRACK, (uint16_t) IFDValueType::RATIONAL);
|
||||
AppendU32(result, 1); // number of components
|
||||
int trackOffset = AppendU32NES(result, 56); // 7 * sizeof(RationalValue)
|
||||
offsets.push_back(AppendTagValueTypeAndGPSRational(result, IFDGPSTag::TRACK, 1, 56)); // 7 * sizeof(RationalValue)
|
||||
|
||||
//
|
||||
|
||||
{
|
||||
int sizeOfResultSoFar = result.size();
|
||||
const int valueToAdd = sizeOfResultSoFar - EXIF_HEADER_SIZE;
|
||||
// Latitude
|
||||
for(const auto &offset : offsets)
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + latitudeOffset, valueToAdd);
|
||||
}
|
||||
|
||||
// Longitude
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + longitudeOffset, valueToAdd);
|
||||
}
|
||||
|
||||
// Altitude
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + altitudeOffset, valueToAdd);
|
||||
}
|
||||
|
||||
// Track
|
||||
{
|
||||
AddValueToU32AndEndianSwap(result.data() + trackOffset, valueToAdd);
|
||||
AddValueToU32AndEndianSwap(result.data() + offset, valueToAdd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -534,7 +466,7 @@ namespace OpenVulkano::Image
|
||||
AppendU32(result, altitude);
|
||||
AppendU32(result, 1); // denominator for altitude
|
||||
|
||||
int const TRACK_PRECISION = 10000;
|
||||
const int TRACK_PRECISION = 10000;
|
||||
AppendU32(result, track * TRACK_PRECISION);
|
||||
AppendU32(result, TRACK_PRECISION);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user