Automatic high detail preview rendering when entering 100% views

See issue 838
This commit is contained in:
Oliver Duis 2011-07-14 13:57:32 +02:00
parent 4b4bf4b79e
commit 091cc56a01
11 changed files with 85 additions and 47 deletions

View File

@ -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) {

View File

@ -30,7 +30,7 @@ extern Settings* settings;
ImProcCoordinator::ImProcCoordinator ()
: awbComputed(false), ipf(&params, 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
}

View File

@ -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 ();

View File

@ -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)

View File

@ -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).

View File

@ -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) {

View File

@ -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;

View File

@ -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
}
}

View File

@ -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)

View File

@ -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 ()

View File

@ -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;