Merge pull request #6806 from Lawrence37/browser-preview-applied-pparams

Enable black level and abstract profile preview in file browser
This commit is contained in:
Lawrence37 2023-09-03 15:15:25 -07:00 committed by GitHub
commit ec12c170a2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 186 additions and 34 deletions

View File

@ -229,7 +229,7 @@ void mappingToCurve(const std::vector<int> &mapping, std::vector<double> &curve)
} // namespace } // namespace
void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, StandardObserver observer, std::vector<double> &outCurve) void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, const procparams::RAWParams &rawParams, StandardObserver observer, std::vector<double> &outCurve)
{ {
BENCHFUN BENCHFUN
@ -311,7 +311,7 @@ void RawImageSource::getAutoMatchedToneCurve(const ColorManagementParams &cp, St
eSensorType sensor_type; eSensorType sensor_type;
double scale; double scale;
int w = fw / skip, h = fh / skip; int w = fw / skip, h = fh / skip;
const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), sensor_type, w, h, 1, false, observer, false, true)); const std::unique_ptr<Thumbnail> thumb(Thumbnail::loadFromRaw(getFileName(), sensor_type, w, h, 1, false, observer, false, &rawParams, true));
if (!thumb) { if (!thumb) {
if (settings->verbose) { if (settings->verbose) {
std::cout << "histogram matching: raw decoding failed, generating a neutral curve" << std::endl; std::cout << "histogram matching: raw decoding failed, generating a neutral curve" << std::endl;

View File

@ -167,7 +167,7 @@ public:
} }
// for RAW files, compute a tone curve using histogram matching on the embedded thumbnail // for RAW files, compute a tone curve using histogram matching on the embedded thumbnail
virtual void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, StandardObserver observer, std::vector<double> &outCurve) virtual void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, const procparams::RAWParams &rawParams, StandardObserver observer, std::vector<double> &outCurve)
{ {
outCurve = { 0.0 }; outCurve = { 0.0 };
} }

View File

@ -1037,7 +1037,7 @@ void ImProcCoordinator::updatePreviewImage(int todo, bool panningRelatedChange)
if (params->toneCurve.histmatching) { if (params->toneCurve.histmatching) {
if (!params->toneCurve.fromHistMatching) { if (!params->toneCurve.fromHistMatching) {
imgsrc->getAutoMatchedToneCurve(params->icm, params->wb.observer, params->toneCurve.curve); imgsrc->getAutoMatchedToneCurve(params->icm, params->raw, params->wb.observer, params->toneCurve.curve);
} }
if (params->toneCurve.autoexp) { if (params->toneCurve.autoexp) {

View File

@ -5645,7 +5645,7 @@ double ImProcFunctions::getAutoDistor(const Glib::ustring &fname, int thumb_size
return 0.0; return 0.0;
} }
Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, sensorType, w_raw, h_raw, 1, 1.0, ColorTemp::DEFAULT_OBSERVER, FALSE); Thumbnail* raw = rtengine::Thumbnail::loadFromRaw(fname, sensorType, w_raw, h_raw, 1, 1.0, ColorTemp::DEFAULT_OBSERVER, FALSE, nullptr);
if (!raw) { if (!raw) {
delete thumb; delete thumb;

View File

@ -186,7 +186,7 @@ public:
} }
void getAutoExpHistogram (LUTu & histogram, int& histcompr) override; void getAutoExpHistogram (LUTu & histogram, int& histcompr) override;
void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) override; void getRAWHistogram (LUTu & histRedRaw, LUTu & histGreenRaw, LUTu & histBlueRaw) override;
void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, StandardObserver observer, std::vector<double> &outCurve) override; void getAutoMatchedToneCurve(const procparams::ColorManagementParams &cp, const procparams::RAWParams &rawParams, StandardObserver observer, std::vector<double> &outCurve) override;
DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) override; DCPProfile *getDCP(const procparams::ColorManagementParams &cmp, DCPProfileApplyState &as) override;
void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override; void convertColorSpace(Imagefloat* image, const procparams::ColorManagementParams &cmp, const ColorTemp &wb) override;

View File

@ -16,6 +16,8 @@
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with RawTherapee. If not, see <https://www.gnu.org/licenses/>. * along with RawTherapee. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <algorithm>
#include <array>
#include <clocale> #include <clocale>
#include <lcms2.h> #include <lcms2.h>
@ -65,6 +67,84 @@ bool checkRawImageThumb (const rtengine::RawImage& raw_image)
return raw_image.get_thumbOffset() + length <= raw_image.get_file()->size; return raw_image.get_thumbOffset() + length <= raw_image.get_file()->size;
} }
/**
* Apply the black level adjustments in the processing parameters.
*
* @param cblack The original black levels that will be modified.
* @param sensorType Sensor type.
* @param rawParams Subset of processing parameters for raw data.
*/
void adjustBlackLevels(float cblack[4], rtengine::eSensorType sensorType, const rtengine::RAWParams *rawParams)
{
if (!rawParams) {
return;
}
std::array<float, 4> black_adjust{0.f, 0.f, 0.f, 0.f};
switch (sensorType) {
case rtengine::eSensorType::ST_BAYER:
case rtengine::eSensorType::ST_FOVEON:
black_adjust[0] = static_cast<float>(rawParams->bayersensor.black1); // R
black_adjust[1] = static_cast<float>(rawParams->bayersensor.black0); // G1
black_adjust[2] = static_cast<float>(rawParams->bayersensor.black2); // B
black_adjust[3] = static_cast<float>(rawParams->bayersensor.black3); // G2
break;
case rtengine::eSensorType::ST_FUJI_XTRANS:
black_adjust[0] = static_cast<float>(rawParams->xtranssensor.blackred);
black_adjust[1] = static_cast<float>(rawParams->xtranssensor.blackgreen);
black_adjust[2] = static_cast<float>(rawParams->xtranssensor.blackblue);
black_adjust[3] = static_cast<float>(rawParams->xtranssensor.blackgreen);
break;
case rtengine::eSensorType::ST_NONE:
break;
}
for (int i = 0; i < black_adjust.size(); i++) {
cblack[i] = std::max(0.f, cblack[i] + black_adjust[i]);
}
}
/**
* Calculate the new scale multipliers based on new black levels.
*
* @param scale_mul The original scale multipliers to be adjusted.
* @param pre_mul Pre-multipliers.
* @param c_black Updated black levels.
* @param isMono Is the image using mono demosaicing?
* @param ri Pointer to the raw image.
*/
void calculate_scale_mul(float scale_mul[4], const float pre_mul_[4], const float c_black[4], bool isMono, const rtengine::RawImage *ri)
{
std::array<float, 4> c_white;
for (int i = 0; i < c_white.size(); ++i) {
c_white[i] = static_cast<float>(ri->get_white(i));
}
if (isMono || ri->get_colors() == 1) {
for (int c = 0; c < 4; c++) {
scale_mul[c] = 65535.f / (c_white[c] - c_black[c]);
}
} else {
std::array<float, 4> pre_mul;
for (int c = 0; c < 4; c++) {
pre_mul[c] = pre_mul_[c];
}
if (pre_mul[3] == 0) {
pre_mul[3] = pre_mul[1]; // G2 == G1
}
float maxpremul = std::max(std::max(std::max(pre_mul[0], pre_mul[1]), pre_mul[2]), pre_mul[3]);
for (int c = 0; c < 4; c++) {
scale_mul[c] = (pre_mul[c] / maxpremul) * 65535.f / (c_white[c] - c_black[c]);
}
}
}
void scale_colors (rtengine::RawImage *ri, float scale_mul[4], float cblack[4], bool multiThread) void scale_colors (rtengine::RawImage *ri, float scale_mul[4], float cblack[4], bool multiThread)
{ {
@ -519,7 +599,7 @@ Thumbnail* Thumbnail::loadQuickFromRaw (const Glib::ustring& fname, eSensorType
#define FISGREEN(filter,row,col) \ #define FISGREEN(filter,row,col) \
((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter) ((filter >> ((((row) << 1 & 14) + ((col) & 1)) << 1) & 3)==1 || !filter)
Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, bool forHistogramMatching) Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, const RAWParams *rawParams, bool forHistogramMatching)
{ {
RawImage *ri = new RawImage (fname); RawImage *ri = new RawImage (fname);
unsigned int tempImageNum = 0; unsigned int tempImageNum = 0;
@ -562,8 +642,15 @@ Thumbnail* Thumbnail::loadFromRaw (const Glib::ustring& fname, eSensorType &sens
tpp->greenMultiplier = ri->get_pre_mul (1); tpp->greenMultiplier = ri->get_pre_mul (1);
tpp->blueMultiplier = ri->get_pre_mul (2); tpp->blueMultiplier = ri->get_pre_mul (2);
bool isMono =
(ri->getSensorType() == ST_FUJI_XTRANS &&
rawParams->xtranssensor.method == RAWParams::XTransSensor::getMethodString(RAWParams::XTransSensor::Method::MONO)) ||
(ri->getSensorType() == ST_BAYER &&
rawParams->bayersensor.method == RAWParams::BayerSensor::getMethodString(RAWParams::BayerSensor::Method::MONO));
float pre_mul[4], scale_mul[4], cblack[4]; float pre_mul[4], scale_mul[4], cblack[4];
ri->get_colorsCoeff (pre_mul, scale_mul, cblack, false); ri->get_colorsCoeff (pre_mul, scale_mul, cblack, false);
adjustBlackLevels(cblack, sensorType, rawParams);
calculate_scale_mul(scale_mul, pre_mul, cblack, isMono, ri);
scale_colors (ri, scale_mul, cblack, forHistogramMatching); // enable multithreading when forHistogramMatching is true scale_colors (ri, scale_mul, cblack, forHistogramMatching); // enable multithreading when forHistogramMatching is true
ri->pre_interpolate(); ri->pre_interpolate();
@ -1434,6 +1521,50 @@ IImage8* Thumbnail::processImage (const procparams::ProcParams& params, eSensorT
ipf.softLight(labView, params.softlight); ipf.softLight(labView, params.softlight);
if (params.icm.workingTRC != ColorManagementParams::WorkingTrc::NONE) {
const int GW = labView->W;
const int GH = labView->H;
std::unique_ptr<LabImage> provis;
const float pres = 0.01f * params.icm.preser;
if (pres > 0.f && params.icm.wprim != ColorManagementParams::Primaries::DEFAULT) {
provis.reset(new LabImage(GW, GH));
provis->CopyFrom(labView);
}
const std::unique_ptr<Imagefloat> tmpImage1(new Imagefloat(GW, GH));
ipf.lab2rgb(*labView, *tmpImage1, params.icm.workingProfile);
const float gamtone = params.icm.workingTRCGamma;
const float slotone = params.icm.workingTRCSlope;
int illum = toUnderlying(params.icm.will);
const int prim = toUnderlying(params.icm.wprim);
Glib::ustring prof = params.icm.workingProfile;
cmsHTRANSFORM dummy = nullptr;
int ill = 0;
ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, -5, prof, 2.4, 12.92310, ill, 0, dummy, true, false, false);
ipf.workingtrc(tmpImage1.get(), tmpImage1.get(), GW, GH, 5, prof, gamtone, slotone, illum, prim, dummy, false, true, true);
ipf.rgb2lab(*tmpImage1, *labView, params.icm.workingProfile);
// labView and provis
if(provis) {
ipf.preserv(labView, provis.get(), GW, GH);
}
if(params.icm.fbw) {
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int x = 0; x < GH; x++)
for (int y = 0; y < GW; y++) {
labView->a[x][y] = 0.f;
labView->b[x][y] = 0.f;
}
}
}
if (params.colorappearance.enabled) { if (params.colorappearance.enabled) {
CurveFactory::curveLightBrightColor ( CurveFactory::curveLightBrightColor (

View File

@ -99,7 +99,7 @@ public:
void getDimensions (int& w, int& h, double& scaleFac); void getDimensions (int& w, int& h, double& scaleFac);
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* 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, StandardObserver wbObserver, bool rotate, bool forHistogramMatching=false); static Thumbnail* loadFromRaw (const Glib::ustring& fname, eSensorType &sensorType, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool rotate, const RAWParams *rawParams, bool forHistogramMatching=false);
static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool inspectorMode = false); static Thumbnail* loadFromImage (const Glib::ustring& fname, int &w, int &h, int fixwh, double wbEq, StandardObserver wbObserver, bool inspectorMode = false);
void getCamWB (double& temp, double& green, StandardObserver observer); void getCamWB (double& temp, double& green, StandardObserver observer);

View File

@ -782,7 +782,7 @@ private:
if (params.toneCurve.histmatching) { if (params.toneCurve.histmatching) {
if (!params.toneCurve.fromHistMatching) { if (!params.toneCurve.fromHistMatching) {
imgsrc->getAutoMatchedToneCurve(params.icm, params.wb.observer, params.toneCurve.curve); imgsrc->getAutoMatchedToneCurve(params.icm, params.raw, params.wb.observer, params.toneCurve.curve);
} }
if (params.toneCurve.autoexp) { if (params.toneCurve.autoexp) {

View File

@ -615,7 +615,7 @@ void BatchToolPanelCoordinator::optionsChanged ()
initSession (); initSession ();
} }
void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt) void BatchToolPanelCoordinator::procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint)
{ {
if (whoChangedIt != BATCHEDITOR && !blockedUpdate) { if (whoChangedIt != BATCHEDITOR && !blockedUpdate) {

View File

@ -73,7 +73,7 @@ public:
void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) override; void getCamWB (double& temp, double& green, rtengine::StandardObserver observer) override;
// thumbnaillistener interface // thumbnaillistener interface
void procParamsChanged (Thumbnail* thm, int whoChangedIt) override; void procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint) override;
// batchpparamschangelistener interface // batchpparamschangelistener interface
void beginBatchPParamsChange(int numberOfEntries) override; void beginBatchPParamsChange(int numberOfEntries) override;

View File

@ -1995,7 +1995,7 @@ bool EditorPanel::handleShortcutKey (GdkEventKey* event)
return false; return false;
} }
void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt) void EditorPanel::procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint)
{ {
if (whoChangedIt != EDITOR) { if (whoChangedIt != EDITOR) {

View File

@ -119,7 +119,7 @@ public:
void clearParamChanges() override; void clearParamChanges() override;
// thumbnaillistener interface // thumbnaillistener interface
void procParamsChanged (Thumbnail* thm, int whoChangedIt) override; void procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint) override;
// HistoryBeforeLineListener // HistoryBeforeLineListener
void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) override; void historyBeforeLineChanged (const rtengine::procparams::ProcParams& params) override;

View File

@ -89,14 +89,19 @@ void FileBrowserEntry::init ()
ps = RTImage::createPixbufFromFile ("filetype-ps.png"); ps = RTImage::createPixbufFromFile ("filetype-ps.png");
} }
void FileBrowserEntry::refreshThumbnailImage () void FileBrowserEntry::refreshThumbnailImage(bool upgradeHint)
{ {
if (!thumbnail) { if (!thumbnail) {
return; return;
} }
thumbImageUpdater->add (this, &updatepriority, false, this); thumbImageUpdater->add (this, &updatepriority, upgradeHint, upgradeHint, this);
}
void FileBrowserEntry::refreshThumbnailImage ()
{
refreshThumbnailImage(false);
} }
void FileBrowserEntry::refreshQuickThumbnailImage () void FileBrowserEntry::refreshQuickThumbnailImage ()
@ -108,7 +113,7 @@ void FileBrowserEntry::refreshQuickThumbnailImage ()
// Only make a (slow) processed preview if the picture has been edited at all // Only make a (slow) processed preview if the picture has been edited at all
bool upgrade_to_processed = (!options.internalThumbIfUntouched || thumbnail->isPParamsValid()); bool upgrade_to_processed = (!options.internalThumbIfUntouched || thumbnail->isPParamsValid());
thumbImageUpdater->add(this, &updatepriority, upgrade_to_processed, this); thumbImageUpdater->add(this, &updatepriority, upgrade_to_processed, false, this);
} }
void FileBrowserEntry::calcThumbnailSize () void FileBrowserEntry::calcThumbnailSize ()
@ -202,13 +207,13 @@ FileThumbnailButtonSet* FileBrowserEntry::getThumbButtonSet ()
return (static_cast<FileThumbnailButtonSet*>(buttonSet)); return (static_cast<FileThumbnailButtonSet*>(buttonSet));
} }
void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt) void FileBrowserEntry::procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint)
{ {
if ( thumbnail->isQuick() ) { if ( thumbnail->isQuick() ) {
refreshQuickThumbnailImage (); refreshQuickThumbnailImage ();
} else { } else {
refreshThumbnailImage (); refreshThumbnailImage(upgradeHint);
} }
} }

View File

@ -68,6 +68,7 @@ class FileBrowserEntry final : public ThumbBrowserEntryBase,
void updateCursor (int x, int y); void updateCursor (int x, int y);
void drawStraightenGuide (Cairo::RefPtr<Cairo::Context> c); void drawStraightenGuide (Cairo::RefPtr<Cairo::Context> c);
void customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c) override; void customBackBufferUpdate (Cairo::RefPtr<Cairo::Context> c) override;
void refreshThumbnailImage(bool upgradeHint);
public: public:
@ -98,7 +99,7 @@ public:
void getIconSize (int& w, int& h) const override; void getIconSize (int& w, int& h) const override;
// thumbnaillistener interface // thumbnaillistener interface
void procParamsChanged (Thumbnail* thm, int whoChangedIt) override; void procParamsChanged (Thumbnail* thm, int whoChangedIt, bool upgradeHint) override;
// thumbimageupdatelistener interface // thumbimageupdatelistener interface
void updateImage(rtengine::IImage8* img, double scale, const rtengine::procparams::CropParams& cropParams) override; void updateImage(rtengine::IImage8* img, double scale, const rtengine::procparams::CropParams& cropParams) override;
void _updateImage(rtengine::IImage8* img, double scale, const rtengine::procparams::CropParams& cropParams); // inside gtk thread void _updateImage(rtengine::IImage8* img, double scale, const rtengine::procparams::CropParams& cropParams); // inside gtk thread

View File

@ -45,12 +45,13 @@ public:
struct Job { struct Job {
Job(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, Job(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade,
ThumbImageUpdateListener* listener): bool forceUpgrade, ThumbImageUpdateListener* listener):
tbe_(tbe), tbe_(tbe),
/*pparams_(pparams), /*pparams_(pparams),
height_(height), */ height_(height), */
priority_(priority), priority_(priority),
upgrade_(upgrade), upgrade_(upgrade),
force_upgrade_(forceUpgrade),
listener_(listener) listener_(listener)
{} {}
@ -58,6 +59,7 @@ public:
tbe_(nullptr), tbe_(nullptr),
priority_(nullptr), priority_(nullptr),
upgrade_(false), upgrade_(false),
force_upgrade_(false),
listener_(nullptr) listener_(nullptr)
{} {}
@ -66,6 +68,7 @@ public:
int height_;*/ int height_;*/
bool* priority_; bool* priority_;
bool upgrade_; bool upgrade_;
bool force_upgrade_;
ThumbImageUpdateListener* listener_; ThumbImageUpdateListener* listener_;
}; };
@ -153,8 +156,8 @@ public:
Thumbnail* thm = j.tbe_->thumbnail; Thumbnail* thm = j.tbe_->thumbnail;
if ( j.upgrade_ ) { if ( j.upgrade_ ) {
if ( thm->isQuick() ) { if ( thm->isQuick() || j.force_upgrade_ ) {
img = thm->upgradeThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); img = thm->upgradeThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale, j.force_upgrade_);
} }
} else { } else {
img = thm->processThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale); img = thm->processThumbImage(thm->getProcParams(), j.tbe_->getPreviewHeight(), scale);
@ -191,7 +194,7 @@ ThumbImageUpdater::~ThumbImageUpdater() {
delete impl_; delete impl_;
} }
void ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, ThumbImageUpdateListener* l) void ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, bool forceUpgrade, ThumbImageUpdateListener* l)
{ {
// nobody listening? // nobody listening?
if ( l == nullptr ) { if ( l == nullptr ) {
@ -206,7 +209,8 @@ void ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upg
for ( ; i != impl_->jobs_.end(); ++i ) { for ( ; i != impl_->jobs_.end(); ++i ) {
if ( i->tbe_ == tbe && if ( i->tbe_ == tbe &&
i->listener_ == l && i->listener_ == l &&
i->upgrade_ == upgrade ) { i->upgrade_ == upgrade &&
i->force_upgrade_ == forceUpgrade) {
DEBUG("updating job %s", tbe->shortname.c_str()); DEBUG("updating job %s", tbe->shortname.c_str());
// we have one, update queue entry, will be picked up by thread when processed // we have one, update queue entry, will be picked up by thread when processed
/*i->pparams_ = params; /*i->pparams_ = params;
@ -218,7 +222,7 @@ void ThumbImageUpdater::add(ThumbBrowserEntryBase* tbe, bool* priority, bool upg
// create a new job and append to queue // create a new job and append to queue
DEBUG("queueing job %s", tbe->shortname.c_str()); DEBUG("queueing job %s", tbe->shortname.c_str());
impl_->jobs_.push_back(Impl::Job(tbe, priority, upgrade, l)); impl_->jobs_.push_back(Impl::Job(tbe, priority, upgrade, forceUpgrade, l));
DEBUG("adding run request %s", tbe->shortname.c_str()); DEBUG("adding run request %s", tbe->shortname.c_str());
impl_->threadPool_->push(sigc::mem_fun(*impl_, &ThumbImageUpdater::Impl::processNextJob)); impl_->threadPool_->push(sigc::mem_fun(*impl_, &ThumbImageUpdater::Impl::processNextJob));

View File

@ -78,7 +78,7 @@ public:
* @param priority if \c true then run as soon as possible * @param priority if \c true then run as soon as possible
* @param l listener waiting on update * @param l listener waiting on update
*/ */
void add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, ThumbImageUpdateListener* l); void add(ThumbBrowserEntryBase* tbe, bool* priority, bool upgrade, bool forceUpgrade, ThumbImageUpdateListener* l);
/** /**
* @brief Remove jobs associated with listener \c l. * @brief Remove jobs associated with listener \c l.

View File

@ -240,7 +240,7 @@ void Thumbnail::_generateThumbnailImage ()
if ( tpp == nullptr ) { if ( tpp == nullptr ) {
quick = false; quick = false;
tpp = rtengine::Thumbnail::loadFromRaw (fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE); tpp = rtengine::Thumbnail::loadFromRaw (fname, sensorType, tw, th, 1, pparams->wb.equal, pparams->wb.observer, TRUE, &(pparams->raw));
} }
cfs.sensortype = sensorType; cfs.sensortype = sensorType;
@ -387,7 +387,7 @@ rtengine::procparams::ProcParams* Thumbnail::createProcParamsForUpdate(bool retu
void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt) void Thumbnail::notifylisterners_procParamsChanged(int whoChangedIt)
{ {
for (size_t i = 0; i < listeners.size(); i++) { for (size_t i = 0; i < listeners.size(); i++) {
listeners[i]->procParamsChanged (this, whoChangedIt); listeners[i]->procParamsChanged (this, whoChangedIt, false);
} }
} }
@ -490,7 +490,7 @@ void Thumbnail::clearProcParams (int whoClearedIt)
} // end of mutex lock } // end of mutex lock
for (size_t i = 0; i < listeners.size(); i++) { for (size_t i = 0; i < listeners.size(); i++) {
listeners[i]->procParamsChanged (this, whoClearedIt); listeners[i]->procParamsChanged (this, whoClearedIt, false);
} }
} }
@ -502,8 +502,18 @@ bool Thumbnail::hasProcParams () const
void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoChangedIt, bool updateCacheNow, bool resetToDefault) void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoChangedIt, bool updateCacheNow, bool resetToDefault)
{ {
const bool blackLevelChanged =
pparams->raw.bayersensor.black0 != pp.raw.bayersensor.black0
|| pparams->raw.bayersensor.black1 != pp.raw.bayersensor.black1
|| pparams->raw.bayersensor.black2 != pp.raw.bayersensor.black2
|| pparams->raw.bayersensor.black3 != pp.raw.bayersensor.black3
|| pparams->raw.xtranssensor.blackred != pp.raw.xtranssensor.blackred
|| pparams->raw.xtranssensor.blackgreen != pp.raw.xtranssensor.blackgreen
|| pparams->raw.xtranssensor.blackblue != pp.raw.xtranssensor.blackblue;
const bool needsReprocessing = const bool needsReprocessing =
resetToDefault resetToDefault
|| blackLevelChanged
|| pparams->raw.expos != pp.raw.expos
|| pparams->toneCurve != pp.toneCurve || pparams->toneCurve != pp.toneCurve
|| pparams->locallab != pp.locallab || pparams->locallab != pp.locallab
|| pparams->labCurve != pp.labCurve || pparams->labCurve != pp.labCurve
@ -538,6 +548,7 @@ void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoCh
|| pparams->filmNegative != pp.filmNegative || pparams->filmNegative != pp.filmNegative
|| whoChangedIt == FILEBROWSER || whoChangedIt == FILEBROWSER
|| whoChangedIt == BATCHEDITOR; || whoChangedIt == BATCHEDITOR;
const bool upgradeHint = blackLevelChanged;
{ {
MyMutex::MyLock lock(mutex); MyMutex::MyLock lock(mutex);
@ -573,7 +584,7 @@ void Thumbnail::setProcParams (const ProcParams& pp, ParamsEdited* pe, int whoCh
if (needsReprocessing) { if (needsReprocessing) {
for (size_t i = 0; i < listeners.size(); i++) { for (size_t i = 0; i < listeners.size(); i++) {
listeners[i]->procParamsChanged (this, whoChangedIt); listeners[i]->procParamsChanged (this, whoChangedIt, upgradeHint);
} }
} }
} }
@ -747,12 +758,12 @@ rtengine::IImage8* Thumbnail::processThumbImage (const rtengine::procparams::Pro
return image; return image;
} }
rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale) rtengine::IImage8* Thumbnail::upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale, bool forceUpgrade)
{ {
MyMutex::MyLock lock(mutex); MyMutex::MyLock lock(mutex);
if ( cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL ) { if ( cfs.thumbImgType != CacheImageData::QUICK_THUMBNAIL && !forceUpgrade ) {
return nullptr; return nullptr;
} }

View File

@ -124,7 +124,7 @@ public:
// unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w // unsigned char* getThumbnailImage (int &w, int &h, int fixwh=1); // fixwh = 0: fix w and calculate h, =1: fix h and calculate w
rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); rtengine::IImage8* processThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale);
rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale); rtengine::IImage8* upgradeThumbImage (const rtengine::procparams::ProcParams& pparams, int h, double& scale, bool forceUpgrade);
void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = nullptr); void getThumbnailSize (int &w, int &h, const rtengine::procparams::ProcParams *pparams = nullptr);
void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h); void getFinalSize (const rtengine::procparams::ProcParams& pparams, int& w, int& h);
void getOriginalSize (int& w, int& h) const; void getOriginalSize (int& w, int& h) const;

View File

@ -24,5 +24,5 @@ class ThumbnailListener
{ {
public: public:
virtual ~ThumbnailListener() = default; virtual ~ThumbnailListener() = default;
virtual void procParamsChanged(Thumbnail* thm, int whoChangedIt) = 0; virtual void procParamsChanged(Thumbnail* thm, int whoChangedIt, bool upgradeHint) = 0;
}; };