diff --git a/rtengine/array2D.h b/rtengine/array2D.h index 997a637ee..eae9caf03 100644 --- a/rtengine/array2D.h +++ b/rtengine/array2D.h @@ -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 & operator[](size_t index) { diff --git a/rtengine/improccoordinator.cc b/rtengine/improccoordinator.cc index a235c67cc..88d0a364f 100644 --- a/rtengine/improccoordinator.cc +++ b/rtengine/improccoordinator.cc @@ -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; iget_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 } diff --git a/rtengine/improccoordinator.h b/rtengine/improccoordinator.h index 660107778..f37785080 100644 --- a/rtengine/improccoordinator.h +++ b/rtengine/improccoordinator.h @@ -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 (); diff --git a/rtengine/refreshmap.h b/rtengine/refreshmap.h index ed848b35b..9d1c896b0 100644 --- a/rtengine/refreshmap.h +++ b/rtengine/refreshmap.h @@ -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) diff --git a/rtengine/rtengine.h b/rtengine/rtengine.h index 233c9ec7e..ef89aa64b 100644 --- a/rtengine/rtengine.h +++ b/rtengine/rtengine.h @@ -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). diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index f1c28be21..8a5bb97e3 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -21,6 +21,7 @@ #include #include +#include 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) { diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 40c9273e1..5ec0f6bbe 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -790,6 +790,7 @@ void CropWindow::expose (Cairo::RefPtr 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; diff --git a/rtgui/editorpanel.cc b/rtgui/editorpanel.cc index 25a2ecb9d..e09e59603 100644 --- a/rtgui/editorpanel.cc +++ b/rtgui/editorpanel.cc @@ -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 } } diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 839fcf919..786e3f5d0 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -23,6 +23,7 @@ #include #include #include +#include ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) { @@ -47,6 +48,16 @@ ImageArea::ImageArea (ImageAreaPanel* p) : parent(p) { ipc = NULL; } +ImageArea::~ImageArea () { + + for (std::list::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::iterator i=cropWins.begin(); i!=cropWins.end(); i++) - delete *i; - cropWins.clear (); - - if (mainCropWindow) - delete mainCropWindow; -} - void ImageArea::styleChanged (const Glib::RefPtr& 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) diff --git a/rtgui/rawprocess.cc b/rtgui/rawprocess.cc index 827b18ea4..c1b471a49 100644 --- a/rtgui/rawprocess.cc +++ b/rtgui/rawprocess.cc @@ -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 () diff --git a/rtgui/toolpanelcoord.cc b/rtgui/toolpanelcoord.cc index 3c6c06df7..a0d9b90b9 100644 --- a/rtgui/toolpanelcoord.cc +++ b/rtgui/toolpanelcoord.cc @@ -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; iread (params); - ipc->paramsUpdateReady (); + ipc->paramsUpdateReady (); // starts the IPC processinp hasChanged = event != rtengine::EvProfileChangeNotification;