From 89a2232c2e394b78e303ad886f179b64974121e8 Mon Sep 17 00:00:00 2001 From: Oliver Duis Date: Tue, 1 Mar 2011 19:32:58 +0100 Subject: [PATCH] Sychronization of crop image processing; see issue #549 --- rtgui/crophandler.cc | 147 ++++++++++++++----------------------------- rtgui/crophandler.h | 7 --- rtgui/cropwindow.cc | 5 +- rtgui/imagearea.cc | 29 ++++----- 4 files changed, 64 insertions(+), 124 deletions(-) diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 5f1489d0f..02697831c 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -25,11 +25,6 @@ CropHandler::CropHandler () : zoom(10), cx(0), cy(0), cw(0), ch(0), cropX(0), cropY(0), cropW(0), cropH(0), enabled(false), cropimg(NULL), ipc(NULL), crop(NULL), listener(NULL) { - - chi = new CropHandlerIdleHelper; - chi->destroyed = false; - chi->pending = 0; - chi->cropHandler = this; } CropHandler::~CropHandler () { @@ -40,12 +35,6 @@ CropHandler::~CropHandler () { setEnabled (false); if (crop) crop->destroy (); - cimg.lock (); - if (chi->pending) - chi->destroyed = true; - else - delete chi; - cimg.unlock (); } 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 - compDim (); - -// this should be put into an idle source!!! -/* if (listener) - listener->cropWindowChanged (); - */ } double CropHandler::getFitZoom () { @@ -80,12 +63,12 @@ double CropHandler::getFitZoom () { double z2 = (double) ww / ipc->getFullWidth (); return z1=1000) { cw = ww * 1000 / zoom; ch = wh * 1000 / zoom; @@ -152,88 +136,20 @@ void CropHandler::getPosition (int& x, int& y) { 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 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) { - if (!enabled) - return; + cimg.lock (); - cimg.lock (); + cropPixbuf.clear (); + if (cropimg) delete [] cropimg; + cropimg = NULL; + + if (!enabled) { + cimg.unlock (); + return; + } cropParams = cp; - - cropPixbuf.clear (); - if (cropimg) - delete [] cropimg; - cropimg = NULL; if (ax==cropX && ay==cropY && aw==cropW && ah==cropH && askip==(zoom>=1000?1:zoom)) { cropimg_width = im->getWidth (); @@ -245,10 +161,41 @@ void CropHandler::setDetailedCrop (IImage8* im, rtengine::procparams::CropParams ciw = aw; cih = ah; cis = askip; - chi->pending++; - g_idle_add (createpixbufs, chi); - } - cimg.unlock (); + + // 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 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) { diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 0b6e8d5f2..f168a29cd 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -30,12 +30,6 @@ class CropHandlerListener { virtual void initialImageArrived () {} }; -class CropHandler; -struct CropHandlerIdleHelper { - CropHandler* cropHandler; - bool destroyed; - int pending; -}; class CropHandler : public rtengine::DetailedCropListener, public rtengine::SizeListener { @@ -55,7 +49,6 @@ class CropHandler : public rtengine::DetailedCropListener, public rtengine::Size rtengine::DetailedCrop* crop; CropHandlerListener* listener; - CropHandlerIdleHelper* chi; void update (); void compDim (); diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 8359d7ac8..e5da4ba24 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -92,9 +92,8 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_) minWidth = bsw + iw + 2*sideBorderWidth; - setSize (100, 100); cropHandler.newImage (ipc_); - cropHandler.setPosition (0,0); + cropHandler.setEnabled (true); cropHandler.setCropHandlerListener (this); @@ -195,6 +194,7 @@ void CropWindow::setSize (int w, int h, bool norefresh) { if (!norefresh) cropHandler.setWSize (imgAreaW, imgAreaH); + iarea->redraw (); } @@ -746,7 +746,6 @@ double CropWindow::getZoom () { } void CropWindow::setZoom (double zoom) { - int cz = MAXZOOMSTEPS; if (zoom < zoomSteps[0].zoom) cz = 0; diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index 99f9cf6b9..05795896d 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -59,20 +59,21 @@ void ImageArea::on_realize() } void ImageArea::on_resized (Gtk::Allocation& req) { - - if (ipc && !mainCropWindow) { - mainCropWindow = new CropWindow (this, ipc); - mainCropWindow->setDecorated (false); - mainCropWindow->setFitZoomEnabled (true); - mainCropWindow->setPosition (0, 0); - mainCropWindow->setSize (get_width(), get_height()); - mainCropWindow->addCropWindowListener (this); - mainCropWindow->setCropGUIListener (cropgl); - mainCropWindow->setPointerMotionListener (pmlistener); - } - else if (ipc) { - mainCropWindow->setSize (get_width(), get_height()); - } + if (ipc && get_width()>1) { // sometimes on_resize is called in some init state, causing wrong sizes + if (!mainCropWindow) { + mainCropWindow = new CropWindow (this, ipc); + mainCropWindow->setDecorated (false); + mainCropWindow->setFitZoomEnabled (true); + mainCropWindow->setPosition (0, 0); + mainCropWindow->setSize (get_width(), get_height()); + mainCropWindow->addCropWindowListener (this); + mainCropWindow->setCropGUIListener (cropgl); + mainCropWindow->setPointerMotionListener (pmlistener); + } + else { + mainCropWindow->setSize (get_width(), get_height()); + } + } } void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) {