feature: added option to use a (fast) neutral RAW rendering in 'inspector mode'
This commit is contained in:
parent
4c3c7a4c09
commit
d17bb0cfe6
@ -1157,6 +1157,10 @@ PREFERENCES_TAB_IMPROC;Image Processing
|
|||||||
PREFERENCES_TAB_PERFORMANCE;Performance & Quality
|
PREFERENCES_TAB_PERFORMANCE;Performance & Quality
|
||||||
PREFERENCES_TAB_SOUND;Sounds
|
PREFERENCES_TAB_SOUND;Sounds
|
||||||
PREFERENCES_THEME;Theme
|
PREFERENCES_THEME;Theme
|
||||||
|
PREFERENCES_THUMBNAIL_INSPECTOR_JPEG;Embedded JPEG preview
|
||||||
|
PREFERENCES_THUMBNAIL_INSPECTOR_MODE;Image to show
|
||||||
|
PREFERENCES_THUMBNAIL_INSPECTOR_RAW;Neutral RAW rendering
|
||||||
|
PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE;Embedded JPEG if fullsize, neutral RAW otherwise
|
||||||
PREFERENCES_TIMAX;High
|
PREFERENCES_TIMAX;High
|
||||||
PREFERENCES_TINB;Number of tiles
|
PREFERENCES_TINB;Number of tiles
|
||||||
PREFERENCES_TISTD;Standard
|
PREFERENCES_TISTD;Standard
|
||||||
|
@ -1518,7 +1518,7 @@ void RawImageSource::vflip (Imagefloat* image)
|
|||||||
|
|
||||||
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
//%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
||||||
|
|
||||||
int RawImageSource::load (const Glib::ustring &fname)
|
int RawImageSource::load (const Glib::ustring &fname, bool firstFrameOnly)
|
||||||
{
|
{
|
||||||
|
|
||||||
MyTime t1, t2;
|
MyTime t1, t2;
|
||||||
@ -1535,7 +1535,7 @@ int RawImageSource::load (const Glib::ustring &fname)
|
|||||||
if (errCode) {
|
if (errCode) {
|
||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
numFrames = ri->getFrameCount();
|
numFrames = firstFrameOnly ? 1 : ri->getFrameCount();
|
||||||
|
|
||||||
errCode = 0;
|
errCode = 0;
|
||||||
|
|
||||||
|
@ -118,7 +118,8 @@ public:
|
|||||||
RawImageSource ();
|
RawImageSource ();
|
||||||
~RawImageSource ();
|
~RawImageSource ();
|
||||||
|
|
||||||
int load (const Glib::ustring &fname);
|
int load(const Glib::ustring &fname) { return load(fname, false); }
|
||||||
|
int load(const Glib::ustring &fname, bool firstFrameOnly);
|
||||||
void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true);
|
void preprocess (const RAWParams &raw, const LensProfParams &lensProf, const CoarseTransformParams& coarse, bool prepareDenoise = true);
|
||||||
void demosaic (const RAWParams &raw);
|
void demosaic (const RAWParams &raw);
|
||||||
void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, const ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D<float, 4> &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI);
|
void retinex (const ColorManagementParams& cmp, const RetinexParams &deh, const ToneCurveParams& Tc, LUTf & cdcurve, LUTf & mapcurve, const RetinextransmissionCurve & dehatransmissionCurve, const RetinexgaintransmissionCurve & dehagaintransmissionCurve, multi_array2D<float, 4> &conversionBuffer, bool dehacontlutili, bool mapcontlutili, bool useHsl, float &minCD, float &maxCD, float &mini, float &maxi, float &Tmean, float &Tsigma, float &Tmin, float &Tmax, LUTu &histLRETI);
|
||||||
|
@ -36,7 +36,10 @@
|
|||||||
#include "jpeg.h"
|
#include "jpeg.h"
|
||||||
#include "../rtgui/ppversion.h"
|
#include "../rtgui/ppversion.h"
|
||||||
#include "improccoordinator.h"
|
#include "improccoordinator.h"
|
||||||
|
#include "settings.h"
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
|
#include "StopWatch.h"
|
||||||
|
#include "median.h"
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@ -147,6 +150,8 @@ extern Options options;
|
|||||||
namespace rtengine
|
namespace rtengine
|
||||||
{
|
{
|
||||||
|
|
||||||
|
extern const Settings *settings;
|
||||||
|
|
||||||
using namespace procparams;
|
using namespace procparams;
|
||||||
|
|
||||||
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode)
|
Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, bool inspectorMode)
|
||||||
@ -261,13 +266,92 @@ Thumbnail* Thumbnail::loadFromImage (const Glib::ustring& fname, int &w, int &h,
|
|||||||
return tpp;
|
return tpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
Image8 *load_inspector_mode(const Glib::ustring &fname, RawMetaDataLocation &rml, eSensorType &sensorType, int &w, int &h)
|
||||||
|
{
|
||||||
|
BENCHFUN
|
||||||
|
|
||||||
|
RawImageSource src;
|
||||||
|
int err = src.load(fname, true);
|
||||||
|
if (err) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
neutral.icm.input = "(camera)";
|
||||||
|
neutral.icm.working = "RT_sRGB";
|
||||||
|
|
||||||
|
src.preprocess(neutral.raw, neutral.lensProf, neutral.coarse, false);
|
||||||
|
src.demosaic(neutral.raw);
|
||||||
|
|
||||||
|
PreviewProps pp(0, 0, w, h, 1);
|
||||||
|
|
||||||
|
Imagefloat tmp(w, h);
|
||||||
|
src.getImage(src.getWB(), TR_NONE, &tmp, pp, neutral.toneCurve, neutral.raw);
|
||||||
|
src.convertColorSpace(&tmp, neutral.icm, src.getWB());
|
||||||
|
|
||||||
|
Image8 *img = new Image8(w, h);
|
||||||
|
const float f = 255.f/65535.f;
|
||||||
|
#ifdef _OPENMP
|
||||||
|
#pragma omp parallel for
|
||||||
|
#endif
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
float r = tmp.r(y, x);
|
||||||
|
float g = tmp.g(y, x);
|
||||||
|
float b = tmp.b(y, x);
|
||||||
|
// avoid magenta highlights
|
||||||
|
if (r > MAXVALF && b > MAXVALF) {
|
||||||
|
float v = CLIP((r + g + b) / 3.f) * f;
|
||||||
|
img->r(y, x) = img->g(y, x) = img->b(y, x) = v;
|
||||||
|
} else {
|
||||||
|
img->r(y, x) = Color::gamma_srgbclipped(r) * f;
|
||||||
|
img->g(y, x) = Color::gamma_srgbclipped(g) * f;
|
||||||
|
img->b(y, x) = Color::gamma_srgbclipped(b) * f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return img;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode)
|
Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataLocation& rml, eSensorType &sensorType, int &w, int &h, int fixwh, bool rotate, bool inspectorMode)
|
||||||
{
|
{
|
||||||
|
Thumbnail* tpp = new Thumbnail ();
|
||||||
|
tpp->isRaw = 1;
|
||||||
|
memset (tpp->colorMatrix, 0, sizeof (tpp->colorMatrix));
|
||||||
|
tpp->colorMatrix[0][0] = 1.0;
|
||||||
|
tpp->colorMatrix[1][1] = 1.0;
|
||||||
|
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);
|
||||||
|
if (!img) {
|
||||||
|
delete tpp;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tpp->scale = 1.;
|
||||||
|
tpp->thumbImg = img;
|
||||||
|
|
||||||
|
return tpp;
|
||||||
|
}
|
||||||
|
|
||||||
RawImage *ri = new RawImage (fname);
|
RawImage *ri = new RawImage (fname);
|
||||||
unsigned int imageNum = 0;
|
unsigned int imageNum = 0;
|
||||||
int r = ri->loadRaw (false, imageNum, false);
|
int r = ri->loadRaw (false, imageNum, false);
|
||||||
|
|
||||||
if ( r ) {
|
if ( r ) {
|
||||||
|
delete tpp;
|
||||||
delete ri;
|
delete ri;
|
||||||
sensorType = ST_NONE;
|
sensorType = ST_NONE;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -301,24 +385,33 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, RawMetaDataL
|
|||||||
// did we succeed?
|
// did we succeed?
|
||||||
if ( err ) {
|
if ( err ) {
|
||||||
printf ("Could not extract thumb from %s\n", fname.data());
|
printf ("Could not extract thumb from %s\n", fname.data());
|
||||||
|
delete tpp;
|
||||||
delete img;
|
delete img;
|
||||||
delete ri;
|
delete ri;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Thumbnail* tpp = new Thumbnail ();
|
|
||||||
|
|
||||||
tpp->isRaw = 1;
|
|
||||||
memset (tpp->colorMatrix, 0, sizeof (tpp->colorMatrix));
|
|
||||||
tpp->colorMatrix[0][0] = 1.0;
|
|
||||||
tpp->colorMatrix[1][1] = 1.0;
|
|
||||||
tpp->colorMatrix[2][2] = 1.0;
|
|
||||||
|
|
||||||
if (inspectorMode) {
|
if (inspectorMode) {
|
||||||
// Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature)
|
// Special case, meaning that we want a full sized thumbnail image (e.g. for the Inspector feature)
|
||||||
w = img->getWidth();
|
w = img->getWidth();
|
||||||
h = img->getHeight();
|
h = img->getHeight();
|
||||||
tpp->scale = 1.;
|
tpp->scale = 1.;
|
||||||
|
|
||||||
|
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);
|
||||||
|
if (!img) {
|
||||||
|
delete tpp;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
tpp->scale = 1.;
|
||||||
|
tpp->thumbImg = img;
|
||||||
|
|
||||||
|
return tpp;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (fixwh == 1) {
|
if (fixwh == 1) {
|
||||||
w = h * img->getWidth() / img->getHeight();
|
w = h * img->getWidth() / img->getHeight();
|
||||||
|
@ -84,6 +84,13 @@ public:
|
|||||||
double level123_cbdl;
|
double level123_cbdl;
|
||||||
Glib::ustring lensfunDbDirectory; ///< The directory containing the lensfun database. If empty, the system defaults will be used (as described in http://lensfun.sourceforge.net/manual/dbsearch.html)
|
Glib::ustring lensfunDbDirectory; ///< The directory containing the lensfun database. If empty, the system defaults will be used (as described in http://lensfun.sourceforge.net/manual/dbsearch.html)
|
||||||
|
|
||||||
|
enum class ThumbnailInspectorMode {
|
||||||
|
JPEG,
|
||||||
|
RAW,
|
||||||
|
RAW_IF_NOT_JPEG_FULLSIZE
|
||||||
|
};
|
||||||
|
ThumbnailInspectorMode thumbnail_inspector_mode;
|
||||||
|
|
||||||
/** Creates a new instance of Settings.
|
/** Creates a new instance of Settings.
|
||||||
* @return a pointer to the new Settings instance. */
|
* @return a pointer to the new Settings instance. */
|
||||||
static Settings* create ();
|
static Settings* create ();
|
||||||
|
@ -592,6 +592,8 @@ void Options::setDefaults ()
|
|||||||
rtSettings.lensfunDbDirectory = ""; // set also in main.cc and main-cli.cc
|
rtSettings.lensfunDbDirectory = ""; // set also in main.cc and main-cli.cc
|
||||||
cropGuides = CROP_GUIDE_FULL;
|
cropGuides = CROP_GUIDE_FULL;
|
||||||
cropAutoFit = false;
|
cropAutoFit = false;
|
||||||
|
|
||||||
|
rtSettings.thumbnail_inspector_mode = rtengine::Settings::ThumbnailInspectorMode::JPEG;
|
||||||
}
|
}
|
||||||
|
|
||||||
Options* Options::copyFrom (Options* other)
|
Options* Options::copyFrom (Options* other)
|
||||||
@ -1065,6 +1067,10 @@ void Options::readFromFile (Glib::ustring fname)
|
|||||||
if (keyFile.has_key ("Performance", "SerializeTiffRead")) {
|
if (keyFile.has_key ("Performance", "SerializeTiffRead")) {
|
||||||
serializeTiffRead = keyFile.get_boolean ("Performance", "SerializeTiffRead");
|
serializeTiffRead = keyFile.get_boolean ("Performance", "SerializeTiffRead");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (keyFile.has_key("Performance", "ThumbnailInspectorMode")) {
|
||||||
|
rtSettings.thumbnail_inspector_mode = static_cast<rtengine::Settings::ThumbnailInspectorMode>(keyFile.get_integer("Performance", "ThumbnailInspectorMode"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keyFile.has_group ("GUI")) {
|
if (keyFile.has_group ("GUI")) {
|
||||||
@ -1844,6 +1850,7 @@ void Options::saveToFile (Glib::ustring fname)
|
|||||||
keyFile.set_integer ("Performance", "PreviewDemosaicFromSidecar", prevdemo);
|
keyFile.set_integer ("Performance", "PreviewDemosaicFromSidecar", prevdemo);
|
||||||
keyFile.set_boolean ("Performance", "Daubechies", rtSettings.daubech);
|
keyFile.set_boolean ("Performance", "Daubechies", rtSettings.daubech);
|
||||||
keyFile.set_boolean ("Performance", "SerializeTiffRead", serializeTiffRead);
|
keyFile.set_boolean ("Performance", "SerializeTiffRead", serializeTiffRead);
|
||||||
|
keyFile.set_integer("Performance", "ThumbnailInspectorMode", int(rtSettings.thumbnail_inspector_mode));
|
||||||
|
|
||||||
keyFile.set_string ("Output", "Format", saveFormat.format);
|
keyFile.set_string ("Output", "Format", saveFormat.format);
|
||||||
keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality);
|
keyFile.set_integer ("Output", "JpegQuality", saveFormat.jpegQuality);
|
||||||
|
@ -657,7 +657,19 @@ Gtk::Widget* Preferences::getPerformancePanel ()
|
|||||||
maxInspectorBuffersSB->set_range (1, 12); // ... we have to set a limit, 12 seem to be enough even for systems with tons of RAM
|
maxInspectorBuffersSB->set_range (1, 12); // ... we have to set a limit, 12 seem to be enough even for systems with tons of RAM
|
||||||
maxIBuffersHB->pack_start (*maxIBufferLbl, Gtk::PACK_SHRINK, 0);
|
maxIBuffersHB->pack_start (*maxIBufferLbl, Gtk::PACK_SHRINK, 0);
|
||||||
maxIBuffersHB->pack_end (*maxInspectorBuffersSB, Gtk::PACK_SHRINK, 0);
|
maxIBuffersHB->pack_end (*maxInspectorBuffersSB, Gtk::PACK_SHRINK, 0);
|
||||||
finspect->add (*maxIBuffersHB);
|
|
||||||
|
Gtk::VBox *inspectorvb = Gtk::manage(new Gtk::VBox());
|
||||||
|
inspectorvb->add(*maxIBuffersHB);
|
||||||
|
|
||||||
|
Gtk::HBox *insphb = Gtk::manage(new Gtk::HBox());
|
||||||
|
thumbnailInspectorMode = Gtk::manage(new Gtk::ComboBoxText());
|
||||||
|
thumbnailInspectorMode->append(M("PREFERENCES_THUMBNAIL_INSPECTOR_JPEG"));
|
||||||
|
thumbnailInspectorMode->append(M("PREFERENCES_THUMBNAIL_INSPECTOR_RAW"));
|
||||||
|
thumbnailInspectorMode->append(M("PREFERENCES_THUMBNAIL_INSPECTOR_RAW_IF_NO_JPEG_FULLSIZE"));
|
||||||
|
insphb->pack_start(*Gtk::manage(new Gtk::Label(M("PREFERENCES_THUMBNAIL_INSPECTOR_MODE") + ": ")), Gtk::PACK_SHRINK, 4);
|
||||||
|
insphb->pack_start(*thumbnailInspectorMode);
|
||||||
|
inspectorvb->pack_start(*insphb);
|
||||||
|
finspect->add (*inspectorvb);
|
||||||
mainContainer->pack_start (*finspect, Gtk::PACK_SHRINK, 4);
|
mainContainer->pack_start (*finspect, Gtk::PACK_SHRINK, 4);
|
||||||
|
|
||||||
Gtk::Frame* fdenoise = Gtk::manage ( new Gtk::Frame (M ("PREFERENCES_NOISE")) );
|
Gtk::Frame* fdenoise = Gtk::manage ( new Gtk::Frame (M ("PREFERENCES_NOISE")) );
|
||||||
@ -1853,6 +1865,7 @@ void Preferences::storePreferences ()
|
|||||||
moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
|
moptions.rgbDenoiseThreadLimit = rgbDenoiseTreadLimitSB->get_value_as_int();
|
||||||
moptions.clutCacheSize = clutCacheSizeSB->get_value_as_int();
|
moptions.clutCacheSize = clutCacheSizeSB->get_value_as_int();
|
||||||
moptions.maxInspectorBuffers = maxInspectorBuffersSB->get_value_as_int();
|
moptions.maxInspectorBuffers = maxInspectorBuffersSB->get_value_as_int();
|
||||||
|
moptions.rtSettings.thumbnail_inspector_mode = static_cast<rtengine::Settings::ThumbnailInspectorMode>(thumbnailInspectorMode->get_active_row_number());
|
||||||
|
|
||||||
// Sounds only on Windows and Linux
|
// Sounds only on Windows and Linux
|
||||||
#if defined(WIN32) || defined(__linux__)
|
#if defined(WIN32) || defined(__linux__)
|
||||||
@ -2072,6 +2085,7 @@ void Preferences::fillPreferences ()
|
|||||||
rgbDenoiseTreadLimitSB->set_value (moptions.rgbDenoiseThreadLimit);
|
rgbDenoiseTreadLimitSB->set_value (moptions.rgbDenoiseThreadLimit);
|
||||||
clutCacheSizeSB->set_value (moptions.clutCacheSize);
|
clutCacheSizeSB->set_value (moptions.clutCacheSize);
|
||||||
maxInspectorBuffersSB->set_value (moptions.maxInspectorBuffers);
|
maxInspectorBuffersSB->set_value (moptions.maxInspectorBuffers);
|
||||||
|
thumbnailInspectorMode->set_active(int(moptions.rtSettings.thumbnail_inspector_mode));
|
||||||
|
|
||||||
darkFrameDir->set_current_folder ( moptions.rtSettings.darkFramesPath );
|
darkFrameDir->set_current_folder ( moptions.rtSettings.darkFramesPath );
|
||||||
darkFrameChanged ();
|
darkFrameChanged ();
|
||||||
|
@ -166,6 +166,7 @@ class Preferences : public Gtk::Dialog, public ProfileStoreListener
|
|||||||
Gtk::SpinButton* rgbDenoiseTreadLimitSB;
|
Gtk::SpinButton* rgbDenoiseTreadLimitSB;
|
||||||
Gtk::SpinButton* clutCacheSizeSB;
|
Gtk::SpinButton* clutCacheSizeSB;
|
||||||
Gtk::SpinButton* maxInspectorBuffersSB;
|
Gtk::SpinButton* maxInspectorBuffersSB;
|
||||||
|
Gtk::ComboBoxText *thumbnailInspectorMode;
|
||||||
|
|
||||||
Gtk::CheckButton* ckbmenuGroupRank;
|
Gtk::CheckButton* ckbmenuGroupRank;
|
||||||
Gtk::CheckButton* ckbmenuGroupLabel;
|
Gtk::CheckButton* ckbmenuGroupLabel;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user