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),
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<z2 ? z1 : z2;
}
else
else {
return 1.0;
}
}
void CropHandler::setZoom (int z, int centerx, int centery) {
int x = cx + cw / 2;
int y = cy + ch / 2;
@@ -116,6 +99,7 @@ void CropHandler::setWSize (int w, int h) {
ww = w;
wh = h;
if (zoom>=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<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) {
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<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) {

View File

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

View File

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

View File

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