Fix coarse initial display (#4224)

This commit is contained in:
Flössie 2018-01-25 18:57:02 +01:00
parent c0ceeb2c95
commit 78045374ad
2 changed files with 114 additions and 126 deletions

View File

@ -29,19 +29,35 @@
using namespace rtengine; using namespace rtengine;
CropHandler::CropHandler () CropHandler::CropHandler() :
: zoom(100), ww(0), wh(0), cax(-1), cay(-1), zoom(100),
cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), ww(0),
cropimg(nullptr), cropimgtrue(nullptr), cropimg_width(0), cropimg_height(0), wh(0),
cix(0), ciy(0), ciw(0), cih(0), cis(1), cax(-1),
initial(false), isLowUpdatePriority(false), ipc(nullptr), crop(nullptr), cay(-1),
displayHandler(nullptr) cx(0),
cy(0),
cw(0),
ch(0),
cropX(0),
cropY(0),
cropW(0),
cropH(0),
enabled(false),
cropimg_width(0),
cropimg_height(0),
cix(0),
ciy(0),
ciw(0),
cih(0),
cis(1),
isLowUpdatePriority(false),
ipc(nullptr),
crop(nullptr),
displayHandler(nullptr),
redraw_needed(false),
initial(false)
{ {
idle_helper = new IdleHelper;
idle_helper->destroyed = false;
idle_helper->pending = 0;
idle_helper->cropHandler = this;
} }
CropHandler::~CropHandler () CropHandler::~CropHandler ()
@ -59,16 +75,6 @@ CropHandler::~CropHandler ()
delete crop; // will do the same than destroy, plus delete the object delete crop; // will do the same than destroy, plus delete the object
crop = nullptr; crop = nullptr;
} }
cimg.lock ();
if (idle_helper->pending) {
idle_helper->destroyed = true;
} else {
delete idle_helper;
}
cimg.unlock ();
} }
void CropHandler::setEditSubscriber (EditSubscriber* newSubscriber) void CropHandler::setEditSubscriber (EditSubscriber* newSubscriber)
@ -308,110 +314,94 @@ void CropHandler::setDetailedCrop (IImage8* im, IImage8* imtrue, rtengine::procp
cropPixbuf.clear (); cropPixbuf.clear ();
if (cropimg) { if (!cropimg.empty()) {
delete [] cropimg; cropimg.clear();
} }
cropimg = nullptr; if (!cropimgtrue.empty()) {
cropimgtrue.clear();
if (cropimgtrue) {
delete [] cropimgtrue;
} }
cropimgtrue = nullptr;
if (ax == cropX && ay == cropY && aw == cropW && ah == cropH && askip == (zoom >= 1000 ? 1 : zoom / 10)) { if (ax == cropX && ay == cropY && aw == cropW && ah == cropH && askip == (zoom >= 1000 ? 1 : zoom / 10)) {
cropimg_width = im->getWidth (); cropimg_width = im->getWidth ();
cropimg_height = im->getHeight (); cropimg_height = im->getHeight ();
cropimg = new unsigned char [3 * cropimg_width * cropimg_height]; const std::size_t cropimg_size = 3 * cropimg_width * cropimg_height;
cropimgtrue = new unsigned char [3 * cropimg_width * cropimg_height]; cropimg.assign(im->getData(), im->getData() + cropimg_size);
memcpy (cropimg, im->getData(), 3 * cropimg_width * cropimg_height); cropimgtrue.assign(imtrue->getData(), imtrue->getData() + cropimg_size);
memcpy (cropimgtrue, imtrue->getData(), 3 * cropimg_width * cropimg_height);
cix = ax; cix = ax;
ciy = ay; ciy = ay;
ciw = aw; ciw = aw;
cih = ah; cih = ah;
cis = askip; cis = askip;
idle_helper->pending++;
bool expected = false;
if (redraw_needed.compare_exchange_strong(expected, true)) {
const auto func = [](gpointer data) -> gboolean { const auto func = [](gpointer data) -> gboolean {
IdleHelper* const idle_helper = static_cast<IdleHelper*>(data); CropHandler* const self = static_cast<CropHandler*>(data);
if (idle_helper->destroyed) { self->cimg.lock ();
if (idle_helper->pending == 1) {
delete idle_helper;
} else {
idle_helper->pending--;
}
if (self->redraw_needed.exchange(false)) {
self->cropPixbuf.clear ();
if (!self->enabled) {
self->cropimg.clear();
self->cropimgtrue.clear();
self->cimg.unlock ();
return FALSE; return FALSE;
} }
CropHandler* ch = idle_helper->cropHandler; if (!self->cropimg.empty()) {
if (self->cix == self->cropX && self->ciy == self->cropY && self->ciw == self->cropW && self->cih == self->cropH && self->cis == (self->zoom >= 1000 ? 1 : self->zoom / 10)) {
ch->cimg.lock ();
ch->cropPixbuf.clear ();
if (!ch->enabled) {
delete [] ch->cropimg;
ch->cropimg = nullptr;
delete [] ch->cropimgtrue;
ch->cropimgtrue = nullptr;
ch->cimg.unlock ();
return FALSE;
}
if (ch->cropimg) {
if (ch->cix == ch->cropX && ch->ciy == ch->cropY && ch->ciw == ch->cropW && ch->cih == ch->cropH && ch->cis == (ch->zoom >= 1000 ? 1 : ch->zoom / 10)) {
// calculate final image size // calculate final image size
float czoom = ch->zoom >= 1000 ? float czoom = self->zoom >= 1000 ?
ch->zoom / 1000.f : self->zoom / 1000.f :
float((ch->zoom/10) * 10) / float(ch->zoom); float((self->zoom/10) * 10) / float(self->zoom);
int imw = ch->cropimg_width * czoom; int imw = self->cropimg_width * czoom;
int imh = ch->cropimg_height * czoom; int imh = self->cropimg_height * czoom;
if (imw > ch->ww) { if (imw > self->ww) {
imw = ch->ww; imw = self->ww;
} }
if (imh > ch->wh) { if (imh > self->wh) {
imh = ch->wh; imh = self->wh;
} }
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuf = Gdk::Pixbuf::create_from_data (ch->cropimg, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, ch->cropimg_height, 3 * ch->cropimg_width); Glib::RefPtr<Gdk::Pixbuf> tmpPixbuf = Gdk::Pixbuf::create_from_data (self->cropimg.data(), Gdk::COLORSPACE_RGB, false, 8, self->cropimg_width, self->cropimg_height, 3 * self->cropimg_width);
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); self->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES); tmpPixbuf->scale (self->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES);
tmpPixbuf.clear (); tmpPixbuf.clear ();
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuftrue = Gdk::Pixbuf::create_from_data (ch->cropimgtrue, Gdk::COLORSPACE_RGB, false, 8, ch->cropimg_width, ch->cropimg_height, 3 * ch->cropimg_width); Glib::RefPtr<Gdk::Pixbuf> tmpPixbuftrue = Gdk::Pixbuf::create_from_data (self->cropimgtrue.data(), Gdk::COLORSPACE_RGB, false, 8, self->cropimg_width, self->cropimg_height, 3 * self->cropimg_width);
ch->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh); self->cropPixbuftrue = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
tmpPixbuftrue->scale (ch->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES); tmpPixbuftrue->scale (self->cropPixbuftrue, 0, 0, imw, imh, 0, 0, czoom, czoom, Gdk::INTERP_TILES);
tmpPixbuftrue.clear (); tmpPixbuftrue.clear ();
} }
delete [] ch->cropimg; self->cropimg.clear();
ch->cropimg = nullptr; self->cropimgtrue.clear();
delete [] ch->cropimgtrue;
ch->cropimgtrue = nullptr;
} }
ch->cimg.unlock (); self->cimg.unlock ();
if (ch->displayHandler) { if (self->displayHandler) {
ch->displayHandler->cropImageUpdated (); self->displayHandler->cropImageUpdated ();
if (ch->initial) { if (self->initial.exchange(false)) {
ch->displayHandler->initialImageArrived (); self->displayHandler->initialImageArrived ();
ch->initial = false;
} }
} }
} else {
idle_helper->pending--; self->cimg.unlock();
}
return FALSE; return FALSE;
}; };
idle_register.add(func, idle_helper, G_PRIORITY_HIGH_IDLE); idle_register.add(func, this/*, G_PRIORITY_HIGH_IDLE*/);
}
} }
cimg.unlock (); cimg.unlock ();
@ -468,13 +458,11 @@ void CropHandler::setEnabled (bool e)
crop->setListener (nullptr); crop->setListener (nullptr);
} }
cimg.lock (); cimg.lock();
delete [] cropimg; cropimg.clear();
cropimg = nullptr; cropimgtrue.clear();
delete [] cropimgtrue; cropPixbuf.clear();
cropimgtrue = nullptr; cimg.unlock();
cropPixbuf.clear ();
cimg.unlock ();
} else { } else {
update (); update ();
} }

View File

@ -19,11 +19,16 @@
#ifndef __CROPHANDLER__ #ifndef __CROPHANDLER__
#define __CROPHANDLER__ #define __CROPHANDLER__
#include <atomic>
#include <vector>
#include <gtkmm.h>
#include "../rtengine/rtengine.h" #include "../rtengine/rtengine.h"
#include "threadutils.h"
#include "edit.h" #include "edit.h"
#include "lockablecolorpicker.h" #include "lockablecolorpicker.h"
#include <gtkmm.h> #include "threadutils.h"
class CropDisplayHandler class CropDisplayHandler
{ {
@ -98,12 +103,6 @@ public:
MyMutex cimg; MyMutex cimg;
private: private:
struct IdleHelper {
CropHandler* cropHandler;
bool destroyed;
int pending;
};
void compDim (); void compDim ();
int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...) int zoom; // scale factor (e.g. 5 if 1:5 scale) ; if 1:1 scale and bigger, factor is multiplied by 1000 (i.e. 1000 for 1:1 scale, 2000 for 2:1, etc...)
@ -112,17 +111,18 @@ private:
int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size int cx, cy, cw, ch; // position and size of the requested crop ; position expressed in image coordinates, so cx and cy might be negative and cw and ch higher than the image's 1:1 size
int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds int cropX, cropY, cropW, cropH; // cropPixbuf's displayed area (position and size), i.e. coordinates in 1:1 scale, i.e. cx, cy, cw & ch trimmed to the image's bounds
bool enabled; bool enabled;
unsigned char* cropimg; std::vector<unsigned char> cropimg;
unsigned char* cropimgtrue; std::vector<unsigned char> cropimgtrue;
int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis; int cropimg_width, cropimg_height, cix, ciy, ciw, cih, cis;
bool initial;
bool isLowUpdatePriority; bool isLowUpdatePriority;
rtengine::StagedImageProcessor* ipc; rtengine::StagedImageProcessor* ipc;
rtengine::DetailedCrop* crop; rtengine::DetailedCrop* crop;
CropDisplayHandler* displayHandler; CropDisplayHandler* displayHandler;
IdleHelper* idle_helper;
std::atomic<bool> redraw_needed;
std::atomic<bool> initial;
IdleRegister idle_register; IdleRegister idle_register;
}; };