Automatic high detail preview rendering when entering 100% views
See issue 838
This commit is contained in:
parent
4b4bf4b79e
commit
091cc56a01
@ -99,7 +99,7 @@ public:
|
||||
// very useful as a member object
|
||||
array2D() :
|
||||
x(0), y(0), owner(0), data(NULL), ptr(NULL), lock(0) {
|
||||
printf("got empty array2D init\n");
|
||||
//printf("got empty array2D init\n");
|
||||
}
|
||||
|
||||
// creator type1
|
||||
@ -252,11 +252,11 @@ private:
|
||||
public:
|
||||
multi_array2D(int x, int y, int flags = 0) {
|
||||
for (int i = 0; i < num; i++)
|
||||
list[i](x, y, flags | ARRAY2D_VERBOSE);
|
||||
list[i](x, y, flags);
|
||||
}
|
||||
|
||||
~multi_array2D() {
|
||||
printf("trying to delete the list of array2D objects\n");
|
||||
//printf("trying to delete the list of array2D objects\n");
|
||||
}
|
||||
|
||||
array2D<T> & operator[](size_t index) {
|
||||
|
@ -30,7 +30,7 @@ extern Settings* settings;
|
||||
|
||||
ImProcCoordinator::ImProcCoordinator ()
|
||||
: awbComputed(false), ipf(¶ms, true), scale(10), allocated(false),
|
||||
pW(-1), pH(-1), plistener(NULL),fineDetailsProcessed(false),
|
||||
pW(-1), pH(-1), plistener(NULL), lastHighDetail(false),
|
||||
imageListener(NULL), aeListener(NULL), hListener(NULL), resultValid(false),
|
||||
changeSinceLast(0), updaterRunning(false), destroying(false), workimg(NULL) {
|
||||
|
||||
@ -96,17 +96,21 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
||||
ipf.setScale (scale);
|
||||
|
||||
// Check if any detail crops need high detail. If not, take a fast path short cut
|
||||
bool highDetailNeeded=false;
|
||||
bool highDetailNeeded = (todo & M_HIGHQUAL);
|
||||
if (!highDetailNeeded) {
|
||||
for (int i=0; i<crops.size(); i++)
|
||||
if (crops[i]->get_skip() == 1 ){
|
||||
if (crops[i]->get_skip() == 1 ) { // skip=1 -> full resolution
|
||||
highDetailNeeded=true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
RAWParams rp = params.raw;
|
||||
if( !highDetailNeeded ){
|
||||
// if below 100% magnification, take a fast path
|
||||
rp.dmethod = RAWParams::methodstring[RAWParams::fast];
|
||||
rp.ca_autocorrect = false;
|
||||
//rp.hotdeadpix_filt = false;
|
||||
rp.hotdeadpix_filt = false;
|
||||
rp.ccSteps = 0;
|
||||
}
|
||||
|
||||
@ -116,10 +120,13 @@ void ImProcCoordinator::updatePreviewImage (int todo, Crop* cropCall) {
|
||||
imgsrc->getRAWHistogram( histRedRaw, histGreenRaw, histBlueRaw );
|
||||
}
|
||||
|
||||
if( todo & M_RAW){
|
||||
fineDetailsProcessed = highDetailNeeded;
|
||||
// If high detail (=100%) is newly selected, do a demosaic update, since the last was just with FAST
|
||||
if ((todo & M_RAW) || (!lastHighDetail && highDetailNeeded)) {
|
||||
if (settings->verbose) printf("Demosaic %s\n",rp.dmethod.c_str());
|
||||
imgsrc->demosaic( rp, params.hlrecovery );
|
||||
}
|
||||
lastHighDetail=highDetailNeeded;
|
||||
|
||||
|
||||
if (todo & M_INIT) {
|
||||
Glib::Mutex::Lock lock(minit); // Also used in crop window
|
||||
@ -574,7 +581,7 @@ void ImProcCoordinator::startProcessing () {
|
||||
updaterRunning = true;
|
||||
updaterThreadStart.unlock ();
|
||||
|
||||
batchThread->yield(); //the running batch should wait other threads to avoid conflict
|
||||
//batchThread->yield(); //the running batch should wait other threads to avoid conflict
|
||||
|
||||
thread = Glib::Thread::create(sigc::mem_fun(*this, &ImProcCoordinator::process), 0, true, true, Glib::THREAD_PRIORITY_NORMAL);
|
||||
|
||||
@ -584,6 +591,14 @@ void ImProcCoordinator::startProcessing () {
|
||||
}
|
||||
}
|
||||
|
||||
void ImProcCoordinator::startProcessing(int changeCode) {
|
||||
paramsUpdateMutex.lock();
|
||||
changeSinceLast |= changeCode;
|
||||
paramsUpdateMutex.unlock();
|
||||
|
||||
startProcessing ();
|
||||
}
|
||||
|
||||
void ImProcCoordinator::process () {
|
||||
|
||||
if (plistener)
|
||||
@ -592,11 +607,12 @@ void ImProcCoordinator::process () {
|
||||
paramsUpdateMutex.lock ();
|
||||
while (changeSinceLast) {
|
||||
params = nextParams;
|
||||
int ch = changeSinceLast;
|
||||
int change = changeSinceLast;
|
||||
changeSinceLast = 0;
|
||||
paramsUpdateMutex.unlock ();
|
||||
if (ch&32767)
|
||||
updatePreviewImage (ch);
|
||||
|
||||
// M_VOID means no update, and is a bit higher that the rest
|
||||
if (change & (M_VOID-1)) updatePreviewImage (change);
|
||||
paramsUpdateMutex.lock ();
|
||||
}
|
||||
paramsUpdateMutex.unlock ();
|
||||
@ -616,7 +632,7 @@ ProcParams* ImProcCoordinator::getParamsForUpdate (ProcEvent change) {
|
||||
void ImProcCoordinator::paramsUpdateReady () {
|
||||
|
||||
paramsUpdateMutex.unlock ();
|
||||
startProcessing ();
|
||||
startProcessing (); // Executes what has been requested with getParamsForUpdate
|
||||
}
|
||||
|
||||
|
||||
|
@ -60,7 +60,7 @@ class ImProcCoordinator : public StagedImageProcessor {
|
||||
ImProcFunctions ipf;
|
||||
|
||||
int scale;
|
||||
bool fineDetailsProcessed;
|
||||
bool lastHighDetail; // was the last update running in high detail?
|
||||
bool allocated;
|
||||
|
||||
void freeAll ();
|
||||
@ -125,8 +125,9 @@ class ImProcCoordinator : public StagedImageProcessor {
|
||||
|
||||
void getParams (procparams::ProcParams* dst) { *dst = params; }
|
||||
|
||||
void startProcessing(int changeCode);
|
||||
ProcParams* getParamsForUpdate (ProcEvent change);
|
||||
void paramsUpdateReady ();
|
||||
void paramsUpdateReady (); // must be called after getParamsForUpdate, triggers full update
|
||||
void stopProcessing ();
|
||||
|
||||
|
||||
|
@ -25,6 +25,8 @@
|
||||
#define M_VOID (1<<15)
|
||||
// Use M_MINUPDATE if you you wish to update the preview without modifying the image (think about it like a "refreshPreview")
|
||||
#define M_MINUPDATE (1<<14)
|
||||
// Force high quality
|
||||
#define M_HIGHQUAL (1<<13)
|
||||
|
||||
// Elementary functions that can be done to
|
||||
// the preview image when an event occurs
|
||||
@ -41,8 +43,8 @@
|
||||
|
||||
// Bitfield of functions to do to the preview image when an event occurs
|
||||
// Use those or create new ones for your new events
|
||||
#define FIRST 65535
|
||||
#define ALL 65535
|
||||
#define FIRST (M_PREPROC|M_RAW|M_INIT|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
|
||||
#define ALL (M_PREPROC|M_RAW|M_INIT|M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR) // without HIGHQUAL
|
||||
#define TRANSFORM (M_TRANSFORM|M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define RETINEX (M_BLURMAP|M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
#define AUTOEXP (M_AUTOEXP|M_RGBCURVE|M_LUMACURVE|M_LUMINANCE|M_COLOR)
|
||||
|
@ -256,6 +256,8 @@ namespace rtengine {
|
||||
* The image update starts immediately in the background. If it is ready, the result is passed to a PreviewImageListener
|
||||
* and to a DetailedCropListener (if enabled). */
|
||||
virtual void paramsUpdateReady () =0;
|
||||
// Starts a minimal update
|
||||
virtual void startProcessing(int changeCode) =0;
|
||||
/** Stops image processing. When it returns, the image processing is already stopped. */
|
||||
virtual void stopProcessing () =0;
|
||||
/** Sets the scale of the preview image. The larger the number is, the faster the image updates are (typical values are 4-5).
|
||||
|
@ -21,6 +21,7 @@
|
||||
|
||||
#include <cstring>
|
||||
#include <guiutils.h>
|
||||
#include <refreshmap.h>
|
||||
|
||||
using namespace rtengine;
|
||||
|
||||
@ -97,6 +98,9 @@ void CropHandler::setZoom (int z, int centerx, int centery) {
|
||||
if (centery>=0)
|
||||
y = centery;
|
||||
|
||||
// maybe demosaic etc. if we cross the border to >100%
|
||||
bool needsFullRefresh = (z>=1000 && zoom<1000);
|
||||
|
||||
zoom = z;
|
||||
if (zoom>=1000) {
|
||||
cw = ww * 1000 / zoom;
|
||||
@ -110,9 +114,13 @@ void CropHandler::setZoom (int z, int centerx, int centery) {
|
||||
cy = y - ch / 2;
|
||||
|
||||
compDim ();
|
||||
if (enabled)
|
||||
if (enabled) {
|
||||
if (needsFullRefresh)
|
||||
ipc->startProcessing(M_HIGHQUAL);
|
||||
else
|
||||
update ();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CropHandler::setWSize (int w, int h) {
|
||||
|
@ -790,6 +790,7 @@ void CropWindow::expose (Cairo::RefPtr<Cairo::Context> cr) {
|
||||
// printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3));
|
||||
}
|
||||
|
||||
// zoom* is called from the zoomPanel
|
||||
void CropWindow::zoomIn () {
|
||||
|
||||
changeZoom (cropZoom+1);
|
||||
@ -867,10 +868,12 @@ void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) {
|
||||
zoom = 0;
|
||||
else if (zoom>MAXZOOMSTEPS)
|
||||
zoom = MAXZOOMSTEPS;
|
||||
if (cropZoom == zoom)
|
||||
|
||||
if (cropZoom == zoom) {
|
||||
// We are already at the start/end of the zoom range, so we do nothing
|
||||
return;
|
||||
else
|
||||
}
|
||||
|
||||
cropZoom = zoom;
|
||||
|
||||
cropLabel = zoomSteps[cropZoom].label;
|
||||
|
@ -1206,7 +1206,7 @@ void EditorPanel::historyBeforeLineChanged (const rtengine::procparams::ProcPara
|
||||
if (beforeIpc) {
|
||||
ProcParams* pparams = beforeIpc->getParamsForUpdate (rtengine::EvProfileChanged);
|
||||
*pparams = params;
|
||||
beforeIpc->paramsUpdateReady ();
|
||||
beforeIpc->paramsUpdateReady (); // starts the IPC processinp
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include <multilangmgr.h>
|
||||
#include <iomanip>
|
||||
#include <cropwindow.h>
|
||||
#include <refreshmap.h>
|
||||
|
||||
ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) {
|
||||
|
||||
@ -47,6 +48,16 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) {
|
||||
ipc = NULL;
|
||||
}
|
||||
|
||||
ImageArea::~ImageArea () {
|
||||
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
delete *i;
|
||||
cropWins.clear ();
|
||||
|
||||
if (mainCropWindow)
|
||||
delete mainCropWindow;
|
||||
}
|
||||
|
||||
void ImageArea::on_realize()
|
||||
{
|
||||
Gtk::DrawingArea::on_realize();
|
||||
@ -100,17 +111,6 @@ void ImageArea::setPreviewHandler (PreviewHandler* ph) {
|
||||
previewHandler = ph;
|
||||
}
|
||||
|
||||
|
||||
ImageArea::~ImageArea () {
|
||||
|
||||
for (std::list<CropWindow*>::iterator i=cropWins.begin(); i!=cropWins.end(); i++)
|
||||
delete *i;
|
||||
cropWins.clear ();
|
||||
|
||||
if (mainCropWindow)
|
||||
delete mainCropWindow;
|
||||
}
|
||||
|
||||
void ImageArea::styleChanged (const Glib::RefPtr<Gtk::Style>& style) {
|
||||
|
||||
// TODO: notify all crop windows that the style has been changed
|
||||
@ -151,6 +151,15 @@ CropWindow* ImageArea::getCropWindow (int x, int y) {
|
||||
return cw;
|
||||
}
|
||||
|
||||
|
||||
void ImageArea::redraw () {
|
||||
// dirty prevents multiple updates queued up
|
||||
if (!dirty) {
|
||||
dirty = true;
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImageArea::on_expose_event(GdkEventExpose* event) {
|
||||
dirty = false;
|
||||
|
||||
@ -252,6 +261,7 @@ void ImageArea::addCropWindow () {
|
||||
cw->setPointerMotionListener (pmlistener);
|
||||
cropWins.push_front (cw);
|
||||
|
||||
// Position the new crop window in a checkerboard, or used the last position
|
||||
if (lastClosedX<0) {
|
||||
int K = 2;
|
||||
int hBorder = get_width()/K/8;
|
||||
@ -273,7 +283,10 @@ void ImageArea::addCropWindow () {
|
||||
cw->getCropSize(wc,hc);
|
||||
cw->setCropPosition(x0+w/2-wc/2,y0+h/2-hc/2);
|
||||
mainCropWindow->setObservedCropWin (cropWins.front());
|
||||
queue_draw ();
|
||||
|
||||
ipc->startProcessing(M_HIGHQUAL);
|
||||
|
||||
// queue_draw ();
|
||||
}
|
||||
|
||||
|
||||
@ -314,14 +327,6 @@ void ImageArea::spotWBSelected (int x, int y) {
|
||||
listener->spotWBselected (x, y);
|
||||
}
|
||||
|
||||
void ImageArea::redraw () {
|
||||
|
||||
if (!dirty) {
|
||||
dirty = true;
|
||||
queue_draw ();
|
||||
}
|
||||
}
|
||||
|
||||
void ImageArea::getScrollImageSize (int& w, int& h) {
|
||||
|
||||
if (mainCropWindow && ipc) {
|
||||
@ -381,6 +386,7 @@ double ImageArea::getZoom () {
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
// Called by imageAreaPanel before/after views
|
||||
void ImageArea::setZoom (double zoom) {
|
||||
|
||||
if (mainCropWindow)
|
||||
|
@ -161,12 +161,12 @@ void RawProcess::methodChanged ()
|
||||
}else{
|
||||
dcbOptions->hide();
|
||||
}
|
||||
Glib::ustring s="";
|
||||
Glib::ustring methodName="";
|
||||
if( curSelection>=0 && curSelection < procparams::RAWParams::numMethods)
|
||||
s = procparams::RAWParams::methodstring[curSelection];
|
||||
methodName = procparams::RAWParams::methodstring[curSelection];
|
||||
|
||||
if (listener)
|
||||
listener->panelChanged (EvDemosaicMethod, s);
|
||||
listener->panelChanged (EvDemosaicMethod, methodName);
|
||||
}
|
||||
|
||||
void RawProcess::dcbEnhanceChanged ()
|
||||
|
@ -271,7 +271,7 @@ void ToolPanelCoordinator::panelChanged (rtengine::ProcEvent event, const Glib::
|
||||
resize->write (params);
|
||||
}
|
||||
|
||||
ipc->paramsUpdateReady ();
|
||||
ipc->paramsUpdateReady (); // starts the IPC processinp
|
||||
|
||||
hasChanged = true;
|
||||
|
||||
@ -301,7 +301,7 @@ void ToolPanelCoordinator::profileChange (const ProcParams *nparams, rtengine::
|
||||
for (unsigned int i=0; i<toolPanels.size(); i++)
|
||||
toolPanels[i]->read (params);
|
||||
|
||||
ipc->paramsUpdateReady ();
|
||||
ipc->paramsUpdateReady (); // starts the IPC processinp
|
||||
|
||||
hasChanged = event != rtengine::EvProfileChangeNotification;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user