diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 9843a1aa1..5f1489d0f 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -153,6 +153,9 @@ void CropHandler::getPosition (int& x, int& y) { } +/* + * Create the piece of preview image that will be integrally copied in the preview area + */ int createpixbufs (void* data) { gdk_threads_enter (); @@ -191,9 +194,13 @@ int createpixbufs (void* data) { 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; diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index 72f76658f..8359d7ac8 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -53,7 +53,7 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_) : onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), backColor(options.bgcolor), decorated(true), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), - imgX(0), imgY(0), imgW(1), imgH(1), xpos(30), ypos(30), iarea(parent), + xpos(30), ypos(30), imgX(0), imgY(0), imgW(1), imgH(1), iarea(parent), cropZoom(0), cropgl(NULL), pmlistener(NULL), observedCropWin(NULL) { Glib::RefPtr context = parent->get_pango_context () ; @@ -307,6 +307,7 @@ void CropWindow::buttonPress (int button, int type, int bstate, int x, int y) { else if (iarea->getToolMode () == TMCropSelect && cropgl) { state = SCropSelecting; translateCoord (x, y, press_x, press_y); + cropHandler.cropParams.enabled = true; cropHandler.cropParams.x = press_x; cropHandler.cropParams.y = press_y; cropHandler.cropParams.w = cropHandler.cropParams.h = 1; @@ -588,16 +589,16 @@ void CropWindow::updateCursor (int x, int y) { void CropWindow::expose (Cairo::RefPtr cr) { - MyTime t1, t2, t3, t4; + //MyTime t1, t2, t3, t4; - t1.set (); + //t1.set (); if (decorated) drawDecoration (cr); int x = xpos, y = ypos, h = height, w = width; - // draw border + // draw the background if (backColor==0) { Gdk::Color cback = iarea->get_style()->get_bg(Gtk::STATE_NORMAL); cr->set_source_rgb (cback.get_red_p(), cback.get_green_p(), cback.get_blue_p()); @@ -606,8 +607,9 @@ void CropWindow::expose (Cairo::RefPtr cr) { cr->set_source_rgb (0,0,0); else if (backColor==2) cr->set_source_rgb (1,1,1); - - cr->rectangle (x+imgAreaX+0.5, y+imgAreaY+0.5, imgAreaW, imgAreaH); + + cr->set_line_width (0.); + cr->rectangle (x+imgAreaX, y+imgAreaY, imgAreaW, imgAreaH); cr->stroke_preserve (); cr->fill (); @@ -624,18 +626,20 @@ void CropWindow::expose (Cairo::RefPtr cr) { Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); -// if (cropHandler.cropParams.enabled) +// if (cropHandler.cropParams.enabled) // drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } + if (observedCropWin) + drawObservedFrame (cr); } - else { + else { if (cropHandler.cropPixbuf) { imgW = cropHandler.cropPixbuf->get_width (); imgH = cropHandler.cropPixbuf->get_height (); imgX = imgAreaX + (imgAreaW-imgW)/2; imgY = imgAreaY + (imgAreaH-imgH)/2; // PERFORMANCE BOTTLENECK STARTS HERE - t3.set (); + //t3.set (); bool showcs = iarea->indClippedPanel->showClippedShadows(); bool showch = iarea->indClippedPanel->showClippedHighlights(); @@ -662,36 +666,36 @@ void CropWindow::expose (Cairo::RefPtr cr) { else if (showcs && (curr[0]<=options.shadowThreshold || curr[1]<=options.shadowThreshold || curr[2]<=options.shadowThreshold)) curr[0] = curr[1] = curr[2] = 255; } - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), tmp, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); } else - iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); - t4.set (); + iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), cropHandler.cropPixbuf, 0, 0, x+imgX, y+imgY, -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + //t4.set (); // END OF BOTTLENECK if (cropHandler.cropParams.enabled) { int cropX, cropY; cropHandler.getPosition (cropX, cropY); drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } + if (observedCropWin) + drawObservedFrame (cr); } else { + // cropHandler.cropPixbuf is null int cropX, cropY; cropHandler.getPosition (cropX, cropY); Glib::RefPtr rough = iarea->getPreviewHandler()->getRoughImage (cropX, cropY, imgAreaW, imgAreaH, zoomSteps[cropZoom].zoom); if (rough) { iarea->get_window()->draw_pixbuf (iarea->get_style()->get_base_gc(Gtk::STATE_NORMAL), rough, 0, 0, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, -1, -1, Gdk::RGB_DITHER_NORMAL, 0, 0); if (cropHandler.cropParams.enabled) { - int cropX, cropY; - cropHandler.getPosition (cropX, cropY); - drawCrop (cr, x+imgX, y+imgY, imgW, imgH, cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); + drawCrop (cr, x+imgAreaX+(imgAreaW-rough->get_width())/2, y+imgAreaY+(imgAreaH-rough->get_height())/2, rough->get_width(), rough->get_height(), cropX, cropY, zoomSteps[cropZoom].zoom, cropHandler.cropParams); } + if (observedCropWin) + drawObservedFrame (cr, rough->get_width(), rough->get_height()); } } } - if (observedCropWin) - drawObservedFrame (cr); - // if cursor stays above resize area, draw the icon if (decorated && (state==SCropWinResize || onResizeArea)) { int rw = resizeSurface->get_width (); @@ -713,7 +717,7 @@ void CropWindow::expose (Cairo::RefPtr cr) { if (state==SNormal && iarea->getToolMode () == TMSpotWB) drawSpotWBRectangle (cr); - t2.set (); + //t2.set (); cropHandler.cimg.unlock (); // printf ("etime --> %d, %d\n", t2.etime (t1), t4.etime (t3)); } @@ -792,11 +796,15 @@ void CropWindow::redrawNeeded (LWButton* button) { void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) { - cropZoom = zoom; - if (cropZoom<0) - cropZoom = 0; - else if (cropZoom>MAXZOOMSTEPS) - cropZoom = MAXZOOMSTEPS; + if (zoom<0) + zoom = 0; + else if (zoom>MAXZOOMSTEPS) + zoom = MAXZOOMSTEPS; + if (cropZoom == zoom) + // We are already at the start/end of the zoom range, so we do nothing + return; + else + cropZoom = zoom; cropLabel = zoomSteps[cropZoom].label; cropHandler.setZoom (zoomSteps[cropZoom].czoom, centerx, centery); @@ -968,24 +976,30 @@ void CropWindow::drawSpotWBRectangle (Cairo::RefPtr cr) { cr->reset_clip (); } -void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h) { - +void CropWindow::getObservedFrameArea (int& x, int& y, int& w, int& h, int rw, int rh) { + int cropX, cropY, cropW, cropH; observedCropWin->getCropRectangle (cropX, cropY, cropW, cropH); int myCropX, myCropY, myCropW, myCropH; getCropRectangle (myCropX, myCropY, myCropW, myCropH); // translate it to screen coordinates - x = xpos + imgX + (cropX-myCropX)*zoomSteps[cropZoom].zoom; - y = ypos + imgY + (cropY-myCropY)*zoomSteps[cropZoom].zoom; + if (rw) { + x = xpos + imgAreaX+(imgAreaW-rw)/2 + (cropX-myCropX)*zoomSteps[cropZoom].zoom; + y = ypos + imgAreaY+(imgAreaH-rh)/2 + (cropY-myCropY)*zoomSteps[cropZoom].zoom; + } + else { + x = xpos + imgX + (cropX-myCropX)*zoomSteps[cropZoom].zoom; + y = ypos + imgY + (cropY-myCropY)*zoomSteps[cropZoom].zoom; + } w = cropW * zoomSteps[cropZoom].zoom; h = cropH * zoomSteps[cropZoom].zoom; } -void CropWindow::drawObservedFrame (Cairo::RefPtr cr) { - +void CropWindow::drawObservedFrame (Cairo::RefPtr cr, int rw, int rh) { + int x, y, w, h; - getObservedFrameArea (x, y, w, h); + getObservedFrameArea (x, y, w, h, rw, rh); cr->set_source_rgb (1.0, 1.0, 1.0); cr->set_line_width (4); diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index 396227a4a..99d816b8b 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -59,11 +59,15 @@ class CropWindow : public LWButtonListener, public CropHandlerListener { int backColor; bool decorated; - // sizes, positions + // crop frame description int titleHeight, sideBorderWidth, lowerBorderWidth, upperBorderWidth, sepWidth, minWidth; - int imgAreaX, imgAreaY, imgAreaW, imgAreaH; - int imgX, imgY, imgW, imgH; + // size & position of the crop relative to the top left corner + // of the main preview area (to be confirmed) int xpos, ypos, width, height; + // size & pos of the drawable area relative to the top left corner of the crop + int imgAreaX, imgAreaY, imgAreaW, imgAreaH; + // size & pos of the piece of preview image relative to the top left corner of the crop + int imgX, imgY, imgW, imgH; // image handling @@ -72,7 +76,7 @@ class CropWindow : public LWButtonListener, public CropHandlerListener { // crop gui listener CropGUIListener* cropgl; - PointerMotionListener* pmlistener; + PointerMotionListener* pmlistener; std::list listeners; CropWindow* observedCropWin; @@ -82,10 +86,10 @@ class CropWindow : public LWButtonListener, public CropHandlerListener { void drawDecoration (Cairo::RefPtr cr); void drawStraightenGuide (Cairo::RefPtr cr); void drawSpotWBRectangle (Cairo::RefPtr cr); - void drawObservedFrame (Cairo::RefPtr cr); + void drawObservedFrame (Cairo::RefPtr cr, int rw=0, int rh=0); void translateCoord (int phyx, int phyy, int& imgx, int& imgy); void changeZoom (int zoom, bool notify=true, int centerx=-1, int centery=-1); - void getObservedFrameArea(int& x, int& y, int& w, int& h); + void getObservedFrameArea(int& x, int& y, int& w, int& h, int rw=0, int rh=0); public: CropHandler cropHandler; diff --git a/rtgui/guiutils.cc b/rtgui/guiutils.cc index ef6d01ba2..496c1c690 100644 --- a/rtgui/guiutils.cc +++ b/rtgui/guiutils.cc @@ -75,7 +75,6 @@ void drawCrop (Cairo::RefPtr cr, int imx, int imy, int imw, int cr->set_source_rgba (options.cutOverlayBrush[0], options.cutOverlayBrush[1], options.cutOverlayBrush[2], options.cutOverlayBrush[3]); - // TODO: not sure if this is right. Seems to leave a thin border on the left/top, but might be bug in calling code cr->rectangle (imx, imy, imw, c1y); cr->rectangle (imx, imy+c2y, imw, imh-c2y); cr->rectangle (imx, imy+c1y, c1x, c2y-c1y+1);