Sychronization of crop image processing; see issue #549
This commit is contained in:
@@ -25,11 +25,6 @@ CropHandler::CropHandler ()
|
|||||||
: zoom(10), cx(0), cy(0), cw(0), ch(0),
|
: zoom(10), cx(0), cy(0), cw(0), ch(0),
|
||||||
cropX(0), cropY(0), cropW(0), cropH(0), enabled(false),
|
cropX(0), cropY(0), cropW(0), cropH(0), enabled(false),
|
||||||
cropimg(NULL), ipc(NULL), crop(NULL), listener(NULL) {
|
cropimg(NULL), ipc(NULL), crop(NULL), listener(NULL) {
|
||||||
|
|
||||||
chi = new CropHandlerIdleHelper;
|
|
||||||
chi->destroyed = false;
|
|
||||||
chi->pending = 0;
|
|
||||||
chi->cropHandler = this;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CropHandler::~CropHandler () {
|
CropHandler::~CropHandler () {
|
||||||
@@ -40,12 +35,6 @@ CropHandler::~CropHandler () {
|
|||||||
setEnabled (false);
|
setEnabled (false);
|
||||||
if (crop)
|
if (crop)
|
||||||
crop->destroy ();
|
crop->destroy ();
|
||||||
cimg.lock ();
|
|
||||||
if (chi->pending)
|
|
||||||
chi->destroyed = true;
|
|
||||||
else
|
|
||||||
delete chi;
|
|
||||||
cimg.unlock ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CropHandler::newImage (StagedImageProcessor* ipc_) {
|
void CropHandler::newImage (StagedImageProcessor* ipc_) {
|
||||||
@@ -64,13 +53,7 @@ void CropHandler::newImage (StagedImageProcessor* ipc_) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CropHandler::sizeChanged (int x, int y, int ow, int oh) { // the ipc notifies it to keep track size changes like rotation
|
void CropHandler::sizeChanged (int x, int y, int ow, int oh) { // the ipc notifies it to keep track size changes like rotation
|
||||||
|
|
||||||
compDim ();
|
compDim ();
|
||||||
|
|
||||||
// this should be put into an idle source!!!
|
|
||||||
/* if (listener)
|
|
||||||
listener->cropWindowChanged ();
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
double CropHandler::getFitZoom () {
|
double CropHandler::getFitZoom () {
|
||||||
@@ -80,12 +63,12 @@ double CropHandler::getFitZoom () {
|
|||||||
double z2 = (double) ww / ipc->getFullWidth ();
|
double z2 = (double) ww / ipc->getFullWidth ();
|
||||||
return z1<z2 ? z1 : z2;
|
return z1<z2 ? z1 : z2;
|
||||||
}
|
}
|
||||||
else
|
else {
|
||||||
return 1.0;
|
return 1.0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CropHandler::setZoom (int z, int centerx, int centery) {
|
void CropHandler::setZoom (int z, int centerx, int centery) {
|
||||||
|
|
||||||
int x = cx + cw / 2;
|
int x = cx + cw / 2;
|
||||||
int y = cy + ch / 2;
|
int y = cy + ch / 2;
|
||||||
|
|
||||||
@@ -116,6 +99,7 @@ void CropHandler::setWSize (int w, int h) {
|
|||||||
|
|
||||||
ww = w;
|
ww = w;
|
||||||
wh = h;
|
wh = h;
|
||||||
|
|
||||||
if (zoom>=1000) {
|
if (zoom>=1000) {
|
||||||
cw = ww * 1000 / zoom;
|
cw = ww * 1000 / zoom;
|
||||||
ch = wh * 1000 / zoom;
|
ch = wh * 1000 / zoom;
|
||||||
@@ -152,89 +136,21 @@ void CropHandler::getPosition (int& x, int& y) {
|
|||||||
y = cropY;
|
y = cropY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Create the piece of preview image that will be integrally copied in the preview area
|
|
||||||
*/
|
|
||||||
int createpixbufs (void* data) {
|
|
||||||
|
|
||||||
gdk_threads_enter ();
|
|
||||||
|
|
||||||
CropHandlerIdleHelper* chi = (CropHandlerIdleHelper*) data;
|
|
||||||
if (chi->destroyed) {
|
|
||||||
if (chi->pending == 1)
|
|
||||||
delete chi;
|
|
||||||
else
|
|
||||||
chi->pending--;
|
|
||||||
gdk_threads_leave ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
CropHandler* ch = chi->cropHandler;
|
|
||||||
|
|
||||||
ch->cimg.lock ();
|
|
||||||
ch->cropPixbuf.clear ();
|
|
||||||
|
|
||||||
if (!ch->enabled) {
|
|
||||||
delete [] ch->cropimg;
|
|
||||||
ch->cropimg = NULL;
|
|
||||||
ch->cimg.unlock ();
|
|
||||||
gdk_threads_leave ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
// calculate final image size
|
|
||||||
int czoom = ch->zoom<1000 ? 1000 : ch->zoom;
|
|
||||||
int imw = ch->cropimg_width * czoom / 1000;
|
|
||||||
int imh = ch->cropimg_height * czoom / 1000;
|
|
||||||
if (imw>ch->ww)
|
|
||||||
imw = ch->ww;
|
|
||||||
if (imh>ch->wh)
|
|
||||||
imh = ch->wh;
|
|
||||||
|
|
||||||
// Create a temporary pixbuf to copy the piece of the full size image
|
|
||||||
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);
|
|
||||||
// Create the real preview image
|
|
||||||
ch->cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
|
||||||
// Rescale the piece of the full size image and put it in the preview image
|
|
||||||
tmpPixbuf->scale (ch->cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
|
||||||
// Delete the temporary pixbuf
|
|
||||||
tmpPixbuf.clear ();
|
|
||||||
}
|
|
||||||
delete [] ch->cropimg;
|
|
||||||
ch->cropimg = NULL;
|
|
||||||
}
|
|
||||||
ch->cimg.unlock ();
|
|
||||||
if (ch->listener) {
|
|
||||||
ch->listener->cropImageUpdated ();
|
|
||||||
if (ch->initial) {
|
|
||||||
ch->listener->initialImageArrived ();
|
|
||||||
ch->initial = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chi->pending--;
|
|
||||||
|
|
||||||
gdk_threads_leave ();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CropHandler::setDetailedCrop (IImage8* im, rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) {
|
void CropHandler::setDetailedCrop (IImage8* im, rtengine::procparams::CropParams cp, int ax, int ay, int aw, int ah, int askip) {
|
||||||
|
|
||||||
if (!enabled)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cimg.lock ();
|
cimg.lock ();
|
||||||
|
|
||||||
cropParams = cp;
|
|
||||||
|
|
||||||
cropPixbuf.clear ();
|
cropPixbuf.clear ();
|
||||||
if (cropimg)
|
if (cropimg) delete [] cropimg;
|
||||||
delete [] cropimg;
|
|
||||||
cropimg = NULL;
|
cropimg = NULL;
|
||||||
|
|
||||||
|
if (!enabled) {
|
||||||
|
cimg.unlock ();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cropParams = cp;
|
||||||
|
|
||||||
if (ax==cropX && ay==cropY && aw==cropW && ah==cropH && askip==(zoom>=1000?1:zoom)) {
|
if (ax==cropX && ay==cropY && aw==cropW && ah==cropH && askip==(zoom>=1000?1:zoom)) {
|
||||||
cropimg_width = im->getWidth ();
|
cropimg_width = im->getWidth ();
|
||||||
cropimg_height = im->getHeight ();
|
cropimg_height = im->getHeight ();
|
||||||
@@ -245,10 +161,41 @@ void CropHandler::setDetailedCrop (IImage8* im, rtengine::procparams::CropParams
|
|||||||
ciw = aw;
|
ciw = aw;
|
||||||
cih = ah;
|
cih = ah;
|
||||||
cis = askip;
|
cis = askip;
|
||||||
chi->pending++;
|
|
||||||
g_idle_add (createpixbufs, chi);
|
// Create the piece of preview image that will be integrally copied in the preview area
|
||||||
|
if (cix==cropX && ciy==cropY && ciw==cropW && cih==cropH && cis==(zoom>=1000?1:zoom)) {
|
||||||
|
// calculate final image size
|
||||||
|
int czoom = zoom<1000 ? 1000 : zoom;
|
||||||
|
int imw = cropimg_width * czoom / 1000;
|
||||||
|
int imh = cropimg_height * czoom / 1000;
|
||||||
|
if (imw>ww)
|
||||||
|
imw = ww;
|
||||||
|
if (imh>wh)
|
||||||
|
imh = wh;
|
||||||
|
|
||||||
|
// Create a temporary pixbuf to copy the piece of the full size image
|
||||||
|
Glib::RefPtr<Gdk::Pixbuf> tmpPixbuf = Gdk::Pixbuf::create_from_data (cropimg, Gdk::COLORSPACE_RGB, false, 8, cropimg_width, cropimg_height, 3*cropimg_width);
|
||||||
|
// Create the real preview image
|
||||||
|
cropPixbuf = Gdk::Pixbuf::create (Gdk::COLORSPACE_RGB, false, 8, imw, imh);
|
||||||
|
// Rescale the piece of the full size image and put it in the preview image
|
||||||
|
tmpPixbuf->scale (cropPixbuf, 0, 0, imw, imh, 0, 0, czoom/1000.0, czoom/1000.0, Gdk::INTERP_NEAREST);
|
||||||
|
// Delete the temporary pixbuf
|
||||||
|
tmpPixbuf.clear ();
|
||||||
}
|
}
|
||||||
|
delete [] cropimg;
|
||||||
|
cropimg = NULL;
|
||||||
|
|
||||||
cimg.unlock ();
|
cimg.unlock ();
|
||||||
|
|
||||||
|
if (listener) {
|
||||||
|
listener->cropImageUpdated ();
|
||||||
|
if (initial) {
|
||||||
|
listener->initialImageArrived (); // sets zoomToFit, so it should be the right size image!
|
||||||
|
initial = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else cimg.unlock ();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) {
|
bool CropHandler::getWindow (int& cwx, int& cwy, int& cww, int& cwh, int& cskip) {
|
||||||
|
@@ -30,12 +30,6 @@ class CropHandlerListener {
|
|||||||
virtual void initialImageArrived () {}
|
virtual void initialImageArrived () {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class CropHandler;
|
|
||||||
struct CropHandlerIdleHelper {
|
|
||||||
CropHandler* cropHandler;
|
|
||||||
bool destroyed;
|
|
||||||
int pending;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener {
|
class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener {
|
||||||
|
|
||||||
@@ -55,7 +49,6 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size
|
|||||||
rtengine::DetailedCrop* crop;
|
rtengine::DetailedCrop* crop;
|
||||||
|
|
||||||
CropHandlerListener* listener;
|
CropHandlerListener* listener;
|
||||||
CropHandlerIdleHelper* chi;
|
|
||||||
|
|
||||||
void update ();
|
void update ();
|
||||||
void compDim ();
|
void compDim ();
|
||||||
|
@@ -92,9 +92,8 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_)
|
|||||||
|
|
||||||
minWidth = bsw + iw + 2*sideBorderWidth;
|
minWidth = bsw + iw + 2*sideBorderWidth;
|
||||||
|
|
||||||
setSize (100, 100);
|
|
||||||
cropHandler.newImage (ipc_);
|
cropHandler.newImage (ipc_);
|
||||||
cropHandler.setPosition (0,0);
|
|
||||||
cropHandler.setEnabled (true);
|
cropHandler.setEnabled (true);
|
||||||
cropHandler.setCropHandlerListener (this);
|
cropHandler.setCropHandlerListener (this);
|
||||||
|
|
||||||
@@ -195,6 +194,7 @@ void CropWindow::setSize (int w, int h, bool norefresh) {
|
|||||||
|
|
||||||
if (!norefresh)
|
if (!norefresh)
|
||||||
cropHandler.setWSize (imgAreaW, imgAreaH);
|
cropHandler.setWSize (imgAreaW, imgAreaH);
|
||||||
|
|
||||||
iarea->redraw ();
|
iarea->redraw ();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -746,7 +746,6 @@ double CropWindow::getZoom () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CropWindow::setZoom (double zoom) {
|
void CropWindow::setZoom (double zoom) {
|
||||||
|
|
||||||
int cz = MAXZOOMSTEPS;
|
int cz = MAXZOOMSTEPS;
|
||||||
if (zoom < zoomSteps[0].zoom)
|
if (zoom < zoomSteps[0].zoom)
|
||||||
cz = 0;
|
cz = 0;
|
||||||
|
@@ -59,8 +59,8 @@ void ImageArea::on_realize()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ImageArea::on_resized (Gtk::Allocation& req) {
|
void ImageArea::on_resized (Gtk::Allocation& req) {
|
||||||
|
if (ipc && get_width()>1) { // sometimes on_resize is called in some init state, causing wrong sizes
|
||||||
if (ipc && !mainCropWindow) {
|
if (!mainCropWindow) {
|
||||||
mainCropWindow = new CropWindow (this, ipc);
|
mainCropWindow = new CropWindow (this, ipc);
|
||||||
mainCropWindow->setDecorated (false);
|
mainCropWindow->setDecorated (false);
|
||||||
mainCropWindow->setFitZoomEnabled (true);
|
mainCropWindow->setFitZoomEnabled (true);
|
||||||
@@ -70,9 +70,10 @@ void ImageArea::on_resized (Gtk::Allocation& req) {
|
|||||||
mainCropWindow->setCropGUIListener (cropgl);
|
mainCropWindow->setCropGUIListener (cropgl);
|
||||||
mainCropWindow->setPointerMotionListener (pmlistener);
|
mainCropWindow->setPointerMotionListener (pmlistener);
|
||||||
}
|
}
|
||||||
else if (ipc) {
|
else {
|
||||||
mainCropWindow->setSize (get_width(), get_height());
|
mainCropWindow->setSize (get_width(), get_height());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {
|
void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {
|
||||||
|
Reference in New Issue
Block a user