diff --git a/rtengine/dcp.cc b/rtengine/dcp.cc index 0f5b32d34..c6c38077a 100644 --- a/rtengine/dcp.cc +++ b/rtengine/dcp.cc @@ -40,7 +40,8 @@ extern const Settings* settings; using namespace rtengine; -namespace { +namespace +{ // This sRGB gamma is taken from DNG reference code, with the added linear extension past 1.0, as we run clipless here @@ -442,8 +443,8 @@ std::map getAliases(const Glib::ustring& profile_dir) return res; } - class DCPMetadata { + // TODO: Review enum TagType { INVALID = 0, BYTE = 1, @@ -465,10 +466,10 @@ class DCPMetadata { INTEL = 0x4949, MOTOROLA = 0x4D4D }; - + public: explicit DCPMetadata(FILE *file): order_(UNKNOWN), file_(file) {} - + bool parse() { int offset = 0; @@ -487,7 +488,7 @@ public: unsigned short bo; fread(&bo, 1, 2, f); order_ = ByteOrder(int(bo)); - + get2(f, order_); if (!offset) { offset = get4(f, order_); @@ -513,12 +514,12 @@ public: return true; } - + bool find(int id) const { return tags_.find(id) != tags_.end(); } - + std::string toString(int id) { auto it = tags_.find(id); @@ -578,12 +579,12 @@ public: return 0; } } - + int toShort(int id, int ofs=0) { return toInt(id, ofs, SHORT); } - + double toDouble(int id, int ofs=0) { auto it = tags_.find(id); @@ -592,7 +593,7 @@ public: } auto &t = it->second; - + union IntFloat { uint32_t i; float f; @@ -651,7 +652,7 @@ private: return s[0] << 8 | s[1]; } } - + static int sget4(unsigned char *s, ByteOrder order) { if (order == INTEL) { @@ -660,21 +661,21 @@ private: return s[0] << 24 | s[1] << 16 | s[2] << 8 | s[3]; } } - + static unsigned short get2(FILE* f, ByteOrder order) - { + { unsigned char str[2] = { 0xff, 0xff }; fread (str, 1, 2, f); return sget2(str, order); } - + static int get4(FILE *f, ByteOrder order) - { + { unsigned char str[4] = { 0xff, 0xff, 0xff, 0xff }; fread (str, 1, 4, f); return sget4 (str, order); } - + static short int int2_to_signed(short unsigned int i) { union { @@ -744,7 +745,6 @@ private: } // namespace - struct DCPProfile::ApplyState::Data { float pro_photo[3][3]; float work[3][3]; @@ -778,22 +778,22 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : constexpr int tiff_float_size = 4; enum TagKey { - 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 + 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[] = { @@ -1065,46 +1065,46 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : DCPMetadata md(file); if (!md.parse()) { - printf ("Unable to load DCP profile '%s' !", filename.c_str()); + printf ("Unable to load DCP profile '%s'.", filename.c_str()); return; } light_source_1 = - md.find(CALIBRATION_ILLUMINANT_1) ? - md.toShort(CALIBRATION_ILLUMINANT_1) : - -1; + md.find(TAG_KEY_CALIBRATION_ILLUMINANT_1) + ? md.toShort(TAG_KEY_CALIBRATION_ILLUMINANT_1) + : -1; light_source_2 = - md.find(CALIBRATION_ILLUMINANT_2) ? - md.toShort(CALIBRATION_ILLUMINANT_2) : - -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 = md.find(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 - has_forward_matrix_1 = md.find(FORWARD_MATRIX_1); + 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] = md.toDouble(FORWARD_MATRIX_1, (col + row * 3) * 8); + forward_matrix_1[row][col] = md.toDouble(TAG_KEY_FORWARD_MATRIX_1, (col + row * 3) * 8); } } } - has_forward_matrix_2 = md.find(FORWARD_MATRIX_2); + 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] = md.toDouble(FORWARD_MATRIX_2, (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) - if (!md.find(COLOR_MATRIX_1)) { + if (!md.find(TAG_KEY_COLOR_MATRIX_1)) { std::cerr << "DCP '" << filename << "' is missing 'ColorMatrix1'. Skipped." << std::endl; fclose(file); return; @@ -1114,24 +1114,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] = md.toDouble(COLOR_MATRIX_1, (col + row * 3) * 8); + color_matrix_1[row][col] = md.toDouble(TAG_KEY_COLOR_MATRIX_1, (col + row * 3) * 8); } } - if (md.find(PROFILE_LOOK_TABLE_DIMS)) { - look_info.hue_divisions = md.toInt(PROFILE_LOOK_TABLE_DIMS, 0); - look_info.sat_divisions = md.toInt(PROFILE_LOOK_TABLE_DIMS, 4); - look_info.val_divisions = md.toInt(PROFILE_LOOK_TABLE_DIMS, 8); + 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); - look_info.srgb_gamma = md.find(PROFILE_LOOK_TABLE_ENCODING) && md.toInt(PROFILE_LOOK_TABLE_ENCODING); + 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(PROFILE_LOOK_TABLE_DATA) / 3; + 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 = md.toDouble(PROFILE_LOOK_TABLE_DATA, (i * 3) * tiff_float_size); - look_table[i].sat_scale = md.toDouble(PROFILE_LOOK_TABLE_DATA, (i * 3 + 1) * tiff_float_size); - look_table[i].val_scale = md.toDouble(PROFILE_LOOK_TABLE_DATA, (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 @@ -1148,20 +1148,20 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : look_info.pc.val_step = look_info.hue_divisions * look_info.pc.hue_step; } - if (md.find(PROFILE_HUE_SAT_MAP_DIMS)) { - delta_info.hue_divisions = md.toInt(PROFILE_HUE_SAT_MAP_DIMS, 0); - delta_info.sat_divisions = md.toInt(PROFILE_HUE_SAT_MAP_DIMS, 4); - delta_info.val_divisions = md.toInt(PROFILE_HUE_SAT_MAP_DIMS, 8); + 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); - delta_info.srgb_gamma = md.find(PROFILE_HUE_SAT_MAP_ENCODING) && md.toInt(PROFILE_HUE_SAT_MAP_ENCODING); + 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(PROFILE_HUE_SAT_MAP_DATA_1) / 3; + 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 = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_1, (i * 3) * tiff_float_size); - deltas_1[i].sat_scale = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_1, (i * 3 + 1) * tiff_float_size); - deltas_1[i].val_scale = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_1, (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 = @@ -1181,14 +1181,14 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : // Second matrix has_color_matrix_2 = true; - bool cm2 = md.find(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] = cm2 - ? md.toDouble(COLOR_MATRIX_2, (col + row * 3) * 8) - : color_matrix_1[row][col]; + ? md.toDouble(TAG_KEY_COLOR_MATRIX_2, (col + row * 3) * 8) + : color_matrix_1[row][col]; } } @@ -1198,20 +1198,20 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : // Saturation maps. Need to be unwinded. for (unsigned int i = 0; i < delta_info.array_count; ++i) { - deltas_2[i].hue_shift = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_2, (i * 3) * tiff_float_size); - deltas_2[i].sat_scale = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_2, (i * 3 + 1) * tiff_float_size); - deltas_2[i].val_scale = md.toDouble(PROFILE_HUE_SAT_MAP_DATA_2, (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); } } } - has_baseline_exposure_offset = md.find(BASELINE_EXPOSURE_OFFSET); + has_baseline_exposure_offset = md.find(TAG_KEY_BASELINE_EXPOSURE_OFFSET); if (has_baseline_exposure_offset) { - baseline_exposure_offset = md.toDouble(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 - if (md.find(PROFILE_TONE_CURVE)) { + if (md.find(TAG_KEY_PROFILE_TONE_CURVE)) { std::vector curve_points = { static_cast(DCT_Spline) // The first value is the curve type }; @@ -1219,9 +1219,9 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : // Push back each X/Y coordinates in a loop bool curve_is_linear = true; - for (unsigned int i = 0, n = md.getCount(PROFILE_TONE_CURVE); i < n; i += 2) { - const double x = md.toDouble(PROFILE_TONE_CURVE, (i + 0) * tiff_float_size); - const double y = md.toDouble(PROFILE_TONE_CURVE, (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; @@ -1237,7 +1237,7 @@ DCPProfile::DCPProfile(const Glib::ustring& filename) : tone_curve.Set(DiagonalCurve(curve_points, CURVES_MIN_POLY_POINTS)); } } else { - if (md.find(PROFILE_TONE_COPYRIGHT) && md.toString(PROFILE_TONE_COPYRIGHT).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 curve_points = { static_cast(DCT_Spline) @@ -2076,7 +2076,7 @@ void DCPStore::init(const Glib::ustring& rt_profile_dir, bool loadAll) std::deque dirs = { rt_profile_dir, - Glib::build_filename(options.rtdir, "dcpprofiles") + Glib::build_filename(options.rtdir, "dcpprofiles") }; while (!dirs.empty()) { diff --git a/rtengine/histmatching.cc b/rtengine/histmatching.cc index 5a17ab6ec..322775ca4 100644 --- a/rtengine/histmatching.cc +++ b/rtengine/histmatching.cc @@ -280,7 +280,7 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st { eSensorType sensor_type; int w, h; - std::unique_ptr thumb(Thumbnail::loadQuickFromRaw(getFileName(), sensor_type, w, h, 1, false, true, true)); + const std::unique_ptr 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; @@ -312,7 +312,7 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, st eSensorType sensor_type; double scale; int w = fw / skip, h = fh / skip; - std::unique_ptr thumb(Thumbnail::loadFromRaw(getFileName(), sensor_type, w, h, 1, false, false, true)); + const std::unique_ptr 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; diff --git a/rtengine/imagedata.cc b/rtengine/imagedata.cc index e0f6b50a3..1890739b8 100644 --- a/rtengine/imagedata.cc +++ b/rtengine/imagedata.cc @@ -17,43 +17,32 @@ * along with RawTherapee. If not, see . */ #include + #include -#include #include + +#include + #include #include "imagedata.h" #include "imagesource.h" #include "rt_math.h" + #pragma GCC diagnostic warning "-Wextra" #define PRINT_HDR_PS_DETECTION 0 using namespace rtengine; - -// namespace { - -// Glib::ustring to_utf8 (const std::string& str) -// { -// try { -// return Glib::locale_to_utf8 (str); -// } catch (Glib::Error&) { -// return Glib::convert_with_fallback (str, "UTF-8", "ISO-8859-1", "?"); -// } -// } - -// } // namespace - - namespace rtengine { extern const Settings *settings; -Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring &fname) +Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring& fname) { #ifdef EXV_UNICODE_PATH - auto *ws = g_utf8_to_utf16(fname.c_str(), -1, NULL, NULL, NULL); - std::wstring wfname(ws); + const auto* const ws = g_utf8_to_utf16(fname.c_str(), -1, NULL, NULL, NULL); + const std::wstring wfname(ws); g_free(ws); auto image = Exiv2::ImageFactory::open(wfname); #else @@ -65,13 +54,12 @@ Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring &fname) } // namespace rtengine - FramesMetaData* FramesMetaData::fromFile (const Glib::ustring& fname) { return new FramesData(fname); } -FramesData::FramesData(const Glib::ustring &fname): +FramesData::FramesData(const Glib::ustring &fname) : ok_(false), fname_(fname), dcrawFrameCount(0), @@ -110,7 +98,7 @@ FramesData::FramesData(const Glib::ustring &fname): try { auto image = open_exiv2(fname); image->readMetadata(); - auto &exif = image->exifData(); + const auto& exif = image->exifData(); ok_ = true; // taken and adapted from darktable (src/common/exif.cc) @@ -133,66 +121,72 @@ FramesData::FramesData(const Glib::ustring &fname): You should have received a copy of the GNU General Public License along with darktable. If not, see . */ - + Exiv2::ExifData::const_iterator pos; - + const auto find_exif_tag = - [&](const std::string &name) -> bool + [&exif, &pos](const std::string &name) -> bool { pos = exif.findKey(Exiv2::ExifKey(name)); - return (pos != exif.end() && pos->size()); + return pos != exif.end() && pos->size(); }; const auto find_tag = - [&](decltype(Exiv2::make) func) -> bool + [&exif, &pos](decltype(Exiv2::make) func) -> bool { pos = func(exif); return pos != exif.end() && pos->size(); }; - /* List of tag names taken from exiv2's printSummary() in actions.cpp */ + // List of tag names taken from exiv2's printSummary() in actions.cpp if (find_tag(Exiv2::make)) { make = pos->print(&exif); } - + if (find_tag(Exiv2::model)) { model = pos->print(&exif); } if (make.size() > 0) { for (const auto& corp : { - "Canon", - "NIKON", - "EPSON", - "KODAK", - "Kodak", - "OLYMPUS", - "PENTAX", - "RICOH", - "MINOLTA", - "Minolta", - "Konica", - "CASIO", - "Sinar", - "Phase One", - "SAMSUNG", - "Mamiya", - "MOTOROLA", - "Leaf", - "Panasonic" - }) { + "Canon", + "NIKON", + "EPSON", + "KODAK", + "Kodak", + "OLYMPUS", + "PENTAX", + "RICOH", + "MINOLTA", + "Minolta", + "Konica", + "CASIO", + "Sinar", + "Phase One", + "SAMSUNG", + "Mamiya", + "MOTOROLA", + "Leaf", + "Panasonic" + }) { if (make.find(corp) != std::string::npos) { // Simplify company names make = corp; break; } } - } - make.erase(make.find_last_not_of(' ') + 1); - model.erase(model.find_last_not_of(' ') + 1); + } + std::string::size_type nonspace_pos = make.find_last_not_of(' '); + if (nonspace_pos != std::string::npos && nonspace_pos + 1 < make.size()) { + make.erase(nonspace_pos + 1); + } + nonspace_pos = model.find_last_not_of(' '); + if (nonspace_pos != std::string::npos && nonspace_pos + 1 < model.size()) { + model.erase(nonspace_pos + 1); + } - if (make.length() > 0 && model.find(make + " ") == 0) { - model = model.substr(make.length() + 1); + if (!make.empty() && model.find(make + ' ') == 0) { + model.erase(0, make.size() + 1); } if (find_tag(Exiv2::exposureTime)) { @@ -203,24 +197,28 @@ FramesData::FramesData(const Glib::ustring &fname): aperture = pos->toFloat(); } - /* Read ISO speed - Nikon happens to return a pair for Lo and Hi modes */ + // Read ISO speed - Nikon happens to return a pair for Lo and Hi modes if (find_tag(Exiv2::isoSpeed)) { - // if standard exif iso tag, use the old way of interpreting the return value to be more regression-save - if (strcmp(pos->key().c_str(), "Exif.Photo.ISOSpeedRatings") == 0) { - int isofield = pos->count() > 1 ? 1 : 0; + // If standard exif iso tag, use the old way of interpreting the return value to be more regression-save + if (pos->key() == "Exif.Photo.ISOSpeedRatings") { + const long isofield = pos->count() > 1 ? 1 : 0; iso_speed = pos->toFloat(isofield); } else { - std::string str = pos->print(); - iso_speed = std::atof(str.c_str()); + iso_speed = std::atof(pos->print().c_str()); } } - // some newer cameras support iso settings that exceed the 16 bit of exif's ISOSpeedRatings + // Some newer cameras support iso settings that exceed the 16 bit of exif's ISOSpeedRatings if (iso_speed == 65535 || iso_speed == 0) { if (find_exif_tag("Exif.PentaxDng.ISO") || find_exif_tag("Exif.Pentax.ISO")) { - std::string str = pos->print(); - iso_speed = std::atof(str.c_str()); - } else if((!g_strcmp0(make.c_str(), "SONY") || !g_strcmp0(make.c_str(), "Canon")) - && find_exif_tag("Exif.Photo.RecommendedExposureIndex")) { + iso_speed = std::atof(pos->print().c_str()); + } + else if ( + ( + make == "SONY" + || make == "Canon" + ) + && find_exif_tag("Exif.Photo.RecommendedExposureIndex") + ) { iso_speed = pos->toFloat(); } } @@ -240,9 +238,9 @@ FramesData::FramesData(const Glib::ustring &fname): } if (find_tag(Exiv2::subjectDistance)) { - focus_dist = (0.01 * pow(10, pos->toFloat() / 40)); + focus_dist = (0.01 * std::pow(10, pos->toFloat() / 40)); } - + if (find_tag(Exiv2::orientation)) { orientation = pos->print(&exif); } @@ -257,7 +255,8 @@ FramesData::FramesData(const Glib::ustring &fname): std::string datetime_taken; if (find_exif_tag("Exif.Image.DateTimeOriginal")) { datetime_taken = pos->print(&exif); - } else if(find_exif_tag("Exif.Photo.DateTimeOriginal")) { + } + else if (find_exif_tag("Exif.Photo.DateTimeOriginal")) { datetime_taken = pos->print(&exif); } if (sscanf(datetime_taken.c_str(), "%d:%d:%d %d:%d:%d", &time.tm_year, &time.tm_mon, &time.tm_mday, &time.tm_hour, &time.tm_min, &time.tm_sec) == 6) { @@ -275,23 +274,23 @@ FramesData::FramesData(const Glib::ustring &fname): // Special file type detection (HDR, PixelShift) // ------------------------ uint16 bitspersample = 0, samplesperpixel = 0, sampleformat = 0, photometric = 0, compression = 0; - auto bps = exif.findKey(Exiv2::ExifKey("Exif.Image.BitsPerSample")); - auto spp = exif.findKey(Exiv2::ExifKey("Exif.Image.SamplesPerPixel")); - auto sf = exif.findKey(Exiv2::ExifKey("Exif.Image.SampleFormat")); - auto pi = exif.findKey(Exiv2::ExifKey("Exif.Image.PhotometricInterpretation")); - auto c = exif.findKey(Exiv2::ExifKey("Exif.Image.Compression")); + const auto bps = exif.findKey(Exiv2::ExifKey("Exif.Image.BitsPerSample")); + const auto spp = exif.findKey(Exiv2::ExifKey("Exif.Image.SamplesPerPixel")); + const auto sf = exif.findKey(Exiv2::ExifKey("Exif.Image.SampleFormat")); + const auto pi = exif.findKey(Exiv2::ExifKey("Exif.Image.PhotometricInterpretation")); + const auto c = exif.findKey(Exiv2::ExifKey("Exif.Image.Compression")); - if ((!make.compare (0, 6, "PENTAX") || (!make.compare (0, 5, "RICOH") && !model.compare (0, 6, "PENTAX")))) { -// if (find_exif_tag("Exif.Pentax.HDR") && pos->toLong() > 0) { -// isHDR = true; -// #if PRINT_HDR_PS_DETECTION -// printf("HDR detected ! -> \"HDR\" tag found\n"); -// #endif -// } else + if ( + !make.compare(0, 6, "PENTAX") + || ( + !make.compare(0, 5, "RICOH") + && !model.compare (0, 6, "PENTAX") + ) + ) { if (find_exif_tag("Exif.Pentax.DriveMode")) { std::string buf = pos->toString(3); buf[3] = 0; - if (!strcmp(buf.c_str(), "HDR")) { + if (buf == "HDR") { isHDR = true; #if PRINT_HDR_PS_DETECTION printf("HDR detected ! -> DriveMode = \"HDR\"\n"); @@ -299,8 +298,14 @@ FramesData::FramesData(const Glib::ustring &fname): } } - if (!isHDR && find_exif_tag("Exif.Pentax.Quality") && - (pos->toLong() == 7 || pos->toLong() == 8)) { + if ( + !isHDR + && find_exif_tag("Exif.Pentax.Quality") + && ( + pos->toLong() == 7 + || pos->toLong() == 8 + ) + ) { isPixelShift = true; #if PRINT_HDR_PS_DETECTION printf("PixelShift detected ! -> \"Quality\" = 7\n"); @@ -434,7 +439,7 @@ FramesData::FramesData(const Glib::ustring &fname): #endif } } - } catch(Exiv2::AnyError &e) { + } catch (const Exiv2::AnyError& e) { if (settings->verbose) { std::cerr << "EXIV2 ERROR: " << e.what() << std::endl; } @@ -564,7 +569,7 @@ void FramesData::setDCRawFrameCount(unsigned int frameCount) unsigned int FramesData::getFrameCount() const { - return dcrawFrameCount ? dcrawFrameCount : 1; + return std::max(1U, dcrawFrameCount); } @@ -578,7 +583,7 @@ Glib::ustring FramesData::getFileName() const std::string FramesMetaData::apertureToString(double aperture) { - + // TODO: Replace sprintf() char buffer[256]; sprintf (buffer, "%0.1f", aperture); return buffer; @@ -618,18 +623,21 @@ std::string FramesMetaData::expcompToString(double expcomp, bool maskZeroexpcomp double FramesMetaData::shutterFromString(std::string s) { - size_t i = s.find_first_of ('/'); + const std::string::size_type i = s.find_first_of ('/'); if (i == std::string::npos) { - return atof (s.c_str()); + return std::atof(s.c_str()); } else { - return atof (s.substr(0, i).c_str()) / atof (s.substr(i + 1).c_str()); + const double denominator = std::atof(s.substr(i + 1).c_str()); + return + denominator + ? std::atof(s.substr(0, i).c_str()) / denominator + : 0.0; } } double FramesMetaData::apertureFromString(std::string s) { - return atof(s.c_str()); + return std::atof(s.c_str()); } - diff --git a/rtengine/imagedata.h b/rtengine/imagedata.h index 6f2147277..eeeefdc58 100644 --- a/rtengine/imagedata.h +++ b/rtengine/imagedata.h @@ -16,24 +16,28 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#ifndef __IMAGEDATA_H__ -#define __IMAGEDATA_H__ +#pragma once #include #include -#include "rawimage.h" #include + #include + #include + +#include "rawimage.h" #include "rtengine.h" namespace rtengine { -Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring &fname); +Exiv2::Image::AutoPtr open_exiv2(const Glib::ustring &fname); // TODO: Global function? -class FramesData : public FramesMetaData { +class FramesData : + public FramesMetaData +{ private: bool ok_; Glib::ustring fname_; @@ -52,9 +56,9 @@ private: IIOSampleFormat sampleFormat; bool isPixelShift; bool isHDR; - + public: - FramesData (const Glib::ustring& fname); + FramesData(const Glib::ustring& fname); void setDCRawFrameCount(unsigned int frameCount); unsigned int getFrameCount() const override; @@ -80,6 +84,4 @@ public: Glib::ustring getFileName() const override; }; - } -#endif diff --git a/rtengine/imageio.cc b/rtengine/imageio.cc index f7d95b2df..83ef10b28 100644 --- a/rtengine/imageio.cc +++ b/rtengine/imageio.cc @@ -36,7 +36,6 @@ #endif #include "imageio.h" -//#include "iptcpairs.h" #include "iccjpeg.h" #include "color.h" #include "imagedata.h" @@ -78,27 +77,51 @@ 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."}; - -void ImageIO::setOutputProfile (const char* pdata, int plen) +MetadataInfo::MetadataInfo(const Glib::ustring& src) : + src_(src), + exif_(new rtengine::procparams::ExifPairs), + iptc_(new rtengine::procparams::IPTCPairs) { +} - delete [] profileData; +const Glib::ustring& MetadataInfo::filename() const +{ + return src_; +} - if (pdata) { - profileData = new char [plen]; - memcpy (profileData, pdata, plen); - } else { - profileData = nullptr; - } +const rtengine::procparams::ExifPairs& MetadataInfo::exif() const +{ + return *exif_; +} - profileLength = plen; +const rtengine::procparams::IPTCPairs& MetadataInfo::iptc() const +{ + return *iptc_; +} + +void MetadataInfo::setExif(const rtengine::procparams::ExifPairs &exif) +{ + *exif_ = exif; +} + +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), @@ -116,8 +139,6 @@ ImageIO::~ImageIO () } deleteLoadedProfileData(); - // delete exifRoot; - delete [] profileData; } void png_read_data(png_struct_def *png_ptr, unsigned char *data, size_t length); @@ -853,7 +874,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) { @@ -887,13 +908,13 @@ 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(profileData); + png_const_charp profdata = reinterpret_cast(profileData.data()); #else - png_bytep profdata = reinterpret_cast(profileData); + png_const_bytep profdata = reinterpret_cast(profileData.data()); #endif - png_set_iCCP(png, info, const_cast("icc"), 0, profdata, profileLength); + png_set_iCCP(png, info, "icc", 0, profdata, profileData.size()); } int rowlen = width * 3 * bps / 8; @@ -1034,8 +1055,8 @@ int ImageIO::saveJPEG (const Glib::ustring &fname, int quality, int subSamp) con jpeg_start_compress(&cinfo, TRUE); // write icc profile to the output - if (profileData) { - write_icc_profile (&cinfo, (JOCTET*)profileData, profileLength); + if (!profileData.empty()) { + write_icc_profile (&cinfo, reinterpret_cast(profileData.data()), profileData.size()); } // write image data @@ -1115,7 +1136,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 = "w"; + const char* const mode = "w"; #ifdef WIN32 FILE *file = g_fopen_withBinaryAndLock (fname); int fileno = _fileno(file); @@ -1153,8 +1174,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++) { @@ -1338,7 +1359,6 @@ void ImageIO::deleteLoadedProfileData( ) loadedProfileData = nullptr; } - bool ImageIO::saveMetadata(const Glib::ustring &fname) const { if (metadataInfo.filename().empty()) { @@ -1351,15 +1371,16 @@ bool ImageIO::saveMetadata(const Glib::ustring &fname) const src->readMetadata(); dst->setMetadata(*src); dst->exifData()["Exif.Image.Software"] = "RawTherapee " RTVERSION; - for (auto &p : metadataInfo.exif()) { + for (const auto& p : metadataInfo.exif()) { try { dst->exifData()[p.first] = p.second; - } catch (Exiv2::AnyError &exc) {} + } catch (const Exiv2::AnyError& exc) { + } } - for (auto &p : metadataInfo.iptc()) { + for (const auto& p : metadataInfo.iptc()) { try { - auto &v = p.second; - if (v.size() >= 1) { + 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)); @@ -1367,11 +1388,12 @@ bool ImageIO::saveMetadata(const Glib::ustring &fname) const dst->iptcData().add(d); } } - } catch (Exiv2::AnyError &exc) {} + } catch (const Exiv2::AnyError& exc) { + } } dst->writeMetadata(); return true; - } catch (Exiv2::AnyError &exc) { + } catch (const Exiv2::AnyError& exc) { std::cout << "EXIF ERROR: " << exc.what() << std::endl; return false; } diff --git a/rtengine/imageio.h b/rtengine/imageio.h index 0bdb7d43a..f0eafc701 100644 --- a/rtengine/imageio.h +++ b/rtengine/imageio.h @@ -31,35 +31,44 @@ #include #include -#include "rtengine.h" -#include "imageformat.h" -#include "imagedimensions.h" -#include "iimage.h" + #include "colortemp.h" -#include "procparams.h" +#include "iimage.h" +#include "imagedimensions.h" +#include "imageformat.h" +#include "rtengine.h" namespace rtengine { +namespace procparams +{ + +class ExifPairs; +class IPTCPairs; + +} + class ProgressListener; class Imagefloat; -class MetadataInfo { +class MetadataInfo final +{ public: - explicit MetadataInfo(const Glib::ustring &src=Glib::ustring()): - src_(src) {} + explicit MetadataInfo(const Glib::ustring& src = {}); - const Glib::ustring &filename() const { return src_; } + const Glib::ustring& filename() const; - const rtengine::procparams::ExifPairs &exif() const { return exif_; } - const rtengine::procparams::IPTCPairs &iptc() const { return iptc_; } - void setExif(const rtengine::procparams::ExifPairs &exif) { exif_ = exif; } - void setIptc(const rtengine::procparams::IPTCPairs &iptc) { iptc_ = iptc; } + 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_; - rtengine::procparams::ExifPairs exif_; - rtengine::procparams::IPTCPairs iptc_; + std::unique_ptr exif_; + std::unique_ptr iptc_; }; class ImageIO : virtual public ImageDatas @@ -68,7 +77,7 @@ class ImageIO : virtual public ImageDatas protected: ProgressListener* pl; cmsHPROFILE embProfile; - char* profileData; + std::string profileData; int profileLength; char* loadedProfileData; bool loadedProfileDataJpg; @@ -82,8 +91,6 @@ private: void deleteLoadedProfileData( ); public: - static Glib::ustring errorMsg[6]; - ImageIO(); ~ImageIO() override; @@ -118,8 +125,8 @@ public: cmsHPROFILE getEmbeddedProfile () const; void getEmbeddedProfileData (int& length, unsigned char*& pdata) const; - void setMetadata(const MetadataInfo &info) { metadataInfo = info; } - void setOutputProfile (const char* pdata, int plen); + void setMetadata(MetadataInfo info); + void setOutputProfile(const std::string& pdata); bool saveMetadata(const Glib::ustring &fname) const; diff --git a/rtengine/imagesource.h b/rtengine/imagesource.h index a18cca9d7..8ce3ee2e9 100644 --- a/rtengine/imagesource.h +++ b/rtengine/imagesource.h @@ -153,7 +153,7 @@ public: { outCurve = { 0.0 }; } - + double getDirPyrDenoiseExpComp ( ) { return dirpyrdenoiseExpComp; diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index 079c5cb48..98ed2eaf0 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -1403,7 +1403,6 @@ 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); diff --git a/rtengine/improcfun.cc b/rtengine/improcfun.cc index 8dd57e74d..669037021 100644 --- a/rtengine/improcfun.cc +++ b/rtengine/improcfun.cc @@ -5656,6 +5656,7 @@ void ImProcFunctions::getAutoExp (const LUTu &histogram, int histcompr, double double ImProcFunctions::getAutoDistor (const Glib::ustring &fname, int thumb_size) { if (fname != "") { + // TODO: std::unique_ptr<> to the rescue int w_raw = -1, h_raw = thumb_size; int w_thumb = -1, h_thumb = thumb_size; diff --git a/rtengine/procparams.cc b/rtengine/procparams.cc index f9daead22..3003cf3e0 100644 --- a/rtengine/procparams.cc +++ b/rtengine/procparams.cc @@ -295,15 +295,14 @@ bool saveToKeyfile( return false; } - -const std::map exif_keys = { +const std::map exif_keys = { {"Copyright", "Exif.Image.Copyright"}, {"Artist", "Exif.Image.Artist"}, {"ImageDescription", "Exif.Image.ImageDescription"}, {"Exif.UserComment", "Exif.Photo.UserComment"} }; -const std::map iptc_keys = { +const std::map iptc_keys = { {"Title", "Iptc.Application2.ObjectName"}, {"Category", "Iptc.Application2.Category"}, {"SupplementalCategories", "Iptc.Application2.SuppCategory"}, @@ -3168,9 +3167,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); // Directional pyramid denoising saveToKeyfile(!pedited || pedited->dirpyrDenoise.enabled, "Directional Pyramid Denoising", "Enabled", dirpyrDenoise.enabled, keyFile); @@ -3611,7 +3610,7 @@ int ProcParams::save(const Glib::ustring& fname, const Glib::ustring& fname2, bo // IPTC change list if (!pedited || pedited->iptc) { - std::map m; + std::map m; for (auto &p : iptc_keys) { m[p.second] = p.first; } @@ -4800,7 +4799,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) assignFromKeyfile(keyFile, "Dehaze", "ShowDepthMap", pedited, dehaze.showDepthMap, pedited->dehaze.showDepthMap); assignFromKeyfile(keyFile, "Dehaze", "Depth", pedited, dehaze.depth, pedited->dehaze.depth); } - + 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); @@ -5193,6 +5192,7 @@ int ProcParams::load(const Glib::ustring& fname, ParamsEdited* pedited) if (it == iptc_keys.end()) { continue; } + auto kk = it->second; const IPTCPairs::iterator element = iptc.find(kk); diff --git a/rtengine/procparams.h b/rtengine/procparams.h index 951b02b1a..07ec2a5fa 100644 --- a/rtengine/procparams.h +++ b/rtengine/procparams.h @@ -1075,8 +1075,104 @@ struct MetaDataParams { }; -typedef std::map ExifPairs; -typedef std::map> IPTCPairs; +/** + * Minimal wrapper allowing forward declaration for representing a key/value for the exif metadata information + */ +class ExifPairs final +{ +private: + using Pairs = std::map; + +public: + 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 + { + return pairs.begin(); + } + + const_iterator end() const + { + return pairs.end(); + } + + void clear() + { + pairs.clear(); + } + + size_type erase(const Glib::ustring& key) + { + return pairs.erase(key); + } + + Glib::ustring& operator[](const Glib::ustring& key) + { + return pairs[key]; + } + + bool operator ==(const ExifPairs& other) const + { + return pairs == other.pairs; + } + +private: + Pairs pairs; +}; + +/** + * The IPTC key/value pairs + */ +class IPTCPairs final +{ +public: + using iterator = std::map>::iterator; + using const_iterator = std::map>::const_iterator; + + iterator find(const Glib::ustring& key) + { + return pairs.find(key); + } + + const_iterator begin() const + { + return pairs.begin(); + } + + const_iterator end() const + { + return pairs.end(); + } + + bool empty() const + { + return pairs.empty(); + } + + void clear() + { + pairs.clear(); + } + + std::vector& operator[](const Glib::ustring& key) + { + return pairs[key]; + } + + bool operator ==(const IPTCPairs& other) const + { + return pairs == other.pairs; + } + +private: + std::map> pairs; +}; struct WaveletParams { std::vector ccwcurve; diff --git a/rtengine/rawimagesource.cc b/rtengine/rawimagesource.cc index 5efb3249c..d605e602c 100644 --- a/rtengine/rawimagesource.cc +++ b/rtengine/rawimagesource.cc @@ -726,7 +726,7 @@ void RawImageSource::getImage (const ColorTemp &ctemp, int tran, Imagefloat* ima rm *= expcomp; gm *= expcomp; bm *= expcomp; - + #ifdef _OPENMP #pragma omp parallel if(!d1x) // omp disabled for D1x to avoid race conditions (see Issue 1088 http://code.google.com/p/rawtherapee/issues/detail?id=1088) { @@ -1693,7 +1693,7 @@ int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly) // Load complete Exif information - idata = new FramesData (fname); + idata = new FramesData(fname); // TODO: std::unique_ptr<> idata->setDCRawFrameCount (numFrames); green(W, H); @@ -1931,16 +1931,16 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le if (!bitmapBads) { bitmapBads = new PixelsMap(W, H); } - + int n = f.mark(rawData, *bitmapBads); totBP += n; if (n > 0) { if (settings->verbose) { - printf("Marked %d hot pixels from PDAF lines\n", n); + printf("Marked %d hot pixels from PDAF lines\n", n); } - auto &thresh = f.greenEqThreshold(); + auto &thresh = f.greenEqThreshold(); if (numFrames == 4) { for (int i = 0; i < 4; ++i) { green_equilibrate(thresh, *rawDataFrames[i]); @@ -1959,7 +1959,7 @@ void RawImageSource::preprocess (const RAWParams &raw, const LensProfParams &le CameraConst *cc = ccs->get(ri->get_maker().c_str(), ri->get_model().c_str()); return cc && cc->get_globalGreenEquilibration(); }; - + if ( ri->getSensorType() == ST_BAYER && (raw.bayersensor.greenthresh || (globalGreenEq() && raw.bayersensor.method != RAWParams::BayerSensor::getMethodString( RAWParams::BayerSensor::Method::VNG4))) ) { if (settings->verbose) { printf("Performing global green equilibration...\n"); @@ -4120,7 +4120,7 @@ void RawImageSource::colorSpaceConversion_ (Imagefloat* im, const ColorManagemen } } } - + lcmsMutex->lock (); switch (camera_icc_type) { diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index b6b7402f9..bdb94fe4a 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -47,15 +47,14 @@ enum RenderingIntent : int; namespace procparams { -typedef std::map ExifPairs; -typedef std::map> IPTCPairs; +class ProcParams; +class IPTCPairs; struct RAWParams; struct ColorManagementParams; struct CropParams; enum class ToneCurveMode : int; -class ProcParams; } @@ -140,7 +139,7 @@ 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); + static FramesMetaData* fromFile(const Glib::ustring& fname); virtual Glib::ustring getFileName() const = 0; }; diff --git a/rtengine/rtthumbnail.cc b/rtengine/rtthumbnail.cc index a3c9ec6ba..2a1024609 100644 --- a/rtengine/rtthumbnail.cc +++ b/rtengine/rtthumbnail.cc @@ -207,7 +207,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; @@ -315,7 +315,7 @@ namespace { 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) { @@ -324,7 +324,7 @@ Image8 *load_inspector_mode(const Glib::ustring &fname, eSensorType &sensorType, 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); @@ -389,7 +389,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType return tpp; } - + RawImage *ri = new RawImage (fname); unsigned int imageNum = 0; int r = ri->loadRaw (false, imageNum, false); @@ -442,7 +442,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType 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, sensorType, w, h); if (!img) { delete tpp; @@ -451,7 +451,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType tpp->scale = 1.; tpp->thumbImg = img; - + return tpp; } } else { @@ -1055,12 +1055,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) { - std::string camName = metadata->getCamera(); - float shutter = metadata->getShutterSpeed(); - float fnumber = metadata->getFNumber(); - float iso = metadata->getISOSpeed(); - float fcomp = metadata->getExpComp(); - + 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; @@ -1155,7 +1155,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); @@ -1192,7 +1192,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT ipf.dehaze(baseImg); ipf.ToneMapFattal02(baseImg); - + // perform transform if (ipf.needsTransform()) { Imagefloat* trImg = new Imagefloat (fw, fh); @@ -1343,7 +1343,7 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT } } - + // luminance processing // ipf.EPDToneMap(labView,0,6); @@ -1416,7 +1416,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); diff --git a/rtengine/simpleprocess.cc b/rtengine/simpleprocess.cc index 64edc5c17..35cf82068 100644 --- a/rtengine/simpleprocess.cc +++ b/rtengine/simpleprocess.cc @@ -776,7 +776,7 @@ private: params.toneCurve.brightness = 0; params.toneCurve.contrast = 0; params.toneCurve.black = 0; - } + } // at this stage, we can flush the raw data to free up quite an important amount of memory // commented out because it makes the application crash when batch processing... @@ -1151,10 +1151,10 @@ private: if (params.colorappearance.enabled) { double adap; - float fnum = imgsrc->getMetaData()->getFNumber (); // F number - float fiso = imgsrc->getMetaData()->getISOSpeed () ; // ISO - float fspeed = imgsrc->getMetaData()->getShutterSpeed () ; //speed - float fcomp = imgsrc->getMetaData()->getExpComp (); //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.; @@ -1295,12 +1295,12 @@ private: // 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(info); + readyImg->setMetadata(std::move(info)); break; case MetaDataParams::EDIT: info.setExif(params.exif); info.setIptc(params.iptc); - readyImg->setMetadata(info); + 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; @@ -1315,7 +1315,7 @@ private: if (!useLCMS) { // use corrected sRGB profile in order to apply a good TRC if present, otherwise use LCMS2 profile generated by lab2rgb16 w/ gamma ProfileContent pc (jprof); - readyImg->setOutputProfile (pc.getData().c_str(), pc.getData().size()); + readyImg->setOutputProfile (pc.getData()); } } else { // use the selected output profile if present, otherwise use LCMS2 profile generate by lab2rgb16 w/ gamma @@ -1335,11 +1335,11 @@ private: } ProfileContent pc = ICCStore::getInstance()->getContent (params.icm.outputProfile); - readyImg->setOutputProfile (pc.getData().c_str(), pc.getData().size()); + readyImg->setOutputProfile (pc.getData()); } } else { // No ICM - readyImg->setOutputProfile (nullptr, 0); + readyImg->setOutputProfile ({}); } } diff --git a/rtgui/cacheimagedata.h b/rtgui/cacheimagedata.h index 397bc1c48..6fe55c460 100644 --- a/rtgui/cacheimagedata.h +++ b/rtgui/cacheimagedata.h @@ -87,7 +87,6 @@ public: // FramesMetaData interface //------------------------------------------------------------------------- - /* unsigned int getRootCount () const override { return -1; } */ unsigned int getFrameCount () const override { return frameCount; } bool hasExif() const override { return false; } tm getDateTime() const override { return tm{}; } diff --git a/rtgui/exifpanel.cc b/rtgui/exifpanel.cc index 661118e32..f4da2d4b1 100644 --- a/rtgui/exifpanel.cc +++ b/rtgui/exifpanel.cc @@ -16,13 +16,15 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ +#include + #include "exifpanel.h" #include "guiutils.h" #include "rtimage.h" #include "options.h" -#include "../rtengine/imagedata.h" +#include "../rtengine/imagedata.h" #include "../rtengine/procparams.h" using namespace rtengine; @@ -31,15 +33,15 @@ using namespace rtengine::procparams; 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"} + } { - editable_ = { - { "Exif.Photo.UserComment", "User Comment" }, - { "Exif.Image.Artist", "Artist" }, - { "Exif.Image.Copyright", "Copyright" }, - { "Exif.Image.ImageDescription", "Image Description"} - }; - + exifTree = Gtk::manage (new Gtk::TreeView()); scrolledWindow = Gtk::manage (new Gtk::ScrolledWindow()); @@ -57,7 +59,7 @@ ExifPanel::ExifPanel() : exifTree->set_model (exifTreeModel); exifTree->set_grid_lines (Gtk::TREE_VIEW_GRID_LINES_NONE); exifTree->set_show_expanders(false); - + keepicon = RTImage::createPixbufFromFile ("tick-small.png"); editicon = RTImage::createPixbufFromFile("add-small.png"); @@ -204,54 +206,61 @@ void ExifPanel::refreshTags() { Glib::RefPtr selection = exifTree->get_selection(); std::vector sel = selection->get_selected_rows(); - + exifTreeModel->clear(); - + if (!idata) { return; } - Glib::ustring fn = idata->getFileName(); + const Glib::ustring fn = idata->getFileName(); if (fn.empty()) { return; } std::unordered_set ed; - for (auto &p : editable_) { + for (const auto &p : editableTags) { ed.insert(p.first); } - + try { auto img = open_exiv2(fn); img->readMetadata(); - auto &exif = img->exifData(); - - for (auto &p : *changeList) { + auto& exif = img->exifData(); + + for (const auto& p : *changeList) { try { exif[p.first] = p.second; - } catch (Exiv2::AnyError &exc) { + } catch (const Exiv2::AnyError& exc) { } } - for (auto &p : editable_) { - auto pos = exif.findKey(Exiv2::ExifKey(p.first)); + for (const auto& p : editableTags) { + const auto pos = exif.findKey(Exiv2::ExifKey(p.first)); if (pos != exif.end() && pos->size()) { - bool edited = changeList->find(pos->key()) != changeList->end(); + const bool edited = changeList->find(pos->key()) != changeList->end(); addTag(pos->key(), pos->tagLabel(), pos->print(&exif), true, edited); } } - for (auto &tag : exif) { - bool editable = ed.find(tag.key()) != ed.end(); - if (!editable && !tag.tagLabel().empty() && tag.typeId() != Exiv2::undefined && - (tag.typeId() == Exiv2::asciiString || tag.size() < 256)) { + 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 (Exiv2::AnyError &exc) { + } catch (const Exiv2::AnyError& exc) { return; } - for (auto &p : sel) { + for (const auto& p : sel) { exifTree->get_selection()->select(p); } } @@ -277,13 +286,13 @@ void ExifPanel::exifSelectionChanged () } -void ExifPanel::resetIt (Gtk::TreeModel::iterator iter) +void ExifPanel::resetIt(const Gtk::TreeModel::const_iterator& iter) { if (!iter) { return; } - auto key = iter->get_value(exifColumns.key); + const auto key = iter->get_value(exifColumns.key); changeList->erase(key); } @@ -324,7 +333,7 @@ void ExifPanel::addPressed () Gtk::Label* tlabel = new Gtk::Label (M ("EXIFPANEL_ADDTAGDLG_SELECTTAG") + ":"); MyComboBoxText* tcombo = new MyComboBoxText (); - for (auto &p : editable_) { + for (const auto& p : editableTags) { tcombo->append(p.second); } @@ -339,11 +348,11 @@ void ExifPanel::addPressed () Glib::ustring sel; Glib::ustring val; { - Glib::RefPtr selection = exifTree->get_selection(); - std::vector rows = selection->get_selected_rows(); + const Glib::RefPtr selection = exifTree->get_selection(); + const std::vector rows = selection->get_selected_rows(); if (rows.size() == 1) { - Gtk::TreeModel::iterator iter = exifTreeModel->get_iter(rows[0]); + 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); @@ -351,11 +360,11 @@ void ExifPanel::addPressed () } } - if (sel == "") { + if (sel.empty()) { tcombo->set_active(0); } else { - for (size_t i = 0; i < editable_.size(); ++i) { - if (editable_[i].first == sel) { + for (size_t i = 0; i < editableTags.size(); ++i) { + if (editableTags[i].first == sel) { tcombo->set_active(i); break; } @@ -375,8 +384,8 @@ void ExifPanel::addPressed () hb2->show (); if (dialog->run () == Gtk::RESPONSE_OK) { - auto key = editable_[tcombo->get_active_row_number()].first; - auto value = ventry->get_text(); + auto key = editableTags[tcombo->get_active_row_number()].first; + const auto value = ventry->get_text(); (*changeList)[key] = value; refreshTags(); notifyListener (); diff --git a/rtgui/exifpanel.h b/rtgui/exifpanel.h index 97708ab7b..de2174f6b 100644 --- a/rtgui/exifpanel.h +++ b/rtgui/exifpanel.h @@ -20,11 +20,23 @@ #define _EXIFPANEL_ #include + #include -#include #include "toolpanel.h" +namespace rtengine +{ + +namespace procparams +{ + +class ExifPairs; + +} + +} + class ExifPanel : public Gtk::VBox, public ToolPanel { @@ -67,11 +79,11 @@ private: Gtk::Button* reset; Gtk::Button* resetAll; - std::vector> editable_; + const std::vector> 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 (Gtk::TreeModel::iterator iter); + void resetIt(const Gtk::TreeModel::const_iterator& iter); void resetPressed(); void resetAllPressed(); void addPressed(); diff --git a/rtgui/iptcpanel.cc b/rtgui/iptcpanel.cc index 9e534db2f..fcdd97101 100644 --- a/rtgui/iptcpanel.cc +++ b/rtgui/iptcpanel.cc @@ -17,11 +17,13 @@ * along with RawTherapee. If not, see . */ #include + #include "iptcpanel.h" + #include "clipboard.h" #include "rtimage.h" -#include "../rtengine/imagedata.h" +#include "../rtengine/imagedata.h" #include "../rtengine/procparams.h" using namespace rtengine; @@ -71,11 +73,10 @@ const std::set iptc_keys = { } // namespace - IPTCPanel::IPTCPanel(): changeList(new rtengine::procparams::IPTCPairs), defChangeList(new rtengine::procparams::IPTCPairs), - embeddedData(new rtengine::procparams::IPTCPairs) + embeddedData(new rtengine::procparams::IPTCPairs) { set_spacing (4); @@ -493,13 +494,13 @@ void IPTCPanel::setImageData (const FramesMetaData* id) try { auto img = open_exiv2(id->getFileName()); img->readMetadata(); - auto &iptc = img->iptcData(); - for (auto &tag : iptc) { + 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 (Exiv2::AnyError &exc) { + } catch (const Exiv2::AnyError& exc) { embeddedData->clear(); } } diff --git a/rtgui/resize.cc b/rtgui/resize.cc index decbfb2f5..40d7ace56 100644 --- a/rtgui/resize.cc +++ b/rtgui/resize.cc @@ -17,6 +17,7 @@ * along with RawTherapee. If not, see . */ #include + #include "resize.h" #include "eventmapper.h" diff --git a/rtgui/shcselector.cc b/rtgui/shcselector.cc index fe436b5ca..55a2ad9dd 100644 --- a/rtgui/shcselector.cc +++ b/rtgui/shcselector.cc @@ -18,7 +18,9 @@ */ #include + #include "shcselector.h" + #include "multilangmgr.h" #include "mycurve.h" diff --git a/rtgui/thumbnail.cc b/rtgui/thumbnail.cc index 17667ea1a..ba335d215 100644 --- a/rtgui/thumbnail.cc +++ b/rtgui/thumbnail.cc @@ -15,28 +15,91 @@ * You should have received a copy of the GNU General Public License * along with RawTherapee. If not, see . */ -#include "multilangmgr.h" -#include "thumbnail.h" -#include -#include -#include "options.h" -#include "../rtengine/mytime.h" #include #include +#include +#include + #include -#include "../rtengine/imagedata.h" -#include "../rtengine/procparams.h" + #include -#include "../rtengine/dynamicprofile.h" -#include "guiutils.h" +#include "thumbnail.h" + #include "batchqueue.h" #include "extprog.h" -#include "profilestorecombobox.h" -#include "procparamchangers.h" +#include "guiutils.h" +#include "multilangmgr.h" +#include "options.h" #include "ppversion.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 kf(new Glib::KeyFile); + + if (!kf) { + return false; + } + + // open the file in write mode + const std::unique_ptr 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; Thumbnail::Thumbnail(CacheManager* cm, const Glib::ustring& fname, CacheImageData* cf) : @@ -219,67 +282,6 @@ const ProcParams& Thumbnail::getProcParamsU () return *pparams; // there is no valid pp to return, but we have to return something } - -namespace { - -bool CPBDump(const Glib::ustring &commFName, const Glib::ustring &imageFName, - const Glib::ustring &profileFName, const Glib::ustring &defaultPParams, - const CacheImageData* cfs, const bool flagMode) -{ - const auto kf = new Glib::KeyFile; - - if (!kf) { - return false; - } - - FILE *f = nullptr; - - // open the file in write mode - f = g_fopen (commFName.c_str (), "wt"); - - if (f == nullptr) { - printf ("CPBDump(\"%s\") >>> Error: unable to open file with write access!\n", commFName.c_str()); - delete kf; - 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 (Glib::KeyFileError&) {} - - try { - fprintf (f, "%s", kf->to_data().c_str()); - } catch (Glib::KeyFileError&) {} - - fclose (f); - delete kf; - - return true; -} - - -} // namespace - /** @brief Create default params on demand and returns a new updatable object * * The loaded profile may be partial, but it return a complete ProcParams (i.e. without ParamsEdited) @@ -304,7 +306,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu const CacheImageData* cfs = getCacheImageData(); Glib::ustring defaultPparamsPath = options.findProfilePath(defProf); const bool create = (!hasProcParams() || force); - const bool run_cpb = false; //!options.CPBPath.empty() && !defaultPparamsPath.empty() && cfs && cfs->exifValid && create; + const bool run_cpb = false; const Glib::ustring outFName = (options.paramsLoadLocation == PLL_Input && options.saveParamsFile) ? @@ -313,16 +315,24 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu if (!run_cpb) { if (defProf == DEFPROFILE_DYNAMIC && create && cfs && cfs->exifValid) { - std::unique_ptr imageMetaData(rtengine::FramesMetaData::fromFile(fname)); - PartialProfile *pp = ProfileStore::getInstance()->loadDynamicProfile(imageMetaData.get()); - 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 imageMetaData(rtengine::FramesMetaData::fromFile(fname)); + const std::unique_ptr 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(); } @@ -333,7 +343,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu 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("\"");