Resolve exiv2 merge conflicts and merge with
This commit is contained in:
commit
8b4389ade9
|
@ -23,7 +23,6 @@ Release
|
|||
|
||||
rtdata/rawtherapee.desktop
|
||||
rtengine/librtengine.a
|
||||
rtexif/librtexif.a
|
||||
rtgui/config.h
|
||||
rtgui/version.h
|
||||
rtgui/rawtherapee
|
||||
|
|
|
@ -467,6 +467,24 @@ pkg_check_modules(SIGC REQUIRED sigc++-2.0>=2.3.1)
|
|||
pkg_check_modules(LENSFUN REQUIRED lensfun>=0.2)
|
||||
pkg_check_modules(RSVG REQUIRED librsvg-2.0>=2.40)
|
||||
|
||||
# Require exiv2 >= 0.24 to make sure everything we need is available
|
||||
#find_package(Exiv2 0.24 REQUIRED)
|
||||
pkg_check_modules(EXIV2 REQUIRED exiv2>=0.24)
|
||||
#include_directories(SYSTEM ${Exiv2_INCLUDE_DIRS})
|
||||
#list(APPEND LIBS ${EXIV2_LIBRARIES})
|
||||
add_definitions(${EXIV2_DEFINITIONS})
|
||||
set(_exiv2_libs ${EXIV2_LIBRARIES})
|
||||
set(EXIV2_LIBRARIES "")
|
||||
foreach(l ${_exiv2_libs})
|
||||
set(_el "_el-NOTFOUND")
|
||||
if(EXIV2_LIBRARY_DIRS)
|
||||
find_library(_el ${l} PATHS ${EXIV2_LIBRARY_DIRS} NO_DEFAULT_PATH)
|
||||
else()
|
||||
find_library(_el ${l} PATHS ${EXIV2_LIBRARY_DIRS})
|
||||
endif()
|
||||
set(EXIV2_LIBRARIES ${EXIV2_LIBRARIES} ${_el})
|
||||
endforeach()
|
||||
|
||||
if(WIN32)
|
||||
add_definitions(-DWIN32)
|
||||
add_definitions(-D_WIN32)
|
||||
|
@ -482,7 +500,6 @@ endif()
|
|||
pkg_check_modules(LCMS REQUIRED lcms2>=2.6)
|
||||
pkg_check_modules(EXPAT REQUIRED expat>=2.1)
|
||||
pkg_check_modules(FFTW3F REQUIRED fftw3f)
|
||||
pkg_check_modules(IPTCDATA REQUIRED libiptcdata)
|
||||
pkg_check_modules(TIFF REQUIRED libtiff-4>=4.0.4)
|
||||
find_package(JPEG REQUIRED)
|
||||
find_package(PNG REQUIRED)
|
||||
|
@ -570,6 +587,7 @@ if(OPENMP_FOUND)
|
|||
set(CMAKE_REQUIRED_INCLUDES ${FFTW3F_INCLUDE_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES)
|
||||
foreach(l ${FFTW3F_LIBRARIES})
|
||||
set(_f "_f-NOTFOUND")
|
||||
find_library(_f ${l} PATHS ${FFTW3F_LIBRARY_DIRS})
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${_f})
|
||||
endforeach()
|
||||
|
@ -747,11 +765,13 @@ foreach(l ${LENSFUN_LIBRARIES})
|
|||
# the NO_DEFAULT_PATH is to make sure we find the lensfun version we
|
||||
# want, and not the system's one (e.g. if we have a custom version
|
||||
# installed in a non-standard location)
|
||||
set(_l "_l-NOTFOUND")
|
||||
find_library(_l ${l} PATHS ${LENSFUN_LIBRARY_DIRS} NO_DEFAULT_PATH)
|
||||
else()
|
||||
# LENSFUN_LIBRARY_DIRS can be empty if lensfun is installed in the
|
||||
# default path. In this case, adding NO_DEFAULT_PATH would make
|
||||
# find_library fail...
|
||||
set(_l "_l-NOTFOUND")
|
||||
find_library(_l ${l})
|
||||
endif()
|
||||
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} ${_l})
|
||||
|
@ -788,7 +808,6 @@ else()
|
|||
CACHE INTERNAL "" FORCE)
|
||||
endif()
|
||||
|
||||
add_subdirectory(rtexif)
|
||||
add_subdirectory(rtengine)
|
||||
add_subdirectory(rtgui)
|
||||
add_subdirectory(rtdata)
|
||||
|
|
|
@ -4,24 +4,20 @@ del .\install_manifest.txt
|
|||
|
||||
rmdir /s /q .\CMakeFiles
|
||||
rmdir /s /q .\rtengine\CMakeFiles
|
||||
rmdir /s /q .\rtexif\CMakeFiles
|
||||
rmdir /s /q .\rtgui\CMakeFiles
|
||||
rmdir /s /q .\rtdata\CMakeFiles
|
||||
|
||||
del .\cmake_*
|
||||
del .\rtengine\cmake_*
|
||||
del .\rtexif\cmake_*
|
||||
del .\rtgui\cmake_*
|
||||
del .\rtdata\cmake_*
|
||||
|
||||
del .\Makefile
|
||||
del .\rtengine\Makefile
|
||||
del .\rtexif\Makefile
|
||||
del .\rtgui\Makefile
|
||||
del .\rtdata\Makefile
|
||||
|
||||
del .\rtengine\librtengine.so
|
||||
del .\rtengine\librtengine.a
|
||||
del .\rtgui\rawtherapee
|
||||
del .\rtexif\librtexif.so
|
||||
del .\rtexif\librtexif.a
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
<<<<<<< HEAD
|
||||
if(EXTRA_INCDIR)
|
||||
include_directories("${EXTRA_INCDIR}")
|
||||
endif()
|
||||
|
@ -42,8 +43,11 @@ if(NOT WITH_SYSTEM_KLT)
|
|||
else()
|
||||
include_directories("${KLT_INCLUDE_DIRS}")
|
||||
endif()
|
||||
if(EXIV2_INCLUDE_DIRS)
|
||||
include_directories("${EXIV2_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
link_directories("${PROJECT_SOURCE_DIR}/rtexif"
|
||||
link_directories(
|
||||
"${EXPAT_LIBRARY_DIRS}"
|
||||
"${EXTRA_LIBDIR}"
|
||||
"${FFTW3F_LIBRARY_DIRS}"
|
||||
|
@ -205,7 +209,7 @@ endif()
|
|||
|
||||
set_target_properties(rtengine PROPERTIES COMPILE_FLAGS "${RTENGINE_CXX_FLAGS}")
|
||||
|
||||
target_link_libraries(rtengine rtexif
|
||||
target_link_libraries(rtengine
|
||||
${EXPAT_LIBRARIES}
|
||||
${EXTRA_LIB}
|
||||
${FFTW3F_LIBRARIES}
|
||||
|
@ -222,6 +226,7 @@ target_link_libraries(rtengine rtexif
|
|||
${LENSFUN_LIBRARIES}
|
||||
${RSVG_LIBRARIES}
|
||||
${KLT_LIBRARIES}
|
||||
)
|
||||
${EXIV2_LIBRARIES}
|
||||
)
|
||||
|
||||
install(FILES ${CAMCONSTSFILE} DESTINATION "${DATADIR}" PERMISSIONS OWNER_WRITE OWNER_READ GROUP_READ WORLD_READ)
|
||||
|
|
540
rtengine/dcp.cc
540
rtengine/dcp.cc
|
@ -39,7 +39,6 @@
|
|||
#include "../rtgui/options.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtexif;
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -430,7 +429,378 @@ std::map<std::string, std::string> getAliases(const Glib::ustring& profile_dir)
|
|||
return res;
|
||||
}
|
||||
|
||||
}
|
||||
class DCPMetadata
|
||||
{
|
||||
private:
|
||||
enum TagType {
|
||||
INVALID = 0,
|
||||
BYTE = 1,
|
||||
ASCII = 2,
|
||||
SHORT = 3,
|
||||
LONG = 4,
|
||||
RATIONAL = 5,
|
||||
SBYTE = 6,
|
||||
UNDEFINED = 7,
|
||||
SSHORT = 8,
|
||||
SLONG = 9,
|
||||
SRATIONAL = 10,
|
||||
FLOAT = 11,
|
||||
DOUBLE = 12
|
||||
};
|
||||
|
||||
enum ByteOrder {
|
||||
UNKNOWN = 0,
|
||||
INTEL = 0x4949,
|
||||
MOTOROLA = 0x4D4D
|
||||
};
|
||||
|
||||
public:
|
||||
explicit DCPMetadata(FILE* file) :
|
||||
file_(file),
|
||||
order_(UNKNOWN)
|
||||
{
|
||||
}
|
||||
|
||||
bool parse()
|
||||
{
|
||||
if (!file_) {
|
||||
#ifndef NDEBUG
|
||||
std::cerr << "ERROR: No file opened." << std::endl;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
setlocale(LC_NUMERIC, "C"); // to set decimal point in sscanf
|
||||
|
||||
// read tiff header
|
||||
std::fseek(file_, 0, SEEK_SET);
|
||||
std::uint16_t bo;
|
||||
std::fread(&bo, 1, 2, file_);
|
||||
order_ = ByteOrder(bo);
|
||||
|
||||
get2(); // Skip
|
||||
|
||||
// Seek to IFD
|
||||
const std::size_t offset = get4();
|
||||
std::fseek(file_, offset, SEEK_SET);
|
||||
|
||||
// First read the IFD directory
|
||||
const std::uint16_t numtags = get2();
|
||||
|
||||
if (numtags > 1000) { // KodakIfd has lots of tags, thus 1000 as the limit
|
||||
return false;
|
||||
}
|
||||
|
||||
for (std::uint16_t i = 0; i < numtags; ++i) {
|
||||
Tag tag;
|
||||
if (parseTag(tag)) {
|
||||
tags_[tag.id] = std::move(tag);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool find(int id) const
|
||||
{
|
||||
return tags_.find(id) != tags_.end();
|
||||
}
|
||||
|
||||
std::string toString(int id) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag != tags_.end()) {
|
||||
if (tag->second.type == ASCII) {
|
||||
return std::string(tag->second.value.begin(), tag->second.value.end()).c_str();
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
std::int32_t toInt(int id, std::size_t offset = 0, TagType as_type = INVALID) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag == tags_.end()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (as_type == INVALID) {
|
||||
as_type = tag->second.type;
|
||||
}
|
||||
|
||||
switch (as_type) {
|
||||
case SBYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return static_cast<signed char>(tag->second.value[offset]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case BYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return tag->second.value[offset];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SSHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return static_cast<std::int16_t>(sget2(tag->second.value.data() + offset));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return sget2(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SLONG:
|
||||
case LONG: {
|
||||
if (offset + 3 < tag->second.value.size()) {
|
||||
return sget4(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL: {
|
||||
if (offset + 7 < tag->second.value.size()) {
|
||||
const std::uint32_t denominator = sget4(tag->second.value.data() + offset + 4);
|
||||
return
|
||||
denominator == 0
|
||||
? 0
|
||||
: static_cast<std::int32_t>(sget4(tag->second.value.data() + offset)) / denominator;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
case FLOAT: {
|
||||
return toDouble(id, offset);
|
||||
}
|
||||
|
||||
default: {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int toShort(int id, std::size_t offset = 0) const
|
||||
{
|
||||
return toInt(id, offset, SHORT);
|
||||
}
|
||||
|
||||
double toDouble(int id, std::size_t offset = 0) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag == tags_.end()) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
switch (tag->second.type) {
|
||||
case SBYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return static_cast<signed char>(tag->second.value[offset]);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case BYTE: {
|
||||
if (offset < tag->second.value.size()) {
|
||||
return tag->second.value[offset];
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SSHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return static_cast<std::int16_t>(sget2(tag->second.value.data() + offset));
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SHORT: {
|
||||
if (offset + 1 < tag->second.value.size()) {
|
||||
return sget2(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SLONG:
|
||||
case LONG: {
|
||||
if (offset + 3 < tag->second.value.size()) {
|
||||
return sget4(tag->second.value.data() + offset);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case SRATIONAL:
|
||||
case RATIONAL: {
|
||||
if (offset + 7 < tag->second.value.size()) {
|
||||
const std::int32_t numerator = sget4(tag->second.value.data() + offset);
|
||||
const std::int32_t denominator = sget4(tag->second.value.data() + offset + 4);
|
||||
return
|
||||
denominator == 0
|
||||
? 0.0
|
||||
: static_cast<double>(numerator) / static_cast<double>(denominator);
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
case FLOAT: {
|
||||
union IntFloat {
|
||||
std::uint32_t i;
|
||||
float f;
|
||||
} conv;
|
||||
|
||||
conv.i = sget4(tag->second.value.data() + offset);
|
||||
return conv.f; // IEEE FLOATs are already C format, they just need a recast
|
||||
}
|
||||
|
||||
default: {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int getCount(int id) const
|
||||
{
|
||||
const Tags::const_iterator tag = tags_.find(id);
|
||||
if (tag != tags_.end()) {
|
||||
return tag->second.count;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private:
|
||||
struct Tag {
|
||||
int id;
|
||||
std::vector<unsigned char> value;
|
||||
TagType type;
|
||||
unsigned int count;
|
||||
};
|
||||
|
||||
using Tags = std::unordered_map<int, Tag>;
|
||||
|
||||
std::uint16_t sget2(const std::uint8_t* s) const
|
||||
{
|
||||
if (order_ == INTEL) {
|
||||
return s[0] | s[1] << 8;
|
||||
} else {
|
||||
return s[0] << 8 | s[1];
|
||||
}
|
||||
}
|
||||
|
||||
std::uint32_t sget4(const std::uint8_t* s) const
|
||||
{
|
||||
if (order_ == INTEL) {
|
||||
return s[0] | s[1] << 8 | s[2] << 16 | s[3] << 24;
|
||||
} else {
|
||||
return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3];
|
||||
}
|
||||
}
|
||||
|
||||
std::uint16_t get2()
|
||||
{
|
||||
std::uint16_t res = std::numeric_limits<std::uint16_t>::max();
|
||||
std::fread(&res, 1, 2, file_);
|
||||
return sget2(reinterpret_cast<const std::uint8_t*>(&res));
|
||||
}
|
||||
|
||||
std::uint32_t get4()
|
||||
{
|
||||
std::uint32_t res = std::numeric_limits<std::uint32_t>::max();
|
||||
std::fread(&res, 1, 4, file_);
|
||||
return sget4(reinterpret_cast<const std::uint8_t*>(&res));
|
||||
}
|
||||
|
||||
static int getTypeSize(TagType type)
|
||||
{
|
||||
switch (type) {
|
||||
case INVALID:
|
||||
case BYTE:
|
||||
case ASCII:
|
||||
case SBYTE:
|
||||
case UNDEFINED: {
|
||||
return 1;
|
||||
}
|
||||
|
||||
case SHORT:
|
||||
case SSHORT: {
|
||||
return 2;
|
||||
}
|
||||
|
||||
case LONG:
|
||||
case SLONG:
|
||||
case FLOAT: {
|
||||
return 4;
|
||||
}
|
||||
|
||||
case RATIONAL:
|
||||
case SRATIONAL:
|
||||
case DOUBLE: {
|
||||
return 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool parseTag(Tag& tag)
|
||||
{
|
||||
tag.id = get2();
|
||||
tag.type = TagType(get2());
|
||||
tag.count = std::max(1U, get4());
|
||||
|
||||
// Filter out invalid tags
|
||||
// Note: The large count is to be able to pass LeafData ASCII tag which can be up to almost 10 megabytes,
|
||||
// (only a small part of it will actually be parsed though)
|
||||
if (
|
||||
tag.type == INVALID
|
||||
|| tag.type > DOUBLE
|
||||
|| tag.count > 10 * 1024 * 1024
|
||||
) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Store next Tag's position in file
|
||||
const std::size_t saved_position = std::ftell(file_) + 4;
|
||||
|
||||
// Load value field (possibly seek before)
|
||||
const std::size_t value_size = tag.count * getTypeSize(tag.type);
|
||||
|
||||
if (value_size > 4) {
|
||||
if (std::fseek(file_, get4(), SEEK_SET) == -1) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Read value
|
||||
tag.value.resize(value_size + 1);
|
||||
const std::size_t read = std::fread(tag.value.data(), 1, value_size, file_);
|
||||
if (read != value_size) {
|
||||
tag.type = INVALID;
|
||||
return false;
|
||||
}
|
||||
tag.value[read] = '\0';
|
||||
|
||||
// Seek back to the saved position
|
||||
std::fseek(file_, saved_position, SEEK_SET);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FILE* const file_;
|
||||
|
||||
Tags tags_;
|
||||
ByteOrder order_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
struct DCPProfileApplyState::Data {
|
||||
float pro_photo[3][3];
|
||||
|
@ -462,23 +832,23 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
delta_info.hue_step = delta_info.val_step = look_info.hue_step = look_info.val_step = 0;
|
||||
constexpr int tiff_float_size = 4;
|
||||
|
||||
enum class TagKey : int {
|
||||
COLOR_MATRIX_1 = 50721,
|
||||
COLOR_MATRIX_2 = 50722,
|
||||
PROFILE_HUE_SAT_MAP_DIMS = 50937,
|
||||
PROFILE_HUE_SAT_MAP_DATA_1 = 50938,
|
||||
PROFILE_HUE_SAT_MAP_DATA_2 = 50939,
|
||||
PROFILE_TONE_CURVE = 50940,
|
||||
PROFILE_TONE_COPYRIGHT = 50942,
|
||||
CALIBRATION_ILLUMINANT_1 = 50778,
|
||||
CALIBRATION_ILLUMINANT_2 = 50779,
|
||||
FORWARD_MATRIX_1 = 50964,
|
||||
FORWARD_MATRIX_2 = 50965,
|
||||
PROFILE_LOOK_TABLE_DIMS = 50981, // ProfileLookup is the low quality variant
|
||||
PROFILE_LOOK_TABLE_DATA = 50982,
|
||||
PROFILE_HUE_SAT_MAP_ENCODING = 51107,
|
||||
PROFILE_LOOK_TABLE_ENCODING = 51108,
|
||||
BASELINE_EXPOSURE_OFFSET = 51109
|
||||
enum TagKey {
|
||||
TAG_KEY_COLOR_MATRIX_1 = 50721,
|
||||
TAG_KEY_COLOR_MATRIX_2 = 50722,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS = 50937,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1 = 50938,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2 = 50939,
|
||||
TAG_KEY_PROFILE_TONE_CURVE = 50940,
|
||||
TAG_KEY_PROFILE_TONE_COPYRIGHT = 50942,
|
||||
TAG_KEY_CALIBRATION_ILLUMINANT_1 = 50778,
|
||||
TAG_KEY_CALIBRATION_ILLUMINANT_2 = 50779,
|
||||
TAG_KEY_FORWARD_MATRIX_1 = 50964,
|
||||
TAG_KEY_FORWARD_MATRIX_2 = 50965,
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_DIMS = 50981, // ProfileLookup is the low quality variant
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_DATA = 50982,
|
||||
TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING = 51107,
|
||||
TAG_KEY_PROFILE_LOOK_TABLE_ENCODING = 51108,
|
||||
TAG_KEY_BASELINE_EXPOSURE_OFFSET = 51109
|
||||
};
|
||||
|
||||
static const float adobe_camera_raw_default_curve[] = {
|
||||
|
@ -748,54 +1118,48 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
return;
|
||||
}
|
||||
|
||||
ExifManager exifManager(file, nullptr, true);
|
||||
exifManager.parseTIFF(false);
|
||||
std::unique_ptr<TagDirectory> tagDir(exifManager.roots.at(0));
|
||||
DCPMetadata md(file);
|
||||
if (!md.parse()) {
|
||||
printf ("Unable to load DCP profile '%s'.", filename.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
Tag* tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_1));
|
||||
light_source_1 =
|
||||
tag
|
||||
? tag->toInt(0, rtexif::SHORT)
|
||||
: -1;
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::CALIBRATION_ILLUMINANT_2));
|
||||
md.find(TAG_KEY_CALIBRATION_ILLUMINANT_1)
|
||||
? md.toShort(TAG_KEY_CALIBRATION_ILLUMINANT_1)
|
||||
: -1;
|
||||
light_source_2 =
|
||||
tag
|
||||
? tag->toInt(0, rtexif::SHORT)
|
||||
: -1;
|
||||
md.find(TAG_KEY_CALIBRATION_ILLUMINANT_2)
|
||||
? md.toShort(TAG_KEY_CALIBRATION_ILLUMINANT_2)
|
||||
: -1;
|
||||
temperature_1 = calibrationIlluminantToTemperature(light_source_1);
|
||||
temperature_2 = calibrationIlluminantToTemperature(light_source_2);
|
||||
|
||||
const bool has_second_hue_sat = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_2)); // Some profiles have two matrices, but just one huesat
|
||||
const bool has_second_hue_sat = md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2); // Some profiles have two matrices, but just one huesat
|
||||
|
||||
// Fetch Forward Matrices, if any
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::FORWARD_MATRIX_1));
|
||||
|
||||
if (tag) {
|
||||
has_forward_matrix_1 = true;
|
||||
has_forward_matrix_1 = md.find(TAG_KEY_FORWARD_MATRIX_1);
|
||||
|
||||
if (has_forward_matrix_1) {
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
forward_matrix_1[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
forward_matrix_1[row][col] = md.toDouble(TAG_KEY_FORWARD_MATRIX_1, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::FORWARD_MATRIX_2));
|
||||
|
||||
if (tag) {
|
||||
has_forward_matrix_2 = true;
|
||||
has_forward_matrix_2 = md.find(TAG_KEY_FORWARD_MATRIX_2);
|
||||
|
||||
if (has_forward_matrix_2) {
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
forward_matrix_2[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
forward_matrix_2[row][col] = md.toDouble(TAG_KEY_FORWARD_MATRIX_2, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Color Matrix (one is always there)
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::COLOR_MATRIX_1));
|
||||
|
||||
if (!tag) {
|
||||
if (!md.find(TAG_KEY_COLOR_MATRIX_1)) {
|
||||
std::cerr << "DCP '" << filename << "' is missing 'ColorMatrix1'. Skipped." << std::endl;
|
||||
fclose(file);
|
||||
return;
|
||||
|
@ -805,29 +1169,24 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
color_matrix_1[row][col] = tag->toDouble((col + row * 3) * 8);
|
||||
color_matrix_1[row][col] = md.toDouble(TAG_KEY_COLOR_MATRIX_1, (col + row * 3) * 8);
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_DIMS));
|
||||
if (md.find(TAG_KEY_PROFILE_LOOK_TABLE_DIMS)) {
|
||||
look_info.hue_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 0);
|
||||
look_info.sat_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 4);
|
||||
look_info.val_divisions = md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_DIMS, 8);
|
||||
|
||||
if (tag) {
|
||||
look_info.hue_divisions = tag->toInt(0);
|
||||
look_info.sat_divisions = tag->toInt(4);
|
||||
look_info.val_divisions = tag->toInt(8);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_ENCODING));
|
||||
look_info.srgb_gamma = tag && tag->toInt(0);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_LOOK_TABLE_DATA));
|
||||
look_info.array_count = tag->getCount() / 3;
|
||||
look_info.srgb_gamma = md.find(TAG_KEY_PROFILE_LOOK_TABLE_ENCODING) && md.toInt(TAG_KEY_PROFILE_LOOK_TABLE_ENCODING);
|
||||
|
||||
look_info.array_count = md.getCount(TAG_KEY_PROFILE_LOOK_TABLE_DATA) / 3;
|
||||
look_table.resize(look_info.array_count);
|
||||
|
||||
for (unsigned int i = 0; i < look_info.array_count; i++) {
|
||||
look_table[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
look_table[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
look_table[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
look_table[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3) * tiff_float_size);
|
||||
look_table[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3 + 1) * tiff_float_size);
|
||||
look_table[i].val_scale = md.toDouble(TAG_KEY_PROFILE_LOOK_TABLE_DATA, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
|
||||
// Precalculated constants for table application
|
||||
|
@ -844,25 +1203,20 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
look_info.pc.val_step = look_info.hue_divisions * look_info.pc.hue_step;
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DIMS));
|
||||
if (md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS)) {
|
||||
delta_info.hue_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 0);
|
||||
delta_info.sat_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 4);
|
||||
delta_info.val_divisions = md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_DIMS, 8);
|
||||
|
||||
if (tag) {
|
||||
delta_info.hue_divisions = tag->toInt(0);
|
||||
delta_info.sat_divisions = tag->toInt(4);
|
||||
delta_info.val_divisions = tag->toInt(8);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_ENCODING));
|
||||
delta_info.srgb_gamma = tag && tag->toInt(0);
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_1));
|
||||
delta_info.array_count = tag->getCount() / 3;
|
||||
delta_info.srgb_gamma = md.find(TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING) && md.toInt(TAG_KEY_PROFILE_HUE_SAT_MAP_ENCODING);
|
||||
|
||||
delta_info.array_count = md.getCount(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1) / 3;
|
||||
deltas_1.resize(delta_info.array_count);
|
||||
|
||||
for (unsigned int i = 0; i < delta_info.array_count; ++i) {
|
||||
deltas_1[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
deltas_1[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
deltas_1[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
deltas_1[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3) * tiff_float_size);
|
||||
deltas_1[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3 + 1) * tiff_float_size);
|
||||
deltas_1[i].val_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_1, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
|
||||
delta_info.pc.h_scale =
|
||||
|
@ -882,14 +1236,14 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
// Second matrix
|
||||
has_color_matrix_2 = true;
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::COLOR_MATRIX_2));
|
||||
const bool cm2 = md.find(TAG_KEY_COLOR_MATRIX_2);
|
||||
|
||||
for (int row = 0; row < 3; ++row) {
|
||||
for (int col = 0; col < 3; ++col) {
|
||||
color_matrix_2[row][col] =
|
||||
tag
|
||||
? tag->toDouble((col + row * 3) * 8)
|
||||
: color_matrix_1[row][col];
|
||||
cm2
|
||||
? md.toDouble(TAG_KEY_COLOR_MATRIX_2, (col + row * 3) * 8)
|
||||
: color_matrix_1[row][col];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -898,27 +1252,21 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
deltas_2.resize(delta_info.array_count);
|
||||
|
||||
// Saturation maps. Need to be unwinded.
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_HUE_SAT_MAP_DATA_2));
|
||||
|
||||
for (unsigned int i = 0; i < delta_info.array_count; ++i) {
|
||||
deltas_2[i].hue_shift = tag->toDouble((i * 3) * tiff_float_size);
|
||||
deltas_2[i].sat_scale = tag->toDouble((i * 3 + 1) * tiff_float_size);
|
||||
deltas_2[i].val_scale = tag->toDouble((i * 3 + 2) * tiff_float_size);
|
||||
deltas_2[i].hue_shift = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3) * tiff_float_size);
|
||||
deltas_2[i].sat_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3 + 1) * tiff_float_size);
|
||||
deltas_2[i].val_scale = md.toDouble(TAG_KEY_PROFILE_HUE_SAT_MAP_DATA_2, (i * 3 + 2) * tiff_float_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::BASELINE_EXPOSURE_OFFSET));
|
||||
|
||||
if (tag) {
|
||||
has_baseline_exposure_offset = true;
|
||||
baseline_exposure_offset = tag->toDouble();
|
||||
has_baseline_exposure_offset = md.find(TAG_KEY_BASELINE_EXPOSURE_OFFSET);
|
||||
if (has_baseline_exposure_offset) {
|
||||
baseline_exposure_offset = md.toDouble(TAG_KEY_BASELINE_EXPOSURE_OFFSET);
|
||||
}
|
||||
|
||||
// Read tone curve points, if any, but disable to RTs own profiles
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_TONE_CURVE));
|
||||
|
||||
if (tag) {
|
||||
if (md.find(TAG_KEY_PROFILE_TONE_CURVE)) {
|
||||
std::vector<double> curve_points = {
|
||||
static_cast<double>(DCT_Spline) // The first value is the curve type
|
||||
};
|
||||
|
@ -926,9 +1274,9 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
// Push back each X/Y coordinates in a loop
|
||||
bool curve_is_linear = true;
|
||||
|
||||
for (int i = 0; i < tag->getCount(); i += 2) {
|
||||
const double x = tag->toDouble((i + 0) * tiff_float_size);
|
||||
const double y = tag->toDouble((i + 1) * tiff_float_size);
|
||||
for (unsigned int i = 0, n = md.getCount(TAG_KEY_PROFILE_TONE_CURVE); i < n; i += 2) {
|
||||
const double x = md.toDouble(TAG_KEY_PROFILE_TONE_CURVE, (i + 0) * tiff_float_size);
|
||||
const double y = md.toDouble(TAG_KEY_PROFILE_TONE_CURVE, (i + 1) * tiff_float_size);
|
||||
|
||||
if (x != y) {
|
||||
curve_is_linear = false;
|
||||
|
@ -944,9 +1292,7 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) :
|
|||
tone_curve.Set(DiagonalCurve(curve_points, CURVES_MIN_POLY_POINTS));
|
||||
}
|
||||
} else {
|
||||
tag = tagDir->getTag(toUnderlying(TagKey::PROFILE_TONE_COPYRIGHT));
|
||||
|
||||
if (tag && tag->valueToString().find("Adobe Systems") != std::string::npos) {
|
||||
if (md.find(TAG_KEY_PROFILE_TONE_COPYRIGHT) && md.toString(TAG_KEY_PROFILE_TONE_COPYRIGHT).find("Adobe Systems") != std::string::npos) {
|
||||
// An Adobe profile without tone curve is expected to have the Adobe Default Curve, we add that
|
||||
std::vector<double> curve_points = {
|
||||
static_cast<double>(DCT_Spline)
|
||||
|
@ -1799,7 +2145,7 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll)
|
|||
|
||||
std::deque<Glib::ustring> dirs = {
|
||||
rt_profile_dir,
|
||||
Glib::build_filename(options.rtdir, "dcpprofiles")
|
||||
Glib::build_filename(options.rtdir, "dcpprofiles")
|
||||
};
|
||||
|
||||
while (!dirs.empty()) {
|
||||
|
|
|
@ -390,7 +390,7 @@ dfInfo* DFManager::addFileInfo (const Glib::ustring& filename, bool pool)
|
|||
return &(iter->second);
|
||||
}
|
||||
|
||||
FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
|
||||
FramesData idata(filename);
|
||||
/* Files are added in the map, divided by same maker/model,ISO and shutter*/
|
||||
std::string key(dfInfo::key(((Glib::ustring)idata.getMake()).uppercase(), ((Glib::ustring)idata.getModel()).uppercase(), idata.getISOSpeed(), idata.getShutterSpeed()));
|
||||
iter = dfList.find(key);
|
||||
|
|
|
@ -86,7 +86,7 @@ bool DynamicProfileRule::matches (const rtengine::FramesMetaData *im) const
|
|||
&& expcomp (im->getExpComp())
|
||||
&& camera (im->getCamera())
|
||||
&& lens (im->getLens())
|
||||
&& imagetype(im->getImageType(0)));
|
||||
&& imagetype(im->getImageType()));
|
||||
}
|
||||
|
||||
namespace
|
||||
|
|
|
@ -342,7 +342,7 @@ ffInfo* FFManager::addFileInfo (const Glib::ustring& filename, bool pool)
|
|||
return &(iter->second);
|
||||
}
|
||||
|
||||
FramesData idata(filename, std::unique_ptr<RawMetaDataLocation>(new RawMetaDataLocation(ri.get_exifBase(), ri.get_ciffBase(), ri.get_ciffLen())), true);
|
||||
FramesData idata(filename);
|
||||
/* Files are added in the map, divided by same maker/model,lens and aperture*/
|
||||
std::string key(ffInfo::key(idata.getMake(), idata.getModel(), idata.getLens(), idata.getFocalLen(), idata.getFNumber()));
|
||||
iter = ffList.find(key);
|
||||
|
|
|
@ -277,10 +277,9 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st
|
|||
|
||||
std::unique_ptr<IImage8> source;
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
eSensorType sensor_type;
|
||||
int w, h;
|
||||
std::unique_ptr<Thumbnail> thumb(Thumbnail::loadQuickFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, true, true));
|
||||
const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadQuickFromRaw(getFileName(), sensor_type, w, h, 1, false, true, true));
|
||||
if (!thumb) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "histogram matching: no thumbnail found, generating a neutral curve" << std::endl;
|
||||
|
@ -309,11 +308,10 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st
|
|||
|
||||
std::unique_ptr<IImage8> target;
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
eSensorType sensor_type;
|
||||
double scale;
|
||||
int w = fw / skip, h = fh / skip;
|
||||
std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), rml, sensor_type, w, h, 1, false, false, true));
|
||||
const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), sensor_type, w, h, 1, false, false, true));
|
||||
if (!thumb) {
|
||||
if (settings->verbose) {
|
||||
std::cout << "histogram matching: raw decoding failed, generating a neutral curve" << std::endl;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -21,36 +21,24 @@
|
|||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <glibmm.h>
|
||||
#include <exiv2/exiv2.hpp>
|
||||
|
||||
|
||||
#include <libiptcdata/iptc-data.h>
|
||||
|
||||
#include "imageio.h"
|
||||
|
||||
namespace Glib
|
||||
{
|
||||
|
||||
class ustring;
|
||||
|
||||
}
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class TagDirectory;
|
||||
}
|
||||
#include "rawimage.h"
|
||||
#include "rtengine.h"
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class FrameData final
|
||||
Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring &fname); // TODO: Global function?
|
||||
|
||||
class FramesData :
|
||||
public FramesMetaData
|
||||
{
|
||||
|
||||
protected:
|
||||
rtexif::TagDirectory* frameRootDir;
|
||||
IptcData* iptc;
|
||||
|
||||
private:
|
||||
bool ok_;
|
||||
Glib::ustring fname_;
|
||||
unsigned int dcrawFrameCount;
|
||||
struct tm time;
|
||||
time_t timeStamp;
|
||||
int iso_speed;
|
||||
|
@ -64,85 +52,35 @@ protected:
|
|||
int rating;
|
||||
std::string lens;
|
||||
IIOSampleFormat sampleFormat;
|
||||
|
||||
// each frame has the knowledge of "being an"
|
||||
// or "being part of an" HDR or PS image
|
||||
bool isPixelShift;
|
||||
bool isHDR;
|
||||
|
||||
public:
|
||||
FramesData(const Glib::ustring& fname);
|
||||
|
||||
FrameData (rtexif::TagDirectory* frameRootDir, rtexif::TagDirectory* rootDir, rtexif::TagDirectory* firstRootDir);
|
||||
virtual ~FrameData ();
|
||||
|
||||
bool getPixelShift () const;
|
||||
bool getHDR () const;
|
||||
std::string getImageType () const;
|
||||
IIOSampleFormat getSampleFormat () const;
|
||||
rtexif::TagDirectory* getExifData () const;
|
||||
procparams::IPTCPairs getIPTCData () const;
|
||||
static procparams::IPTCPairs getIPTCData (IptcData* iptc_);
|
||||
bool hasExif () const;
|
||||
bool hasIPTC () const;
|
||||
tm getDateTime () const;
|
||||
time_t getDateTimeAsTS () const;
|
||||
int getISOSpeed () const;
|
||||
double getFNumber () const;
|
||||
double getFocalLen () const;
|
||||
double getFocalLen35mm () const;
|
||||
float getFocusDist () const;
|
||||
double getShutterSpeed () const;
|
||||
double getExpComp () const;
|
||||
std::string getMake () const;
|
||||
std::string getModel () const;
|
||||
std::string getLens () const;
|
||||
std::string getSerialNumber () const;
|
||||
std::string getOrientation () const;
|
||||
int getRating () const;
|
||||
void setDCRawFrameCount(unsigned int frameCount);
|
||||
unsigned int getFrameCount() const override;
|
||||
bool getPixelShift() const override;
|
||||
bool getHDR() const override;
|
||||
std::string getImageType() const override;
|
||||
IIOSampleFormat getSampleFormat() const override;
|
||||
bool hasExif() const override;
|
||||
tm getDateTime() const override;
|
||||
time_t getDateTimeAsTS() const override;
|
||||
int getISOSpeed() const override;
|
||||
double getFNumber() const override;
|
||||
double getFocalLen() const override;
|
||||
double getFocalLen35mm() const override;
|
||||
float getFocusDist() const override;
|
||||
double getShutterSpeed() const override;
|
||||
double getExpComp() const override;
|
||||
std::string getMake() const override;
|
||||
std::string getModel() const override;
|
||||
std::string getLens() const override;
|
||||
std::string getSerialNumber() const;
|
||||
std::string getOrientation() const override;
|
||||
int getRating() const override;
|
||||
Glib::ustring getFileName() const override;
|
||||
};
|
||||
|
||||
class FramesData final : public FramesMetaData {
|
||||
private:
|
||||
// frame's root IFD, can be a file root IFD or a SUB-IFD
|
||||
std::vector<std::unique_ptr<FrameData>> frames;
|
||||
// root IFD in the file
|
||||
std::vector<rtexif::TagDirectory*> roots;
|
||||
IptcData* iptc;
|
||||
unsigned int dcrawFrameCount;
|
||||
|
||||
public:
|
||||
explicit FramesData (const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml = nullptr, bool firstFrameOnly = false);
|
||||
~FramesData () override;
|
||||
|
||||
void setDCRawFrameCount (unsigned int frameCount);
|
||||
unsigned int getRootCount () const override;
|
||||
unsigned int getFrameCount () const override;
|
||||
bool getPixelShift () const override;
|
||||
bool getHDR (unsigned int frame = 0) const override;
|
||||
std::string getImageType (unsigned int frame) const override;
|
||||
IIOSampleFormat getSampleFormat (unsigned int frame = 0) const override;
|
||||
rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const override;
|
||||
rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const override;
|
||||
rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const override;
|
||||
procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const override;
|
||||
bool hasExif (unsigned int frame = 0) const override;
|
||||
bool hasIPTC (unsigned int frame = 0) const override;
|
||||
tm getDateTime (unsigned int frame = 0) const override;
|
||||
time_t getDateTimeAsTS (unsigned int frame = 0) const override;
|
||||
int getISOSpeed (unsigned int frame = 0) const override;
|
||||
double getFNumber (unsigned int frame = 0) const override;
|
||||
double getFocalLen (unsigned int frame = 0) const override;
|
||||
double getFocalLen35mm (unsigned int frame = 0) const override;
|
||||
float getFocusDist (unsigned int frame = 0) const override;
|
||||
double getShutterSpeed (unsigned int frame = 0) const override;
|
||||
double getExpComp (unsigned int frame = 0) const override;
|
||||
std::string getMake (unsigned int frame = 0) const override;
|
||||
std::string getModel (unsigned int frame = 0) const override;
|
||||
std::string getLens (unsigned int frame = 0) const override;
|
||||
std::string getSerialNumber (unsigned int frame = 0) const;
|
||||
std::string getOrientation (unsigned int frame = 0) const override;
|
||||
int getRating (unsigned int frame = 0) const override;
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <fcntl.h>
|
||||
#include <libiptcdata/iptc-jpeg.h>
|
||||
#include "rt_math.h"
|
||||
#include "procparams.h"
|
||||
#include "utils.h"
|
||||
|
@ -39,9 +38,9 @@
|
|||
#endif
|
||||
|
||||
#include "imageio.h"
|
||||
#include "iptcpairs.h"
|
||||
#include "iccjpeg.h"
|
||||
#include "color.h"
|
||||
#include "imagedata.h"
|
||||
|
||||
#include "jpeg.h"
|
||||
|
||||
|
@ -80,125 +79,55 @@ FILE* g_fopen_withBinaryAndLock(const Glib::ustring& fname)
|
|||
|
||||
}
|
||||
|
||||
Glib::ustring ImageIO::errorMsg[6] = {"Success", "Cannot read file.", "Invalid header.", "Error while reading header.", "File reading error", "Image format not supported."};
|
||||
|
||||
// For only copying the raw input data
|
||||
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot)
|
||||
MetadataInfo::MetadataInfo(const Glib::ustring& src) :
|
||||
src_(src),
|
||||
exif_(new rtengine::procparams::ExifPairs),
|
||||
iptc_(new rtengine::procparams::IPTCPairs)
|
||||
{
|
||||
if (exifRoot != nullptr) {
|
||||
delete exifRoot;
|
||||
exifRoot = nullptr;
|
||||
}
|
||||
|
||||
if (eroot) {
|
||||
rtexif::TagDirectory* td = eroot->clone (nullptr);
|
||||
|
||||
// make IPTC and XMP pass through
|
||||
td->keepTag(0x83bb); // IPTC
|
||||
td->keepTag(0x02bc); // XMP
|
||||
|
||||
exifRoot = td;
|
||||
}
|
||||
}
|
||||
|
||||
// For merging with RT specific data
|
||||
void ImageIO::setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc)
|
||||
const Glib::ustring& MetadataInfo::filename() const
|
||||
{
|
||||
|
||||
// store exif info
|
||||
exifChange->clear();
|
||||
*exifChange = exif;
|
||||
|
||||
if (exifRoot != nullptr) {
|
||||
delete exifRoot;
|
||||
exifRoot = nullptr;
|
||||
}
|
||||
|
||||
if (eroot) {
|
||||
exifRoot = eroot->clone (nullptr);
|
||||
}
|
||||
|
||||
if (iptc != nullptr) {
|
||||
iptc_data_free (iptc);
|
||||
iptc = nullptr;
|
||||
}
|
||||
|
||||
// build iptc structures for libiptcdata
|
||||
if (iptcc.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
iptc = iptc_data_new ();
|
||||
|
||||
const unsigned char utf8Esc[] = {0x1B, '%', 'G'};
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_OBJECT_ENV, IPTC_TAG_CHARACTER_SET);
|
||||
iptc_dataset_set_data (ds, utf8Esc, 3, IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
|
||||
for (rtengine::procparams::IPTCPairs::const_iterator i = iptcc.begin(); i != iptcc.end(); ++i) {
|
||||
if (i->first == "Keywords" && !(i->second.empty())) {
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_KEYWORDS);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(64), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
|
||||
continue;
|
||||
} else if (i->first == "SupplementalCategories" && !(i->second.empty())) {
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, IPTC_TAG_SUPPL_CATEGORY);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(j).c_str(), min(static_cast<size_t>(32), i->second.at(j).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < 16; j++)
|
||||
if (i->first == strTags[j].field && !(i->second.empty())) {
|
||||
IptcDataSet * ds = iptc_dataset_new ();
|
||||
iptc_dataset_set_tag (ds, IPTC_RECORD_APP_2, strTags[j].tag);
|
||||
iptc_dataset_set_data (ds, (const unsigned char*)i->second.at(0).c_str(), min(strTags[j].size, i->second.at(0).bytes()), IPTC_DONT_VALIDATE);
|
||||
iptc_data_add_dataset (iptc, ds);
|
||||
iptc_dataset_unref (ds);
|
||||
}
|
||||
}
|
||||
|
||||
iptc_data_sort (iptc);
|
||||
return src_;
|
||||
}
|
||||
|
||||
void ImageIO::setOutputProfile (const char* pdata, int plen)
|
||||
const rtengine::procparams::ExifPairs& MetadataInfo::exif() const
|
||||
{
|
||||
return *exif_;
|
||||
}
|
||||
|
||||
delete [] profileData;
|
||||
const rtengine::procparams::IPTCPairs& MetadataInfo::iptc() const
|
||||
{
|
||||
return *iptc_;
|
||||
}
|
||||
|
||||
if (pdata) {
|
||||
profileData = new char [plen];
|
||||
memcpy (profileData, pdata, plen);
|
||||
} else {
|
||||
profileData = nullptr;
|
||||
}
|
||||
void MetadataInfo::setExif(const rtengine::procparams::ExifPairs &exif)
|
||||
{
|
||||
*exif_ = exif;
|
||||
}
|
||||
|
||||
profileLength = plen;
|
||||
void MetadataInfo::setIptc(const rtengine::procparams::IPTCPairs &iptc)
|
||||
{
|
||||
*iptc_ = iptc;
|
||||
}
|
||||
|
||||
void ImageIO::setMetadata(MetadataInfo info)
|
||||
{
|
||||
metadataInfo = std::move(info);
|
||||
}
|
||||
|
||||
void ImageIO::setOutputProfile(const std::string& pdata)
|
||||
{
|
||||
profileData = pdata;
|
||||
}
|
||||
|
||||
ImageIO::ImageIO() :
|
||||
pl(nullptr),
|
||||
embProfile(nullptr),
|
||||
profileData(nullptr),
|
||||
profileLength(0),
|
||||
loadedProfileData(nullptr),
|
||||
loadedProfileDataJpg(false),
|
||||
loadedProfileLength(0),
|
||||
exifChange(new procparams::ExifPairs),
|
||||
iptc(nullptr),
|
||||
exifRoot(nullptr),
|
||||
sampleFormat(IIOSF_UNKNOWN),
|
||||
sampleArrangement(IIOSA_UNKNOWN)
|
||||
{
|
||||
|
@ -212,8 +141,6 @@ ImageIO::~ImageIO ()
|
|||
}
|
||||
|
||||
deleteLoadedProfileData();
|
||||
delete exifRoot;
|
||||
delete [] profileData;
|
||||
}
|
||||
|
||||
void png_read_data(png_struct_def *png_ptr, unsigned char *data, size_t length);
|
||||
|
@ -925,76 +852,6 @@ int ImageIO::loadPPMFromMemory(const char* buffer, int width, int height, bool s
|
|||
}
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// Taken from Darktable -- src/imageio/format/png.c
|
||||
//
|
||||
/* Write EXIF data to PNG file.
|
||||
* Code copied from DigiKam's libs/dimg/loaders/pngloader.cpp.
|
||||
* The EXIF embedding is defined by ImageMagicK.
|
||||
* It is documented in the ExifTool page:
|
||||
* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/PNG.html
|
||||
*
|
||||
* ..and in turn copied from ufraw. thanks to udi and colleagues
|
||||
* for making useful code much more readable and discoverable ;)
|
||||
*/
|
||||
|
||||
void PNGwriteRawProfile(png_struct *ping, png_info *ping_info, const char *profile_type, guint8 *profile_data, png_uint_32 length)
|
||||
{
|
||||
png_textp text;
|
||||
long i;
|
||||
guint8 *sp;
|
||||
png_charp dp;
|
||||
png_uint_32 allocated_length, description_length;
|
||||
|
||||
const guint8 hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
|
||||
text = static_cast<png_textp>(png_malloc(ping, sizeof(png_text)));
|
||||
description_length = strlen(profile_type);
|
||||
allocated_length = length * 2 + (length >> 5) + 20 + description_length;
|
||||
|
||||
text[0].text = static_cast<png_charp>(png_malloc(ping, allocated_length));
|
||||
text[0].key = static_cast<png_charp>(png_malloc(ping, 80));
|
||||
text[0].key[0] = '\0';
|
||||
|
||||
g_strlcat(text[0].key, "Raw profile type ", 80);
|
||||
g_strlcat(text[0].key, profile_type, 80);
|
||||
|
||||
sp = profile_data;
|
||||
dp = text[0].text;
|
||||
*dp++ = '\n';
|
||||
|
||||
g_strlcpy(dp, profile_type, allocated_length);
|
||||
|
||||
dp += description_length;
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
|
||||
g_snprintf(dp, allocated_length - strlen(text[0].text), "%8lu ", static_cast<unsigned long int>(length));
|
||||
|
||||
dp += 8;
|
||||
|
||||
for(i = 0; i < long(length); i++)
|
||||
{
|
||||
if(i % 36 == 0) *dp++ = '\n';
|
||||
|
||||
*(dp++) = hex[((*sp >> 4) & 0x0f)];
|
||||
*(dp++) = hex[((*sp++) & 0x0f)];
|
||||
}
|
||||
|
||||
*dp++ = '\n';
|
||||
*dp = '\0';
|
||||
text[0].text_length = (dp - text[0].text);
|
||||
text[0].compression = -1;
|
||||
|
||||
if(text[0].text_length <= allocated_length) png_set_text(ping, ping_info, text, 1);
|
||||
|
||||
png_free(ping, text[0].text);
|
||||
png_free(ping, text[0].key);
|
||||
png_free(ping, text);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
||||
{
|
||||
if (getWidth() < 1 || getHeight() < 1) {
|
||||
|
@ -1023,7 +880,7 @@ int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
|||
#if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && defined(PNG_SET_OPTION_SUPPORTED)
|
||||
png_set_option(png, PNG_SKIP_sRGB_CHECK_PROFILE, PNG_OPTION_ON);
|
||||
#endif
|
||||
|
||||
|
||||
png_infop info = png_create_info_struct(png);
|
||||
|
||||
if (!info) {
|
||||
|
@ -1057,39 +914,15 @@ int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
|||
png_set_IHDR(png, info, width, height, bps, PNG_COLOR_TYPE_RGB,
|
||||
PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_BASE);
|
||||
|
||||
if (profileData) {
|
||||
if (!profileData.empty()) {
|
||||
#if PNG_LIBPNG_VER < 10500
|
||||
png_charp profdata = reinterpret_cast<png_charp>(profileData);
|
||||
png_const_charp profdata = reinterpret_cast<png_const_charp>(profileData.data());
|
||||
#else
|
||||
png_bytep profdata = reinterpret_cast<png_bytep>(profileData);
|
||||
png_const_bytep profdata = reinterpret_cast<png_const_bytep>(profileData.data());
|
||||
#endif
|
||||
png_set_iCCP(png, info, const_cast<png_charp>("icc"), 0, profdata, profileLength);
|
||||
png_set_iCCP(png, info, "icc", 0, profdata, profileData.size());
|
||||
}
|
||||
|
||||
{
|
||||
// buffer for the exif and iptc
|
||||
unsigned int bufferSize;
|
||||
unsigned char* buffer = nullptr; // buffer will be allocated in createTIFFHeader
|
||||
unsigned char* iptcdata = nullptr;
|
||||
unsigned int iptclen = 0;
|
||||
|
||||
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen) && iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
iptcdata = nullptr;
|
||||
}
|
||||
|
||||
int size = rtexif::ExifManager::createPNGMarker(exifRoot, *exifChange, width, height, bps, (char*)iptcdata, iptclen, buffer, bufferSize);
|
||||
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
if (buffer && size) {
|
||||
PNGwriteRawProfile(png, info, "exif", buffer, size);
|
||||
delete[] buffer;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int rowlen = width * 3 * bps / 8;
|
||||
unsigned char *row = new unsigned char [rowlen];
|
||||
|
||||
|
@ -1123,6 +956,11 @@ int ImageIO::savePNG (const Glib::ustring &fname, int bps) const
|
|||
delete [] row;
|
||||
fclose (file);
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
g_remove(fname.c_str());
|
||||
return IMIO_CANNOTWRITEFILE;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
|
@ -1222,52 +1060,9 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
|||
|
||||
jpeg_start_compress(&cinfo, TRUE);
|
||||
|
||||
// buffer for exif and iptc markers
|
||||
unsigned char* buffer = new unsigned char[165535]; //FIXME: no buffer size check so it can be overflowed in createJPEGMarker() for large tags, and then software will crash
|
||||
unsigned int size;
|
||||
|
||||
// assemble and write exif marker
|
||||
if (exifRoot) {
|
||||
int size = rtexif::ExifManager::createJPEGMarker (exifRoot, *exifChange, cinfo.image_width, cinfo.image_height, buffer);
|
||||
|
||||
if (size > 0 && size < 65530) {
|
||||
jpeg_write_marker(&cinfo, JPEG_APP0 + 1, buffer, size);
|
||||
}
|
||||
}
|
||||
|
||||
// assemble and write iptc marker
|
||||
if (iptc) {
|
||||
unsigned char* iptcdata;
|
||||
bool error = false;
|
||||
|
||||
if (iptc_data_save (iptc, &iptcdata, &size)) {
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
|
||||
error = true;
|
||||
}
|
||||
|
||||
int bytes = 0;
|
||||
|
||||
if (!error && (bytes = iptc_jpeg_ps3_save_iptc (nullptr, 0, iptcdata, size, buffer, 65532)) < 0) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
|
||||
if (!error) {
|
||||
jpeg_write_marker(&cinfo, JPEG_APP0 + 13, buffer, bytes);
|
||||
}
|
||||
}
|
||||
|
||||
delete [] buffer;
|
||||
|
||||
// write icc profile to the output
|
||||
if (profileData) {
|
||||
write_icc_profile (&cinfo, (JOCTET*)profileData, profileLength);
|
||||
if (!profileData.empty()) {
|
||||
write_icc_profile (&cinfo, reinterpret_cast<const JOCTET*>(profileData.data()), profileData.size());
|
||||
}
|
||||
|
||||
// write image data
|
||||
|
@ -1316,6 +1111,11 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con
|
|||
|
||||
fclose (file);
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
g_remove(fname.c_str());
|
||||
return IMIO_CANNOTWRITEFILE;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
|
@ -1342,7 +1142,7 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
unsigned char* linebuffer = new unsigned char[lineWidth];
|
||||
|
||||
// little hack to get libTiff to use proper byte order (see TIFFClienOpen()):
|
||||
const char *mode = !exifRoot ? "w" : (exifRoot->getOrder() == rtexif::INTEL ? "wl" : "wb");
|
||||
const char* const mode = "w";
|
||||
#ifdef WIN32
|
||||
FILE *file = g_fopen_withBinaryAndLock (fname);
|
||||
int fileno = _fileno(file);
|
||||
|
@ -1350,7 +1150,7 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
TIFF* out = TIFFFdOpen (osfileno, fname.c_str(), mode);
|
||||
#else
|
||||
TIFF* out = TIFFOpen(fname.c_str(), mode);
|
||||
int fileno = TIFFFileno (out);
|
||||
// int fileno = TIFFFileno (out);
|
||||
#endif
|
||||
|
||||
if (!out) {
|
||||
|
@ -1363,113 +1163,7 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
pl->setProgress (0.0);
|
||||
}
|
||||
|
||||
bool applyExifPatch = false;
|
||||
|
||||
if (exifRoot) {
|
||||
rtexif::TagDirectory* cl = (const_cast<rtexif::TagDirectory*> (exifRoot))->clone (nullptr);
|
||||
|
||||
// ------------------ remove some unknown top level tags which produce warnings when opening a tiff (might be useless) -----------------
|
||||
|
||||
rtexif::Tag *removeTag = cl->getTag (0x9003);
|
||||
|
||||
if (removeTag) {
|
||||
removeTag->setKeep (false);
|
||||
}
|
||||
|
||||
removeTag = cl->getTag (0x9211);
|
||||
|
||||
if (removeTag) {
|
||||
removeTag->setKeep (false);
|
||||
}
|
||||
|
||||
// ------------------ Apply list of change -----------------
|
||||
|
||||
for (auto currExifChange : *exifChange) {
|
||||
cl->applyChange (currExifChange.first, currExifChange.second);
|
||||
}
|
||||
|
||||
rtexif::Tag *tag = cl->getTag (TIFFTAG_EXIFIFD);
|
||||
|
||||
if (tag && tag->isDirectory()) {
|
||||
rtexif::TagDirectory *exif = tag->getDirectory();
|
||||
|
||||
if (exif) {
|
||||
int exif_size = exif->calculateSize();
|
||||
unsigned char *buffer = new unsigned char[exif_size + 8];
|
||||
// TIFFOpen writes out the header and sets file pointer at position 8
|
||||
|
||||
exif->write (8, buffer);
|
||||
|
||||
write (fileno, buffer + 8, exif_size);
|
||||
|
||||
delete [] buffer;
|
||||
// let libtiff know that scanlines or any other following stuff should go
|
||||
// at a different offset:
|
||||
TIFFSetWriteOffset (out, exif_size + 8);
|
||||
TIFFSetField (out, TIFFTAG_EXIFIFD, 8);
|
||||
applyExifPatch = true;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Even though we are saving EXIF IFD - MakerNote still comes out screwed.
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_MODEL)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_MODEL, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_MAKE)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_MAKE, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_DATETIME)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_DATETIME, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_ARTIST)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_ARTIST, tag->getValue());
|
||||
}
|
||||
|
||||
if ((tag = cl->getTag (TIFFTAG_COPYRIGHT)) != nullptr) {
|
||||
TIFFSetField (out, TIFFTAG_COPYRIGHT, tag->getValue());
|
||||
}
|
||||
|
||||
delete cl;
|
||||
}
|
||||
|
||||
unsigned char* iptcdata = nullptr;
|
||||
unsigned int iptclen = 0;
|
||||
|
||||
if (iptc && iptc_data_save (iptc, &iptcdata, &iptclen)) {
|
||||
if (iptcdata) {
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
iptcdata = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::MOTOROLA;
|
||||
#else
|
||||
bool needsReverse = exifRoot && exifRoot->getOrder() == rtexif::INTEL;
|
||||
#endif
|
||||
if (iptcdata) {
|
||||
rtexif::Tag iptcTag(nullptr, rtexif::lookupAttrib (rtexif::ifdAttribs, "IPTCData"));
|
||||
iptcTag.initLongArray((char*)iptcdata, iptclen);
|
||||
if (needsReverse) {
|
||||
unsigned char *ptr = iptcTag.getValue();
|
||||
for (int a = 0; a < iptcTag.getCount(); ++a) {
|
||||
unsigned char cc;
|
||||
cc = ptr[3];
|
||||
ptr[3] = ptr[0];
|
||||
ptr[0] = cc;
|
||||
cc = ptr[2];
|
||||
ptr[2] = ptr[1];
|
||||
ptr[1] = cc;
|
||||
ptr += 4;
|
||||
}
|
||||
}
|
||||
TIFFSetField (out, TIFFTAG_RICHTIFFIPTC, iptcTag.getCount(), (long*)iptcTag.getValue());
|
||||
iptc_data_free_buf (iptc, iptcdata);
|
||||
}
|
||||
bool needsReverse = false;
|
||||
|
||||
TIFFSetField (out, TIFFTAG_SOFTWARE, "RawTherapee " RTVERSION);
|
||||
TIFFSetField (out, TIFFTAG_IMAGEWIDTH, width);
|
||||
|
@ -1499,8 +1193,8 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
if (!uncompressed) {
|
||||
TIFFSetField (out, TIFFTAG_PREDICTOR, (bps == 16 || bps == 32) && isFloat ? PREDICTOR_FLOATINGPOINT : PREDICTOR_HORIZONTAL);
|
||||
}
|
||||
if (profileData) {
|
||||
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileLength, profileData);
|
||||
if (!profileData.empty()) {
|
||||
TIFFSetField (out, TIFFTAG_ICCPROFILE, profileData.size(), profileData.data());
|
||||
}
|
||||
|
||||
for (int row = 0; row < height; row++) {
|
||||
|
@ -1542,38 +1236,6 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
writeOk = false;
|
||||
}
|
||||
|
||||
/************************************************************************************************************
|
||||
*
|
||||
* Hombre: This is a dirty hack to update the Exif tag data type to 0x0004 so that Windows can understand it.
|
||||
* libtiff will set this data type to 0x000d and doesn't provide any mechanism to update it before
|
||||
* dumping to the file.
|
||||
*
|
||||
*/
|
||||
if (applyExifPatch) {
|
||||
unsigned char b[10];
|
||||
uint16 tagCount = 0;
|
||||
lseek(fileno, 4, SEEK_SET);
|
||||
read(fileno, b, 4);
|
||||
uint32 ifd0Offset = rtexif::sget4(b, exifRoot->getOrder());
|
||||
lseek(fileno, ifd0Offset, SEEK_SET);
|
||||
read(fileno, b, 2);
|
||||
tagCount = rtexif::sget2(b, exifRoot->getOrder());
|
||||
for (size_t i = 0; i < tagCount ; ++i) {
|
||||
uint16 tagID = 0;
|
||||
read(fileno, b, 2);
|
||||
tagID = rtexif::sget2(b, exifRoot->getOrder());
|
||||
if (tagID == 0x8769) {
|
||||
rtexif::sset2(4, b, exifRoot->getOrder());
|
||||
write(fileno, b, 2);
|
||||
break;
|
||||
} else {
|
||||
read(fileno, b, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
/************************************************************************************************************/
|
||||
|
||||
|
||||
TIFFClose (out);
|
||||
#ifdef WIN32
|
||||
fclose (file);
|
||||
|
@ -1581,6 +1243,10 @@ int ImageIO::saveTIFF (const Glib::ustring &fname, int bps, bool isFloat, bool u
|
|||
|
||||
delete [] linebuffer;
|
||||
|
||||
if (!saveMetadata(fname)) {
|
||||
writeOk = false;
|
||||
}
|
||||
|
||||
if (pl) {
|
||||
pl->setProgressStr ("PROGRESSBAR_READY");
|
||||
pl->setProgress (1.0);
|
||||
|
@ -1711,3 +1377,43 @@ void ImageIO::deleteLoadedProfileData( )
|
|||
|
||||
loadedProfileData = nullptr;
|
||||
}
|
||||
|
||||
bool ImageIO::saveMetadata(const Glib::ustring &fname) const
|
||||
{
|
||||
if (metadataInfo.filename().empty()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
auto src = open_exiv2(metadataInfo.filename());
|
||||
auto dst = open_exiv2(fname);
|
||||
src->readMetadata();
|
||||
dst->setMetadata(*src);
|
||||
dst->exifData()["Exif.Image.Software"] = "RawTherapee " RTVERSION;
|
||||
for (const auto& p : metadataInfo.exif()) {
|
||||
try {
|
||||
dst->exifData()[p.first] = p.second;
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
}
|
||||
}
|
||||
for (const auto& p : metadataInfo.iptc()) {
|
||||
try {
|
||||
auto& v = p.second;
|
||||
if (!v.empty()) {
|
||||
dst->iptcData()[p.first] = v[0];
|
||||
for (size_t j = 1; j < v.size(); ++j) {
|
||||
Exiv2::Iptcdatum d(Exiv2::IptcKey(p.first));
|
||||
d.setValue(v[j]);
|
||||
dst->iptcData().add(d);
|
||||
}
|
||||
}
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
}
|
||||
}
|
||||
dst->writeMetadata();
|
||||
return true;
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
std::cout << "EXIF ERROR: " << exc.what() << std::endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include <libiptcdata/iptc-data.h>
|
||||
|
||||
#include "iimage.h"
|
||||
#include "imagedimensions.h"
|
||||
#include "imageformat.h"
|
||||
|
@ -40,51 +37,60 @@ enum {
|
|||
IMIO_CANNOTWRITEFILE
|
||||
};
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class TagDirectory;
|
||||
|
||||
}
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class ColorTemp;
|
||||
class ProgressListener;
|
||||
class Imagefloat;
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
|
||||
class ExifPairs;
|
||||
class IPTCPairs;
|
||||
|
||||
}
|
||||
|
||||
class ColorTemp;
|
||||
class ProgressListener;
|
||||
class Imagefloat;
|
||||
|
||||
class MetadataInfo final
|
||||
{
|
||||
public:
|
||||
explicit MetadataInfo(const Glib::ustring& src = {});
|
||||
|
||||
const Glib::ustring& filename() const;
|
||||
|
||||
const rtengine::procparams::ExifPairs& exif() const;
|
||||
const rtengine::procparams::IPTCPairs& iptc() const;
|
||||
|
||||
void setExif(const rtengine::procparams::ExifPairs &exif);
|
||||
void setIptc(const rtengine::procparams::IPTCPairs &iptc);
|
||||
|
||||
private:
|
||||
Glib::ustring src_;
|
||||
std::unique_ptr<rtengine::procparams::ExifPairs> exif_;
|
||||
std::unique_ptr<rtengine::procparams::IPTCPairs> iptc_;
|
||||
};
|
||||
|
||||
class ImageIO : virtual public ImageDatas
|
||||
{
|
||||
|
||||
protected:
|
||||
ProgressListener* pl;
|
||||
cmsHPROFILE embProfile;
|
||||
char* profileData;
|
||||
std::string profileData;
|
||||
int profileLength;
|
||||
char* loadedProfileData;
|
||||
bool loadedProfileDataJpg;
|
||||
int loadedProfileLength;
|
||||
const std::unique_ptr<procparams::ExifPairs> exifChange;
|
||||
IptcData* iptc;
|
||||
const rtexif::TagDirectory* exifRoot;
|
||||
MyMutex imutex;
|
||||
IIOSampleFormat sampleFormat;
|
||||
IIOSampleArrangement sampleArrangement;
|
||||
MetadataInfo metadataInfo;
|
||||
|
||||
private:
|
||||
void deleteLoadedProfileData( );
|
||||
|
||||
public:
|
||||
static Glib::ustring errorMsg[6];
|
||||
|
||||
ImageIO();
|
||||
~ImageIO() override;
|
||||
|
||||
|
@ -119,9 +125,10 @@ public:
|
|||
cmsHPROFILE getEmbeddedProfile () const;
|
||||
void getEmbeddedProfileData (int& length, unsigned char*& pdata) const;
|
||||
|
||||
void setMetadata (const rtexif::TagDirectory* eroot);
|
||||
void setMetadata (const rtexif::TagDirectory* eroot, const rtengine::procparams::ExifPairs& exif, const rtengine::procparams::IPTCPairs& iptcc);
|
||||
void setOutputProfile (const char* pdata, int plen);
|
||||
void setMetadata(MetadataInfo info);
|
||||
void setOutputProfile(const std::string& pdata);
|
||||
|
||||
bool saveMetadata(const Glib::ustring &fname) const;
|
||||
|
||||
MyMutex& mutex ();
|
||||
};
|
||||
|
|
|
@ -173,7 +173,7 @@ public:
|
|||
{
|
||||
outCurve = { 0.0 };
|
||||
}
|
||||
|
||||
|
||||
double getDirPyrDenoiseExpComp ( )
|
||||
{
|
||||
return dirpyrdenoiseExpComp;
|
||||
|
|
|
@ -1510,20 +1510,10 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
|
|||
customColCurve1, customColCurve2, customColCurve3, 1);
|
||||
|
||||
const FramesMetaData* metaData = imgsrc->getMetaData();
|
||||
int imgNum = 0;
|
||||
|
||||
if (imgsrc->isRAW()) {
|
||||
if (imgsrc->getSensorType() == ST_BAYER) {
|
||||
imgNum = rtengine::LIM<unsigned int>(params->raw.bayersensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
|
||||
//imgNum = rtengine::LIM<unsigned int>(params->raw.xtranssensor.imageNum, 0, metaData->getFrameCount() - 1);
|
||||
}
|
||||
}
|
||||
|
||||
float fnum = metaData->getFNumber(imgNum); // F number
|
||||
float fiso = metaData->getISOSpeed(imgNum) ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed(imgNum) ; // Speed
|
||||
double fcomp = metaData->getExpComp(imgNum); // Compensation +/-
|
||||
float fnum = metaData->getFNumber(); // F number
|
||||
float fiso = metaData->getISOSpeed() ; // ISO
|
||||
float fspeed = metaData->getShutterSpeed() ; // Speed
|
||||
double fcomp = metaData->getExpComp(); // Compensation +/-
|
||||
double adap;
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) { //if no exif data or wrong
|
||||
|
@ -2075,7 +2065,7 @@ void ImProcCoordinator::saveInputICCReference(const Glib::ustring& fname, bool a
|
|||
im = tempImage;
|
||||
}
|
||||
|
||||
im->setMetadata(imgsrc->getMetaData()->getRootExifData());
|
||||
im->setMetadata(MetadataInfo(imgsrc->getFileName()));
|
||||
|
||||
im->saveTIFF(fname, 16, false, true);
|
||||
delete im;
|
||||
|
|
|
@ -5622,18 +5622,18 @@ void ImProcFunctions::getAutoExp(const LUTu &histogram, int histcompr, double cl
|
|||
double ImProcFunctions::getAutoDistor(const Glib::ustring &fname, int thumb_size)
|
||||
{
|
||||
if (!fname.empty()) {
|
||||
rtengine::RawMetaDataLocation ri;
|
||||
// TODO: std::unique_ptr<> to the rescue
|
||||
int w_raw = -1, h_raw = thumb_size;
|
||||
int w_thumb = -1, h_thumb = thumb_size;
|
||||
|
||||
eSensorType sensorType = rtengine::ST_NONE;
|
||||
Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw(fname, ri, sensorType, w_thumb, h_thumb, 1, FALSE);
|
||||
Thumbnail* thumb = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, w_thumb, h_thumb, 1, FALSE);
|
||||
|
||||
if (!thumb) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, ri, sensorType, w_raw, h_raw, 1, 1.0, FALSE);
|
||||
Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, sensorType, w_raw, h_raw, 1, 1.0, FALSE);
|
||||
|
||||
if (!raw) {
|
||||
delete thumb;
|
||||
|
|
|
@ -1,44 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
struct IptcPair {
|
||||
IptcTag tag;
|
||||
size_t size;
|
||||
Glib::ustring field;
|
||||
};
|
||||
|
||||
const IptcPair strTags[] = {
|
||||
{IPTC_TAG_CAPTION, 2000, "Caption"},
|
||||
{IPTC_TAG_WRITER_EDITOR, 32, "CaptionWriter"},
|
||||
{IPTC_TAG_HEADLINE, 256, "Headline"},
|
||||
{IPTC_TAG_SPECIAL_INSTRUCTIONS, 256, "Instructions"},
|
||||
{IPTC_TAG_CATEGORY, 3, "Category"},
|
||||
{IPTC_TAG_BYLINE, 32, "Creator"},
|
||||
{IPTC_TAG_BYLINE_TITLE, 32, "CreatorJobTitle"},
|
||||
{IPTC_TAG_CREDIT, 32, "Credit"},
|
||||
{IPTC_TAG_SOURCE, 32, "Source"},
|
||||
{IPTC_TAG_COPYRIGHT_NOTICE, 128, "Copyright"},
|
||||
{IPTC_TAG_CITY, 32, "City"},
|
||||
{IPTC_TAG_STATE, 32, "Province"},
|
||||
{IPTC_TAG_COUNTRY_NAME, 64, "Country"},
|
||||
{IPTC_TAG_OBJECT_NAME, 64, "Title"},
|
||||
{IPTC_TAG_ORIG_TRANS_REF, 32, "TransReference"},
|
||||
{IPTC_TAG_DATE_CREATED, 8, "DateCreated"}
|
||||
};
|
|
@ -61,9 +61,8 @@ PreviewImage::PreviewImage (const Glib::ustring &fname, const Glib::ustring &ext
|
|||
data = tpp->getImage8Data();
|
||||
}
|
||||
} else {
|
||||
rtengine::RawMetaDataLocation ri;
|
||||
eSensorType sensorType = rtengine::ST_NONE;
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, width, height, 1, true, true);
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, width, height, 1, true, true);
|
||||
|
||||
if (tpp) {
|
||||
data = tpp->getImage8Data();
|
||||
|
|
|
@ -310,7 +310,35 @@ bool saveToKeyfile(
|
|||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
const std::map<std::string, std::string> exif_keys = {
|
||||
{"Copyright", "Exif.Image.Copyright"},
|
||||
{"Artist", "Exif.Image.Artist"},
|
||||
{"ImageDescription", "Exif.Image.ImageDescription"},
|
||||
{"Exif.UserComment", "Exif.Photo.UserComment"}
|
||||
};
|
||||
|
||||
const std::map<std::string, std::string> iptc_keys = {
|
||||
{"Title", "Iptc.Application2.ObjectName"},
|
||||
{"Category", "Iptc.Application2.Category"},
|
||||
{"SupplementalCategories", "Iptc.Application2.SuppCategory"},
|
||||
{"Keywords", "Iptc.Application2.Keywords"},
|
||||
{"Instructions", "Iptc.Application2.SpecialInstructions"},
|
||||
{"DateCreated", "Iptc.Application2.DateCreated"},
|
||||
{"Creator", "Iptc.Application2.Byline"},
|
||||
{"CreatorJobTitle", "Iptc.Application2.BylineTitle"},
|
||||
{"City", "Iptc.Application2.City"},
|
||||
{"Province", "Iptc.Application2.ProvinceState"},
|
||||
{"Country", "Iptc.Application2.CountryName"},
|
||||
{"TransReference", "Iptc.Application2.TransmissionReference"},
|
||||
{"Headline", "Iptc.Application2.Headline"},
|
||||
{"Credit", "Iptc.Application2.Credit"},
|
||||
{"Source", "Iptc.Application2.Source"},
|
||||
{"Copyright", "Iptc.Application2.Copyright"},
|
||||
{"Caption", "Iptc.Application2.Caption"},
|
||||
{"CaptionWriter", "Iptc.Application2.Writer"}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
@ -5348,9 +5376,9 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
|||
|
||||
// Dehaze
|
||||
saveToKeyfile(!pedited || pedited->dehaze.enabled, "Dehaze", "Enabled", dehaze.enabled, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.showDepthMap, "Dehaze", "ShowDepthMap", dehaze.showDepthMap, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Depth", dehaze.depth, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.strength, "Dehaze", "Strength", dehaze.strength, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.showDepthMap, "Dehaze", "ShowDepthMap", dehaze.showDepthMap, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Depth", dehaze.depth, keyFile);
|
||||
saveToKeyfile(!pedited || pedited->dehaze.depth, "Dehaze", "Luminance", dehaze.luminance, keyFile);
|
||||
|
||||
// Directional pyramid denoising
|
||||
|
@ -6388,16 +6416,30 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo
|
|||
|
||||
// EXIF change list
|
||||
if (!pedited || pedited->exif) {
|
||||
std::map<Glib::ustring, Glib::ustring> m;
|
||||
for (auto &p : exif_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (ExifPairs::const_iterator i = exif.begin(); i != exif.end(); ++i) {
|
||||
keyFile.set_string("Exif", i->first, i->second);
|
||||
auto it = m.find(i->first);
|
||||
if (it != m.end()) {
|
||||
keyFile.set_string("Exif", it->second, i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// IPTC change list
|
||||
if (!pedited || pedited->iptc) {
|
||||
std::map<std::string, std::string> m;
|
||||
for (auto &p : iptc_keys) {
|
||||
m[p.second] = p.first;
|
||||
}
|
||||
for (IPTCPairs::const_iterator i = iptc.begin(); i != iptc.end(); ++i) {
|
||||
Glib::ArrayHandle<Glib::ustring> values = i->second;
|
||||
keyFile.set_string_list("IPTC", i->first, values);
|
||||
auto it = m.find(i->first);
|
||||
if (it != m.end()) {
|
||||
Glib::ArrayHandle<Glib::ustring> values = i->second;
|
||||
keyFile.set_string_list("IPTC", it->second, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8322,7 +8364,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
|||
assignFromKeyfile(keyFile, "Dehaze", "Depth", pedited, dehaze.depth, pedited->dehaze.depth);
|
||||
assignFromKeyfile(keyFile, "Dehaze", "Luminance", pedited, dehaze.luminance, pedited->dehaze.luminance);
|
||||
}
|
||||
|
||||
|
||||
if (keyFile.has_group("Film Simulation")) {
|
||||
assignFromKeyfile(keyFile, "Film Simulation", "Enabled", pedited, filmSimulation.enabled, pedited->filmSimulation.enabled);
|
||||
assignFromKeyfile(keyFile, "Film Simulation", "ClutFilename", pedited, filmSimulation.clutFilename, pedited->filmSimulation.clutFilename);
|
||||
|
@ -8724,10 +8766,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
|||
|
||||
if (keyFile.has_group("Exif")) {
|
||||
for (const auto& key : keyFile.get_keys("Exif")) {
|
||||
exif[key] = keyFile.get_string("Exif", key);
|
||||
auto it = exif_keys.find(key);
|
||||
if (it != exif_keys.end()) {
|
||||
exif[it->second] = keyFile.get_string("Exif", key);
|
||||
|
||||
if (pedited) {
|
||||
pedited->exif = true;
|
||||
if (pedited) {
|
||||
pedited->exif = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8747,7 +8792,13 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
|||
if (keyFile.has_group("IPTC")) {
|
||||
for (const auto& key : keyFile.get_keys("IPTC")) {
|
||||
// does this key already exist?
|
||||
const IPTCPairs::iterator element = iptc.find(key);
|
||||
auto it = iptc_keys.find(key);
|
||||
if (it == iptc_keys.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto kk = it->second;
|
||||
const IPTCPairs::iterator element = iptc.find(kk);
|
||||
|
||||
if (element != iptc.end()) {
|
||||
// it already exist so we cleanup the values
|
||||
|
@ -8756,7 +8807,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited)
|
|||
|
||||
// TODO: look out if merging Keywords and SupplementalCategories from the procparams chain would be interesting
|
||||
for (const auto& currLoadedTagValue : keyFile.get_string_list("IPTC", key)) {
|
||||
iptc[key].push_back(currLoadedTagValue);
|
||||
iptc[kk].push_back(currLoadedTagValue);
|
||||
}
|
||||
|
||||
if (pedited) {
|
||||
|
|
|
@ -1651,8 +1651,17 @@ struct MetaDataParams {
|
|||
*/
|
||||
class ExifPairs final
|
||||
{
|
||||
private:
|
||||
using Pairs = std::map<Glib::ustring, Glib::ustring>;
|
||||
|
||||
public:
|
||||
using const_iterator = std::map<Glib::ustring, Glib::ustring>::const_iterator;
|
||||
using const_iterator = Pairs::const_iterator;
|
||||
using size_type = Pairs::size_type;
|
||||
|
||||
const_iterator find(const Glib::ustring& key) const
|
||||
{
|
||||
return pairs.find(key);
|
||||
}
|
||||
|
||||
const_iterator begin() const
|
||||
{
|
||||
|
@ -1669,6 +1678,11 @@ public:
|
|||
pairs.clear();
|
||||
}
|
||||
|
||||
size_type erase(const Glib::ustring& key)
|
||||
{
|
||||
return pairs.erase(key);
|
||||
}
|
||||
|
||||
Glib::ustring& operator[](const Glib::ustring& key)
|
||||
{
|
||||
return pairs[key];
|
||||
|
@ -1680,7 +1694,7 @@ public:
|
|||
}
|
||||
|
||||
private:
|
||||
std::map<Glib::ustring, Glib::ustring> pairs;
|
||||
Pairs pairs;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -1201,8 +1201,7 @@ int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly)
|
|||
|
||||
|
||||
// Load complete Exif information
|
||||
std::unique_ptr<RawMetaDataLocation> rml(new RawMetaDataLocation (ri->get_exifBase(), ri->get_ciffBase(), ri->get_ciffLen()));
|
||||
idata = new FramesData (fname, std::move(rml));
|
||||
idata = new FramesData(fname); // TODO: std::unique_ptr<>
|
||||
idata->setDCRawFrameCount (numFrames);
|
||||
|
||||
green(W, H);
|
||||
|
|
|
@ -1,37 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
class RawMetaDataLocation {
|
||||
|
||||
public:
|
||||
int exifBase;
|
||||
int ciffBase;
|
||||
int ciffLength;
|
||||
|
||||
RawMetaDataLocation () : exifBase(-1), ciffBase(-1), ciffLength(-1) {}
|
||||
explicit RawMetaDataLocation (int exifBase) : exifBase(exifBase), ciffBase(-1), ciffLength(-1) {}
|
||||
RawMetaDataLocation (int ciffBase, int ciffLength) : exifBase(-1), ciffBase(ciffBase), ciffLength(ciffLength) {}
|
||||
RawMetaDataLocation (int exifBase, int ciffBase, int ciffLength) : exifBase(exifBase), ciffBase(ciffBase), ciffLength(ciffLength) {}
|
||||
};
|
||||
|
||||
}
|
|
@ -30,7 +30,6 @@
|
|||
#include "iimage.h"
|
||||
#include "imageformat.h"
|
||||
#include "procevents.h"
|
||||
#include "rawmetadatalocation.h"
|
||||
#include "settings.h"
|
||||
|
||||
#include "../rtgui/threadutils.h"
|
||||
|
@ -87,78 +86,56 @@ class FramesMetaData
|
|||
{
|
||||
|
||||
public:
|
||||
/** @return Returns the number of root Metadata */
|
||||
virtual unsigned int getRootCount () const = 0;
|
||||
/** @return Returns the number of frame contained in the file based on Metadata */
|
||||
virtual unsigned int getFrameCount () const = 0;
|
||||
virtual unsigned int getFrameCount() const = 0;
|
||||
|
||||
/** Checks the availability of exif metadata tags.
|
||||
* @return Returns true if image contains exif metadata tags */
|
||||
virtual bool hasExif (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags.
|
||||
* @param root root number in the metadata tree
|
||||
* @return The directory of exif metadata tags */
|
||||
virtual rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags.
|
||||
* @param frame frame number in the metadata tree
|
||||
* @return The directory of exif metadata tags */
|
||||
virtual rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of exif metadata tags containing at least the 'Make' tag for the requested frame.
|
||||
* If no usable metadata exist in the frame, send back the best TagDirectory describing the frame content.
|
||||
* @param imgSource rawimage that we want the metadata from
|
||||
* @param rawParams RawParams to select the frame number
|
||||
* @return The directory of exif metadata tags containing at least the 'Make' tag */
|
||||
virtual rtexif::TagDirectory* getBestExifData (ImageSource *imgSource, procparams::RAWParams *rawParams) const = 0;
|
||||
/** Checks the availability of IPTC tags.
|
||||
* @return Returns true if image contains IPTC tags */
|
||||
virtual bool hasIPTC (unsigned int frame = 0) const = 0;
|
||||
/** Returns the directory of IPTC tags.
|
||||
* @return The directory of IPTC tags */
|
||||
virtual procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const = 0;
|
||||
virtual bool hasExif() const = 0;
|
||||
/** @return a struct containing the date and time of the image */
|
||||
virtual tm getDateTime (unsigned int frame = 0) const = 0;
|
||||
virtual tm getDateTime() const = 0;
|
||||
/** @return a timestamp containing the date and time of the image */
|
||||
virtual time_t getDateTimeAsTS(unsigned int frame = 0) const = 0;
|
||||
virtual time_t getDateTimeAsTS() const = 0;
|
||||
/** @return the ISO of the image */
|
||||
virtual int getISOSpeed (unsigned int frame = 0) const = 0;
|
||||
virtual int getISOSpeed() const = 0;
|
||||
/** @return the F number of the image */
|
||||
virtual double getFNumber (unsigned int frame = 0) const = 0;
|
||||
virtual double getFNumber() const = 0;
|
||||
/** @return the focal length used at the exposure */
|
||||
virtual double getFocalLen (unsigned int frame = 0) const = 0;
|
||||
virtual double getFocalLen() const = 0;
|
||||
/** @return the focal length in 35mm used at the exposure */
|
||||
virtual double getFocalLen35mm (unsigned int frame = 0) const = 0;
|
||||
virtual double getFocalLen35mm() const = 0;
|
||||
/** @return the focus distance in meters, 0=unknown, 10000=infinity */
|
||||
virtual float getFocusDist (unsigned int frame = 0) const = 0;
|
||||
virtual float getFocusDist() const = 0;
|
||||
/** @return the shutter speed */
|
||||
virtual double getShutterSpeed (unsigned int frame = 0) const = 0;
|
||||
virtual double getShutterSpeed() const = 0;
|
||||
/** @return the exposure compensation */
|
||||
virtual double getExpComp (unsigned int frame = 0) const = 0;
|
||||
virtual double getExpComp() const = 0;
|
||||
/** @return the maker of the camera */
|
||||
virtual std::string getMake (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getMake() const = 0;
|
||||
/** @return the model of the camera */
|
||||
virtual std::string getModel (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getModel() const = 0;
|
||||
|
||||
std::string getCamera (unsigned int frame = 0) const
|
||||
std::string getCamera() const
|
||||
{
|
||||
return getMake(frame) + " " + getModel(frame);
|
||||
return getMake() + " " + getModel();
|
||||
}
|
||||
|
||||
/** @return the lens on the camera */
|
||||
virtual std::string getLens (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getLens() const = 0;
|
||||
/** @return the orientation of the image */
|
||||
virtual std::string getOrientation (unsigned int frame = 0) const = 0;
|
||||
virtual std::string getOrientation() const = 0;
|
||||
/** @return the rating of the image */
|
||||
virtual int getRating (unsigned int frame = 0) const = 0;
|
||||
virtual int getRating () const = 0;
|
||||
|
||||
/** @return true if the file is a PixelShift shot (Pentax and Sony bodies) */
|
||||
virtual bool getPixelShift () const = 0;
|
||||
/** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */
|
||||
virtual bool getHDR (unsigned int frame = 0) const = 0;
|
||||
virtual bool getHDR() const = 0;
|
||||
|
||||
/** @return false: not an HDR file ; true: single or multi-frame HDR file (e.g. Pentax HDR raw file or 32 bit float DNG file or Log compressed) */
|
||||
virtual std::string getImageType (unsigned int frame) const = 0;
|
||||
virtual std::string getImageType() const = 0;
|
||||
/** @return the sample format based on MetaData */
|
||||
virtual IIOSampleFormat getSampleFormat (unsigned int frame = 0) const = 0;
|
||||
virtual IIOSampleFormat getSampleFormat() const = 0;
|
||||
|
||||
/** Functions to convert between floating point and string representation of shutter and aperture */
|
||||
static std::string apertureToString (double aperture);
|
||||
|
@ -179,7 +156,9 @@ public:
|
|||
* Use it only for raw files. In caseof jpgs and tiffs pass a NULL pointer.
|
||||
* @param firstFrameOnly must be true to get the MetaData of the first frame only, e.g. for a PixelShift file.
|
||||
* @return The metadata */
|
||||
static FramesMetaData* fromFile (const Glib::ustring& fname, std::unique_ptr<RawMetaDataLocation> rml, bool firstFrameOnly = false);
|
||||
static FramesMetaData* fromFile(const Glib::ustring& fname);
|
||||
|
||||
virtual Glib::ustring getFileName() const = 0;
|
||||
};
|
||||
|
||||
/** This listener interface is used to indicate the progress of time consuming operations */
|
||||
|
|
|
@ -209,7 +209,7 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||
if (std::max(img->getWidth(), img->getHeight()) / std::min(img->getWidth(), img->getHeight()) >= 10) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
Thumbnail* tpp = new Thumbnail ();
|
||||
|
||||
unsigned char* data;
|
||||
|
@ -314,10 +314,10 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||
|
||||
namespace {
|
||||
|
||||
Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml, eSensorType &sensorType, int &w, int &h)
|
||||
Image8 *load_inspector_mode(const Glib::ustring &fname, eSensorType &sensorType, int &w, int &h)
|
||||
{
|
||||
BENCHFUN
|
||||
|
||||
|
||||
RawImageSource src;
|
||||
int err = src.load(fname, true);
|
||||
if (err) {
|
||||
|
@ -326,7 +326,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml
|
|||
|
||||
src.getFullSize(w, h);
|
||||
sensorType = src.getSensorType();
|
||||
|
||||
|
||||
ProcParams neutral;
|
||||
neutral.raw.bayersensor.method = RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::FAST);
|
||||
neutral.raw.xtranssensor.method = RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::FAST);
|
||||
|
@ -370,7 +370,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml
|
|||
|
||||
} // namespace
|
||||
|
||||
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode, bool forHistogramMatching)
|
||||
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode, bool forHistogramMatching)
|
||||
{
|
||||
Thumbnail* tpp = new Thumbnail ();
|
||||
tpp->isRaw = 1;
|
||||
|
@ -380,7 +380,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
tpp->colorMatrix[2][2] = 1.0;
|
||||
|
||||
if (inspectorMode && !forHistogramMatching && settings->thumbnail_inspector_mode == Settings::ThumbnailInspectorMode::RAW) {
|
||||
Image8 *img = load_inspector_mode(fname, rml, sensorType, w, h);
|
||||
Image8 *img = load_inspector_mode(fname, sensorType, w, h);
|
||||
if (!img) {
|
||||
delete tpp;
|
||||
return nullptr;
|
||||
|
@ -391,7 +391,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
|
||||
return tpp;
|
||||
}
|
||||
|
||||
|
||||
RawImage *ri = new RawImage (fname);
|
||||
unsigned int imageNum = 0;
|
||||
int r = ri->loadRaw (false, imageNum, false);
|
||||
|
@ -405,10 +405,6 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
|
||||
sensorType = ri->getSensorType();
|
||||
|
||||
rml.exifBase = ri->get_exifBase();
|
||||
rml.ciffBase = ri->get_ciffBase();
|
||||
rml.ciffLength = ri->get_ciffLen();
|
||||
|
||||
Image8* img = new Image8 ();
|
||||
// No sample format detection occurred earlier, so we set them here,
|
||||
// as they are mandatory for the setScanline method
|
||||
|
@ -448,8 +444,8 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
if (!forHistogramMatching && settings->thumbnail_inspector_mode == Settings::ThumbnailInspectorMode::RAW_IF_NOT_JPEG_FULLSIZE && float(std::max(w, h))/float(std::max(ri->get_width(), ri->get_height())) < 0.9f) {
|
||||
delete img;
|
||||
delete ri;
|
||||
|
||||
img = load_inspector_mode(fname, rml, sensorType, w, h);
|
||||
|
||||
img = load_inspector_mode(fname, sensorType, w, h);
|
||||
if (!img) {
|
||||
delete tpp;
|
||||
return nullptr;
|
||||
|
@ -457,7 +453,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
|
||||
tpp->scale = 1.;
|
||||
tpp->thumbImg = img;
|
||||
|
||||
|
||||
return tpp;
|
||||
}
|
||||
} else {
|
||||
|
@ -513,28 +509,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||
#define FISGREEN(filter,row,col) \
|
||||
((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter)
|
||||
|
||||
RawMetaDataLocation Thumbnail::loadMetaDataFromRaw (const Glib::ustring& fname)
|
||||
{
|
||||
RawMetaDataLocation rml;
|
||||
rml.exifBase = -1;
|
||||
rml.ciffBase = -1;
|
||||
rml.ciffLength = -1;
|
||||
|
||||
RawImage ri (fname);
|
||||
unsigned int imageNum = 0;
|
||||
|
||||
int r = ri.loadRaw (false, imageNum);
|
||||
|
||||
if ( !r ) {
|
||||
rml.exifBase = ri.get_exifBase();
|
||||
rml.ciffBase = ri.get_ciffBase();
|
||||
rml.ciffLength = ri.get_ciffLen();
|
||||
}
|
||||
|
||||
return rml;
|
||||
}
|
||||
|
||||
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching)
|
||||
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching)
|
||||
{
|
||||
RawImage *ri = new RawImage (fname);
|
||||
unsigned int tempImageNum = 0;
|
||||
|
@ -583,10 +558,6 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, RawMetaDataLocati
|
|||
|
||||
ri->pre_interpolate();
|
||||
|
||||
rml.exifBase = ri->get_exifBase();
|
||||
rml.ciffBase = ri->get_ciffBase();
|
||||
rml.ciffLength = ri->get_ciffLen();
|
||||
|
||||
tpp->camwbRed = tpp->redMultiplier / pre_mul[0]; //ri->get_pre_mul(0);
|
||||
tpp->camwbGreen = tpp->greenMultiplier / pre_mul[1]; //ri->get_pre_mul(1);
|
||||
tpp->camwbBlue = tpp->blueMultiplier / pre_mul[2]; //ri->get_pre_mul(2);
|
||||
|
@ -1098,20 +1069,12 @@ IImage8* Thumbnail::quickProcessImage (const procparams::ProcParams& params, int
|
|||
// Full thumbnail processing, second stage if complete profile exists
|
||||
IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorType sensorType, int rheight, TypeInterpolation interp, const FramesMetaData *metadata, double& myscale, bool forMonitor, bool forHistogramMatching)
|
||||
{
|
||||
unsigned int imgNum = 0;
|
||||
if (isRaw) {
|
||||
if (sensorType == ST_BAYER) {
|
||||
imgNum = rtengine::LIM<unsigned int>(params.raw.bayersensor.imageNum, 0, metadata->getFrameCount() - 1);
|
||||
} else if (sensorType == ST_FUJI_XTRANS) {
|
||||
//imgNum = rtengine::LIM<unsigned int>(params.raw.xtranssensor.imageNum, 0, metadata->getFrameCount() - 1)
|
||||
}
|
||||
}
|
||||
std::string camName = metadata->getCamera(imgNum);
|
||||
float shutter = metadata->getShutterSpeed(imgNum);
|
||||
float fnumber = metadata->getFNumber(imgNum);
|
||||
float iso = metadata->getISOSpeed(imgNum);
|
||||
float fcomp = metadata->getExpComp(imgNum);
|
||||
|
||||
const std::string camName = metadata->getCamera();
|
||||
const float shutter = metadata->getShutterSpeed();
|
||||
const float fnumber = metadata->getFNumber();
|
||||
const float iso = metadata->getISOSpeed();
|
||||
const float fcomp = metadata->getExpComp();
|
||||
|
||||
// check if the WB's equalizer value has changed
|
||||
if (wbEqual < (params.wb.equal - 5e-4) || wbEqual > (params.wb.equal + 5e-4) || wbTempBias < (params.wb.tempBias - 5e-4) || wbTempBias > (params.wb.tempBias + 5e-4)) {
|
||||
wbEqual = params.wb.equal;
|
||||
|
@ -1210,7 +1173,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||
float red = baseImg->r (i, j) * rmi;
|
||||
float green = baseImg->g (i, j) * gmi;
|
||||
float blue = baseImg->b (i, j) * bmi;
|
||||
|
||||
|
||||
// avoid magenta highlights if highlight recovery is enabled
|
||||
if (params.toneCurve.hrenabled && red > MAXVALF && blue > MAXVALF) {
|
||||
baseImg->r(i, j) = baseImg->g(i, j) = baseImg->b(i, j) = CLIP((red + green + blue) / 3.f);
|
||||
|
@ -1398,7 +1361,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// luminance processing
|
||||
// ipf.EPDToneMap(labView,0,6);
|
||||
|
||||
|
@ -1471,7 +1434,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
|
|||
ipf.ciecam_02float (cieView, adap, 1, 2, labView, ¶ms, customColCurve1, customColCurve2, customColCurve3, dummy, dummy, CAMBrightCurveJ, CAMBrightCurveQ, CAMMean, 5, sk, execsharp, d, dj, yb, rtt);
|
||||
delete cieView;
|
||||
}
|
||||
|
||||
|
||||
// color processing
|
||||
//ipf.colorCurve (labView, labView);
|
||||
|
||||
|
|
|
@ -93,10 +93,9 @@ public:
|
|||
int getImageWidth (const procparams::ProcParams& pparams, int rheight, float &ratio);
|
||||
void getDimensions (int& w, int& h, double& scaleFac);
|
||||
|
||||
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, rtengine::RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadQuickFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode = false, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, bool rotate, bool forHistogramMatching = false);
|
||||
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode = false);
|
||||
static RawMetaDataLocation loadMetaDataFromRaw (const Glib::ustring& fname);
|
||||
|
||||
void getCamWB (double& temp, double& green);
|
||||
void getAutoWB (double& temp, double& green, double equal, double tempBias);
|
||||
|
|
|
@ -1544,18 +1544,11 @@ private:
|
|||
|
||||
if (params.colorappearance.enabled) {
|
||||
double adap;
|
||||
int imgNum = 0;
|
||||
|
||||
if (imgsrc->getSensorType() == ST_BAYER) {
|
||||
imgNum = params.raw.bayersensor.imageNum;
|
||||
} else if (imgsrc->getSensorType() == ST_FUJI_XTRANS) {
|
||||
//imgNum = params.raw.xtranssensor.imageNum;
|
||||
}
|
||||
|
||||
float fnum = imgsrc->getMetaData()->getFNumber(imgNum); // F number
|
||||
float fiso = imgsrc->getMetaData()->getISOSpeed(imgNum) ; // ISO
|
||||
float fspeed = imgsrc->getMetaData()->getShutterSpeed(imgNum) ; //speed
|
||||
float fcomp = imgsrc->getMetaData()->getExpComp(imgNum); //compensation + -
|
||||
const float fnum = imgsrc->getMetaData()->getFNumber(); // F number
|
||||
const float fiso = imgsrc->getMetaData()->getISOSpeed() ; // ISO
|
||||
const float fspeed = imgsrc->getMetaData()->getShutterSpeed() ; // Speed
|
||||
const float fcomp = imgsrc->getMetaData()->getExpComp(); // Compensation + -
|
||||
|
||||
if (fnum < 0.3f || fiso < 5.f || fspeed < 0.00001f) {
|
||||
adap = 2000.;
|
||||
|
@ -1687,21 +1680,24 @@ private:
|
|||
readyImg = tempImage;
|
||||
}
|
||||
|
||||
MetadataInfo info(imgsrc->getFileName());
|
||||
switch (params.metadata.mode) {
|
||||
case MetaDataParams::TUNNEL:
|
||||
// Sending back the whole first root, which won't necessarily be the selected frame number
|
||||
// and may contain subframe depending on initial raw's hierarchy
|
||||
readyImg->setMetadata(initialImage->getMetaData()->getRootExifData());
|
||||
break;
|
||||
|
||||
case MetaDataParams::EDIT:
|
||||
// ask for the correct frame number, but may contain subframe depending on initial raw's hierarchy
|
||||
readyImg->setMetadata(initialImage->getMetaData()->getBestExifData(imgsrc, ¶ms.raw), params.exif, params.iptc);
|
||||
break;
|
||||
|
||||
default: // case MetaDataParams::STRIP
|
||||
// nothing to do
|
||||
break;
|
||||
case MetaDataParams::TUNNEL:
|
||||
// Sending back the whole first root, which won't necessarily be the selected frame number
|
||||
// and may contain subframe depending on initial raw's hierarchy
|
||||
// readyImg->setMetadata (ii->getMetaData()->getRootExifData ());
|
||||
readyImg->setMetadata(std::move(info));
|
||||
break;
|
||||
case MetaDataParams::EDIT:
|
||||
info.setExif(params.exif);
|
||||
info.setIptc(params.iptc);
|
||||
readyImg->setMetadata(std::move(info));
|
||||
// ask for the correct frame number, but may contain subframe depending on initial raw's hierarchy
|
||||
// readyImg->setMetadata (ii->getMetaData()->getBestExifData(imgsrc, ¶ms.raw), params.exif, params.iptc);
|
||||
break;
|
||||
default: // case MetaDataParams::STRIP
|
||||
// nothing to do
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,29 +0,0 @@
|
|||
add_library(rtexif STATIC
|
||||
canonattribs.cc
|
||||
fujiattribs.cc
|
||||
kodakattribs.cc
|
||||
nikonattribs.cc
|
||||
olympusattribs.cc
|
||||
panasonicattribs.cc
|
||||
pentaxattribs.cc
|
||||
rtexif.cc
|
||||
sonyminoltaattribs.cc
|
||||
stdattribs.cc
|
||||
)
|
||||
|
||||
add_dependencies(rtexif UpdateInfo)
|
||||
|
||||
if(WIN32)
|
||||
include_directories(${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS})
|
||||
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif" ${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS})
|
||||
else()
|
||||
set_target_properties(rtexif PROPERTIES COMPILE_FLAGS " -fPIC")
|
||||
include_directories("${EXTRA_INCDIR} ${GLIB2_INCLUDE_DIRS} ${GLIBMM_INCLUDE_DIRS} ${GTK_INCLUDE_DIRS} ${GTKMM_INCLUDE_DIRS}")
|
||||
link_directories("${EXTRA_LIBDIR} ${GLIB2_LIBRARY_DIRS} ${GLIBMM_LIBRARY_DIRS} ${GTK_LIBRARY_DIRS} ${GTKMM_LIBRARY_DIRS} ${LENSFUN_LIBRARY_DIRS}")
|
||||
endif()
|
||||
|
||||
include_directories(BEFORE "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
|
||||
if(BUILD_SHARED_LIBS)
|
||||
install(TARGETS rtexif DESTINATION "${LIBDIR}")
|
||||
endif()
|
File diff suppressed because it is too large
Load Diff
|
@ -1,313 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class FAOnOffInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAOnOffInterpreter ()
|
||||
{
|
||||
choices[0] = "Off";
|
||||
choices[1] = "On";
|
||||
}
|
||||
};
|
||||
FAOnOffInterpreter faOnOffInterpreter;
|
||||
|
||||
class FASharpnessInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FASharpnessInterpreter ()
|
||||
{
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Soft2";
|
||||
choices[3] = "Normal";
|
||||
choices[4] = "Hard";
|
||||
choices[5] = "Hard2";
|
||||
choices[0x82] = "Medium Soft";
|
||||
choices[0x84] = "Medium Hard";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
choices[0xffff] = "n/a";
|
||||
}
|
||||
};
|
||||
FASharpnessInterpreter faSharpnessInterpreter;
|
||||
|
||||
class FAWhiteBalanceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAWhiteBalanceInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[0x100] = "Daylight";
|
||||
choices[0x200] = "Cloudy";
|
||||
choices[0x300] = "Daylight Fluorescent";
|
||||
choices[0x301] = "Day White Fluorescent";
|
||||
choices[0x302] = "White Fluorescent";
|
||||
choices[0x303] = "Warm White Fluorescent";
|
||||
choices[0x304] = "Living Room Warm White Fluorescent";
|
||||
choices[0x400] = "Incandescent";
|
||||
choices[0x500] = "Flash";
|
||||
choices[0x600] = "Underwater";
|
||||
choices[0xf00] = "Custom";
|
||||
choices[0xf01] = "Custom2";
|
||||
choices[0xf02] = "Custom3";
|
||||
choices[0xf03] = "Custom4";
|
||||
choices[0xf04] = "Custom5";
|
||||
choices[0xff0] = "Kelvin";
|
||||
}
|
||||
};
|
||||
FAWhiteBalanceInterpreter faWhiteBalanceInterpreter;
|
||||
|
||||
class FASaturationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FASaturationInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[128] = "Medium High";
|
||||
choices[256] = "High";
|
||||
choices[384] = "Medium Low";
|
||||
choices[512] = "Low";
|
||||
choices[768] = "None (B&W)";
|
||||
choices[769] = "B&W Red Filter";
|
||||
choices[770] = "B&W Yellow Filter";
|
||||
choices[771] = "B&W Green Filter";
|
||||
choices[784] = "B&W Sepia";
|
||||
choices[1024] = "Low 2";
|
||||
choices[1280] = "Acros";
|
||||
choices[1281] = "Acros Red Filter";
|
||||
choices[1282] = "Acros Yellow Filter";
|
||||
choices[1283] = "Acros Green Filter";
|
||||
choices[32768] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FASaturationInterpreter faSaturationInterpreter;
|
||||
|
||||
class FAContrastInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAContrastInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[0x80] = "Medium High";
|
||||
choices[0x100] = "High";
|
||||
choices[0x180] = "Medium Low";
|
||||
choices[0x200] = "Low";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FAContrastInterpreter faContrastInterpreter;
|
||||
|
||||
class FAContrast2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAContrast2Interpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[0x100] = "High";
|
||||
choices[0x300] = "Low";
|
||||
}
|
||||
};
|
||||
FAContrast2Interpreter faContrast2Interpreter;
|
||||
|
||||
class FANoiseReductionInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FANoiseReductionInterpreter ()
|
||||
{
|
||||
choices[0x40] = "Low";
|
||||
choices[0x80] = "Normal";
|
||||
choices[0x100] = "n/a";
|
||||
}
|
||||
};
|
||||
FANoiseReductionInterpreter faNoiseReductionInterpreter;
|
||||
|
||||
class FAFlashInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// FujiFlashMode
|
||||
FAFlashInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "On";
|
||||
choices[2] = "Off";
|
||||
choices[3] = "Red-eye reduction";
|
||||
choices[4] = "External";
|
||||
}
|
||||
};
|
||||
FAFlashInterpreter faFlashInterpreter;
|
||||
|
||||
class FAFocusModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAFocusModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "Manual";
|
||||
}
|
||||
};
|
||||
FAFocusModeInterpreter faFocusModeInterpreter;
|
||||
|
||||
class FAColorModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAColorModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[0x10] = "Chrome";
|
||||
choices[0x30] = "B & W";
|
||||
}
|
||||
};
|
||||
FAColorModeInterpreter faColorModeInterpreter;
|
||||
|
||||
class FADynamicRangeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FADynamicRangeInterpreter ()
|
||||
{
|
||||
choices[1] = "Standard";
|
||||
choices[3] = "Wide";
|
||||
}
|
||||
};
|
||||
FADynamicRangeInterpreter faDynamicRangeInterpreter;
|
||||
|
||||
class FAFilmModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAFilmModeInterpreter ()
|
||||
{
|
||||
choices[0x0] = "F0/Standard (Provia)";
|
||||
choices[0x100] = "F1/Studio Portrait";
|
||||
choices[0x110] = "F1a/Studio Portrait Enhanced Saturation";
|
||||
choices[0x120] = "F1b/Studio Portrait Smooth Skin Tone (Astia)";
|
||||
choices[0x130] = "F1c/Studio Portrait Increased Sharpness";
|
||||
choices[0x200] = "F2/Fujichrome (Velvia)";
|
||||
choices[0x300] = "F3/Studio Portrait Ex";
|
||||
choices[0x400] = "F4/Velvia";
|
||||
choices[0x500] = "Pro Neg. Std";
|
||||
choices[0x501] = "Pro Neg. Hi";
|
||||
choices[0x600] = "Classic Chrome";
|
||||
}
|
||||
};
|
||||
FAFilmModeInterpreter faFilmModeInterpreter;
|
||||
|
||||
class FADRSettingInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// DynamicRangeSetting
|
||||
FADRSettingInterpreter ()
|
||||
{
|
||||
choices[0x0] = "Auto (100-400%)";
|
||||
choices[0x1] = "Manual";
|
||||
choices[0x100] = "Standard (100%)";
|
||||
choices[0x200] = "Wide1 (230%)";
|
||||
choices[0x201] = "Wide2 (400%)";
|
||||
choices[0x8000] = "Film Simulation";
|
||||
}
|
||||
};
|
||||
FADRSettingInterpreter faDRSettingInterpreter;
|
||||
|
||||
class FAPictureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
FAPictureModeInterpreter ()
|
||||
{
|
||||
choices[0x0] = "Auto";
|
||||
choices[0x1] = "Portrait";
|
||||
choices[0x2] = "Landscape";
|
||||
choices[0x3] = "Macro";
|
||||
choices[0x4] = "Sports";
|
||||
choices[0x5] = "Night Scene";
|
||||
choices[0x6] = "Program AE";
|
||||
choices[0x7] = "Natural Light";
|
||||
choices[0x8] = "Anti-blur";
|
||||
choices[0x9] = "Beach & Snow";
|
||||
choices[0xa] = "Sunset";
|
||||
choices[0xb] = "Museum";
|
||||
choices[0xc] = "Party";
|
||||
choices[0xd] = "Flower";
|
||||
choices[0xe] = "Text";
|
||||
choices[0xf] = "Natural Light & Flash";
|
||||
choices[0x10] = "Beach";
|
||||
choices[0x11] = "Snow";
|
||||
choices[0x12] = "Fireworks";
|
||||
choices[0x13] = "Underwater";
|
||||
choices[0x14] = "Portrait with Skin Correction";
|
||||
choices[0x16] = "Panorama";
|
||||
choices[0x17] = "Night (tripod)";
|
||||
choices[0x18] = "Pro Low-light";
|
||||
choices[0x19] = "Pro Focus";
|
||||
choices[0x1a] = "Portrait 2";
|
||||
choices[0x1b] = "Dog Face Detection";
|
||||
choices[0x1c] = "Cat Face Detection";
|
||||
choices[0x40] = "Advanced Filter";
|
||||
choices[0x100] = "Aperture-priority AE";
|
||||
choices[0x200] = "Shutter speed priority AE";
|
||||
choices[0x300] = "Manual";
|
||||
}
|
||||
};
|
||||
FAPictureModeInterpreter faPictureModeInterpreter;
|
||||
|
||||
|
||||
|
||||
const TagAttrib fujiAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "Version", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0010, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "Sharpness", &faSharpnessInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "WhiteBalance", &faWhiteBalanceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "Saturation", &faSaturationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1004, AUTO, "Contrast", &faContrastInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1005, AUTO, "ColorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1006, AUTO, "Contrast2", &faContrast2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100a, AUTO, "WhiteBalanceFineTune", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100b, AUTO, "NoiseReduction", &faNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "FujiFlashMode", &faFlashInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1020, AUTO, "Macro", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1021, AUTO, "FocusMode", &faFocusModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1023, AUTO, "FocusPixel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1030, AUTO, "SlowSync", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1031, AUTO, "PictureMode", &faPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1100, AUTO, "AutoBracketing", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1101, AUTO, "SequenceNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1210, AUTO, "ColorMode", &faColorModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1300, AUTO, "BlurWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1301, AUTO, "FocusWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1302, AUTO, "ExposureWarning", &faOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1400, AUTO, "DynamicRange", &faDynamicRangeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1401, AUTO, "FilmMode", &faFilmModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1402, AUTO, "DynamicRangeSetting", &faDRSettingInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1403, AUTO, "DevelopmentDynamicRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1404, AUTO, "MinFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1405, AUTO, "MaxFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1406, AUTO, "MaxApertureAtMinFocal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1407, AUTO, "MaxApertureAtMaxFocal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x140b, AUTO, "AutoDynamicRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x4100, AUTO, "FacesDetected", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8000, AUTO, "FileSource", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8002, AUTO, "OrderNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8003, AUTO, "FrameNumber", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
||||
|
|
@ -1,162 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
|
||||
void parseKodakIfdTextualInfo (Tag *textualInfo, Tag* exif_)
|
||||
{
|
||||
// parse TextualInfo and copy values into corresponding standard Exif
|
||||
if (textualInfo->getType() != ASCII) {
|
||||
return;
|
||||
}
|
||||
|
||||
TagDirectory *exif = exif_->getDirectory();
|
||||
char *value = (char *)textualInfo->getValue();
|
||||
|
||||
char *p = value;
|
||||
char *pc, *plf;
|
||||
|
||||
while ((pc = strchr (p, ':')) != nullptr && (plf = strchr (pc, '\n')) != nullptr) {
|
||||
while (*p == ' ') {
|
||||
p++;
|
||||
}
|
||||
|
||||
size_t len = pc - p;
|
||||
|
||||
while (len > 1 && p[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
|
||||
std::string key = std::string (p, len);
|
||||
++pc;
|
||||
|
||||
while (*pc == ' ') {
|
||||
pc++;
|
||||
}
|
||||
|
||||
len = plf - pc;
|
||||
|
||||
while (len > 1 && pc[len - 1] == ' ') {
|
||||
len--;
|
||||
}
|
||||
|
||||
std::string val = std::string (pc, len);
|
||||
p = ++plf;
|
||||
|
||||
// we pick out a few select tags here
|
||||
Tag *t;
|
||||
|
||||
if (key == "Lens") {
|
||||
// Proback645 may have "Lens" but not "Focal Length"
|
||||
float flen = atof (val.c_str());
|
||||
|
||||
if (flen != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FocalLength"));
|
||||
t->initRational (flen * 32, 32);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Focal Length") {
|
||||
float flen = atof (val.c_str());
|
||||
|
||||
if (flen != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FocalLength"));
|
||||
t->initRational (flen * 32, 32);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Aperture") {
|
||||
float aperture = atof (&val.c_str()[1]);
|
||||
|
||||
if (aperture != 0.f) {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "FNumber"));
|
||||
t->initRational ((int) (aperture * 10), 10);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
} else if (key == "Exposure Bias" || key == "Compensation") {
|
||||
float bias = 0.0;
|
||||
|
||||
if (val != "Off") {
|
||||
bias = atof (val.c_str());
|
||||
}
|
||||
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ExposureBiasValue"));
|
||||
t->initRational ((int) (bias * 1000), 1000);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "ISO Speed") {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ISOSpeedRatings"));
|
||||
t->initInt (atoi (val.c_str()), SHORT);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "Shutter") {
|
||||
const char *p1 = strchr (val.c_str(), '/');
|
||||
int a, b;
|
||||
|
||||
if (p1 == nullptr) {
|
||||
a = atoi (val.c_str());
|
||||
b = 1;
|
||||
} else {
|
||||
a = atoi (val.c_str());
|
||||
b = atoi (&p1[1]);
|
||||
}
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ExposureTime"));
|
||||
t->initRational (a, b);
|
||||
exif->replaceTag (t);
|
||||
|
||||
const float ssv = -log2 ((float)a / std::max((float)b, 0.0001f)); // convert to APEX value, avoid division by zero
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "ShutterSpeedValue"));
|
||||
t->initRational (1000000 * ssv, 1000000);
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "Flash Fired") {
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "Flash"));
|
||||
|
||||
if (val == "No") {
|
||||
t->initInt (0, SHORT);
|
||||
} else {
|
||||
// not sure if "Flash Fired" is only yes/no, only seen "No" in test pictures
|
||||
t->initInt (1, SHORT);
|
||||
}
|
||||
|
||||
exif->replaceTag (t);
|
||||
} else if (key == "White balance") { // yes should be small 'b' int 'balance'.
|
||||
t = new Tag (exif, lookupAttrib (exifAttribs, "Flash"));
|
||||
t->initInt ((val == "Auto") ? 0 : 1, SHORT);
|
||||
exif->replaceTag (t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// table not complete, not all proprietary Kodak tags are known
|
||||
const TagAttrib kodakIfdAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "UnknownEV?", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "ExposureValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03e9, AUTO, "OriginalFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03eb, AUTO, "SensorLeftBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ec, AUTO, "SensorTopBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ed, AUTO, "SensorImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03ee, AUTO, "SensorImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03f1, AUTO, "TextualInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03fc, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x03fd, AUTO, "Processing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0401, AUTO, "Time", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0414, AUTO, "NCDFileInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0846, AUTO, "ColorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0852, AUTO, "WB_RGBMul0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0853, AUTO, "WB_RGBMul1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0854, AUTO, "WB_RGBMul2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0855, AUTO, "WB_RGBMul3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085c, AUTO, "WB_RGBCoeffs0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085d, AUTO, "WB_RGBCoeffs1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085e, AUTO, "WB_RGBCoeffs2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x085f, AUTO, "WB_RGBCoeffs3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0ce5, AUTO, "FirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1391, AUTO, "ToneCurveFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1784, AUTO, "ISO", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,855 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <sstream>
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class OLOnOffInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLOnOffInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
if (t->toInt() == 0) {
|
||||
return "Off";
|
||||
} else {
|
||||
return "On";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLOnOffInterpreter olOnOffInterpreter;
|
||||
|
||||
class OLYesNoInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLYesNoInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
if (t->toInt() == 0) {
|
||||
return "No";
|
||||
} else {
|
||||
return "Yes";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLYesNoInterpreter olYesNoInterpreter;
|
||||
|
||||
class OLApertureInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLApertureInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
str.precision (2);
|
||||
str << pow (2, t->toInt() / 512.0);
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLApertureInterpreter olApertureInterpreter;
|
||||
|
||||
class OLLensTypeInterpreter : public Interpreter
|
||||
{
|
||||
std::map<std::string, std::string> lenses;
|
||||
public:
|
||||
OLLensTypeInterpreter ()
|
||||
{
|
||||
lenses["00 01 00"] = "Olympus Zuiko Digital ED 50mm f/2.0 Macro";
|
||||
lenses["00 01 01"] = "Olympus Zuiko Digital 40-150mm f/3.5-4.5";
|
||||
lenses["00 01 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6";
|
||||
lenses["00 02 00"] = "Olympus Zuiko Digital ED 150mm f/2.0";
|
||||
lenses["00 02 10"] = "Olympus M.Zuiko Digital 17mm f/2.8 Pancake";
|
||||
lenses["00 03 00"] = "Olympus Zuiko Digital ED 300mm f/2.8";
|
||||
lenses["00 03 10"] = "Olympus M.Zuiko Digital ED 14-150mm f/4.0-5.6 [II]";
|
||||
lenses["00 04 10"] = "Olympus M.Zuiko Digital ED 9-18mm f/4.0-5.6";
|
||||
lenses["00 05 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5";
|
||||
lenses["00 05 01"] = "Olympus Zuiko Digital Pro ED 90-250mm f/2.8";
|
||||
lenses["00 05 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 L";
|
||||
lenses["00 06 00"] = "Olympus Zuiko Digital ED 50-200mm f/2.8-3.5";
|
||||
lenses["00 06 01"] = "Olympus Zuiko Digital ED 8mm f/3.5 Fisheye";
|
||||
lenses["00 06 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6";
|
||||
lenses["00 07 00"] = "Olympus Zuiko Digital 11-22mm f/2.8-3.5";
|
||||
lenses["00 07 01"] = "Olympus Zuiko Digital 18-180mm f/3.5-6.3";
|
||||
lenses["00 07 10"] = "Olympus M.Zuiko Digital ED 12mm f/2.0";
|
||||
lenses["00 08 01"] = "Olympus Zuiko Digital 70-300mm f/4.0-5.6";
|
||||
lenses["00 08 10"] = "Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7";
|
||||
lenses["00 09 10"] = "Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II";
|
||||
lenses["00 10 01"] = "Kenko Tokina Reflex 300mm f/6.3 MF Macro";
|
||||
lenses["00 10 10"] = "Olympus M.Zuiko Digital ED 12-50mm f/3.5-6.3 EZ";
|
||||
lenses["00 11 10"] = "Olympus M.Zuiko Digital 45mm f/1.8";
|
||||
lenses["00 12 10"] = "Olympus M.Zuiko Digital ED 60mm f/2.8 Macro";
|
||||
lenses["00 13 10"] = "Olympus M.Zuiko Digital 14-42mm f/3.5-5.6 II R";
|
||||
lenses["00 14 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/4.0-5.6 R";
|
||||
lenses["00 15 00"] = "Olympus Zuiko Digital ED 7-14mm f/4.0";
|
||||
lenses["00 15 10"] = "Olympus M.Zuiko Digital ED 75mm f/1.8";
|
||||
lenses["00 16 10"] = "Olympus M.Zuiko Digital 17mm f/1.8";
|
||||
lenses["00 17 00"] = "Olympus Zuiko Digital Pro ED 35-100mm f/2.0";
|
||||
lenses["00 18 00"] = "Olympus Zuiko Digital 14-45mm f/3.5-5.6";
|
||||
lenses["00 18 10"] = "Olympus M.Zuiko Digital ED 75-300mm f/4.8-6.7 II";
|
||||
lenses["00 19 10"] = "Olympus M.Zuiko Digital ED 12-40mm f/2.8 Pro";
|
||||
lenses["00 20 00"] = "Olympus Zuiko Digital 35mm f/3.5 Macro";
|
||||
lenses["00 20 10"] = "Olympus M.Zuiko Digital ED 40-150mm f/2.8 Pro";
|
||||
lenses["00 21 10"] = "Olympus M.Zuiko Digital ED 14-42mm f/3.5-5.6 EZ";
|
||||
lenses["00 22 00"] = "Olympus Zuiko Digital 17.5-45mm f/3.5-5.6";
|
||||
lenses["00 22 10"] = "Olympus M.Zuiko Digital 25mm f/1.8";
|
||||
lenses["00 23 00"] = "Olympus Zuiko Digital ED 14-42mm f/3.5-5.6";
|
||||
lenses["00 23 10"] = "Olympus M.Zuiko Digital ED 7-14mm f/2.8 Pro";
|
||||
lenses["00 24 00"] = "Olympus Zuiko Digital ED 40-150mm f/4.0-5.6";
|
||||
lenses["00 24 10"] = "Olympus M.Zuiko Digital ED 300mm f/4.0 IS Pro";
|
||||
lenses["00 25 10"] = "Olympus M.Zuiko Digital ED 8mm f/1.8 Fisheye Pro";
|
||||
lenses["00 26 10"] = "Olympus M.Zuiko Digital ED 12-100mm f/4.0 IS Pro";
|
||||
lenses["00 27 10"] = "Olympus M.Zuiko Digital ED 30mm f/3.5 Macro";
|
||||
lenses["00 28 10"] = "Olympus M.Zuiko Digital ED 25mm f/1.2 Pro";
|
||||
lenses["00 29 10"] = "Olympus M.Zuiko Digital ED 17mm f/1.2 Pro";
|
||||
lenses["00 30 00"] = "Olympus Zuiko Digital ED 50-200mm f/2.8-3.5 SWD";
|
||||
lenses["00 30 10"] = "Olympus M.Zuiko Digital ED 45mm f/1.2 Pro";
|
||||
lenses["00 31 00"] = "Olympus Zuiko Digital ED 12-60mm f/2.8-4.0 SWD";
|
||||
lenses["00 32 00"] = "Olympus Zuiko Digital ED 14-35mm f/2.0 SWD";
|
||||
lenses["00 32 10"] = "Olympus M.Zuiko Digital ED 12-200mm f/3.5-6.3";
|
||||
lenses["00 33 00"] = "Olympus Zuiko Digital 25mm f/2.8";
|
||||
lenses["00 34 00"] = "Olympus Zuiko Digital ED 9-18mm f/4.0-5.6";
|
||||
lenses["00 34 10"] = "Olympus M.Zuiko Digital ED 12-45mm f/4.0 Pro";
|
||||
lenses["00 35 00"] = "Olympus Zuiko Digital 14-54mm f/2.8-3.5 II";
|
||||
lenses["01 01 00"] = "Sigma 18-50mm f/3.5-5.6 DC";
|
||||
lenses["01 01 10"] = "Sigma 30mm f/2.8 EX DN";
|
||||
lenses["01 02 00"] = "Sigma 55-200mm f/4.0-5.6 DC";
|
||||
lenses["01 02 10"] = "Sigma 19mm f/2.8 EX DN";
|
||||
lenses["01 03 00"] = "Sigma 18-125mm f/3.5-5.6 DC";
|
||||
lenses["01 03 10"] = "Sigma 30mm f/2.8 DN | A";
|
||||
lenses["01 04 00"] = "Sigma 18-125mm f/3.5-5.6 DC";
|
||||
lenses["01 04 10"] = "Sigma 19mm f/2.8 DN | A";
|
||||
lenses["01 05 00"] = "Sigma 30mm f/1.4 EX DC HSM";
|
||||
lenses["01 05 10"] = "Sigma 60mm f/2.8 DN | A";
|
||||
lenses["01 06 00"] = "Sigma APO 50-500mm f/4.0-6.3 EX DG HSM";
|
||||
lenses["01 06 10"] = "Sigma 30mm f/1.4 DC DN | C";
|
||||
lenses["01 07 00"] = "Sigma Macro 105mm f/2.8 EX DG";
|
||||
lenses["01 07 10"] = "Sigma 16mm f/1.4 DC DN | C (017)";
|
||||
lenses["01 08 00"] = "Sigma APO Macro 150mm f/2.8 EX DG HSM";
|
||||
lenses["01 09 00"] = "Sigma 18-50mm f/2.8 EX DC Macro";
|
||||
lenses["01 10 00"] = "Sigma 24mm f/1.8 EX DG Aspherical Macro";
|
||||
lenses["01 11 00"] = "Sigma APO 135-400mm f/4.5-5.6 DG";
|
||||
lenses["01 12 00"] = "Sigma APO 300-800mm f/5.6 EX DG HSM";
|
||||
lenses["01 13 00"] = "Sigma 30mm f/1.4 EX DC HSM";
|
||||
lenses["01 14 00"] = "Sigma APO 50-500mm f/4.0-6.3 EX DG HSM";
|
||||
lenses["01 15 00"] = "Sigma 10-20mm f/4.0-5.6 EX DC HSM";
|
||||
lenses["01 16 00"] = "Sigma APO 70-200mm f/2.8 II EX DG Macro HSM";
|
||||
lenses["01 17 00"] = "Sigma 50mm f/1.4 EX DG HSM";
|
||||
lenses["02 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph.";
|
||||
lenses["02 01 10"] = "Lumix G Vario 14-45mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 02 00"] = "Leica D Summilux 25mm f/1.4 Asph.";
|
||||
lenses["02 02 10"] = "Lumix G Vario 45-200mm f/4.0-5.6 Mega OIS";
|
||||
lenses["02 03 00"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph. Mega OIS";
|
||||
lenses["02 03 01"] = "Leica D Vario Elmar 14-50mm f/3.8-5.6 Asph.";
|
||||
lenses["02 03 10"] = "Lumix G Vario HD 14-140mm f/4.0-5.8 Asph. Mega OIS";
|
||||
lenses["02 04 00"] = "Leica D Vario Elmar 14-150mm f/3.5-5.6";
|
||||
lenses["02 04 10"] = "Lumix G Vario 7-14mm f/4.0 Asph.";
|
||||
lenses["02 05 10"] = "Lumix G 20mm f/1.7 Asph.";
|
||||
lenses["02 06 10"] = "Leica DG Macro-Elmarit 45mm f/2.8 Asph. Mega OIS";
|
||||
lenses["02 07 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 08 10"] = "Lumix G Fisheye 8mm f/3.5";
|
||||
lenses["02 09 10"] = "Lumix G Vario 100-300mm f/4.0-5.6 Mega OIS";
|
||||
lenses["02 10 10"] = "Lumix G 14mm f/2.5 Asph.";
|
||||
lenses["02 11 10"] = "Lumix G 12.5mm f/12 3D";
|
||||
lenses["02 12 10"] = "Leica DG Summilux 25mm f/1.4 Asph.";
|
||||
lenses["02 13 10"] = "Lumix G X Vario PZ 45-175mm f/4.0-5.6 Asph. Power OIS";
|
||||
lenses["02 14 10"] = "Lumix G X Vario PZ 14-42mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 15 10"] = "Lumix G X Vario 12-35mm f/2.8 Asph. Power OIS";
|
||||
lenses["02 16 10"] = "Lumix G Vario 45-150mm f/4.0-5.6 Asph. Mega OIS";
|
||||
lenses["02 17 10"] = "Lumix G X Vario 35-100mm f/2.8 Power OIS";
|
||||
lenses["02 18 10"] = "Lumix G Vario 14-42mm f/3.5-5.6 II Asph. Mega OIS";
|
||||
lenses["02 19 10"] = "Lumix G Vario 14-140mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 20 10"] = "Lumix G Vario 12-32mm f/3.5-5.6 Asph. Mega OIS";
|
||||
lenses["02 21 10"] = "Leica DG Nocticron 42.5mm f/1.2 Asph. Power OIS";
|
||||
lenses["02 22 10"] = "Leica DG Summilux 15mm f/1.7 Asph.";
|
||||
lenses["02 23 10"] = "Lumix G Vario 35-100mm f/4.0-5.6 Asph. Mega OIS";
|
||||
lenses["02 24 10"] = "Lumix G Macro 30mm f/2.8 Asph. Mega OIS";
|
||||
lenses["02 25 10"] = "Lumix G 42.5mm f/1.7 Asph. Power OIS";
|
||||
lenses["02 26 10"] = "Lumix G 25mm f/1.7 Asph.";
|
||||
lenses["02 27 10"] = "Leica DG Vario-Elmar 100-400mm f/4.0-6.3 Asph. Power OIS";
|
||||
lenses["02 28 10"] = "Lumix G Vario 12-60mm f/3.5-5.6 Asph. Power OIS";
|
||||
lenses["02 29 10"] = "Leica DG Summilux 12mm f/1.4 Asph.";
|
||||
lenses["02 30 10"] = "Leica DG Vario-Elmarit 12-60mm f/2.8-4 Asph. Power OIS";
|
||||
lenses["02 31 10"] = "Lumix G Vario 45-200mm f/4.0-5.6 II";
|
||||
lenses["02 32 10"] = "Lumix G Vario 100-300mm f/4.0-5.6 II";
|
||||
lenses["02 33 10"] = "Lumix G X Vario 12-35mm f/2.8 II Asph. Power OIS";
|
||||
lenses["02 34 10"] = "Lumix G Vario 35-100mm f/2.8 II";
|
||||
lenses["02 35 10"] = "Leica DG Vario-Elmarit 8-18mm f/2.8-4 Asph.";
|
||||
lenses["02 36 10"] = "Leica DG Elmarit 200mm f/2.8 Power OIS";
|
||||
lenses["02 37 10"] = "Leica DG Vario-Elmarit 50-200mm f/2.8-4 Asph. Power OIS";
|
||||
lenses["02 38 10"] = "Leica DG Vario-Summilux 10-25mm f/1.7 Asph.";
|
||||
lenses["03 01 00"] = "Leica D Vario Elmarit 14-50mm f/2.8-3.5 Asph.";
|
||||
lenses["03 02 00"] = "Leica D Summilux 25mm f/1.4 Asph.";
|
||||
lenses["05 01 10"] = "Tamron 14-150mm f/3.5-5.8 Di III";
|
||||
lenses["024 01 10"] = "Venus Optics Laowa 50mm f/2.8 2x Macro";
|
||||
}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream lid;
|
||||
lid.setf (std::ios_base::hex, std::ios_base::basefield);
|
||||
lid.setf (std::ios_base::uppercase);
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (0) << ' '; //maker
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (2) << ' '; //model
|
||||
lid << std::setw (2) << std::setfill ('0') << t->toInt (3); // submodel
|
||||
|
||||
std::map<std::string, std::string>::const_iterator r = lenses.find (lid.str());
|
||||
|
||||
if (r != lenses.end()) {
|
||||
return r->second;
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLLensTypeInterpreter olLensTypeInterpreter;
|
||||
|
||||
class OLFlashTypeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFlashTypeInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[2] = "Simple E-System";
|
||||
choices[3] = "E-System";
|
||||
}
|
||||
};
|
||||
OLFlashTypeInterpreter olFlashTypeInterpreter;
|
||||
|
||||
class OLExposureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLExposureModeInterpreter ()
|
||||
{
|
||||
choices[1] = "Manual";
|
||||
choices[2] = "Program";
|
||||
choices[3] = "Aperture-priority AE";
|
||||
choices[4] = "Shutter speed priority AE";
|
||||
choices[5] = "Program-shift";
|
||||
}
|
||||
};
|
||||
OLExposureModeInterpreter olExposureModeInterpreter;
|
||||
|
||||
class OLMeteringModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLMeteringModeInterpreter ()
|
||||
{
|
||||
choices[2] = "Center-weighted average";
|
||||
choices[3] = "Spot";
|
||||
choices[5] = "ESP";
|
||||
choices[261] = "Pattern+AF";
|
||||
choices[515] = "Spot+Highlight control";
|
||||
choices[1027] = "Spot+Shadow control";
|
||||
}
|
||||
};
|
||||
OLMeteringModeInterpreter olMeteringModeInterpreter;
|
||||
|
||||
class OLFocusModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFocusModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Single AF";
|
||||
choices[1] = "Sequential shooting AF";
|
||||
choices[2] = "Continuous AF";
|
||||
choices[3] = "Multi AF";
|
||||
choices[4] = "Face detect";
|
||||
choices[10] = "MF";
|
||||
}
|
||||
};
|
||||
OLFocusModeInterpreter olFocusModeInterpreter;
|
||||
|
||||
class OLWhitebalance2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLWhitebalance2Interpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "Auto (Keep Warm Color Off)";
|
||||
choices[16] = "7500K (Fine Weather with Shade)";
|
||||
choices[17] = "6000K (Cloudy)";
|
||||
choices[18] = "5300K (Fine Weather)";
|
||||
choices[20] = "3000K (Tungsten light)";
|
||||
choices[21] = "3600K (Tungsten light-like)";
|
||||
choices[22] = "Auto Setup";
|
||||
choices[23] = "5500K (Flash)";
|
||||
choices[33] = "6600K (Daylight fluorescent)";
|
||||
choices[34] = "4500K (Neutral white fluorescent)";
|
||||
choices[35] = "4000K (Cool white fluorescent)";
|
||||
choices[36] = "White Fluorescent";
|
||||
choices[48] = "3600K (Tungsten light-like)";
|
||||
choices[67] = "Underwater";
|
||||
choices[256] = "One Touch WB 1";
|
||||
choices[257] = "One Touch WB 2";
|
||||
choices[258] = "One Touch WB 3";
|
||||
choices[259] = "One Touch WB 4";
|
||||
choices[512] = "Custom WB 1";
|
||||
choices[513] = "Custom WB 2";
|
||||
choices[514] = "Custom WB 3";
|
||||
choices[515] = "Custom WB 4";
|
||||
}
|
||||
};
|
||||
OLWhitebalance2Interpreter olWhitebalance2Interpreter;
|
||||
|
||||
class OLSceneModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLSceneModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[6] = "Auto";
|
||||
choices[7] = "Sport";
|
||||
choices[8] = "Portrait";
|
||||
choices[9] = "Landscape+Portrait";
|
||||
choices[10] = "Landscape";
|
||||
choices[11] = "Night Scene";
|
||||
choices[12] = "Self Portrait";
|
||||
choices[13] = "Panorama";
|
||||
choices[14] = "2 in 1";
|
||||
choices[15] = "Movie";
|
||||
choices[16] = "Landscape+Portrait";
|
||||
choices[17] = "Night+Portrait";
|
||||
choices[18] = "Indoor";
|
||||
choices[19] = "Fireworks";
|
||||
choices[20] = "Sunset";
|
||||
choices[21] = "Beauty Skin";
|
||||
choices[22] = "Macro";
|
||||
choices[23] = "Super Macro";
|
||||
choices[24] = "Food";
|
||||
choices[25] = "Documents";
|
||||
choices[26] = "Museum";
|
||||
choices[27] = "Shoot & Select";
|
||||
choices[28] = "Beach & Snow";
|
||||
choices[29] = "Self Protrait+Timer";
|
||||
choices[30] = "Candle";
|
||||
choices[31] = "Available Light";
|
||||
choices[32] = "Behind Glass";
|
||||
choices[33] = "My Mode";
|
||||
choices[34] = "Pet";
|
||||
choices[35] = "Underwater Wide1";
|
||||
choices[36] = "Underwater Macro";
|
||||
choices[37] = "Shoot & Select1";
|
||||
choices[38] = "Shoot & Select2";
|
||||
choices[39] = "High Key";
|
||||
choices[40] = "Digital Image Stabilization";
|
||||
choices[41] = "Auction";
|
||||
choices[42] = "Beach";
|
||||
choices[43] = "Snow";
|
||||
choices[44] = "Underwater Wide2";
|
||||
choices[45] = "Low Key";
|
||||
choices[46] = "Children";
|
||||
choices[47] = "Vivid";
|
||||
choices[48] = "Nature Macro";
|
||||
choices[49] = "Underwater Snapshot";
|
||||
choices[50] = "Shooting Guide";
|
||||
choices[54] = "Face Portrait";
|
||||
choices[57] = "Bulb";
|
||||
choices[59] = "Smile Shot";
|
||||
choices[60] = "Quick Shutter";
|
||||
choices[63] = "Slow Shutter";
|
||||
choices[64] = "Bird Watching";
|
||||
choices[65] = "Multiple Exposure";
|
||||
choices[66] = "e-Portrait";
|
||||
choices[67] = "Soft Background Shot";
|
||||
choices[142] = "Hand-held Starlight";
|
||||
choices[154] = "HDR";
|
||||
}
|
||||
};
|
||||
OLSceneModeInterpreter olSceneModeInterpreter;
|
||||
|
||||
class OLPictureModeBWFilterInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeBWFilterInterpreter ()
|
||||
{
|
||||
choices[0] = "n/a";
|
||||
choices[1] = "Neutral";
|
||||
choices[2] = "Yellow";
|
||||
choices[3] = "Orange";
|
||||
choices[4] = "Red";
|
||||
choices[5] = "Green";
|
||||
}
|
||||
};
|
||||
OLPictureModeBWFilterInterpreter olPictureModeBWFilterInterpreter;
|
||||
|
||||
class OLPictureModeToneInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeToneInterpreter ()
|
||||
{
|
||||
choices[0] = "n/a";
|
||||
choices[1] = "Neutral";
|
||||
choices[2] = "Sepia";
|
||||
choices[3] = "Blue";
|
||||
choices[4] = "Purple";
|
||||
choices[5] = "Green";
|
||||
}
|
||||
};
|
||||
OLPictureModeToneInterpreter olPictureModeToneInterpreter;
|
||||
|
||||
class OLImageQuality2Interpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLImageQuality2Interpreter ()
|
||||
{
|
||||
choices[1] = "SQ";
|
||||
choices[2] = "HQ";
|
||||
choices[3] = "SHQ";
|
||||
choices[4] = "RAW";
|
||||
choices[5] = "SQ (5)";
|
||||
}
|
||||
};
|
||||
OLImageQuality2Interpreter olImageQuality2Interpreter;
|
||||
|
||||
class OLDevEngineInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
// RawDevEngine
|
||||
OLDevEngineInterpreter ()
|
||||
{
|
||||
choices[0] = "High Speed";
|
||||
choices[1] = "High Function";
|
||||
choices[2] = "Advanced High Speed";
|
||||
choices[3] = "Advanced High Function";
|
||||
}
|
||||
};
|
||||
OLDevEngineInterpreter olDevEngineInterpreter;
|
||||
|
||||
class OLPictureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLPictureModeInterpreter ()
|
||||
{
|
||||
choices[1] = "Vivid";
|
||||
choices[2] = "Natural";
|
||||
choices[3] = "Muted";
|
||||
choices[4] = "Portrait";
|
||||
choices[5] = "i-Enhance";
|
||||
choices[7] = "Color Creator";
|
||||
choices[9] = "Color Profile 1";
|
||||
choices[10] = "Color Profile 2";
|
||||
choices[11] = "Color Profile 3";
|
||||
choices[12] = "Monochrome Profile 1";
|
||||
choices[13] = "Monochrome Profile 2";
|
||||
choices[14] = "Monochrome Profile 3";
|
||||
choices[256] = "Monotone";
|
||||
choices[512] = "Sepia";
|
||||
}
|
||||
};
|
||||
OLPictureModeInterpreter olPictureModeInterpreter;
|
||||
|
||||
class OLColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLColorSpaceInterpreter ()
|
||||
{
|
||||
choices[0] = "sRGB";
|
||||
choices[1] = "Adobe RGB";
|
||||
choices[2] = "Pro Photo RGB";
|
||||
}
|
||||
};
|
||||
OLColorSpaceInterpreter olColorSpaceInterpreter;
|
||||
|
||||
class OLNoiseFilterInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLNoiseFilterInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int a = t->toInt (0);
|
||||
int b = t->toInt (2);
|
||||
int c = t->toInt (4);
|
||||
|
||||
if (a == -1 && b == -2 && c == 1) {
|
||||
return "Low";
|
||||
} else if (a == -2 && b == -2 && c == 1) {
|
||||
return "Off";
|
||||
} else if (a == 0 && b == -2 && c == 1) {
|
||||
return "Standard";
|
||||
} else if (a == 1 && b == -2 && c == 1) {
|
||||
return "High";
|
||||
} else {
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
};
|
||||
OLNoiseFilterInterpreter olNoiseFilterInterpreter;
|
||||
|
||||
class OLFlashModeInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLFlashModeInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
int a = t->toInt ();
|
||||
str << "Flash Used = " << ((a & 1) ? "Yes" : "No") << std::endl;
|
||||
str << "Fill-in = " << ((a & 2) ? "On" : "Off") << std::endl;
|
||||
str << "Red-eye = " << ((a & 4) ? "On" : "Off") << std::endl;
|
||||
str << "Slow-sync = " << ((a & 8) ? "On" : "Off") << std::endl;
|
||||
str << "Forced On = " << ((a & 16) ? "On" : "Off") << std::endl;
|
||||
str << "2nd Curtain = " << ((a & 32) ? "On" : "Off");
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLFlashModeInterpreter olFlashModeInterpreter;
|
||||
|
||||
class OLNoiseReductionInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
OLNoiseReductionInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
std::ostringstream str;
|
||||
int a = t->toInt ();
|
||||
str << "Noise Reduction = " << ((a & 1) ? "On" : "Off") << std::endl;
|
||||
str << "Noise Filter = " << ((a & 2) ? "On" : "Off") << std::endl;
|
||||
str << "Noise Filter (ISO Boost) = " << ((a & 4) ? "On" : "Off") << std::endl;
|
||||
str << "Auto = " << ((a & 8) ? "On" : "Off");
|
||||
return str.str();
|
||||
}
|
||||
};
|
||||
OLNoiseReductionInterpreter olNoiseReductionInterpreter;
|
||||
|
||||
class OLFlashModelInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OLFlashModelInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[1] = "FL-20";
|
||||
choices[2] = "FL-50";
|
||||
choices[3] = "RF-11";
|
||||
choices[4] = "TF-22";
|
||||
choices[5] = "FL-36";
|
||||
choices[6] = "FL-50R";
|
||||
choices[7] = "FL-36R";
|
||||
choices[9] = "FL-14";
|
||||
choices[11] = "FL-600R";
|
||||
}
|
||||
};
|
||||
OLFlashModelInterpreter olFlashModelInterpreter;
|
||||
|
||||
const TagAttrib olyFocusInfoAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "FocusInfoVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0209, AUTO, "AutoFocus", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0210, AUTO, "SceneDetect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0211, AUTO, "SceneArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0212, AUTO, "SceneDetectData", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "ZoomStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "FocusStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "FocusStepInfinity", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "FocusStepNear", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0305, AUTO, "FocusDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0308, AUTO, "AFPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1201, AUTO, "ExternalFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1203, AUTO, "ExternalFlashGuideNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1204, AUTO, "ExternalFlashBounce", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1205, AUTO, "ExternalFlashZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1208, AUTO, "InternalFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1209, AUTO, "ManualFlash", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1500, AUTO, "SensorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1600, AUTO, "ImageStabilization", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyImageProcessingAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "ImageProcessingVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "WB_RBLevels", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "WB_RBLevels3000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "WB_RBLevels3300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "WB_RBLevels3600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "WB_RBLevels3900K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "WB_RBLevels4000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "WB_RBLevels4300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "WB_RBLevels4500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "WB_RBLevels4800K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "WB_RBLevels5300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "WB_RBLevels6000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "WB_RBLevels6600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010d, AUTO, "WB_RBLevels7500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010e, AUTO, "WB_RBLevelsCWB1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "WB_RBLevelsCWB2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "WB_RBLevelsCWB3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "WB_RBLevelsCWB4", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0113, AUTO, "WB_GLevel3000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0114, AUTO, "WB_GLevel3300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0115, AUTO, "WB_GLevel3600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0116, AUTO, "WB_GLevel3900K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0117, AUTO, "WB_GLevel4000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0118, AUTO, "WB_GLevel4300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0119, AUTO, "WB_GLevel4500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011a, AUTO, "WB_GLevel4800K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011b, AUTO, "WB_GLevel5300K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011c, AUTO, "WB_GLevel6000K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011d, AUTO, "WB_GLevel6600K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011e, AUTO, "WB_GLevel7500K", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x011f, AUTO, "WB_GLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "ColorMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "Enhancer", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "EnhancerValues", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0310, AUTO, "CoringFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0311, AUTO, "CoringValues", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0600, AUTO, "BlackLevel2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0610, AUTO, "GainBase", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0611, AUTO, "ValidBits", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0612, AUTO, "CropLeft", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0613, AUTO, "CropTop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0614, AUTO, "CropWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0615, AUTO, "CropHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "NoiseReduction2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "DistortionCorrection2", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1012, AUTO, "ShadingCompensation2", &olOnOffInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1103, AUTO, "UnknownBlock", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1200, AUTO, "FaceDetect", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1201, AUTO, "FaceDetectArea", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyRawDevelopmentAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "RawDevVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "RawDevWBFineAdjustment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "RawDevGrayPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "RawDevSaturationEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "RawDevContrastValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "RawDevSharpnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "RawDevEngine", &olDevEngineInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "RawDevEditStatus", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "RawDevSettings", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyRawDevelopment2Attribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "RawDevVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "RawDevExposureBiasValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "RawDevWhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "RawDevWhiteBalanceValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "RawDevWBFineAdjustment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "RawDevGrayPoint", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0105, AUTO, "RawDevContrastValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0106, AUTO, "RawDevSharpnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0107, AUTO, "RawDevSaturationEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0108, AUTO, "RawDevMemoryColorEmphasis", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0109, AUTO, "RawDevColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010a, AUTO, "RawDevNoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010b, AUTO, "RawDevEngine", &olDevEngineInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010c, AUTO, "RawDevPictureMode", &olPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010d, AUTO, "RawDevPMSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010e, AUTO, "RawDevPMContrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "RawDevPMSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "RawDevPM_BWFilter", &olPictureModeBWFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "RawDevPMPictureTone", &olPictureModeToneInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0112, AUTO, "RawDevGradation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0113, AUTO, "RawDevSaturation3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0119, AUTO, "RawDevAutoGradation", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0120, AUTO, "RawDevPMNoiseFilter", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyCameraSettingsAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "CameraSettingsVersion", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0100, AUTO, "PreviewImageValid", &olYesNoInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0101, AUTO, "PreviewImageStart", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0102, AUTO, "PreviewImageLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "ExposureMode", &olExposureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "AELock", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "MeteringMode", &olMeteringModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "MacroMode", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "FocusMode", &olFocusModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "FocusProcess", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "AFSearch", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "AFAreas", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0400, AUTO, "FlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0401, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0500, AUTO, "WhiteBalance2", &olWhitebalance2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0501, AUTO, "WhiteBalanceTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0502, AUTO, "WhiteBalanceBracket", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0503, AUTO, "CustomSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0504, AUTO, "ModifiedSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0505, AUTO, "ContrastSetting", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0506, AUTO, "SharpnessSetting", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0507, AUTO, "ColorSpace", &olColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0509, AUTO, "SceneMode", &olSceneModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050a, AUTO, "NoiseReduction", &olNoiseReductionInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050b, AUTO, "DistortionCorrection", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050c, AUTO, "ShadingCompensation", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050d, AUTO, "CompressionFactor", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x050f, AUTO, "Gradation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0520, AUTO, "PictureMode", &olPictureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0521, AUTO, "PictureModeSaturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0522, AUTO, "PictureModeHue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0523, AUTO, "PictureModeContrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0524, AUTO, "PictureModeSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0525, AUTO, "PictureModeBWFilter", &olPictureModeBWFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0526, AUTO, "PictureModeTone", &olPictureModeToneInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0527, AUTO, "NoiseFilter", &olNoiseFilterInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0600, AUTO, "DriveMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0601, AUTO, "PanoramaMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0603, AUTO, "ImageQuality2", &olImageQuality2Interpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0900, AUTO, "ManometerPressure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0901, AUTO, "ManometerReading", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0902, AUTO, "ExtendedWBDetect", &olOnOffInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olyEquipmentAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "EquipmentVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0100, AUTO, "CameraType2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0101, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0102, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0103, AUTO, "FocalPlaneDiagonal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "LensType", &olLensTypeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0204, AUTO, "LensFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0205, AUTO, "MaxApertureAtMinFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0206, AUTO, "MaxApertureAtMaxFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0207, AUTO, "MinFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0208, AUTO, "MaxFocalLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020a, AUTO, "MaxApertureAtCurrentFocal", &olApertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020b, AUTO, "LensProperties", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "Extender", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "ExtenderSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "ExtenderModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "ExtenderFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "FlashType", &olFlashTypeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "FlashModel", &olFlashModelInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "FlashFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "FlashSerialNumber", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
|
||||
const TagAttrib olympusAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0104, AUTO, "BodyFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0200, AUTO, "SpecialMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0201, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0202, AUTO, "Macro", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0203, AUTO, "BWMode", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0204, AUTO, "DigitalZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0205, AUTO, "FocalPlaneDiagonal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0206, AUTO, "LensDistortionParams", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0207, AUTO, "CameraType", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0208, AUTO, "TextInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0209, AUTO, "CameraID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020b, AUTO, "EpsonImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020c, AUTO, "EpsonImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x020d, AUTO, "EpsonSoftware", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0280, AUTO, "PreviewImage", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0300, AUTO, "PreCaptureFrames", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0301, AUTO, "WhiteBoard", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0302, AUTO, "OneTouchWB", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0303, AUTO, "WhiteBalanceBracket", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0304, AUTO, "WhiteBalanceBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0403, AUTO, "SceneMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0404, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0405, AUTO, "Firmware", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x0e00, AUTO, "PrintIM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0f00, AUTO, "DataDump", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0f01, AUTO, "DataDump2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1000, AUTO, "ShutterSpeedValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1001, AUTO, "ISOValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1002, AUTO, "ApertureValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1003, AUTO, "BrightnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1004, AUTO, "FlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1005, AUTO, "FlashDevice", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1006, AUTO, "ExposureCompensation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1007, AUTO, "SensorTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1008, AUTO, "LensTemperature", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1009, AUTO, "LightCondition", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100a, AUTO, "FocusRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100b, AUTO, "FocusMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100c, AUTO, "ManualFocusDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100d, AUTO, "ZoomStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100e, AUTO, "FocusStepCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x100f, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1010, AUTO, "FlashChargeLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1011, AUTO, "ColorMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1012, AUTO, "BlackLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1013, AUTO, "ColorTemperatureBG", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1014, AUTO, "ColorTemperatureRG", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1015, AUTO, "WBMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1017, AUTO, "RedBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1018, AUTO, "BlueBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1019, AUTO, "ColorMatrixNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101a, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101b, AUTO, "ExternalFlashAE1_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101c, AUTO, "ExternalFlashAE2_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101d, AUTO, "InternalFlashAE1_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101e, AUTO, "InternalFlashAE2_0", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x101f, AUTO, "ExternalFlashAE1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1020, AUTO, "ExternalFlashAE2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1021, AUTO, "InternalFlashAE1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1022, AUTO, "InternalFlashAE2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1023, AUTO, "FlashExposureComp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1024, AUTO, "InternalFlashTable", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1025, AUTO, "ExternalFlashGValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1026, AUTO, "ExternalFlashBounce", &olYesNoInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1027, AUTO, "ExternalFlashZoom", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1028, AUTO, "ExternalFlashMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1029, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102a, AUTO, "SharpnessFactor", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102b, AUTO, "ColorControl", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102c, AUTO, "ValidBits", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102d, AUTO, "CoringFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102e, AUTO, "OlympusImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x102f, AUTO, "OlympusImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1030, AUTO, "SceneDetect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1031, AUTO, "SceneArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1033, AUTO, "SceneDetectData", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1034, AUTO, "CompressionRatio", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1035, AUTO, "PreviewImageValid", &olYesNoInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1036, AUTO, "PreviewImageStart", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x1037, AUTO, "PreviewImageLength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1038, AUTO, "AFResult", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x1039, AUTO, "CCDScanMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103a, AUTO, "NoiseReduction", &olOnOffInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103b, AUTO, "InfinityLensStep", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103c, AUTO, "NearLensStep", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103d, AUTO, "LightValueCenter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103e, AUTO, "LightValuePeriphery", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x103f, AUTO, "FieldCount", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyEquipmentAttribs, 0x2010, AUTO, "Equipment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyCameraSettingsAttribs, 0x2020, AUTO, "CameraSettings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyRawDevelopmentAttribs, 0x2030, AUTO, "RawDevelopment", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyRawDevelopment2Attribs, 0x2031, AUTO, "RawDev2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyImageProcessingAttribs, 0x2040, AUTO, "ImageProcessing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, olyFocusInfoAttribs, 0x2050, AUTO, "FocusInfo", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2100, AUTO, "Olympus2100", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2300, AUTO, "Olympus2300", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2400, AUTO, "Olympus2400", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2500, AUTO, "Olympus2500", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2600, AUTO, "Olympus2600", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2700, AUTO, "Olympus2700", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2800, AUTO, "Olympus2800", &stdInterpreter},
|
||||
{1, AC_WRITE, 0, nullptr, 0x2900, AUTO, "Olympus2900", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x3000, AUTO, "RawInfo", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
|
@ -1,138 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
// TODO: write interpreters
|
||||
|
||||
const TagAttrib panasonicAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "Quality", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "FirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "FocusMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000f, AUTO, "AFMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001a, AUTO, "ImageStabilization", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001c, AUTO, "Macro", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001f, AUTO, "ShootingMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0020, AUTO, "Audio", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0023, AUTO, "WhiteBalanceBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0024, AUTO, "FlashBias", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0025, AUTO, "InternalSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0026, AUTO, "ExifVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0028, AUTO, "ColorEffect", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0029, AUTO, "TimeSincePowerOn", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002a, AUTO, "BurstMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002b, AUTO, "SequenceNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002c, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002d, AUTO, "NoiseReduction", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002e, AUTO, "SelfTimer", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0030, AUTO, "Rotation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0031, AUTO, "AFAssistLamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0032, AUTO, "ColorMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0033, AUTO, "BabyAge1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0034, AUTO, "OpticalZoomMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0035, AUTO, "ConversionLens", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0036, AUTO, "TravelDay", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0039, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003a, AUTO, "WorldTimeLocation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003b, AUTO, "TextStamp1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003c, AUTO, "ProgramISO", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003d, AUTO, "AdvancedSceneType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003e, AUTO, "TextStamp2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x003f, AUTO, "FacesDetected", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0040, AUTO, "Saturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0041, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0042, AUTO, "FilmMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0044, AUTO, "ColorTempKelvin", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0045, AUTO, "BracketSettings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0046, AUTO, "WBAdjustAB", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0047, AUTO, "WBAdjustGM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0048, AUTO, "FlashCurtain", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0049, AUTO, "LongShutterNoiseReduction", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004b, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004c, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004d, AUTO, "AFPointPosition", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x004e, AUTO, "FaceDetInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0051, AUTO, "LensType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0052, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0053, AUTO, "AccessoryType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0054, AUTO, "AccessorySerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0059, AUTO, "Transform1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x005d, AUTO, "IntelligentExposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0060, AUTO, "LensFirmwareVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0061, AUTO, "FaceRecInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0062, AUTO, "FlashWarning", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0065, AUTO, "Title", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0066, AUTO, "BabyName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0067, AUTO, "Location", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0069, AUTO, "Country", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006b, AUTO, "State", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006d, AUTO, "City", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x006f, AUTO, "Landmark", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0070, AUTO, "IntelligentResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0077, AUTO, "BurstSheed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0079, AUTO, "IntelligentDRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x007c, AUTO, "ClearRetouch", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0080, AUTO, "City2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0086, AUTO, "ManometerPressure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0089, AUTO, "PhotoStyle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008a, AUTO, "ShadingCompensation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008c, AUTO, "AccelerometerZ", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008d, AUTO, "AccelerometerX", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008e, AUTO, "AccelerometerY", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x008f, AUTO, "CameraOrientation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0090, AUTO, "RollAngle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0091, AUTO, "PitchAngle", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0093, AUTO, "SweepPanoramaDirection", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0094, AUTO, "PanoramaFieldOfView", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0096, AUTO, "TimerRecording", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009d, AUTO, "InternalNDFilter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009e, AUTO, "HDR", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x009f, AUTO, "ShutterType", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x00a3, AUTO, "ClearRetouchValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x00ab, AUTO, "TouchAE", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0e00, AUTO, "PrintIM", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8000, AUTO, "MakerNoteVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8001, AUTO, "SceneMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8004, AUTO, "WBRedLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8005, AUTO, "WBGreenLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8006, AUTO, "WBBlueLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8007, AUTO, "FlashFired", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8008, AUTO, "TextStamp3", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8009, AUTO, "TextStamp4", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8010, AUTO, "BabyAge2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8012, AUTO, "Transform2", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib panasonicRawAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "Version", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "SensorWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "SensorHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0004, AUTO, "SensorTopBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0005, AUTO, "SensorLeftBorder", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0006, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0011, AUTO, "RedBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0012, AUTO, "BlueBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0017, AUTO, "ISOSpeed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0024, AUTO, "WBRedLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0025, AUTO, "WBGreenLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0026, AUTO, "WBBlueLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x002e, AUTO, "PreviewImage", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010f, AUTO, "Make", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "Model", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0111, AUTO, "StripOffsets", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0112, AUTO, "Orientation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0117, AUTO, "StripByteCounts", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0118, AUTO, "RawDataOffset", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
3553
rtexif/rtexif.cc
3553
rtexif/rtexif.cc
File diff suppressed because it is too large
Load Diff
706
rtexif/rtexif.h
706
rtexif/rtexif.h
|
@ -1,706 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <iomanip>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <glibmm/ustring.h>
|
||||
|
||||
#include "../rtengine/noncopyable.h"
|
||||
#include "../rtengine/rawmetadatalocation.h"
|
||||
|
||||
namespace Glib
|
||||
{
|
||||
class KeyFile;
|
||||
}
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
class ExifPairs;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class CacheImageData;
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
enum TagType {INVALID = 0, BYTE = 1, ASCII = 2, SHORT = 3, LONG = 4, RATIONAL = 5, SBYTE = 6, UNDEFINED = 7, SSHORT = 8, SLONG = 9, SRATIONAL = 10, FLOAT = 11, DOUBLE = 12, OLYUNDEF = 13, AUTO = 98, SUBDIR = 99};
|
||||
enum ActionCode {
|
||||
AC_DONTWRITE, // don't write it to the output
|
||||
AC_WRITE, // write it to the output
|
||||
AC_SYSTEM, // changed by RT (not editable/deletable) - don't write, don't show
|
||||
AC_NEW, // new addition - write, don't show
|
||||
|
||||
AC_INVALID = 100, // invalid state
|
||||
};
|
||||
enum ByteOrder {UNKNOWN = 0, INTEL = 0x4949, MOTOROLA = 0x4D4D};
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
const ByteOrder HOSTORDER = INTEL;
|
||||
#else
|
||||
const enum ByteOrder HOSTORDER = MOTOROLA;
|
||||
#endif
|
||||
enum MNKind {NOMK, IFD, HEADERIFD, NIKON3, OLYMPUS2, FUJI, TABLESUBDIR};
|
||||
|
||||
bool extractLensInfo (const std::string &fullname, double &minFocal, double &maxFocal, double &maxApertureAtMinFocal, double &maxApertureAtMaxFocal);
|
||||
|
||||
unsigned short sget2 (unsigned char *s, ByteOrder order);
|
||||
int sget4 (unsigned char *s, ByteOrder order);
|
||||
unsigned short get2 (FILE* f, ByteOrder order);
|
||||
int get4 (FILE* f, ByteOrder order);
|
||||
void sset2 (unsigned short v, unsigned char *s, ByteOrder order);
|
||||
void sset4 (int v, unsigned char *s, ByteOrder order);
|
||||
float int_to_float (int i);
|
||||
short int int2_to_signed (short unsigned int i);
|
||||
|
||||
struct TIFFHeader {
|
||||
|
||||
unsigned short byteOrder;
|
||||
unsigned short fixed;
|
||||
unsigned int ifdOffset;
|
||||
};
|
||||
|
||||
class Tag;
|
||||
class Interpreter;
|
||||
|
||||
/// Structure of information describing an Exif tag
|
||||
struct TagAttrib {
|
||||
int ignore; // =0: never ignore, =1: always ignore, =2: ignore if the subdir type is reduced image, =-1: end of table
|
||||
ActionCode action;
|
||||
int editable;
|
||||
const TagAttrib* subdirAttribs; // !NULL if this tag points to a subdir
|
||||
/** Numeric identifier of tag (or index inside DirectoryTable)
|
||||
To avoid rewriting all the tables, and to address the problem of TagDirectoryTable with heterogeneous tag's type,
|
||||
this parameter is now an unsigned int, where the leftmost 2 bytes represent the tag's type, which by default will be aqual
|
||||
to 0 (INVALID). Only non null tag type will be used. See nikon attrib for an example
|
||||
*/
|
||||
unsigned short ID;
|
||||
TagType type;
|
||||
const char* name;
|
||||
Interpreter* interpreter; // Call back hook
|
||||
};
|
||||
|
||||
const TagAttrib* lookupAttrib (const TagAttrib* dir, const char* field);
|
||||
|
||||
/// A directory of tags
|
||||
class TagDirectory
|
||||
{
|
||||
|
||||
protected:
|
||||
std::vector<Tag*> tags; // tags in the directory
|
||||
const TagAttrib* attribs; // descriptor table to decode the tags
|
||||
ByteOrder order; // byte order
|
||||
TagDirectory* parent; // parent directory (NULL if root)
|
||||
bool parseJPEG;
|
||||
static Glib::ustring getDumpKey (int tagID, const Glib::ustring &tagName);
|
||||
|
||||
public:
|
||||
TagDirectory ();
|
||||
TagDirectory (TagDirectory* p, FILE* f, int base, const TagAttrib* ta, ByteOrder border, bool skipIgnored = true, bool parseJpeg = true);
|
||||
TagDirectory (TagDirectory* p, const TagAttrib* ta, ByteOrder border);
|
||||
virtual ~TagDirectory ();
|
||||
|
||||
inline ByteOrder getOrder () const
|
||||
{
|
||||
return order;
|
||||
}
|
||||
TagDirectory* getParent ()
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
inline bool getParseJpeg() const
|
||||
{
|
||||
return parseJPEG;
|
||||
}
|
||||
TagDirectory* getRoot ();
|
||||
inline int getCount () const
|
||||
{
|
||||
return tags.size ();
|
||||
}
|
||||
const TagAttrib* getAttrib (int id);
|
||||
// Find a Tag by scanning the whole tag tree and stopping at the first occurrence
|
||||
const TagAttrib* getAttrib (const char* name);
|
||||
// Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength")
|
||||
const TagAttrib* getAttribP (const char* name);
|
||||
const TagAttrib* getAttribTable()
|
||||
{
|
||||
return attribs;
|
||||
}
|
||||
// Find a Tag by scanning the whole tag tree and stopping at the first occurrence
|
||||
Tag* getTag (const char* name) const;
|
||||
// Try to get the Tag at a given location. 'name' is a path relative to this directory (e.g. "LensInfo/FocalLength")
|
||||
Tag* getTagP (const char* name) const;
|
||||
Tag* getTag (int ID) const;
|
||||
|
||||
// Try to get the Tag in the current directory and in subdirectories
|
||||
// if lookUpward = true, it will scan the parents TagDirectory up to the root one,
|
||||
// but w/o looking into their subdirs
|
||||
Tag* findTag (const char* name, bool lookUpward = false) const;
|
||||
// Find a all Tags with the given name by scanning the whole tag tree
|
||||
std::vector<const Tag*> findTags (const char* name);
|
||||
// Find a all Tags with the given ID by scanning the whole tag tree
|
||||
std::vector<const Tag*> findTags (int ID);
|
||||
// Try to get the Tag in the current directory and in parent directories
|
||||
// (won't look into subdirs)
|
||||
Tag* findTagUpward (const char* name) const;
|
||||
bool getXMPTagValue (const char* name, char* value) const;
|
||||
|
||||
void keepTag (int ID);
|
||||
void addTag (Tag* &a);
|
||||
void addTagFront (Tag* &a);
|
||||
void replaceTag (Tag* a);
|
||||
inline Tag* getTagByIndex (int ix)
|
||||
{
|
||||
return tags[ix];
|
||||
}
|
||||
inline void setOrder (ByteOrder bo)
|
||||
{
|
||||
order = bo;
|
||||
}
|
||||
|
||||
virtual int calculateSize ();
|
||||
virtual int write (int start, unsigned char* buffer);
|
||||
virtual TagDirectory* clone (TagDirectory* parent) const;
|
||||
void applyChange (const std::string &field, const Glib::ustring &value);
|
||||
|
||||
void printAll (unsigned int level = 0) const; // reentrant debug function, keep level=0 on first call !
|
||||
bool CPBDump (const Glib::ustring &commFName, const Glib::ustring &imageFName, const Glib::ustring &profileFName, const Glib::ustring &defaultPParams,
|
||||
const CacheImageData* cfs, const bool flagMode, Glib::KeyFile *keyFile = nullptr, Glib::ustring tagDirName = "") const;
|
||||
void sort ();
|
||||
};
|
||||
|
||||
// a table of tags: id are offset from beginning and not identifiers
|
||||
class TagDirectoryTable: public TagDirectory, public rtengine::NonCopyable
|
||||
{
|
||||
protected:
|
||||
unsigned char *values; // Tags values are saved internally here
|
||||
long zeroOffset; // Offset 0 (index 0) could be at an offset from values
|
||||
long valuesSize; // Size of allocated memory
|
||||
TagType defaultType; // Default type of all tags in this directory
|
||||
public:
|
||||
TagDirectoryTable();
|
||||
TagDirectoryTable (TagDirectory* p, unsigned char *v, int memsize, int offs, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
TagDirectoryTable (TagDirectory* p, FILE* f, int memsize, int offset, TagType type, const TagAttrib* ta, ByteOrder border);
|
||||
~TagDirectoryTable() override;
|
||||
int calculateSize () override;
|
||||
int write (int start, unsigned char* buffer) override;
|
||||
TagDirectory* clone (TagDirectory* parent) const override;
|
||||
};
|
||||
|
||||
// a class representing a single tag
|
||||
class Tag :
|
||||
public rtengine::NonCopyable
|
||||
{
|
||||
|
||||
protected:
|
||||
unsigned short tag;
|
||||
TagType type;
|
||||
unsigned int count;
|
||||
unsigned char* value;
|
||||
int valuesize;
|
||||
bool keep;
|
||||
bool allocOwnMemory;
|
||||
|
||||
const TagAttrib* attrib;
|
||||
TagDirectory* parent;
|
||||
TagDirectory** directory;
|
||||
MNKind makerNoteKind;
|
||||
bool parseMakerNote (FILE* f, int base, ByteOrder bom );
|
||||
|
||||
public:
|
||||
Tag (TagDirectory* parent, FILE* f, int base); // parse next tag from the file
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, unsigned char *data, TagType t);
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, int data, TagType t); // create a new tag from array (used
|
||||
Tag (TagDirectory* parent, const TagAttrib* attr, const char* data); // create a new tag from array (used
|
||||
|
||||
~Tag ();
|
||||
void initType (unsigned char *data, TagType type);
|
||||
void initInt (int data, TagType t, int count = 1);
|
||||
void initUserComment (const Glib::ustring &text);
|
||||
void initString (const char* text);
|
||||
void initSubDir ();
|
||||
void initSubDir (TagDirectory* dir);
|
||||
void initMakerNote (MNKind mnk, const TagAttrib* ta);
|
||||
void initUndefArray (const char* data, int len);
|
||||
void initLongArray (const char* data, int len);
|
||||
void initRational (int num, int den);
|
||||
|
||||
static void swapByteOrder2 (unsigned char *buffer, int count);
|
||||
|
||||
// get basic tag properties
|
||||
int getID () const
|
||||
{
|
||||
return tag;
|
||||
}
|
||||
int getCount () const
|
||||
{
|
||||
return count;
|
||||
}
|
||||
TagType getType () const
|
||||
{
|
||||
return (attrib && attrib->type > INVALID && attrib->type < AUTO) ? attrib->type : type;
|
||||
}
|
||||
unsigned char* getValue () const
|
||||
{
|
||||
return value;
|
||||
}
|
||||
signed char* getSignedValue () const
|
||||
{
|
||||
return reinterpret_cast<signed char*> (value);
|
||||
}
|
||||
const TagAttrib* getAttrib () const
|
||||
{
|
||||
return attrib;
|
||||
}
|
||||
inline ByteOrder getOrder () const
|
||||
{
|
||||
return parent ? parent->getOrder() : HOSTORDER;
|
||||
}
|
||||
inline TagDirectory* getParent () const
|
||||
{
|
||||
return parent;
|
||||
}
|
||||
int getValueSize () const
|
||||
{
|
||||
return valuesize;
|
||||
}
|
||||
bool getOwnMemory () const
|
||||
{
|
||||
return allocOwnMemory;
|
||||
}
|
||||
|
||||
// read/write value
|
||||
int toInt (int ofs = 0, TagType astype = INVALID) const;
|
||||
void fromInt (int v);
|
||||
double toDouble (int ofs = 0) const;
|
||||
double* toDoubleArray (int ofs = 0) const;
|
||||
void toRational (int& num, int& denom, int ofs = 0) const;
|
||||
void toString (char* buffer, std::size_t size, int ofs = 0) const;
|
||||
void fromString (const char* v, int size = -1);
|
||||
void setInt (int v, int ofs = 0, TagType astype = LONG);
|
||||
int getDistanceFrom (const TagDirectory *root);
|
||||
|
||||
// additional getter/setter for more comfortable use
|
||||
std::string valueToString () const;
|
||||
std::string nameToString (int i = 0);
|
||||
void valueFromString (const std::string& value);
|
||||
void userCommentFromString (const Glib::ustring& text);
|
||||
|
||||
// functions for writing
|
||||
int calculateSize ();
|
||||
int write (int offs, int dataOffs, unsigned char* buffer);
|
||||
Tag* clone (TagDirectory* parent) const;
|
||||
|
||||
// to control if the tag shall be written
|
||||
bool getKeep ()
|
||||
{
|
||||
return keep;
|
||||
}
|
||||
void setKeep (bool k)
|
||||
{
|
||||
keep = k;
|
||||
}
|
||||
|
||||
// get subdirectory (there can be several, the last is NULL)
|
||||
bool isDirectory ()
|
||||
{
|
||||
return directory != nullptr;
|
||||
}
|
||||
TagDirectory* getDirectory (int i = 0)
|
||||
{
|
||||
return (directory) ? directory[i] : nullptr;
|
||||
}
|
||||
|
||||
MNKind getMakerNoteFormat ()
|
||||
{
|
||||
return makerNoteKind;
|
||||
}
|
||||
};
|
||||
|
||||
class ExifManager
|
||||
{
|
||||
|
||||
Tag* saveCIFFMNTag (TagDirectory* root, int len, const char* name);
|
||||
void parseCIFF (int length, TagDirectory* root);
|
||||
void parse (bool isRaw, bool skipIgnored = true, bool parseJpeg = true);
|
||||
|
||||
public:
|
||||
FILE* f;
|
||||
std::unique_ptr<rtengine::RawMetaDataLocation> rml;
|
||||
ByteOrder order;
|
||||
bool onlyFirst; // Only first IFD
|
||||
unsigned int IFDOffset;
|
||||
std::vector<TagDirectory*> roots;
|
||||
std::vector<TagDirectory*> frames;
|
||||
|
||||
ExifManager (FILE* fHandle, std::unique_ptr<rtengine::RawMetaDataLocation> _rml, bool onlyFirstIFD)
|
||||
: f(fHandle), rml(std::move(_rml)), order(UNKNOWN), onlyFirst(onlyFirstIFD),
|
||||
IFDOffset(0) {}
|
||||
|
||||
void setIFDOffset(unsigned int offset);
|
||||
|
||||
|
||||
void parseRaw (bool skipIgnored = true);
|
||||
void parseStd (bool skipIgnored = true);
|
||||
void parseJPEG (int offset = 0); // offset: to extract exif data from a embedded preview/thumbnail
|
||||
void parseTIFF (bool skipIgnored = true);
|
||||
void parseCIFF ();
|
||||
|
||||
/// @brief Get default tag for TIFF
|
||||
/// @param forthis The byte order will be taken from the given directory.
|
||||
/// @return The ownership of the return tags is passed to the caller.
|
||||
static std::vector<Tag*> getDefaultTIFFTags (TagDirectory* forthis);
|
||||
static int createJPEGMarker (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, unsigned char* buffer);
|
||||
static int createTIFFHeader (const TagDirectory* root, const rtengine::procparams::ExifPairs& changeList, int W, int H, int bps, const char* profiledata, int profilelen, const char* iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize);
|
||||
static int createPNGMarker(const TagDirectory *root, const rtengine::procparams::ExifPairs &changeList, int W, int H, int bps, const char *iptcdata, int iptclen, unsigned char *&buffer, unsigned &bufferSize);
|
||||
};
|
||||
|
||||
class Interpreter
|
||||
{
|
||||
public:
|
||||
Interpreter () {}
|
||||
virtual ~Interpreter() {};
|
||||
virtual std::string toString (const Tag* t) const
|
||||
{
|
||||
char buffer[1024];
|
||||
t->toString (buffer, sizeof(buffer));
|
||||
std::string s (buffer);
|
||||
std::string::size_type p1 = s.find_first_not_of (' ');
|
||||
|
||||
if ( p1 == std::string::npos ) {
|
||||
return s;
|
||||
} else {
|
||||
return s.substr (p1, s.find_last_not_of (' ') - p1 + 1);
|
||||
}
|
||||
}
|
||||
virtual void fromString (Tag* t, const std::string& value)
|
||||
{
|
||||
if (t->getType() == SHORT || t->getType() == LONG) {
|
||||
t->fromInt (atoi (value.c_str()));
|
||||
} else {
|
||||
t->fromString (value.c_str());
|
||||
}
|
||||
}
|
||||
// Get the value as a double
|
||||
virtual double toDouble (const Tag* t, int ofs = 0)
|
||||
{
|
||||
|
||||
switch (t->getType()) {
|
||||
case SBYTE:
|
||||
return double (int (t->getSignedValue()[ofs]));
|
||||
|
||||
case BYTE:
|
||||
return (double) ((int)t->getValue()[ofs]);
|
||||
|
||||
case ASCII:
|
||||
return 0.0;
|
||||
|
||||
case SSHORT:
|
||||
return (double)int2_to_signed (sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SHORT:
|
||||
return (double) ((int)sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SLONG:
|
||||
case LONG:
|
||||
return (double) ((int)sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SRATIONAL: {
|
||||
const double dividend = (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
const double dividend = (uint32_t)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
const double divisor = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return divisor == 0. ? 0. : dividend / divisor;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return double (sget4 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case UNDEFINED:
|
||||
return 0.;
|
||||
|
||||
default:
|
||||
return 0.; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||
}
|
||||
}
|
||||
// Get the value as an int
|
||||
virtual int toInt (const Tag* t, int ofs = 0, TagType astype = INVALID)
|
||||
{
|
||||
if (astype == INVALID || astype == AUTO) {
|
||||
astype = t->getType();
|
||||
}
|
||||
|
||||
switch (astype) {
|
||||
case SBYTE:
|
||||
return int (t->getSignedValue()[ofs]);
|
||||
|
||||
case BYTE:
|
||||
return t->getValue()[ofs];
|
||||
|
||||
case ASCII:
|
||||
return 0;
|
||||
|
||||
case SSHORT:
|
||||
return (int)int2_to_signed (sget2 (t->getValue() + ofs, t->getOrder()));
|
||||
|
||||
case SHORT:
|
||||
return (int)sget2 (t->getValue() + ofs, t->getOrder());
|
||||
|
||||
case SLONG:
|
||||
case LONG:
|
||||
return (int)sget4 (t->getValue() + ofs, t->getOrder());
|
||||
|
||||
case SRATIONAL: {
|
||||
int a = (int)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (int)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case RATIONAL: {
|
||||
uint32_t a = (uint32_t)sget4 (t->getValue() + ofs + 4, t->getOrder());
|
||||
return a == 0 ? 0 : (uint32_t)sget4 (t->getValue() + ofs, t->getOrder()) / a;
|
||||
}
|
||||
|
||||
case FLOAT:
|
||||
return (int)toDouble (t, ofs);
|
||||
|
||||
case UNDEFINED:
|
||||
return 0;
|
||||
|
||||
default:
|
||||
return 0; // Quick fix for missing cases (INVALID, DOUBLE, OLYUNDEF, SUBDIR)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
extern Interpreter stdInterpreter;
|
||||
|
||||
template<typename T = std::uint32_t>
|
||||
class ChoiceInterpreter : public Interpreter
|
||||
{
|
||||
protected:
|
||||
using Choices = std::map<T, std::string>;
|
||||
using ChoicesIterator = typename Choices::const_iterator;
|
||||
Choices choices;
|
||||
public:
|
||||
ChoiceInterpreter () {};
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
const typename std::map<T, std::string>::const_iterator r = choices.find(t->toInt());
|
||||
|
||||
if (r != choices.end()) {
|
||||
return r->second;
|
||||
} else {
|
||||
char buffer[1024];
|
||||
t->toString(buffer, sizeof(buffer));
|
||||
return buffer;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template< class T >
|
||||
class IntLensInterpreter : public Interpreter
|
||||
{
|
||||
protected:
|
||||
typedef std::multimap< T, std::string> container_t;
|
||||
typedef typename std::multimap< T, std::string>::const_iterator it_t;
|
||||
typedef std::pair< T, std::string> p_t;
|
||||
container_t choices;
|
||||
|
||||
virtual std::string guess (const T lensID, double focalLength, double maxApertureAtFocal, double *lensInfoArray) const
|
||||
{
|
||||
it_t r;
|
||||
size_t nFound = choices.count ( lensID );
|
||||
|
||||
switch ( nFound ) {
|
||||
case 0: { // lens Unknown
|
||||
std::ostringstream s;
|
||||
s << lensID;
|
||||
return s.str();
|
||||
}
|
||||
|
||||
case 1: // lens found
|
||||
r = choices.find ( lensID );
|
||||
return r->second;
|
||||
|
||||
default:
|
||||
// More than one hit: we must guess
|
||||
break;
|
||||
}
|
||||
|
||||
std::string bestMatch ("Unknown");
|
||||
double a1, a2, f1, f2;
|
||||
|
||||
/* FIRST TRY
|
||||
*
|
||||
* Get the lens info (min/man focal, min/max aperture) and compare them to the possible choice
|
||||
*/
|
||||
if (lensInfoArray) {
|
||||
for ( r = choices.lower_bound ( lensID ); r != choices.upper_bound (lensID); ++r ) {
|
||||
if ( !extractLensInfo ( r->second, f1, f2, a1, a2) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (f1 == lensInfoArray[0] && f2 == lensInfoArray[1] && a1 == lensInfoArray[2] && a2 == lensInfoArray[3])
|
||||
// can't match better! we take this entry as being the one
|
||||
{
|
||||
return r->second;
|
||||
}
|
||||
}
|
||||
|
||||
// No lens found, we update the "unknown" string with the lens info values
|
||||
if (lensInfoArray[0] == lensInfoArray[1]) {
|
||||
bestMatch += Glib::ustring::compose (" (%1mm", int (lensInfoArray[0]));
|
||||
} else {
|
||||
bestMatch += Glib::ustring::compose (" (%1-%2mm", int (lensInfoArray[0]), int (lensInfoArray[1]));
|
||||
}
|
||||
|
||||
if (lensInfoArray[2] == lensInfoArray[3]) {
|
||||
bestMatch += Glib::ustring::compose (" f/%1)", Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[2]));
|
||||
} else
|
||||
bestMatch += Glib::ustring::compose (" f/%1-%2)",
|
||||
Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[2]),
|
||||
Glib::ustring::format (std::fixed, std::setprecision (1), lensInfoArray[3]));
|
||||
}
|
||||
|
||||
/* SECOND TRY
|
||||
*
|
||||
* Choose the best match: thanks to exiftool by Phil Harvey
|
||||
* first throws for "out of focal range" and lower or upper aperture of the lens compared to MaxApertureAtFocal
|
||||
* if the lens is not constant aperture, calculate aprox. aperture of the lens at focalLength
|
||||
* and compare with actual aperture.
|
||||
*/
|
||||
std::ostringstream candidates;
|
||||
double deltaMin = 1000.;
|
||||
|
||||
for ( r = choices.lower_bound ( lensID ); r != choices.upper_bound (lensID); ++r ) {
|
||||
double dif;
|
||||
|
||||
if ( !extractLensInfo ( r->second, f1, f2, a1, a2) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( f1 == 0. || a1 == 0.) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( focalLength < f1 - .5 || focalLength > f2 + 0.5 ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( maxApertureAtFocal > 0.1) {
|
||||
double lensAperture;
|
||||
|
||||
if ( maxApertureAtFocal < a1 - 0.15 || maxApertureAtFocal > a2 + 0.15) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( a1 == a2 || f1 == f2) {
|
||||
lensAperture = a1;
|
||||
} else {
|
||||
lensAperture = exp ( log (a1) + (log (a2) - log (a1)) / (log (f2) - log (f1)) * (log (focalLength) - log (f1)) );
|
||||
}
|
||||
|
||||
dif = std::abs (lensAperture - maxApertureAtFocal);
|
||||
} else {
|
||||
dif = 0;
|
||||
}
|
||||
|
||||
if ( dif < deltaMin ) {
|
||||
deltaMin = dif;
|
||||
bestMatch = r->second;
|
||||
}
|
||||
|
||||
if ( dif < 0.15) {
|
||||
if ( candidates.tellp() ) {
|
||||
candidates << "\n or " << r->second;
|
||||
} else {
|
||||
candidates << r->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !candidates.tellp() ) {
|
||||
return bestMatch;
|
||||
} else {
|
||||
return candidates.str();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
inline static int getTypeSize ( TagType type )
|
||||
{
|
||||
return ("11124811248484"[type < 14 ? type : 0] - '0');
|
||||
}
|
||||
|
||||
extern const TagAttrib exifAttribs[];
|
||||
extern const TagAttrib gpsAttribs[];
|
||||
extern const TagAttrib iopAttribs[];
|
||||
extern const TagAttrib ifdAttribs[];
|
||||
extern const TagAttrib nikon2Attribs[];
|
||||
extern const TagAttrib nikon3Attribs[];
|
||||
extern const TagAttrib canonAttribs[];
|
||||
extern const TagAttrib pentaxAttribs[];
|
||||
extern const TagAttrib pentaxLensDataAttribs[];
|
||||
extern const TagAttrib pentaxLensInfoQAttribs[];
|
||||
extern const TagAttrib pentaxLensCorrAttribs[];
|
||||
extern const TagAttrib pentaxAEInfoAttribs[];
|
||||
extern const TagAttrib pentaxAEInfo2Attribs[];
|
||||
extern const TagAttrib pentaxAEInfo3Attribs[];
|
||||
extern const TagAttrib pentaxCameraSettingsAttribs[];
|
||||
extern const TagAttrib pentaxFlashInfoAttribs[];
|
||||
extern const TagAttrib pentaxSRInfoAttribs[];
|
||||
extern const TagAttrib pentaxSRInfo2Attribs[];
|
||||
extern const TagAttrib pentaxBatteryInfoAttribs[];
|
||||
extern const TagAttrib pentaxCameraInfoAttribs[];
|
||||
extern const TagAttrib fujiAttribs[];
|
||||
extern const TagAttrib minoltaAttribs[];
|
||||
extern const TagAttrib sonyAttribs[];
|
||||
extern const TagAttrib sonyTag9405Attribs[];
|
||||
extern const TagAttrib sonyCameraInfoAttribs[];
|
||||
extern const TagAttrib sonyCameraInfo2Attribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs2[];
|
||||
extern const TagAttrib sonyCameraSettingsAttribs3[];
|
||||
//extern const TagAttrib sonyDNGMakerNote[];
|
||||
extern const TagAttrib olympusAttribs[];
|
||||
extern const TagAttrib kodakIfdAttribs[];
|
||||
void parseKodakIfdTextualInfo (Tag *textualInfo, Tag* exif);
|
||||
extern const TagAttrib panasonicAttribs[];
|
||||
extern const TagAttrib panasonicRawAttribs[];
|
||||
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -1,927 +0,0 @@
|
|||
/*
|
||||
* This file is part of RawTherapee.
|
||||
*
|
||||
* Copyright (c) 2004-2010 Gabor Horvath <hgabor@rawtherapee.com>
|
||||
* Copyright (c) 2010 Oliver Duis <www.oliverduis.de>
|
||||
*
|
||||
* RawTherapee is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* RawTherapee is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
|
||||
#include "rtexif.h"
|
||||
|
||||
namespace rtexif
|
||||
{
|
||||
|
||||
class ColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ColorSpaceInterpreter ()
|
||||
{
|
||||
choices[1] = "sRGB";
|
||||
choices[2] = "Adobe RGB";
|
||||
choices[0xffff] = "Uncalibrated";
|
||||
}
|
||||
};
|
||||
ColorSpaceInterpreter colorSpaceInterpreter;
|
||||
|
||||
class PreviewColorSpaceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PreviewColorSpaceInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Gray Gamma 2.2";
|
||||
choices[2] = "sRGB";
|
||||
choices[3] = "Adobe RGB";
|
||||
choices[4] = "ProPhoto RGB";
|
||||
}
|
||||
};
|
||||
PreviewColorSpaceInterpreter previewColorSpaceInterpreter;
|
||||
|
||||
class LinearSRGBInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
LinearSRGBInterpreter ()
|
||||
{
|
||||
choices[0] = "Linear";
|
||||
choices[1] = "sRGB";
|
||||
}
|
||||
};
|
||||
LinearSRGBInterpreter linearSRGBInterpreter;
|
||||
|
||||
class DefaultBlackRenderInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
DefaultBlackRenderInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto";
|
||||
choices[1] = "None";
|
||||
}
|
||||
};
|
||||
DefaultBlackRenderInterpreter defaultBlackRenderInterpreter;
|
||||
|
||||
class ExposureProgramInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ExposureProgramInterpreter ()
|
||||
{
|
||||
choices[0] = "Not defined";
|
||||
choices[1] = "Manual";
|
||||
choices[2] = "Normal program";
|
||||
choices[3] = "Aperture priority";
|
||||
choices[4] = "Shutter priority";
|
||||
choices[5] = "Creative program";
|
||||
choices[6] = "Action program";
|
||||
choices[7] = "Portrait mode";
|
||||
choices[8] = "Landscape mode";
|
||||
}
|
||||
};
|
||||
ExposureProgramInterpreter exposureProgramInterpreter;
|
||||
|
||||
class MeteringModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
MeteringModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Average";
|
||||
choices[2] = "Center weighted";
|
||||
choices[3] = "Spot";
|
||||
choices[4] = "Multispot";
|
||||
choices[5] = "Pattern";
|
||||
choices[6] = "Partial";
|
||||
choices[255] = "Other";
|
||||
}
|
||||
};
|
||||
MeteringModeInterpreter meteringModeInterpreter;
|
||||
|
||||
class ExposureModeInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ExposureModeInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto exposure";
|
||||
choices[1] = "Manual exposure";
|
||||
choices[2] = "Auto bracket";
|
||||
}
|
||||
};
|
||||
ExposureModeInterpreter exposureModeInterpreter;
|
||||
|
||||
class WhiteBalanceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
WhiteBalanceInterpreter ()
|
||||
{
|
||||
choices[0] = "Auto white balance";
|
||||
choices[1] = "Manual white balance";
|
||||
}
|
||||
};
|
||||
WhiteBalanceInterpreter whiteBalanceInterpreter;
|
||||
|
||||
class SceneCaptureInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SceneCaptureInterpreter ()
|
||||
{
|
||||
choices[0] = "Standard";
|
||||
choices[1] = "Landscape";
|
||||
choices[2] = "Portrait";
|
||||
choices[3] = "Night scene";
|
||||
}
|
||||
};
|
||||
SceneCaptureInterpreter sceneCaptureInterpreter;
|
||||
|
||||
class GainControlInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
GainControlInterpreter ()
|
||||
{
|
||||
choices[0] = "None";
|
||||
choices[1] = "Low gain up";
|
||||
choices[2] = "High gain up";
|
||||
choices[3] = "Low gain down";
|
||||
choices[4] = "High gain down";
|
||||
}
|
||||
};
|
||||
GainControlInterpreter gainControlInterpreter;
|
||||
|
||||
class ContrastInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ContrastInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Hard";
|
||||
}
|
||||
};
|
||||
ContrastInterpreter contrastInterpreter;
|
||||
|
||||
class SharpnessInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SharpnessInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Soft";
|
||||
choices[2] = "Hard";
|
||||
}
|
||||
};
|
||||
SharpnessInterpreter sharpnessInterpreter;
|
||||
|
||||
class SaturationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
SaturationInterpreter ()
|
||||
{
|
||||
choices[0] = "Normal";
|
||||
choices[1] = "Low saturation";
|
||||
choices[2] = "High saturation";
|
||||
}
|
||||
};
|
||||
SaturationInterpreter saturationInterpreter;
|
||||
|
||||
class FlashInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
FlashInterpreter ()
|
||||
{
|
||||
choices[0x0000] = "Flash did not fire";
|
||||
choices[0x0001] = "Flash fired";
|
||||
choices[0x0005] = "Strobe return light not detected";
|
||||
choices[0x0007] = "Strobe return light detected";
|
||||
choices[0x0009] = "Flash fired, compulsory flash mode";
|
||||
choices[0x000D] = "Flash fired, compulsory flash mode, return light not detected";
|
||||
choices[0x000F] = "Flash fired, compulsory flash mode, return light detected";
|
||||
choices[0x0010] = "Flash did not fire, compulsory flash mode";
|
||||
choices[0x0018] = "Flash did not fire, auto mode";
|
||||
choices[0x0019] = "Flash fired, auto mode";
|
||||
choices[0x001D] = "Flash fired, auto mode, return light not detected";
|
||||
choices[0x001F] = "Flash fired, auto mode, return light detected";
|
||||
choices[0x0020] = "No flash function";
|
||||
choices[0x0041] = "Flash fired, red-eye reduction mode";
|
||||
choices[0x0045] = "Flash fired, red-eye reduction mode, return light not detected";
|
||||
choices[0x0047] = "Flash fired, red-eye reduction mode, return light detected";
|
||||
choices[0x0049] = "Flash fired, compulsory flash mode, red-eye reduction mode";
|
||||
choices[0x004D] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light not detected";
|
||||
choices[0x004F] = "Flash fired, compulsory flash mode, red-eye reduction mode, return light detected";
|
||||
choices[0x0059] = "Flash fired, auto mode, red-eye reduction mode";
|
||||
choices[0x005D] = "Flash fired, auto mode, return light not detected, red-eye reduction mode";
|
||||
choices[0x005F] = "Flash fired, auto mode, return light detected, red-eye reduction mode";
|
||||
}
|
||||
};
|
||||
FlashInterpreter flashInterpreter;
|
||||
|
||||
class LightSourceInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
LightSourceInterpreter ()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "Daylight";
|
||||
choices[2] = "Fluorescent";
|
||||
choices[3] = "Tungsten";
|
||||
choices[4] = "Flash";
|
||||
choices[9] = "Fine weather";
|
||||
choices[10] = "Cloudy weather";
|
||||
choices[11] = "Shade";
|
||||
choices[12] = "Daylight fluorescent";
|
||||
choices[13] = "Day white fluorescent";
|
||||
choices[14] = "Cool white fluorescent";
|
||||
choices[15] = "White fluorescent";
|
||||
choices[17] = "Standard light A";
|
||||
choices[18] = "Standard light B";
|
||||
choices[19] = "Standard light C";
|
||||
choices[20] = "D55";
|
||||
choices[21] = "D65";
|
||||
choices[22] = "D75";
|
||||
choices[23] = "D50";
|
||||
choices[24] = "ISO studio tungsten";
|
||||
choices[255] = "Other light source";
|
||||
}
|
||||
};
|
||||
LightSourceInterpreter lightSourceInterpreter;
|
||||
|
||||
class CompressionInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
CompressionInterpreter ()
|
||||
{
|
||||
choices[1] = "Uncompressed";
|
||||
choices[6] = "JPEG Compression";
|
||||
}
|
||||
};
|
||||
CompressionInterpreter compressionInterpreter;
|
||||
|
||||
class PhotometricInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PhotometricInterpreter ()
|
||||
{
|
||||
choices[2] = "RGB";
|
||||
choices[6] = "YCbCr";
|
||||
}
|
||||
};
|
||||
PhotometricInterpreter photometricInterpreter;
|
||||
|
||||
class ProfileEmbedPolicyInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
ProfileEmbedPolicyInterpreter ()
|
||||
{
|
||||
choices[0] = "Allow Copying";
|
||||
choices[1] = "Embed if Used";
|
||||
choices[2] = "Never Embed";
|
||||
choices[3] = "No Restrictions";
|
||||
}
|
||||
};
|
||||
ProfileEmbedPolicyInterpreter profileEmbedPolicyInterpreter;
|
||||
|
||||
class PlanarConfigInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
|
||||
public:
|
||||
PlanarConfigInterpreter ()
|
||||
{
|
||||
choices[1] = "Chunky format";
|
||||
choices[2] = "Planar format";
|
||||
}
|
||||
};
|
||||
PlanarConfigInterpreter planarConfigInterpreter;
|
||||
|
||||
class FNumberInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
FNumberInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v < 0. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%0.1f", v);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
FNumberInterpreter fNumberInterpreter;
|
||||
|
||||
class ApertureInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ApertureInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = pow (2.0, t->toDouble() / 2.0);
|
||||
|
||||
if ( v < 0. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ApertureInterpreter apertureInterpreter;
|
||||
|
||||
class ExposureBiasInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ExposureBiasInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v < -1000. || v > 1000. ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%+0.2f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ExposureBiasInterpreter exposureBiasInterpreter;
|
||||
|
||||
class ShutterSpeedInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ShutterSpeedInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double d = pow (2.0, -t->toDouble());
|
||||
|
||||
if (d > 0.0 && d <= 0.5) {
|
||||
snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", d);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ShutterSpeedInterpreter shutterSpeedInterpreter;
|
||||
|
||||
class ExposureTimeInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
ExposureTimeInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double d = t->toDouble();
|
||||
|
||||
if (d > 0.0 && d <= 0.5) {
|
||||
snprintf(buffer, sizeof(buffer), "1/%.0f", 1.0 / d);
|
||||
} else {
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", d);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
ExposureTimeInterpreter exposureTimeInterpreter;
|
||||
|
||||
class FocalLengthInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
FocalLengthInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char buffer[32];
|
||||
double v = t->toDouble();
|
||||
|
||||
if ( v > 1000000. || v < 0 ) {
|
||||
return "undef";
|
||||
}
|
||||
|
||||
snprintf(buffer, sizeof(buffer), "%.1f", v );
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
FocalLengthInterpreter focalLengthInterpreter;
|
||||
|
||||
class UserCommentInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
UserCommentInterpreter () {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int count = t->getCount();
|
||||
|
||||
if (count <= 8) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
count = std::min (count, 65535); // limit to 65535 chars to avoid crashes in case of corrupted metadata
|
||||
unsigned char *buffer = new unsigned char[count - 6]; // include 2 ending null chars for UCS-2 string (possibly)
|
||||
unsigned char *value = t->getValue();
|
||||
|
||||
if (!memcmp(value, "ASCII\0\0\0", 8)) {
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 8] = '\0';
|
||||
} else if (!memcmp(value, "UNICODE\0", 8)) {
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 7] = buffer[count - 8] = '\0';
|
||||
Glib::ustring tmp1((char*)buffer);
|
||||
|
||||
|
||||
bool hasBOM = false;
|
||||
enum ByteOrder bo = UNKNOWN;
|
||||
if (count % 2 || (count >= 11 && (buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF))) {
|
||||
// odd string length can only be UTF-8, don't change anything
|
||||
std::string retVal ((char*)buffer + 3);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
} else if (count >= 10) {
|
||||
if (buffer[0] == 0xFF && buffer[1] == 0xFE) {
|
||||
bo = INTEL; // little endian
|
||||
hasBOM = true;
|
||||
} else if (buffer[0] == 0xFE && buffer[1] == 0xFF) {
|
||||
bo = MOTOROLA; // big endian
|
||||
hasBOM = true;
|
||||
}
|
||||
}
|
||||
if (bo == UNKNOWN) {
|
||||
// auto-detecting byte order; we still don't know if it's UCS-2 or UTF-8
|
||||
int a = 0, b = 0, c = 0, d = 0;
|
||||
for (int j = 8; j < count; j++) {
|
||||
unsigned char cc = value[j];
|
||||
if (!(j%2)) {
|
||||
// counting zeros for first byte
|
||||
if (!cc) {
|
||||
++a;
|
||||
}
|
||||
} else {
|
||||
// counting zeros for second byte
|
||||
if (!cc) {
|
||||
++b;
|
||||
}
|
||||
}
|
||||
if (!(cc & 0x80) || ((cc & 0xC0) == 0xC0) || ((cc & 0xC0) == 0x80)) {
|
||||
++c;
|
||||
}
|
||||
if ((cc & 0xC0) == 0x80) {
|
||||
++d;
|
||||
}
|
||||
}
|
||||
if (c == (count - 8) && d) {
|
||||
// this is an UTF-8 string
|
||||
std::string retVal ((char*)buffer);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
}
|
||||
if ((a || b) && a != b) {
|
||||
bo = a > b ? MOTOROLA : INTEL;
|
||||
}
|
||||
}
|
||||
if (bo == UNKNOWN) {
|
||||
// assuming platform's byte order
|
||||
#if __BYTE_ORDER__==__ORDER_LITTLE_ENDIAN__
|
||||
bo = INTEL;
|
||||
#else
|
||||
bo = MOTOROLA;
|
||||
#endif
|
||||
}
|
||||
|
||||
// now swapping if necessary
|
||||
if (!hasBOM && bo != HOSTORDER) {
|
||||
if (t->getOrder() != HOSTORDER) {
|
||||
Tag::swapByteOrder2(buffer, count - 8);
|
||||
}
|
||||
}
|
||||
|
||||
glong written;
|
||||
char* utf8Str = g_utf16_to_utf8((unsigned short int*)buffer, -1, nullptr, &written, nullptr);
|
||||
delete [] buffer;
|
||||
buffer = new unsigned char[written + 1];
|
||||
memcpy(buffer, utf8Str, written);
|
||||
buffer[written] = 0;
|
||||
g_free(utf8Str);
|
||||
} else if (!memcmp(value, "\0\0\0\0\0\0\0\0", 8)) {
|
||||
// local charset string, whatever it is
|
||||
memcpy(buffer, value + 8, count - 8);
|
||||
buffer[count - 7] = buffer[count - 8] = '\0';
|
||||
|
||||
gsize written = 0;
|
||||
char *utf8Str = g_locale_to_utf8((char*)buffer, count - 8, nullptr, &written, nullptr);
|
||||
if (utf8Str && written) {
|
||||
delete [] buffer;
|
||||
size_t length = strlen(utf8Str);
|
||||
buffer = new unsigned char[length + 1];
|
||||
strcpy((char*)buffer, utf8Str);
|
||||
} else {
|
||||
buffer[0] = 0;
|
||||
}
|
||||
if (utf8Str) {
|
||||
g_free(utf8Str);
|
||||
}
|
||||
} else {
|
||||
// JIS: unsupported
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
std::string retVal ((char*)buffer);
|
||||
delete [] buffer;
|
||||
return retVal;
|
||||
}
|
||||
void fromString (Tag* t, const std::string& value) override
|
||||
{
|
||||
Glib::ustring tmpStr(value);
|
||||
t->userCommentFromString (tmpStr);
|
||||
}
|
||||
};
|
||||
UserCommentInterpreter userCommentInterpreter;
|
||||
|
||||
class CFAInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
CFAInterpreter() {}
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
char colors[] = "RGB";
|
||||
char buffer[1024];
|
||||
|
||||
for ( int i = 0; i < t->getCount(); i++) {
|
||||
unsigned char c = t->toInt (i, BYTE);
|
||||
buffer[i] = c < 3 ? colors[c] : ' ';
|
||||
}
|
||||
|
||||
buffer[t->getCount()] = 0;
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
CFAInterpreter cfaInterpreter;
|
||||
|
||||
class OrientationInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
OrientationInterpreter ()
|
||||
{
|
||||
choices[1] = "Horizontal (normal)";
|
||||
choices[2] = "Mirror horizontal ";
|
||||
choices[3] = "Rotate 180";
|
||||
choices[4] = "Mirror vertical";
|
||||
choices[5] = "Mirror horizontal and rotate 270 CW";
|
||||
choices[6] = "Rotate 90 CW";
|
||||
choices[7] = "Mirror horizontal and rotate 90 CW";
|
||||
choices[8] = "Rotate 270 CW";
|
||||
// '9' is an "unofficial" value for Orientation but used by some older cameras that lacks orientation sensor, such as Kodak DCS
|
||||
choices[9] = "Unknown";
|
||||
}
|
||||
};
|
||||
OrientationInterpreter orientationInterpreter;
|
||||
|
||||
class UnitsInterpreter : public ChoiceInterpreter<>
|
||||
{
|
||||
public:
|
||||
UnitsInterpreter()
|
||||
{
|
||||
choices[0] = "Unknown";
|
||||
choices[1] = "inches";
|
||||
choices[2] = "cm";
|
||||
}
|
||||
};
|
||||
UnitsInterpreter unitsInterpreter;
|
||||
|
||||
class UTF8BinInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
UTF8BinInterpreter () {}
|
||||
};
|
||||
UTF8BinInterpreter utf8BinInterpreter;
|
||||
|
||||
class RawImageSegmentationInterpreter : public Interpreter
|
||||
{
|
||||
public:
|
||||
std::string toString (const Tag* t) const override
|
||||
{
|
||||
int segmentNumber = t->toInt(0, SHORT);
|
||||
int segmentWidth = t->toInt(2, SHORT);
|
||||
int lastSegmentWidth = t->toInt(4, SHORT);
|
||||
|
||||
char buffer[32];
|
||||
snprintf(buffer, sizeof(buffer), "%d %d %d", segmentNumber, segmentWidth, lastSegmentWidth);
|
||||
return buffer;
|
||||
}
|
||||
};
|
||||
RawImageSegmentationInterpreter rawImageSegmentationInterpreter;
|
||||
|
||||
const TagAttrib exifAttribs[] = {
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x829A, AUTO, "ExposureTime", &exposureTimeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x829D, AUTO, "FNumber", &fNumberInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8822, AUTO, "ExposureProgram", &exposureProgramInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8824, AUTO, "SpectralSensitivity", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8827, AUTO, "ISOSpeedRatings", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8828, AUTO, "OECF", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x8832, AUTO, "RecommendedExposureIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9000, AUTO, "ExifVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x9101, AUTO, "ComponentsConfiguration", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x9102, AUTO, "CompressedBitsPerPixel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9201, AUTO, "ShutterSpeedValue", &shutterSpeedInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9202, AUTO, "ApertureValue", &apertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9203, AUTO, "BrightnessValue", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9204, AUTO, "ExposureBiasValue", &exposureBiasInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9205, AUTO, "MaxApertureValue", &apertureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9206, AUTO, "SubjectDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9207, AUTO, "MeteringMode", &meteringModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9208, AUTO, "LightSource", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9209, AUTO, "Flash", &flashInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x920A, AUTO, "FocalLength", &focalLengthInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9214, AUTO, "SubjectArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9215, AUTO, "ExposureIndex", &stdInterpreter}, // Note: exists as 0xA215 too, it should be that way
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0x9216, AUTO, "TIFFEPSStandardID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9217, AUTO, "SensingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x927C, AUTO, "MakerNote", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x9286, AUTO, "UserComment", &userCommentInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9290, AUTO, "SubSecTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9291, AUTO, "SubSecTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9292, AUTO, "SubSecTimeDigitized", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA000, AUTO, "FlashpixVersion", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xA001, AUTO, "ColorSpace", &colorSpaceInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA002, AUTO, "PixelXDimension", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xA003, AUTO, "PixelYDimension", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0xA004, AUTO, "RelatedSoundFile", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter}, // do not enable, as it causes trouble with FUJI files
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20B, AUTO, "FlashEnergy", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20C, AUTO, "SpatialFrequencyResponse", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20E, AUTO, "FocalPlaneXResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA20F, AUTO, "FocalPlaneYResolution", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA210, AUTO, "FocalPlaneResolutionUnit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA214, AUTO, "SubjectLocation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA215, AUTO, "ExposureIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA217, AUTO, "SensingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA300, AUTO, "FileSource", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA301, AUTO, "SceneType", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xA302, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA401, AUTO, "CustomRendered", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA402, AUTO, "ExposureMode", &exposureModeInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA403, AUTO, "WhiteBalance", &whiteBalanceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA404, AUTO, "DigitalZoomRatio", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA405, AUTO, "FocalLengthIn35mmFilm", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA406, AUTO, "SceneCaptureType", &sceneCaptureInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA407, AUTO, "GainControl", &gainControlInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA408, AUTO, "Contrast", &contrastInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA409, AUTO, "Saturation", &saturationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40A, AUTO, "Sharpness", &sharpnessInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40B, AUTO, "DeviceSettingDescription", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA40C, AUTO, "SubjectDistanceRange", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA420, AUTO, "ImageUniqueID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA431, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA432, AUTO, "LensInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA433, AUTO, "LensMake", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA434, AUTO, "LensModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA435, AUTO, "LensSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xA500, AUTO, "Gamma", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC618, AUTO, "LinearizationTable", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC619, AUTO, "BlackLevelRepeatDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61A, AUTO, "BlackLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61B, AUTO, "BlackLevelDeltaH", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61C, AUTO, "BlackLevelDeltaV", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61D, AUTO, "WhiteLevel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61E, AUTO, "DefaultScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC61F, AUTO, "DefaultCropOrigin", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC620, AUTO, "DefaultCropSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC621, AUTO, "ColorMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC622, AUTO, "ColorMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC623, AUTO, "CameraCalibration1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC624, AUTO, "CameraCalibration2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC625, AUTO, "ReductionMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC626, AUTO, "ReductionMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC627, AUTO, "AnalogBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC628, AUTO, "AsShotNeutral", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC629, AUTO, "AsShotWhiteXY", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62A, AUTO, "BaselineExposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62B, AUTO, "BaselineNoise", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62C, AUTO, "BaselineSharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62D, AUTO, "BayerGreenSplit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62E, AUTO, "LinearResponseLimit", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC62F, AUTO, "CameraSerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC630, AUTO, "DNGLensInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC631, AUTO, "ChromaBlurRadius", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC632, AUTO, "AntiAliasStrength", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC633, AUTO, "ShadowScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65A, AUTO, "CalibrationIlluminant1", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65B, AUTO, "CalibrationIlluminant2", &lightSourceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65C, AUTO, "BestQualityScale", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC65D, AUTO, "RawDataUniqueID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68B, AUTO, "OriginalRawFileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68D, AUTO, "ActiveArea", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC68E, AUTO, "MaskedAreas", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC68F, AUTO, "AsShotICCProfile", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC690, AUTO, "AsShotPreProfileMatrix", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC691, AUTO, "CurrentICCProfile", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC692, AUTO, "CurrentPreProfileMatrix", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6BF, AUTO, "ColorimetricReference", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F3, AUTO, "CameraCalibrationSig", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F4, AUTO, "ProfileCalibrationSig", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F5, AUTO, "ProfileIFD", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F6, AUTO, "AsShotProfileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F7, AUTO, "NoiseReductionApplied", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F8, AUTO, "ProfileName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6F9, AUTO, "ProfileHueSatMapDims", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FA, AUTO, "ProfileHueSatMapData1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FB, AUTO, "ProfileHueSatMapData2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FC, AUTO, "ProfileToneCurve", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FD, AUTO, "ProfileEmbedPolicy", &profileEmbedPolicyInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC6FE, AUTO, "ProfileCopyright", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC714, AUTO, "ForwardMatrix1", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC715, AUTO, "ForwardMatrix2", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC716, AUTO, "PreviewApplicationName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC717, AUTO, "PreviewApplicationVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC718, AUTO, "PreviewSettingsName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC719, AUTO, "PreviewSettingsDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71A, AUTO, "PreviewColorSpace", &previewColorSpaceInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71B, AUTO, "PreviewDateTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71C, AUTO, "RawImageDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC71D, AUTO, "OriginalRawFileDigest", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC71E, AUTO, "SubTileBlockSize", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC71F, AUTO, "RowInterleaveFactor", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC725, AUTO, "ProfileLookTableDims", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC726, AUTO, "ProfileLookTableData", &stdInterpreter},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC740, AUTO, "OpcodeList1", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC741, AUTO, "OpcodeList2", & ???},
|
||||
// {0, AC_WRITE, 0, nullptr, 0xC74E, AUTO, "OpcodeList3", & ???},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC761, AUTO, "NoiseProfile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC763, AUTO, "TimeCodes", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC764, AUTO, "FrameRate", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC772, AUTO, "TStop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC789, AUTO, "ReelName", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC791, AUTO, "OriginalDefaultFinalSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC792, AUTO, "OriginalBestQualitySize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC793, AUTO, "OriginalDefaultCropSize", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A1, AUTO, "CameraLabel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A3, AUTO, "ProfileHueSatMapEncoding", &linearSRGBInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A4, AUTO, "ProfileLookTableEncoding", &linearSRGBInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A5, AUTO, "BaselineExposureOffset", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A6, AUTO, "DefaultBlackRender", &defaultBlackRenderInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A7, AUTO, "NewRawImageDigest", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7A8, AUTO, "RawToPreviewGain", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC7B5, AUTO, "DefaultUserCrop", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFDE9, AUTO, "SerialNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFDEA, AUTO, "Lens", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4C, AUTO, "RawFile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4D, AUTO, "Converter", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE4E, AUTO, "WhiteBalance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE51, AUTO, "Exposure", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE52, AUTO, "Shadows", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE53, AUTO, "Brightness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE54, AUTO, "Contrast", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE55, AUTO, "Saturation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE56, AUTO, "Sharpness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE57, AUTO, "Smoothness", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xFE58, AUTO, "MoireFilter", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
|
||||
const TagAttrib gpsAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0000, AUTO, "GPSVersionID", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "GPSLatitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "GPSLatitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0003, AUTO, "GPSLongitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0004, AUTO, "GPSLongitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0005, AUTO, "GPSAltitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0006, AUTO, "GPSAltitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0007, AUTO, "GPSTimeStamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0008, AUTO, "GPSSatelites", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0009, AUTO, "GPSStatus", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000a, AUTO, "GPSMeasureMode", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000b, AUTO, "GPSDOP", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000c, AUTO, "GPSSpeedRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000d, AUTO, "GPSSpeed", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000e, AUTO, "GPSTrackRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x000f, AUTO, "GPSTrack", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0010, AUTO, "GPSImgDirectionRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0011, AUTO, "GPSImgDirection", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0012, AUTO, "GPSMapDatum", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0013, AUTO, "GPSDestLatitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0014, AUTO, "GPSDestLatitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0015, AUTO, "GPSDestLongitudeRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0016, AUTO, "GPSDestLongitude", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0017, AUTO, "GPSDestBearingRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0018, AUTO, "GPSDestBearing", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0019, AUTO, "GPSDestDistanceRef", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001a, AUTO, "GPSDestDistance", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001b, AUTO, "GPSProcessingMethod", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001c, AUTO, "GPSAreaInformation", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001d, AUTO, "GPSDateStamp", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x001e, AUTO, "GPSDifferential", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib iopAttribs[] = {
|
||||
{0, AC_WRITE, 0, nullptr, 0x0001, AUTO, "InteroperabilityIndex", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0002, AUTO, "InteroperabilityVersion", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr }
|
||||
};
|
||||
|
||||
const TagAttrib ifdAttribs[] = {
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0017, AUTO, "PanaISO", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x00fe, AUTO, "NewSubFileType", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0100, AUTO, "ImageWidth", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0101, AUTO, "ImageHeight", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0102, AUTO, "BitsPerSample", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0103, AUTO, "Compression", &compressionInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0106, AUTO, "PhotometricInterpretation", &photometricInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x010E, AUTO, "ImageDescription", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x010F, AUTO, "Make", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0110, AUTO, "Model", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0111, AUTO, "StripOffsets", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0112, AUTO, "Orientation", &orientationInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0115, AUTO, "SamplesPerPixel", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0116, AUTO, "RowsPerStrip", &stdInterpreter},
|
||||
{1, AC_DONTWRITE, 0, nullptr, 0x0117, AUTO, "StripByteCounts", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011A, AUTO, "XResolution", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011B, AUTO, "YResolution", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x011C, AUTO, "PlanarConfiguration", &planarConfigInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0128, AUTO, "ResolutionUnit", &unitsInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x012D, AUTO, "TransferFunction", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0131, AUTO, "Software", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x0132, AUTO, "DateTime", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x013B, AUTO, "Artist", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x013E, AUTO, "WhitePoint", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x013F, AUTO, "PriomaryChromaticities", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, ifdAttribs, 0x014A, AUTO, "SubIFD", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0153, AUTO, "SampleFormat", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0201, AUTO, "JPEGInterchangeFormat", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0202, AUTO, "JPEGInterchangeFormatLength", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0211, AUTO, "YCbCrCoefficients", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0212, AUTO, "YCbCrSubSampling", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0213, AUTO, "YCbCrPositioning", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x0214, AUTO, "ReferenceBlackWhite", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x02bc, AUTO, "ApplicationNotes", &utf8BinInterpreter}, // XMP
|
||||
{0, AC_WRITE, 0, nullptr, 0x4746, AUTO, "Rating", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x4749, AUTO, "RatingPercent", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828d, AUTO, "CFAPatternDim", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x828e, AUTO, "CFAPattern", &cfaInterpreter},
|
||||
{0, AC_WRITE, 0, kodakIfdAttribs, 0x8290, AUTO, "KodakIFD", &stdInterpreter},
|
||||
{0, AC_WRITE, 1, nullptr, 0x8298, AUTO, "Copyright", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x83BB, AUTO, "IPTCData", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0x8606, AUTO, "LeafData", &stdInterpreter}, // is actually a subdir, but a proprietary format
|
||||
{0, AC_WRITE, 0, exifAttribs, 0x8769, AUTO, "Exif", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0x8773, AUTO, "ICCProfile", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, gpsAttribs, 0x8825, AUTO, "GPSInfo", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9003, AUTO, "DateTimeOriginal", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9004, AUTO, "DateTimeDigitized", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0x9211, AUTO, "ImageNumber", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, iopAttribs, 0xA005, AUTO, "Interoperability", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC4A5, AUTO, "PrintIMInformation", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC612, AUTO, "DNGVersion", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC613, AUTO, "DNGBackwardVersion", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC614, AUTO, "UniqueCameraModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xC615, AUTO, "LocalizedCameraModel", &stdInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xc62f, AUTO, "CameraSerialNumber", &stdInterpreter},
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xc630, AUTO, "DNGLensInfo", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xC634, AUTO, "MakerNote", &stdInterpreter}, //DNGPrivateData
|
||||
{0, AC_SYSTEM, 0, nullptr, 0xC640, AUTO, "RawImageSegmentation", &rawImageSegmentationInterpreter},
|
||||
{0, AC_WRITE, 0, nullptr, 0xc65d, AUTO, "RawDataUniqueID", &stdInterpreter},
|
||||
{0, AC_DONTWRITE, 0, nullptr, 0xc761, AUTO, "NoiseProfile", &stdInterpreter},
|
||||
{ -1, AC_DONTWRITE, 0, nullptr, 0, AUTO, "", nullptr}
|
||||
};
|
||||
}
|
|
@ -193,7 +193,7 @@ if(WIN32)
|
|||
${LENSFUN_INCLUDE_DIRS}
|
||||
${RSVG_INCLUDE_DIRS}
|
||||
)
|
||||
link_directories(. "${PROJECT_SOURCE_DIR}/rtexif"
|
||||
link_directories(.
|
||||
${EXTRA_LIBDIR}
|
||||
${GIOMM_LIBRARY_DIRS}
|
||||
${GIO_LIBRARY_DIRS}
|
||||
|
|
|
@ -335,7 +335,3 @@ int CacheImageData::save (const Glib::ustring& fname)
|
|||
}
|
||||
}
|
||||
|
||||
rtengine::procparams::IPTCPairs CacheImageData::getIPTCData(unsigned int frame) const
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
|
|
@ -89,30 +89,25 @@ public:
|
|||
// FramesMetaData interface
|
||||
//-------------------------------------------------------------------------
|
||||
|
||||
unsigned int getRootCount () const override { return -1; }
|
||||
unsigned int getFrameCount () const override { return frameCount; }
|
||||
bool hasExif (unsigned int frame = 0) const override { return false; }
|
||||
rtexif::TagDirectory* getRootExifData (unsigned int root = 0) const override { return nullptr; }
|
||||
rtexif::TagDirectory* getFrameExifData (unsigned int frame = 0) const override { return nullptr; }
|
||||
rtexif::TagDirectory* getBestExifData (rtengine::ImageSource *imgSource, rtengine::procparams::RAWParams *rawParams) const override { return nullptr; }
|
||||
bool hasIPTC (unsigned int frame = 0) const override { return false; }
|
||||
rtengine::procparams::IPTCPairs getIPTCData (unsigned int frame = 0) const override;
|
||||
tm getDateTime (unsigned int frame = 0) const override { return tm{}; }
|
||||
time_t getDateTimeAsTS(unsigned int frame = 0) const override { return time_t(-1); }
|
||||
int getISOSpeed (unsigned int frame = 0) const override { return iso; }
|
||||
double getFNumber (unsigned int frame = 0) const override { return fnumber; }
|
||||
double getFocalLen (unsigned int frame = 0) const override { return focalLen; }
|
||||
double getFocalLen35mm (unsigned int frame = 0) const override { return focalLen35mm; }
|
||||
float getFocusDist (unsigned int frame = 0) const override { return focusDist; }
|
||||
double getShutterSpeed (unsigned int frame = 0) const override { return shutter; }
|
||||
double getExpComp (unsigned int frame = 0) const override { return atof(expcomp.c_str()); }
|
||||
std::string getMake (unsigned int frame = 0) const override { return camMake; }
|
||||
std::string getModel (unsigned int frame = 0) const override { return camModel; }
|
||||
std::string getLens (unsigned int frame = 0) const override { return lens; }
|
||||
std::string getOrientation (unsigned int frame = 0) const override { return ""; } // TODO
|
||||
int getRating (unsigned int frame = 0) const override { return rating; } // FIXME-piotr : missing rating
|
||||
bool hasExif() const override { return false; }
|
||||
tm getDateTime() const override { return tm{}; }
|
||||
time_t getDateTimeAsTS() const override { return time_t(-1); }
|
||||
int getISOSpeed() const override { return iso; }
|
||||
double getFNumber() const override { return fnumber; }
|
||||
double getFocalLen() const override { return focalLen; }
|
||||
double getFocalLen35mm() const override { return focalLen35mm; }
|
||||
float getFocusDist() const override { return focusDist; }
|
||||
double getShutterSpeed() const override { return shutter; }
|
||||
double getExpComp() const override { return atof(expcomp.c_str()); }
|
||||
std::string getMake() const override { return camMake; }
|
||||
std::string getModel() const override { return camModel; }
|
||||
std::string getLens() const override { return lens; }
|
||||
std::string getOrientation() const override { return ""; } // TODO
|
||||
Glib::ustring getFileName() const override { return ""; }
|
||||
int getRating () const override { return rating; } // FIXME-piotr : missing rating
|
||||
bool getPixelShift () const override { return isPixelShift; }
|
||||
bool getHDR (unsigned int frame = 0) const override { return isHDR; }
|
||||
std::string getImageType (unsigned int frame) const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; }
|
||||
rtengine::IIOSampleFormat getSampleFormat (unsigned int frame = 0) const override { return sampleFormat; }
|
||||
bool getHDR() const override { return isHDR; }
|
||||
std::string getImageType() const override { return isPixelShift ? "PS" : isHDR ? "HDR" : "STD"; }
|
||||
rtengine::IIOSampleFormat getSampleFormat() const override { return sampleFormat; }
|
||||
};
|
||||
|
|
|
@ -1323,16 +1323,16 @@ void EditorPanel::info_toggled ()
|
|||
|
||||
const rtengine::FramesMetaData* idata = ipc->getInitialImage()->getMetaData();
|
||||
|
||||
if (idata && idata->hasExif(selectedFrame)) {
|
||||
if (idata && idata->hasExif()) {
|
||||
infoString = Glib::ustring::compose ("%1 + %2\n<span size=\"small\">f/</span><span size=\"large\">%3</span> <span size=\"large\">%4</span><span size=\"small\">s</span> <span size=\"small\">%5</span><span size=\"large\">%6</span> <span size=\"large\">%7</span><span size=\"small\">mm</span>",
|
||||
Glib::ustring (idata->getMake() + " " + idata->getModel()),
|
||||
Glib::ustring (idata->getLens()),
|
||||
Glib::ustring (idata->apertureToString (idata->getFNumber(selectedFrame))),
|
||||
Glib::ustring (idata->shutterToString (idata->getShutterSpeed(selectedFrame))),
|
||||
M ("QINFO_ISO"), idata->getISOSpeed(selectedFrame),
|
||||
Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen(selectedFrame)));
|
||||
Glib::ustring (idata->apertureToString (idata->getFNumber())),
|
||||
Glib::ustring (idata->shutterToString (idata->getShutterSpeed())),
|
||||
M ("QINFO_ISO"), idata->getISOSpeed(),
|
||||
Glib::ustring::format (std::setw (3), std::fixed, std::setprecision (2), idata->getFocalLen()));
|
||||
|
||||
expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(selectedFrame), true)); // maskZeroexpcomp
|
||||
expcomp = Glib::ustring (idata->expcompToString (idata->getExpComp(), true)); // maskZeroexpcomp
|
||||
|
||||
if (!expcomp.empty ()) {
|
||||
infoString = Glib::ustring::compose ("%1 <span size=\"large\">%2</span><span size=\"small\">EV</span>",
|
||||
|
@ -1360,7 +1360,7 @@ void EditorPanel::info_toggled ()
|
|||
if (isHDR) {
|
||||
infoString = Glib::ustring::compose ("%1\n" + M("QINFO_HDR"), infoString, numFrames);
|
||||
if (numFrames == 1) {
|
||||
int sampleFormat = idata->getSampleFormat(selectedFrame);
|
||||
int sampleFormat = idata->getSampleFormat();
|
||||
infoString = Glib::ustring::compose ("%1 / %2", infoString, M(Glib::ustring::compose("SAMPLEFORMAT_%1", sampleFormat)));
|
||||
}
|
||||
} else if (isPixelShift) {
|
||||
|
|
|
@ -16,24 +16,31 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <unordered_set>
|
||||
|
||||
#include "exifpanel.h"
|
||||
|
||||
#include "guiutils.h"
|
||||
#include "rtimage.h"
|
||||
#include "options.h"
|
||||
|
||||
#include "../rtengine/imagedata.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
using namespace rtexif;
|
||||
|
||||
ExifPanel::ExifPanel() :
|
||||
idata(nullptr),
|
||||
changeList(new rtengine::procparams::ExifPairs),
|
||||
defChangeList(new rtengine::procparams::ExifPairs)
|
||||
defChangeList(new rtengine::procparams::ExifPairs),
|
||||
editableTags{
|
||||
{"Exif.Photo.UserComment", "User Comment"},
|
||||
{"Exif.Image.Artist", "Artist"},
|
||||
{"Exif.Image.Copyright", "Copyright"},
|
||||
{"Exif.Image.ImageDescription", "Image Description"}
|
||||
}
|
||||
{
|
||||
recursiveOp = true;
|
||||
|
||||
exifTree = Gtk::manage (new Gtk::TreeView());
|
||||
scrolledWindow = Gtk::manage (new Gtk::ScrolledWindow());
|
||||
|
@ -51,11 +58,10 @@ ExifPanel::ExifPanel() :
|
|||
exifTreeModel = Gtk::TreeStore::create (exifColumns);
|
||||
exifTree->set_model (exifTreeModel);
|
||||
exifTree->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_NONE);
|
||||
exifTree->set_row_separator_func (sigc::mem_fun(*this, &ExifPanel::rowSeperatorFunc));
|
||||
exifTree->set_show_expanders(false);
|
||||
|
||||
delicon = RTImage::createPixbufFromFile ("cancel-small.png");
|
||||
keepicon = RTImage::createPixbufFromFile ("tick-small.png");
|
||||
editicon = RTImage::createPixbufFromFile ("add-small.png");
|
||||
editicon = RTImage::createPixbufFromFile("add-small.png");
|
||||
|
||||
Gtk::TreeView::Column *viewcol = Gtk::manage (new Gtk::TreeView::Column ("Field Name"));
|
||||
Gtk::CellRendererPixbuf* render_pb = Gtk::manage (new Gtk::CellRendererPixbuf ());
|
||||
|
@ -64,7 +70,7 @@ ExifPanel::ExifPanel() :
|
|||
viewcol->pack_start (*render_pb, false);
|
||||
viewcol->pack_start (*render_txt, true);
|
||||
viewcol->add_attribute (*render_pb, "pixbuf", exifColumns.icon);
|
||||
viewcol->add_attribute (*render_txt, "markup", exifColumns.field);
|
||||
viewcol->add_attribute (*render_txt, "markup", exifColumns.label);
|
||||
viewcol->set_expand (true);
|
||||
viewcol->set_resizable (true);
|
||||
viewcol->set_fixed_width (35);
|
||||
|
@ -99,24 +105,6 @@ ExifPanel::ExifPanel() :
|
|||
buttons1->set_row_homogeneous (true);
|
||||
buttons1->set_column_homogeneous (true);
|
||||
setExpandAlignProperties (buttons1, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
Gtk::Grid* buttons2 = Gtk::manage (new Gtk::Grid());
|
||||
buttons2->set_row_homogeneous (true);
|
||||
buttons2->set_column_homogeneous (true);
|
||||
setExpandAlignProperties (buttons2, true, false, Gtk::ALIGN_FILL, Gtk::ALIGN_CENTER);
|
||||
|
||||
remove = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_REMOVE")
|
||||
remove->set_image (*Gtk::manage (new RTImage(delicon)));
|
||||
remove->set_tooltip_text (M ("EXIFPANEL_REMOVEHINT"));
|
||||
remove->get_style_context()->add_class ("Left");
|
||||
setExpandAlignProperties (remove, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
buttons1->attach_next_to (*remove, Gtk::POS_LEFT, 1, 1);
|
||||
|
||||
keep = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_KEEP")
|
||||
keep->set_image (*Gtk::manage (new RTImage(keepicon)));
|
||||
keep->set_tooltip_text (M ("EXIFPANEL_KEEPHINT"));
|
||||
keep->get_style_context()->add_class ("MiddleH");
|
||||
setExpandAlignProperties (keep, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
buttons1->attach_next_to (*keep, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
add = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_ADDEDIT")
|
||||
add->set_image (*Gtk::manage (new RTImage(editicon)));
|
||||
|
@ -125,39 +113,28 @@ ExifPanel::ExifPanel() :
|
|||
setExpandAlignProperties (add, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
buttons1->attach_next_to (*add, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
showAll = Gtk::manage (new Gtk::ToggleButton (M ("EXIFPANEL_SHOWALL")));
|
||||
//add->set_tooltip_text (M("EXIFPANEL_SHOWALL"));
|
||||
showAll->get_style_context()->add_class ("Left");
|
||||
setExpandAlignProperties (showAll, false, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
showAll->set_active (options.lastShowAllExif);
|
||||
buttons2->attach_next_to (*showAll, Gtk::POS_LEFT, 1, 1);
|
||||
|
||||
reset = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESET")
|
||||
reset->set_image (*Gtk::manage (new RTImage("undo.png", "redo.png")));
|
||||
reset->set_tooltip_text (M ("EXIFPANEL_RESETHINT"));
|
||||
reset->get_style_context()->add_class ("MiddleH");
|
||||
setExpandAlignProperties (reset, true, true, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
buttons2->attach_next_to (*reset, Gtk::POS_RIGHT, 1, 1);
|
||||
buttons1->attach_next_to (*reset, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
resetAll = Gtk::manage (new Gtk::Button ()); // M("EXIFPANEL_RESETALL")
|
||||
resetAll->set_image (*Gtk::manage (new RTImage ("undo-all.png", "redo-all.png")));
|
||||
resetAll->set_tooltip_text (M ("EXIFPANEL_RESETALLHINT"));
|
||||
resetAll->get_style_context()->add_class ("Right");
|
||||
setExpandAlignProperties (resetAll, false, false, Gtk::ALIGN_FILL, Gtk::ALIGN_FILL);
|
||||
buttons2->attach_next_to (*resetAll, Gtk::POS_RIGHT, 1, 1);
|
||||
buttons1->attach_next_to (*resetAll, Gtk::POS_RIGHT, 1, 1);
|
||||
|
||||
pack_end (*buttons2, Gtk::PACK_SHRINK);
|
||||
pack_end (*buttons1, Gtk::PACK_SHRINK);
|
||||
|
||||
exifTree->get_selection()->signal_changed().connect (sigc::mem_fun (*this, &ExifPanel::exifSelectionChanged));
|
||||
exifTree->signal_row_activated().connect (sigc::mem_fun (*this, &ExifPanel::row_activated));
|
||||
// exifTree->signal_row_activated().connect (sigc::mem_fun (*this, &ExifPanel::row_activated));
|
||||
|
||||
remove->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::removePressed) );
|
||||
keep->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::keepPressed) );
|
||||
reset->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetPressed) );
|
||||
resetAll->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::resetAllPressed) );
|
||||
add->signal_clicked().connect ( sigc::mem_fun (*this, &ExifPanel::addPressed) );
|
||||
showAll->signal_toggled().connect ( sigc::mem_fun (*this, &ExifPanel::showAlltoggled) );
|
||||
|
||||
show_all ();
|
||||
}
|
||||
|
@ -168,21 +145,18 @@ ExifPanel::~ExifPanel ()
|
|||
|
||||
void ExifPanel::read (const ProcParams* pp, const ParamsEdited* pedited)
|
||||
{
|
||||
|
||||
disableListener ();
|
||||
|
||||
*changeList = pp->exif;
|
||||
setImageData (idata);
|
||||
applyChangeList ();
|
||||
exifSelectionChanged ();
|
||||
refreshTags();
|
||||
|
||||
enableListener ();
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::write (ProcParams* pp, ParamsEdited* pedited)
|
||||
{
|
||||
|
||||
// updateChangeList ();
|
||||
pp->exif = *changeList;
|
||||
}
|
||||
|
||||
|
@ -196,107 +170,97 @@ void ExifPanel::setImageData (const FramesMetaData* id)
|
|||
{
|
||||
|
||||
idata = id;
|
||||
exifTreeModel->clear ();
|
||||
|
||||
if (idata) {
|
||||
for (unsigned int rootNum = 0; rootNum < id->getRootCount (); ++rootNum) {
|
||||
if ( id->getRootExifData (rootNum)) {
|
||||
addDirectory (id->getRootExifData (rootNum), exifTreeModel->children(), rootNum > 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Gtk::TreeModel::Children ExifPanel::addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable)
|
||||
Gtk::TreeModel::Children ExifPanel::addTag(const std::string &key, const Glib::ustring &label, const Glib::ustring &value, bool editable, bool edited)
|
||||
{
|
||||
|
||||
if (!value.validate()) {
|
||||
value = "???";
|
||||
}
|
||||
|
||||
auto root = exifTreeModel->children();
|
||||
|
||||
Gtk::TreeModel::Row row = * (exifTreeModel->append (root));
|
||||
row[exifColumns.action] = action;
|
||||
row[exifColumns.editable] = editable;
|
||||
row[exifColumns.edited] = false;
|
||||
row[exifColumns.field_nopango] = field;
|
||||
row[exifColumns.edited] = edited;
|
||||
row[exifColumns.key] = key;
|
||||
row[exifColumns.label] = label;
|
||||
row[exifColumns.value_nopango] = value;
|
||||
row[exifColumns.orig_value] = value;
|
||||
row[exifColumns.value] = value;
|
||||
|
||||
if (action == AC_WRITE) {
|
||||
row[exifColumns.label] = escapeHtmlChars(label);
|
||||
row[exifColumns.value] = escapeHtmlChars(value);
|
||||
|
||||
if (edited) {
|
||||
row[exifColumns.icon] = editicon;
|
||||
} else if (editable) {
|
||||
row[exifColumns.icon] = keepicon;
|
||||
} else if (action == AC_DONTWRITE) {
|
||||
row[exifColumns.icon] = delicon;
|
||||
}
|
||||
|
||||
if (editable) {
|
||||
row[exifColumns.field] = Glib::ustring ("<b>") + escapeHtmlChars (field) + "</b>";
|
||||
row[exifColumns.value] = Glib::ustring ("<b>") + escapeHtmlChars (value) + "</b>";
|
||||
} else if (action == AC_SYSTEM) {
|
||||
row[exifColumns.field] = Glib::ustring ("<i>") + escapeHtmlChars (field) + "</i>";
|
||||
row[exifColumns.value] = Glib::ustring ("<i>") + escapeHtmlChars (value) + "</i>";
|
||||
} else {
|
||||
row[exifColumns.field] = escapeHtmlChars (field);
|
||||
row[exifColumns.value] = escapeHtmlChars (value);
|
||||
}
|
||||
|
||||
return row.children();
|
||||
}
|
||||
|
||||
Gtk::TreeModel::Children ExifPanel::addSeparator ()
|
||||
void ExifPanel::refreshTags()
|
||||
{
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> sel = selection->get_selected_rows();
|
||||
|
||||
Gtk::TreeModel::Row row = * (exifTreeModel->append (exifTreeModel->children()));
|
||||
row[exifColumns.action] = rtexif::ActionCode::AC_INVALID;
|
||||
row[exifColumns.editable] = false;
|
||||
row[exifColumns.edited] = false;
|
||||
row[exifColumns.field_nopango] = "";
|
||||
row[exifColumns.value_nopango] = "";
|
||||
row[exifColumns.orig_value] = "";
|
||||
row[exifColumns.isSeparator] = true;
|
||||
exifTreeModel->clear();
|
||||
|
||||
return row.children();
|
||||
}
|
||||
if (!idata) {
|
||||
return;
|
||||
}
|
||||
|
||||
void ExifPanel::addDirectory (const TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator)
|
||||
{
|
||||
const Glib::ustring fn = idata->getFileName();
|
||||
if (fn.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dir->getCount(); ++i) {
|
||||
Tag* t = (const_cast<TagDirectory*> (dir))->getTagByIndex (i);
|
||||
std::unordered_set<std::string> ed;
|
||||
for (const auto &p : editableTags) {
|
||||
ed.insert(p.first);
|
||||
}
|
||||
|
||||
bool hasContent = false;
|
||||
try {
|
||||
auto img = open_exiv2(fn);
|
||||
img->readMetadata();
|
||||
auto& exif = img->exifData();
|
||||
|
||||
if (checkForSeparator && i == 0) {
|
||||
for (int j = 0; j < dir->getCount(); ++j) {
|
||||
Tag* t2 = (const_cast<TagDirectory*> (dir))->getTagByIndex (j);
|
||||
const TagAttrib* currAttrib = t2->getAttrib();
|
||||
|
||||
if (currAttrib && (options.lastShowAllExif || currAttrib->action != AC_SYSTEM)) {
|
||||
addSeparator();
|
||||
hasContent = true;
|
||||
break;
|
||||
}
|
||||
for (const auto& p : *changeList) {
|
||||
try {
|
||||
exif[p.first] = p.second;
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
}
|
||||
} else {
|
||||
hasContent = true;
|
||||
}
|
||||
|
||||
if (!hasContent) {
|
||||
return;
|
||||
}
|
||||
|
||||
const TagAttrib* currAttrib = t->getAttrib();
|
||||
|
||||
if (!options.lastShowAllExif && currAttrib && currAttrib->action == AC_SYSTEM) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t->isDirectory()) {
|
||||
for (int j = 0; t->getDirectory (j); j++) {
|
||||
Gtk::TreeModel::Children ch = addTag (root, t->nameToString (j), M ("EXIFPANEL_SUBDIRECTORY"), currAttrib ? currAttrib->action : AC_DONTWRITE, currAttrib && currAttrib->editable);
|
||||
addDirectory (t->getDirectory (j), ch);
|
||||
for (const auto& p : editableTags) {
|
||||
const auto pos = exif.findKey(Exiv2::ExifKey(p.first));
|
||||
if (pos != exif.end() && pos->size()) {
|
||||
const bool edited = changeList->find(pos->key()) != changeList->end();
|
||||
addTag(pos->key(), pos->tagLabel(), pos->print(&exif), true, edited);
|
||||
}
|
||||
} else {
|
||||
addTag (root, t->nameToString (), t->valueToString (), currAttrib ? (t->getOwnMemory() ? currAttrib->action : AC_SYSTEM) : AC_DONTWRITE, currAttrib && currAttrib->editable);
|
||||
}
|
||||
for (const auto& tag : exif) {
|
||||
const bool editable = ed.find(tag.key()) != ed.end();
|
||||
if (
|
||||
!editable
|
||||
&& !tag.tagLabel().empty()
|
||||
&& tag.typeId() != Exiv2::undefined
|
||||
&& (
|
||||
tag.typeId() == Exiv2::asciiString
|
||||
|| tag.size() < 256
|
||||
)
|
||||
) {
|
||||
addTag(tag.key(), tag.tagLabel(), tag.print(&exif), false, false);
|
||||
}
|
||||
}
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& p : sel) {
|
||||
exifTree->get_selection()->select(p);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,167 +271,46 @@ void ExifPanel::exifSelectionChanged ()
|
|||
std::vector<Gtk::TreeModel::Path> sel = selection->get_selected_rows();
|
||||
|
||||
if (sel.size() > 1) {
|
||||
remove->set_sensitive (1);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
} else if (sel.size() == 1) {
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (sel[0]);
|
||||
|
||||
if (iter->get_value (exifColumns.action) == AC_SYSTEM) {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (0);
|
||||
reset->set_sensitive (0);
|
||||
} else if (!iter->children().empty()) {
|
||||
remove->set_sensitive (1);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
} else if (iter->get_value (exifColumns.icon) == delicon) {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (1);
|
||||
reset->set_sensitive (1);
|
||||
} else if (iter->get_value (exifColumns.icon) == keepicon || iter->get_value (exifColumns.icon) == editicon) {
|
||||
keep->set_sensitive (0);
|
||||
remove->set_sensitive (1);
|
||||
if (iter->get_value(exifColumns.icon) == editicon) {
|
||||
reset->set_sensitive (1);
|
||||
}
|
||||
} else {
|
||||
remove->set_sensitive (0);
|
||||
keep->set_sensitive (0);
|
||||
reset->set_sensitive (0);
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::delIt (Gtk::TreeModel::iterator iter)
|
||||
void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter)
|
||||
{
|
||||
|
||||
if (!iter) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.action) != AC_SYSTEM) {
|
||||
iter->set_value (exifColumns.icon, delicon);
|
||||
}
|
||||
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i = iter->children().begin(); i != iter->children().end(); ++i) {
|
||||
delIt (i);
|
||||
}
|
||||
const auto key = iter->get_value(exifColumns.key);
|
||||
changeList->erase(key);
|
||||
}
|
||||
|
||||
void ExifPanel::removePressed ()
|
||||
{
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
|
||||
for (size_t i = 0; i < sel.size(); i++) {
|
||||
delIt (exifTreeModel->get_iter (sel[i]));
|
||||
}
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
void ExifPanel::keepIt (Gtk::TreeModel::iterator iter)
|
||||
{
|
||||
|
||||
if (!iter) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.action) != AC_SYSTEM) {
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon);
|
||||
}
|
||||
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i = iter->children().begin(); i != iter->children().end(); ++i) {
|
||||
keepIt (i);
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::keepPressed ()
|
||||
{
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
|
||||
for (size_t i = 0; i < sel.size(); i++) {
|
||||
keepIt (exifTreeModel->get_iter (sel[i]));
|
||||
}
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
/*void ExifPanel::resetIt (Gtk::TreeModel::iterator iter) {
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
if (iter->get_value (exifColumns.action)!=AC_SYSTEM)
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.action) ? keepicon : delicon);
|
||||
if (iter->get_value (exifColumns.edited)) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring("<b>") + iter->get_value(exifColumns.orig_value) + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, iter->get_value(exifColumns.orig_value));
|
||||
iter->set_value (exifColumns.edited, false);
|
||||
}
|
||||
if (iter->get_value (exifColumns.action)==AC_INVALID)
|
||||
exifTreeModel->erase (iter);
|
||||
else
|
||||
if (recursiveOp)
|
||||
for (Gtk::TreeModel::iterator i=iter->children().begin(); i!=iter->children().end(); i++)
|
||||
resetIt (i);
|
||||
}*/
|
||||
Gtk::TreeModel::iterator ExifPanel::resetIt (Gtk::TreeModel::iterator iter)
|
||||
{
|
||||
|
||||
if (!iter) {
|
||||
return iter;
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.action) != AC_SYSTEM) {
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.action) ? keepicon : delicon);
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.edited)) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring ("<b>") + iter->get_value (exifColumns.orig_value) + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, iter->get_value (exifColumns.orig_value));
|
||||
iter->set_value (exifColumns.edited, false);
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.action) == AC_INVALID) {
|
||||
return exifTreeModel->erase (iter);
|
||||
} else if (recursiveOp) {
|
||||
Gtk::TreeModel::iterator i = iter->children().begin();
|
||||
|
||||
while (i && i != iter->children().end()) {
|
||||
i = resetIt (i);
|
||||
}
|
||||
}
|
||||
|
||||
return ++iter;
|
||||
}
|
||||
void ExifPanel::resetPressed ()
|
||||
{
|
||||
|
||||
std::vector<Gtk::TreeModel::Path> sel = exifTree->get_selection()->get_selected_rows();
|
||||
|
||||
for (size_t i = 0; i < sel.size(); i++) {
|
||||
resetIt (exifTreeModel->get_iter (sel[i]));
|
||||
resetIt(exifTreeModel->get_iter(sel[i]));
|
||||
}
|
||||
|
||||
exifSelectionChanged ();
|
||||
updateChangeList ();
|
||||
notifyListener ();
|
||||
refreshTags();
|
||||
notifyListener();
|
||||
}
|
||||
|
||||
void ExifPanel::resetAllPressed ()
|
||||
{
|
||||
|
||||
setImageData (idata);
|
||||
setImageData(idata);
|
||||
*changeList = *defChangeList;
|
||||
applyChangeList ();
|
||||
exifSelectionChanged ();
|
||||
refreshTags();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
|
@ -484,10 +327,9 @@ void ExifPanel::addPressed ()
|
|||
Gtk::Label* tlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":");
|
||||
MyComboBoxText* tcombo = new MyComboBoxText ();
|
||||
|
||||
tcombo->append ("Artist");
|
||||
tcombo->append ("Copyright");
|
||||
tcombo->append ("ImageDescription");
|
||||
tcombo->append ("Exif.UserComment");
|
||||
for (const auto& p : editableTags) {
|
||||
tcombo->append(p.second);
|
||||
}
|
||||
|
||||
hb1->pack_start (*tlabel, Gtk::PACK_SHRINK, 4);
|
||||
hb1->pack_start (*tcombo);
|
||||
|
@ -497,21 +339,33 @@ void ExifPanel::addPressed ()
|
|||
hb2->pack_start (*vlabel, Gtk::PACK_SHRINK, 4);
|
||||
hb2->pack_start (*ventry);
|
||||
|
||||
Glib::ustring sel = getSelection (true);
|
||||
Glib::ustring sel;
|
||||
Glib::ustring val;
|
||||
{
|
||||
const Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
const std::vector<Gtk::TreeModel::Path> rows = selection->get_selected_rows();
|
||||
|
||||
if (sel.empty()) {
|
||||
tcombo->set_active_text ("Exif.UserComment");
|
||||
} else {
|
||||
tcombo->set_active_text (sel);
|
||||
|
||||
if (!tcombo->get_active ()) {
|
||||
tcombo->append (sel);
|
||||
tcombo->set_active_text (sel);
|
||||
if (rows.size() == 1) {
|
||||
const Gtk::TreeModel::iterator iter = exifTreeModel->get_iter(rows[0]);
|
||||
if (iter->get_value(exifColumns.editable)) {
|
||||
sel = iter->get_value(exifColumns.key);
|
||||
val = iter->get_value(exifColumns.value_nopango);
|
||||
}
|
||||
}
|
||||
|
||||
ventry->set_text (getSelectedValue ());
|
||||
}
|
||||
|
||||
if (sel.empty()) {
|
||||
tcombo->set_active(0);
|
||||
} else {
|
||||
for (size_t i = 0; i < editableTags.size(); ++i) {
|
||||
if (editableTags[i].first == sel) {
|
||||
tcombo->set_active(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ventry->set_text(val);
|
||||
ventry->set_activates_default (true);
|
||||
dialog->set_default_response (Gtk::RESPONSE_OK);
|
||||
dialog->get_content_area()->pack_start (*hb1, Gtk::PACK_SHRINK);
|
||||
|
@ -524,8 +378,10 @@ void ExifPanel::addPressed ()
|
|||
hb2->show ();
|
||||
|
||||
if (dialog->run () == Gtk::RESPONSE_OK) {
|
||||
editTag (exifTreeModel->children(), tcombo->get_active_text(), ventry->get_text());
|
||||
updateChangeList ();
|
||||
auto key = editableTags[tcombo->get_active_row_number()].first;
|
||||
const auto value = ventry->get_text();
|
||||
(*changeList)[key] = value;
|
||||
refreshTags();
|
||||
notifyListener ();
|
||||
}
|
||||
|
||||
|
@ -538,186 +394,8 @@ void ExifPanel::addPressed ()
|
|||
delete hb2;
|
||||
}
|
||||
|
||||
void ExifPanel::showAlltoggled ()
|
||||
{
|
||||
options.lastShowAllExif = showAll->get_active();
|
||||
setImageData (idata);
|
||||
}
|
||||
|
||||
bool ExifPanel::rowSeperatorFunc(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter)
|
||||
{
|
||||
return iter->get_value(exifColumns.isSeparator);
|
||||
}
|
||||
|
||||
void ExifPanel::editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value)
|
||||
{
|
||||
|
||||
Glib::ustring::size_type dp = name.find_first_of ('.');
|
||||
Glib::ustring fseg = name.substr (0, dp);
|
||||
// look up first segment of the path
|
||||
Gtk::TreeModel::iterator iter;
|
||||
|
||||
for (iter = root.begin(); iter != root.end(); ++iter)
|
||||
if (iter->get_value (exifColumns.field_nopango) == fseg) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (iter == root.end() && value != "#keep" && value != "#delete") {
|
||||
iter = exifTreeModel->append (root);
|
||||
iter->set_value (exifColumns.field_nopango, fseg);
|
||||
iter->set_value (exifColumns.action, AC_INVALID);
|
||||
|
||||
if (dp == Glib::ustring::npos) {
|
||||
iter->set_value (exifColumns.value, Glib::ustring ("<b>") + value + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, value);
|
||||
iter->set_value (exifColumns.orig_value, value);
|
||||
iter->set_value (exifColumns.field, Glib::ustring ("<b>") + fseg + "</b>");
|
||||
iter->set_value (exifColumns.edited, true);
|
||||
iter->set_value (exifColumns.editable, true);
|
||||
iter->set_value (exifColumns.icon, editicon);
|
||||
} else {
|
||||
iter->set_value (exifColumns.value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY")));
|
||||
iter->set_value (exifColumns.value_nopango, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY")));
|
||||
iter->set_value (exifColumns.field, fseg);
|
||||
iter->set_value (exifColumns.icon, keepicon);
|
||||
iter->set_value (exifColumns.orig_value, Glib::ustring (M ("EXIFPANEL_SUBDIRECTORY")));
|
||||
}
|
||||
}
|
||||
|
||||
if (iter == root.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (dp == Glib::ustring::npos) {
|
||||
if (value == "#keep" && iter->get_value (exifColumns.action) != AC_SYSTEM) {
|
||||
iter->set_value (exifColumns.icon, iter->get_value (exifColumns.edited) ? editicon : keepicon);
|
||||
} else if (value == "#delete" && iter->get_value (exifColumns.action) != AC_SYSTEM) {
|
||||
iter->set_value (exifColumns.icon, delicon);
|
||||
} else {
|
||||
iter->set_value (exifColumns.value, Glib::ustring ("<b>") + value + "</b>");
|
||||
iter->set_value (exifColumns.value_nopango, value);
|
||||
iter->set_value (exifColumns.edited, true);
|
||||
iter->set_value (exifColumns.icon, editicon);
|
||||
}
|
||||
} else {
|
||||
editTag (iter->children(), name.substr (dp + 1, Glib::ustring::npos), value);
|
||||
}
|
||||
}
|
||||
|
||||
Glib::ustring ExifPanel::getSelectedValue ()
|
||||
{
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> rows = selection->get_selected_rows();
|
||||
|
||||
if (rows.size() != 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]);
|
||||
|
||||
if (iter) {
|
||||
return iter->get_value (exifColumns.value_nopango);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
Glib::ustring ExifPanel::getSelection (bool onlyeditable)
|
||||
{
|
||||
|
||||
Glib::RefPtr<Gtk::TreeSelection> selection = exifTree->get_selection();
|
||||
std::vector<Gtk::TreeModel::Path> rows = selection->get_selected_rows();
|
||||
|
||||
if (rows.size() != 1) {
|
||||
return "";
|
||||
}
|
||||
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (rows[0]);
|
||||
|
||||
Glib::ustring ret;
|
||||
bool first = true;
|
||||
bool editable = false;
|
||||
|
||||
while (iter) {
|
||||
if (first) {
|
||||
ret = iter->get_value (exifColumns.field_nopango);
|
||||
editable = iter->get_value (exifColumns.editable);
|
||||
} else {
|
||||
ret = iter->get_value (exifColumns.field_nopango) + "." + ret;
|
||||
}
|
||||
|
||||
iter = iter->parent ();
|
||||
first = false;
|
||||
}
|
||||
|
||||
if (!editable && onlyeditable) {
|
||||
return "";
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ExifPanel::updateChangeList (Gtk::TreeModel::Children root, std::string prefix)
|
||||
{
|
||||
|
||||
if (!prefix.empty()) {
|
||||
prefix = prefix + ".";
|
||||
}
|
||||
|
||||
Gtk::TreeModel::iterator iter;
|
||||
|
||||
for (iter = root.begin(); iter != root.end(); ++iter) {
|
||||
if (iter->get_value (exifColumns.edited)) {
|
||||
(*changeList)[ prefix + iter->get_value (exifColumns.field_nopango) ] = iter->get_value (exifColumns.value_nopango);
|
||||
} else if (iter->get_value (exifColumns.action) == AC_WRITE && iter->get_value (exifColumns.icon) == delicon) {
|
||||
(*changeList)[ prefix + iter->get_value (exifColumns.field_nopango) ] = "#delete";
|
||||
} else if (iter->get_value (exifColumns.action) == AC_DONTWRITE && iter->get_value (exifColumns.icon) == keepicon) {
|
||||
(*changeList)[ prefix + iter->get_value (exifColumns.field_nopango) ] = "#keep";
|
||||
}
|
||||
|
||||
if (iter->get_value (exifColumns.icon) == keepicon) {
|
||||
updateChangeList (iter->children(), prefix + iter->get_value (exifColumns.field_nopango));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::updateChangeList ()
|
||||
{
|
||||
|
||||
changeList->clear ();
|
||||
updateChangeList (exifTreeModel->children(), "");
|
||||
}
|
||||
|
||||
void ExifPanel::applyChangeList ()
|
||||
{
|
||||
|
||||
for (rtengine::procparams::ExifPairs::const_iterator i = changeList->begin(); i != changeList->end(); ++i) {
|
||||
editTag (exifTreeModel->children(), i->first, i->second);
|
||||
}
|
||||
}
|
||||
|
||||
void ExifPanel::row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column)
|
||||
{
|
||||
|
||||
Gtk::TreeModel::iterator iter = exifTreeModel->get_iter (path);
|
||||
|
||||
if (iter) {
|
||||
if (!iter->children().empty())
|
||||
if (exifTree->row_expanded (path)) {
|
||||
exifTree->collapse_row (path);
|
||||
} else {
|
||||
exifTree->expand_row (path, false);
|
||||
} else if (iter->get_value (exifColumns.editable)) {
|
||||
addPressed ();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ExifPanel::notifyListener ()
|
||||
{
|
||||
|
||||
if (listener) {
|
||||
listener->panelChanged (EvExif, M ("HISTORY_CHANGED"));
|
||||
}
|
||||
|
|
|
@ -25,6 +25,18 @@
|
|||
#include "toolpanel.h"
|
||||
#include "../rtexif/rtexif.h"
|
||||
|
||||
namespace rtengine
|
||||
{
|
||||
|
||||
namespace procparams
|
||||
{
|
||||
|
||||
class ExifPairs;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ExifPanel final :
|
||||
public Gtk::VBox,
|
||||
public ToolPanel
|
||||
|
@ -34,37 +46,29 @@ private:
|
|||
const rtengine::FramesMetaData* idata;
|
||||
const std::unique_ptr<rtengine::procparams::ExifPairs> changeList;
|
||||
const std::unique_ptr<rtengine::procparams::ExifPairs> defChangeList;
|
||||
bool recursiveOp;
|
||||
|
||||
class ExifColumns : public Gtk::TreeModelColumnRecord
|
||||
{
|
||||
public:
|
||||
Gtk::TreeModelColumn<Glib::RefPtr<Gdk::Pixbuf> > icon;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field;
|
||||
Gtk::TreeModelColumn<Glib::ustring> field_nopango;
|
||||
Gtk::TreeModelColumn<Glib::ustring> key;
|
||||
Gtk::TreeModelColumn<Glib::ustring> label;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value;
|
||||
Gtk::TreeModelColumn<Glib::ustring> value_nopango;
|
||||
Gtk::TreeModelColumn<Glib::ustring> orig_value;
|
||||
Gtk::TreeModelColumn<rtexif::ActionCode> action;
|
||||
Gtk::TreeModelColumn<bool> editable;
|
||||
Gtk::TreeModelColumn<bool> edited;
|
||||
Gtk::TreeModelColumn<bool> isSeparator;
|
||||
|
||||
ExifColumns()
|
||||
{
|
||||
add (field);
|
||||
add (value);
|
||||
add (icon);
|
||||
add (action);
|
||||
add (edited);
|
||||
add (field_nopango);
|
||||
add (value_nopango);
|
||||
add (editable);
|
||||
add (orig_value);
|
||||
add (isSeparator);
|
||||
add(key);
|
||||
add(label);
|
||||
add(value);
|
||||
add(icon);
|
||||
add(edited);
|
||||
add(value_nopango);
|
||||
add(editable);
|
||||
}
|
||||
};
|
||||
Glib::RefPtr<Gdk::Pixbuf> delicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> keepicon;
|
||||
Glib::RefPtr<Gdk::Pixbuf> editicon;
|
||||
|
||||
|
@ -73,32 +77,18 @@ private:
|
|||
Gtk::ScrolledWindow* scrolledWindow;
|
||||
Glib::RefPtr<Gtk::TreeStore> exifTreeModel;
|
||||
|
||||
Gtk::Button* remove;
|
||||
Gtk::Button* keep;
|
||||
Gtk::Button* add;
|
||||
Gtk::Button* reset;
|
||||
Gtk::Button* resetAll;
|
||||
Gtk::ToggleButton* showAll;
|
||||
|
||||
Gtk::TreeModel::Children addTag (const Gtk::TreeModel::Children& root, Glib::ustring field, Glib::ustring value, rtexif::ActionCode action, bool editable);
|
||||
void editTag (Gtk::TreeModel::Children root, Glib::ustring name, Glib::ustring value);
|
||||
void updateChangeList (Gtk::TreeModel::Children root, std::string prefix);
|
||||
void addDirectory (const rtexif::TagDirectory* dir, Gtk::TreeModel::Children root, bool checkForSeparator = false);
|
||||
Gtk::TreeModel::Children addSeparator();
|
||||
Glib::ustring getSelection (bool onlyifeditable = false);
|
||||
Glib::ustring getSelectedValue();
|
||||
void updateChangeList();
|
||||
void applyChangeList();
|
||||
void keepIt (Gtk::TreeModel::iterator iter);
|
||||
void delIt (Gtk::TreeModel::iterator iter);
|
||||
Gtk::TreeModel::iterator resetIt (Gtk::TreeModel::iterator iter);
|
||||
void removePressed();
|
||||
void keepPressed();
|
||||
const std::vector<std::pair<std::string, Glib::ustring>> editableTags;
|
||||
|
||||
Gtk::TreeModel::Children addTag(const std::string &key, const Glib::ustring &label, const Glib::ustring &value, bool editable, bool edited);
|
||||
void refreshTags();
|
||||
void resetIt(const Gtk::TreeModel::const_iterator& iter);
|
||||
void resetPressed();
|
||||
void resetAllPressed();
|
||||
void addPressed();
|
||||
void showAlltoggled();
|
||||
bool rowSeperatorFunc(const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::iterator& iter);
|
||||
|
||||
public:
|
||||
ExifPanel ();
|
||||
|
@ -111,7 +101,7 @@ public:
|
|||
void setImageData (const rtengine::FramesMetaData* id);
|
||||
|
||||
void exifSelectionChanged();
|
||||
void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
// void row_activated (const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column);
|
||||
|
||||
void notifyListener();
|
||||
|
||||
|
|
|
@ -16,16 +16,64 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <set>
|
||||
|
||||
#include "iptcpanel.h"
|
||||
|
||||
#include "clipboard.h"
|
||||
#include "rtimage.h"
|
||||
|
||||
#include "../rtengine/imagedata.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
|
||||
using namespace rtengine;
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
IPTCPanel::IPTCPanel () :
|
||||
namespace {
|
||||
|
||||
const std::string CAPTION("Iptc.Application2.Caption");
|
||||
const std::string CAPTION_WRITER("Iptc.Application2.Writer");
|
||||
const std::string CATEGORY("Iptc.Application2.Category");
|
||||
const std::string CITY("Iptc.Application2.City");
|
||||
const std::string COPYRIGHT("Iptc.Application2.Copyright");
|
||||
const std::string COUNTRY("Iptc.Application2.CountryName");
|
||||
const std::string CREATOR("Iptc.Application2.Byline");
|
||||
const std::string CREATOR_JOB_TITLE("Iptc.Application2.BylineTitle");
|
||||
const std::string CREDIT("Iptc.Application2.Credit");
|
||||
const std::string DATE_CREATED("Iptc.Application2.DateCreated");
|
||||
const std::string HEADLINE("Iptc.Application2.Headline");
|
||||
const std::string INSTRUCTIONS("Iptc.Application2.SpecialInstructions");
|
||||
const std::string KEYWORDS("Iptc.Application2.Keywords");
|
||||
const std::string PROVINCE("Iptc.Application2.ProvinceState");
|
||||
const std::string SOURCE("Iptc.Application2.Source");
|
||||
const std::string SUPPLEMENTAL_CATEGORIES("Iptc.Application2.SuppCategory");
|
||||
const std::string TITLE("Iptc.Application2.ObjectName");
|
||||
const std::string TRANS_REFERENCE("Iptc.Application2.TransmissionReference");
|
||||
|
||||
const std::set<std::string> iptc_keys = {
|
||||
CAPTION,
|
||||
CAPTION_WRITER,
|
||||
CATEGORY,
|
||||
CITY,
|
||||
COPYRIGHT,
|
||||
COUNTRY,
|
||||
CREATOR,
|
||||
CREATOR_JOB_TITLE,
|
||||
CREDIT,
|
||||
DATE_CREATED,
|
||||
HEADLINE,
|
||||
INSTRUCTIONS,
|
||||
KEYWORDS,
|
||||
PROVINCE,
|
||||
SOURCE,
|
||||
SUPPLEMENTAL_CATEGORIES,
|
||||
TITLE,
|
||||
TRANS_REFERENCE
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
IPTCPanel::IPTCPanel():
|
||||
changeList(new rtengine::procparams::IPTCPairs),
|
||||
defChangeList(new rtengine::procparams::IPTCPairs),
|
||||
embeddedData(new rtengine::procparams::IPTCPairs)
|
||||
|
@ -441,11 +489,20 @@ void IPTCPanel::setDefaults (const ProcParams* defParams, const ParamsEdited* pe
|
|||
|
||||
void IPTCPanel::setImageData (const FramesMetaData* id)
|
||||
{
|
||||
|
||||
embeddedData->clear();
|
||||
if (id) {
|
||||
*embeddedData = id->getIPTCData ();
|
||||
} else {
|
||||
embeddedData->clear ();
|
||||
try {
|
||||
auto img = open_exiv2(id->getFileName());
|
||||
img->readMetadata();
|
||||
auto& iptc = img->iptcData();
|
||||
for (const auto& tag : iptc) {
|
||||
if (iptc_keys.find(tag.key()) != iptc_keys.end()) {
|
||||
(*embeddedData)[tag.key()].push_back(tag.toString());
|
||||
}
|
||||
}
|
||||
} catch (const Exiv2::AnyError& exc) {
|
||||
embeddedData->clear();
|
||||
}
|
||||
}
|
||||
|
||||
file->set_sensitive (!embeddedData->empty());
|
||||
|
@ -570,32 +627,32 @@ void IPTCPanel::updateChangeList ()
|
|||
{
|
||||
|
||||
changeList->clear ();
|
||||
(*changeList)["Caption" ].push_back (captionText->get_text ());
|
||||
(*changeList)["CaptionWriter" ].push_back (captionWriter->get_text ());
|
||||
(*changeList)["Headline" ].push_back (headline->get_text ());
|
||||
(*changeList)["Instructions" ].push_back (instructions->get_text ());
|
||||
(*changeList)[CAPTION].push_back (captionText->get_text ());
|
||||
(*changeList)[CAPTION_WRITER].push_back (captionWriter->get_text ());
|
||||
(*changeList)[HEADLINE].push_back (headline->get_text ());
|
||||
(*changeList)[INSTRUCTIONS].push_back (instructions->get_text ());
|
||||
|
||||
for (unsigned int i = 0; i < keywords->size(); i++) {
|
||||
(*changeList)["Keywords" ].push_back (keywords->get_text (i));
|
||||
(*changeList)[KEYWORDS].push_back (keywords->get_text (i));
|
||||
}
|
||||
|
||||
(*changeList)["Category" ].push_back (category->get_entry()->get_text ());
|
||||
(*changeList)[CATEGORY].push_back (category->get_entry()->get_text ());
|
||||
|
||||
for (unsigned int i = 0; i < suppCategories->size(); i++) {
|
||||
(*changeList)["SupplementalCategories"].push_back (suppCategories->get_text (i));
|
||||
(*changeList)[SUPPLEMENTAL_CATEGORIES].push_back (suppCategories->get_text (i));
|
||||
}
|
||||
|
||||
(*changeList)["Creator" ].push_back (creator->get_text ());
|
||||
(*changeList)["CreatorJobTitle"].push_back (creatorJobTitle->get_text ());
|
||||
(*changeList)["Credit" ].push_back (credit->get_text ());
|
||||
(*changeList)["Source" ].push_back (source->get_text ());
|
||||
(*changeList)["Copyright" ].push_back (copyright->get_text ());
|
||||
(*changeList)["City" ].push_back (city->get_text ());
|
||||
(*changeList)["Province" ].push_back (province->get_text ());
|
||||
(*changeList)["Country" ].push_back (country->get_text ());
|
||||
(*changeList)["Title" ].push_back (title->get_text ());
|
||||
(*changeList)["DateCreated" ].push_back (dateCreated->get_text ());
|
||||
(*changeList)["TransReference" ].push_back (transReference->get_text ());
|
||||
(*changeList)[CREATOR].push_back (creator->get_text ());
|
||||
(*changeList)[CREATOR_JOB_TITLE].push_back (creatorJobTitle->get_text ());
|
||||
(*changeList)[CREDIT].push_back (credit->get_text ());
|
||||
(*changeList)[SOURCE].push_back (source->get_text ());
|
||||
(*changeList)[COPYRIGHT].push_back (copyright->get_text ());
|
||||
(*changeList)[CITY].push_back (city->get_text ());
|
||||
(*changeList)[PROVINCE].push_back (province->get_text ());
|
||||
(*changeList)[COUNTRY].push_back (country->get_text ());
|
||||
(*changeList)[TITLE].push_back (title->get_text ());
|
||||
(*changeList)[DATE_CREATED].push_back (dateCreated->get_text ());
|
||||
(*changeList)[TRANS_REFERENCE].push_back (transReference->get_text ());
|
||||
|
||||
notifyListener ();
|
||||
}
|
||||
|
@ -629,45 +686,45 @@ void IPTCPanel::applyChangeList ()
|
|||
suppCategory->get_entry()->set_text ("");
|
||||
|
||||
for (rtengine::procparams::IPTCPairs::const_iterator i = changeList->begin(); i != changeList->end(); ++i) {
|
||||
if (i->first == "Caption" && !i->second.empty()) {
|
||||
if (i->first == CAPTION && !i->second.empty()) {
|
||||
captionText->set_text (i->second.at(0));
|
||||
} else if (i->first == "CaptionWriter" && !i->second.empty()) {
|
||||
} else if (i->first == CAPTION_WRITER && !i->second.empty()) {
|
||||
captionWriter->set_text (i->second.at(0));
|
||||
} else if (i->first == "Headline" && !i->second.empty()) {
|
||||
} else if (i->first == HEADLINE && !i->second.empty()) {
|
||||
headline->set_text (i->second.at(0));
|
||||
} else if (i->first == "Instructions" && !i->second.empty()) {
|
||||
} else if (i->first == INSTRUCTIONS && !i->second.empty()) {
|
||||
instructions->set_text (i->second.at(0));
|
||||
} else if (i->first == "Keywords")
|
||||
} else if (i->first == KEYWORDS)
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
keywords->append (i->second.at(j));
|
||||
}
|
||||
else if (i->first == "Category" && !i->second.empty()) {
|
||||
else if (i->first == CATEGORY && !i->second.empty()) {
|
||||
category->get_entry()->set_text (i->second.at(0));
|
||||
} else if (i->first == "SupplementalCategories")
|
||||
} else if (i->first == SUPPLEMENTAL_CATEGORIES)
|
||||
for (unsigned int j = 0; j < i->second.size(); j++) {
|
||||
suppCategories->append (i->second.at(j));
|
||||
}
|
||||
else if (i->first == "Creator" && !i->second.empty()) {
|
||||
else if (i->first == CREATOR && !i->second.empty()) {
|
||||
creator->set_text (i->second.at(0));
|
||||
} else if (i->first == "CreatorJobTitle" && !i->second.empty()) {
|
||||
} else if (i->first == CREATOR_JOB_TITLE && !i->second.empty()) {
|
||||
creatorJobTitle->set_text (i->second.at(0));
|
||||
} else if (i->first == "Credit" && !i->second.empty()) {
|
||||
} else if (i->first == CREDIT && !i->second.empty()) {
|
||||
credit->set_text (i->second.at(0));
|
||||
} else if (i->first == "Source" && !i->second.empty()) {
|
||||
} else if (i->first == SOURCE && !i->second.empty()) {
|
||||
source->set_text (i->second.at(0));
|
||||
} else if (i->first == "Copyright" && !i->second.empty()) {
|
||||
} else if (i->first == COPYRIGHT && !i->second.empty()) {
|
||||
copyright->set_text (i->second.at(0));
|
||||
} else if (i->first == "City" && !i->second.empty()) {
|
||||
} else if (i->first == CITY && !i->second.empty()) {
|
||||
city->set_text (i->second.at(0));
|
||||
} else if (i->first == "Province" && !i->second.empty()) {
|
||||
} else if (i->first == PROVINCE && !i->second.empty()) {
|
||||
province->set_text (i->second.at(0));
|
||||
} else if (i->first == "Country" && !i->second.empty()) {
|
||||
} else if (i->first == COUNTRY && !i->second.empty()) {
|
||||
country->set_text (i->second.at(0));
|
||||
} else if (i->first == "Title" && !i->second.empty()) {
|
||||
} else if (i->first == TITLE && !i->second.empty()) {
|
||||
title->set_text (i->second.at(0));
|
||||
} else if (i->first == "DateCreated" && !i->second.empty()) {
|
||||
} else if (i->first == DATE_CREATED && !i->second.empty()) {
|
||||
dateCreated->set_text (i->second.at(0));
|
||||
} else if (i->first == "TransReference" && !i->second.empty()) {
|
||||
} else if (i->first == TRANS_REFERENCE && !i->second.empty()) {
|
||||
transReference->set_text (i->second.at(0));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <iomanip>
|
||||
|
||||
#include "shcselector.h"
|
||||
|
||||
#include "multilangmgr.h"
|
||||
#include "mycurve.h"
|
||||
#include "rtscalable.h"
|
||||
|
|
|
@ -35,14 +35,80 @@
|
|||
#include "../rtengine/dynamicprofile.h"
|
||||
#include "../rtengine/profilestore.h"
|
||||
#include "../rtengine/settings.h"
|
||||
#include "../rtexif/rtexif.h"
|
||||
#include "guiutils.h"
|
||||
#include "batchqueue.h"
|
||||
#include "extprog.h"
|
||||
#include "md5helper.h"
|
||||
#include "pathutils.h"
|
||||
#include "paramsedited.h"
|
||||
|
||||
#include "procparamchangers.h"
|
||||
#include "profilestorecombobox.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "../rtengine/dynamicprofile.h"
|
||||
#include "../rtengine/imagedata.h"
|
||||
#include "../rtengine/mytime.h"
|
||||
#include "../rtengine/procparams.h"
|
||||
|
||||
namespace {
|
||||
|
||||
bool CPBDump(
|
||||
const Glib::ustring& commFName,
|
||||
const Glib::ustring& imageFName,
|
||||
const Glib::ustring& profileFName,
|
||||
const Glib::ustring& defaultPParams,
|
||||
const CacheImageData* cfs,
|
||||
bool flagMode
|
||||
)
|
||||
{
|
||||
const std::unique_ptr<Glib::KeyFile> kf(new Glib::KeyFile);
|
||||
|
||||
if (!kf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// open the file in write mode
|
||||
const std::unique_ptr<FILE, decltype(&std::fclose)> f(g_fopen(commFName.c_str (), "wt"), &std::fclose);
|
||||
|
||||
if (!f) {
|
||||
printf ("CPBDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
kf->set_string ("RT General", "CachePath", options.cacheBaseDir);
|
||||
kf->set_string ("RT General", "AppVersion", RTVERSION);
|
||||
kf->set_integer ("RT General", "ProcParamsVersion", PPVERSION);
|
||||
kf->set_string ("RT General", "ImageFileName", imageFName);
|
||||
kf->set_string ("RT General", "OutputProfileFileName", profileFName);
|
||||
kf->set_string ("RT General", "DefaultProcParams", defaultPParams);
|
||||
kf->set_boolean ("RT General", "FlaggingMode", flagMode);
|
||||
|
||||
kf->set_integer ("Common Data", "FrameCount", cfs->frameCount);
|
||||
kf->set_integer ("Common Data", "SampleFormat", cfs->sampleFormat);
|
||||
kf->set_boolean ("Common Data", "IsHDR", cfs->isHDR);
|
||||
kf->set_boolean ("Common Data", "IsPixelShift", cfs->isPixelShift);
|
||||
kf->set_double ("Common Data", "FNumber", cfs->fnumber);
|
||||
kf->set_double ("Common Data", "Shutter", cfs->shutter);
|
||||
kf->set_double ("Common Data", "FocalLength", cfs->focalLen);
|
||||
kf->set_integer ("Common Data", "ISO", cfs->iso);
|
||||
kf->set_string ("Common Data", "Lens", cfs->lens);
|
||||
kf->set_string ("Common Data", "Make", cfs->camMake);
|
||||
kf->set_string ("Common Data", "Model", cfs->camModel);
|
||||
|
||||
} catch (const Glib::KeyFileError&) {
|
||||
}
|
||||
|
||||
try {
|
||||
fprintf (f.get(), "%s", kf->to_data().c_str());
|
||||
} catch (const Glib::KeyFileError&) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
using namespace rtengine::procparams;
|
||||
|
||||
|
@ -162,24 +228,23 @@ void Thumbnail::_generateThumbnailImage ()
|
|||
// image out of the RAW. Mark as "quick".
|
||||
// 2. if we don't find that then just grab the real image.
|
||||
bool quick = false;
|
||||
rtengine::RawMetaDataLocation ri;
|
||||
|
||||
rtengine::eSensorType sensorType = rtengine::ST_NONE;
|
||||
if ( initial_ && options.internalThumbIfUntouched) {
|
||||
quick = true;
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, ri, sensorType, tw, th, 1, TRUE);
|
||||
tpp = rtengine::Thumbnail::loadQuickFromRaw (fname, sensorType, tw, th, 1, TRUE);
|
||||
}
|
||||
|
||||
if ( tpp == nullptr ) {
|
||||
quick = false;
|
||||
tpp = rtengine::Thumbnail::loadFromRaw (fname, ri, sensorType, tw, th, 1, pparams->wb.equal, TRUE);
|
||||
tpp = rtengine::Thumbnail::loadFromRaw (fname, sensorType, tw, th, 1, pparams->wb.equal, TRUE);
|
||||
}
|
||||
|
||||
cfs.sensortype = sensorType;
|
||||
if (tpp) {
|
||||
cfs.format = FT_Raw;
|
||||
cfs.thumbImgType = quick ? CacheImageData::QUICK_THUMBNAIL : CacheImageData::FULL_THUMBNAIL;
|
||||
infoFromImage (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(ri)));
|
||||
infoFromImage (fname);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +305,6 @@ const ProcParams& Thumbnail::getProcParamsU ()
|
|||
*/
|
||||
rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool returnParams, bool force, bool flaggingMode)
|
||||
{
|
||||
|
||||
// try to load the last saved parameters from the cache or from the paramfile file
|
||||
ProcParams* ldprof = nullptr;
|
||||
|
||||
|
@ -258,52 +322,35 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
|
|||
|
||||
if (!run_cpb) {
|
||||
if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) {
|
||||
rtengine::FramesMetaData* imageMetaData;
|
||||
if (getType() == FT_Raw) {
|
||||
// Should we ask all frame's MetaData ?
|
||||
imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true);
|
||||
} else {
|
||||
// Should we ask all frame's MetaData ?
|
||||
imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true);
|
||||
}
|
||||
PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData);
|
||||
delete imageMetaData;
|
||||
int err = pp->pparams->save(outFName);
|
||||
pp->deleteInstance();
|
||||
delete pp;
|
||||
if (!err) {
|
||||
const auto pp_deleter =
|
||||
[](PartialProfile* pp)
|
||||
{
|
||||
pp->deleteInstance();
|
||||
delete pp;
|
||||
};
|
||||
const std::unique_ptr<const rtengine::FramesMetaData> imageMetaData(rtengine::FramesMetaData::fromFile(fname));
|
||||
const std::unique_ptr<PartialProfile, decltype(pp_deleter)> pp(
|
||||
imageMetaData
|
||||
? ProfileStore::getInstance()->loadDynamicProfile(imageMetaData.get())
|
||||
: nullptr,
|
||||
pp_deleter
|
||||
);
|
||||
if (pp && !pp->pparams->save(outFName)) {
|
||||
loadProcParams();
|
||||
}
|
||||
} else if (create && defProf != DEFPROFILE_DYNAMIC) {
|
||||
const PartialProfile *p = ProfileStore::getInstance()->getProfile(defProf);
|
||||
const PartialProfile* const p = ProfileStore::getInstance()->getProfile(defProf);
|
||||
if (p && !p->pparams->save(outFName)) {
|
||||
loadProcParams();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// First generate the communication file, with general values and EXIF metadata
|
||||
rtengine::FramesMetaData* imageMetaData;
|
||||
|
||||
if (getType() == FT_Raw) {
|
||||
// Should we ask all frame's MetaData ?
|
||||
imageMetaData = rtengine::FramesMetaData::fromFile (fname, std::unique_ptr<rtengine::RawMetaDataLocation>(new rtengine::RawMetaDataLocation(rtengine::Thumbnail::loadMetaDataFromRaw(fname))), true);
|
||||
} else {
|
||||
// Should we ask all frame's MetaData ?
|
||||
imageMetaData = rtengine::FramesMetaData::fromFile (fname, nullptr, true);
|
||||
}
|
||||
|
||||
static int index = 0; // Will act as unique identifier during the session
|
||||
Glib::ustring tmpFileName( Glib::build_filename(options.cacheBaseDir, Glib::ustring::compose("CPB_temp_%1.txt", index++)) );
|
||||
|
||||
const rtexif::TagDirectory* exifDir = nullptr;
|
||||
|
||||
if (imageMetaData && (exifDir = imageMetaData->getRootExifData())) {
|
||||
exifDir->CPBDump(tmpFileName, fname, outFName,
|
||||
defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension),
|
||||
cfs,
|
||||
flaggingMode);
|
||||
}
|
||||
delete imageMetaData;
|
||||
CPBDump(tmpFileName, fname, outFName,
|
||||
defaultPparamsPath == DEFPROFILE_INTERNAL ? DEFPROFILE_INTERNAL : Glib::build_filename(defaultPparamsPath, Glib::path_get_basename(defProf) + paramFileExtension), cfs, flaggingMode);
|
||||
|
||||
// For the filename etc. do NOT use streams, since they are not UTF8 safe
|
||||
Glib::ustring cmdLine = options.CPBPath + Glib::ustring(" \"") + tmpFileName + Glib::ustring("\"");
|
||||
|
@ -781,9 +828,9 @@ ThFileType Thumbnail::getType ()
|
|||
return (ThFileType) cfs.format;
|
||||
}
|
||||
|
||||
int Thumbnail::infoFromImage (const Glib::ustring& fname, std::unique_ptr<rtengine::RawMetaDataLocation> rml)
|
||||
int Thumbnail::infoFromImage (const Glib::ustring& fname)
|
||||
{
|
||||
rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname, std::move(rml));
|
||||
rtengine::FramesMetaData* idata = rtengine::FramesMetaData::fromFile (fname);
|
||||
|
||||
if (!idata) {
|
||||
return 0;
|
||||
|
|
|
@ -82,7 +82,7 @@ class Thumbnail
|
|||
void _loadThumbnail (bool firstTrial = true);
|
||||
void _saveThumbnail ();
|
||||
void _generateThumbnailImage ();
|
||||
int infoFromImage (const Glib::ustring& fname, std::unique_ptr<rtengine::RawMetaDataLocation> rml = nullptr);
|
||||
int infoFromImage (const Glib::ustring& fname);
|
||||
void loadThumbnail (bool firstTrial = true);
|
||||
void generateExifDateTimeStrings ();
|
||||
|
||||
|
|
|
@ -1,155 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
# This Bash4 script generates lens ID and other parameter lists for rtexif/*.cc
|
||||
# using ExifTool. It uses xmlstarlet to parse ExifTool's output.
|
||||
#
|
||||
# Run the script from the project root:
|
||||
# ./tools/generateRtexifUpdates
|
||||
#
|
||||
# Manually replace old code in rtexif/* with new from /tmp/rt-generateRtexifUpdates/*
|
||||
#
|
||||
# Blame DrSlony
|
||||
# Please report bugs or enhancements to https://github.com/Beep6581/RawTherapee
|
||||
|
||||
et="$HOME/programs/code-exiftool/exiftool"
|
||||
|
||||
hash "$et" 2>/dev/null || { echo >&2 "ExifTool not found, install it first."; exit 1; }
|
||||
hash xmlstarlet 2>/dev/null || { echo >&2 "XMLStarlet not found, install it first."; exit 1; }
|
||||
|
||||
unset cam cams
|
||||
|
||||
tmpdir="/tmp/rt-generateRtexifUpdates"
|
||||
|
||||
printf '%s\n' "ExifTool version: $("$et" -ver)" "" "XMLStarlet version: $(xmlstarlet --version)" | sed 's/^/# /'
|
||||
|
||||
if [[ -d ${tmpdir} ]]; then
|
||||
printf '%s\n' "" "Must remove temp folder from previous run: $tmpdir"
|
||||
rm -rvI "$tmpdir" || exit 1
|
||||
fi
|
||||
mkdir -p "$tmpdir" || { printf '%s\n' "Error creating $tmpdir" ""; exit 1; }
|
||||
echo
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Canon
|
||||
printf '%s\n' "Saving ${tmpdir}/canon_lenses"
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensType']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -canon:all) | sort -fuV > "${tmpdir}/canon_lenses"
|
||||
|
||||
#In :10.1 Sigma 50mm f/2.8 EX
|
||||
#Out: {10, "Sigma 50mm f/2.8 EX"},
|
||||
# delete lines matching '-1<tab>n/a'
|
||||
# replace '10.1<tab>Sigma' with '10, "Sigma'
|
||||
# prepend whitespace
|
||||
# append closing braces
|
||||
# replace ' F/11' with ' f/11'
|
||||
sed -r -i \
|
||||
-e '/-1\tn\/a/d' \
|
||||
-e 's/([0-9]+)[0-9.]*\t/\1, "/' \
|
||||
-e 's/^/ {/' \
|
||||
-e 's/$/"},/' \
|
||||
-e 's| F/([0-9]+)| f/\1|' \
|
||||
"${tmpdir}/canon_lenses"
|
||||
|
||||
#In :16842752 PowerShot A30
|
||||
#Out: choices[16842752] = "PowerShot A30";
|
||||
# prepend whitespace and 'choices['
|
||||
# replace <tab> with '] = "'
|
||||
# append '";'
|
||||
printf '%s\n' "Saving ${tmpdir}/canon_cameras"
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='CanonModelID']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -canon:all) | sort -fuV > "${tmpdir}/canon_cameras"
|
||||
|
||||
sed -r -i \
|
||||
-e 's/^/ choices[/' \
|
||||
-e 's/\t/] = "/' \
|
||||
-e 's/$/";/' \
|
||||
"${tmpdir}/canon_cameras"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Nikon LensIDs are composite tags
|
||||
printf '%s\n' "Saving ${tmpdir}/nikon"
|
||||
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensID']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -composite:all) > "${tmpdir}/nikon"
|
||||
|
||||
sed -r -i \
|
||||
-e '/^... /d' \
|
||||
-e 's/^/ {"/' \
|
||||
-e 's/([A-F0-9]+)[A-F0-9.]*\t/\1", "/' \
|
||||
-e 's/$/"},/' \
|
||||
-e 's|(.* ")(.*) F([0-9]+)|\1\2 f/\3|' \
|
||||
-e 's| F/([0-9]+)| f/\1|' \
|
||||
"${tmpdir}/nikon"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Olympus
|
||||
printf '%s\n' "Saving ${tmpdir}/olympus"
|
||||
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensType']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -olympus:all) | sort -fuV > "${tmpdir}/olympus"
|
||||
|
||||
sed -r -i \
|
||||
-e '/0 00 00\tNone/d' \
|
||||
-e 's/^/ lenses["0/' \
|
||||
-e 's/\t/"] = "/' \
|
||||
-e 's/$/";/' \
|
||||
-e 's| F([0-9]+)| f/\1|g' \
|
||||
"${tmpdir}/olympus"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Pentax
|
||||
printf '%s\n' "Saving ${tmpdir}/pentax"
|
||||
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensType']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -pentax:all) | sort -fuV > "${tmpdir}/pentax"
|
||||
|
||||
sed -r -i \
|
||||
-e 's/^/ choices.insert (p_t (256 * /' \
|
||||
-e 's/([0-9]+) ([0-9]+)([0-9.]*)/\1 + \2/' \
|
||||
-e 's/\t/, "/' \
|
||||
-e 's/$/"));/' \
|
||||
-e 's| F([0-9]+)| f/\1|' \
|
||||
"${tmpdir}/pentax"
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Sony
|
||||
printf '%s\n' "Saving ${tmpdir}/sony"
|
||||
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensType']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -sony:all) | sort -fuV > "${tmpdir}/sony"
|
||||
|
||||
# Sony has more lenses under the LensType2 tag
|
||||
printf '%s\n' "Saving ${tmpdir}/sony-lenstype2"
|
||||
|
||||
xmlstarlet sel -T -t \
|
||||
-m "taginfo/table/tag[@name='LensType2']/values/key" \
|
||||
-v "concat(@id,' ',val)" \
|
||||
-n < <("$et" -listx -sony:all) | sort -fuV > "${tmpdir}/sony-lenstype2"
|
||||
|
||||
sed -r -i \
|
||||
-e 's/^/ {/' \
|
||||
-e 's/([0-9]+)[0-9.]*\t/\1, "/' \
|
||||
-e 's/$/"},/' \
|
||||
-e 's| F([0-9]+)| f/\1|g' \
|
||||
"${tmpdir}/sony"
|
||||
|
||||
sed -r -i \
|
||||
-e '/255\tTamron Lens (255)/d' \
|
||||
-e 's/([0-9]+)[0-9.]*\t/\1, "/' \
|
||||
-e 's/^/ choices.insert (p_t (/' \
|
||||
-e 's/$/"));/' \
|
||||
-e 's| F([0-9]+)| f/\1|g' \
|
||||
"${tmpdir}/sony-lenstype2"
|
||||
|
Loading…
Reference in New Issue