Sychronization of crop image processing; see issue #549

This commit is contained in:
Oliver Duis
2011-03-01 19:32:58 +01:00
parent daee8cae5f
commit 89a2232c2e
4 changed files with 64 additions and 124 deletions

View File

@@ -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,88 +136,20 @@ 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) cimg.lock ();
return;
cimg.lock (); cropPixbuf.clear ();
if (cropimg) delete [] cropimg;
cropimg = NULL;
if (!enabled) {
cimg.unlock ();
return;
}
cropParams = cp; cropParams = cp;
cropPixbuf.clear ();
if (cropimg)
delete [] cropimg;
cropimg = NULL;
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 ();
@@ -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)) {
cimg.unlock (); // 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 ();
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) {

View File

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

View File

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

View File

@@ -59,20 +59,21 @@ 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);
mainCropWindow->setPosition (0, 0); mainCropWindow->setPosition (0, 0);
mainCropWindow->setSize (get_width(), get_height()); mainCropWindow->setSize (get_width(), get_height());
mainCropWindow->addCropWindowListener (this); mainCropWindow->addCropWindowListener (this);
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_) {