From 773a65b5be550d6facfe4cf5d46a894c828fdb7e Mon Sep 17 00:00:00 2001 From: Hombre Date: Fri, 7 Oct 2016 01:25:45 +0200 Subject: [PATCH] Bugfix and using the Navigator's range for displaying values Thanks a lot to Heckflosse and Floessie for the bugfix --- rtgui/crophandler.cc | 40 +++++++++++-- rtgui/crophandler.h | 2 +- rtgui/cropwindow.cc | 85 +++++++++++++++++++++----- rtgui/cropwindow.h | 26 +++----- rtgui/imagearea.cc | 11 +++- rtgui/imagearea.h | 3 +- rtgui/lockablecolorpicker.cc | 97 +++++++++++++++++++----------- rtgui/lockablecolorpicker.h | 7 ++- rtgui/navigator.cc | 109 +++++++++++++++++++++------------- rtgui/navigator.h | 4 ++ rtgui/pointermotionlistener.h | 17 +++++- 11 files changed, 279 insertions(+), 122 deletions(-) diff --git a/rtgui/crophandler.cc b/rtgui/crophandler.cc index 522b34c41..64bca19f4 100644 --- a/rtgui/crophandler.cc +++ b/rtgui/crophandler.cc @@ -475,15 +475,22 @@ bool CropHandler::getEnabled () return enabled; } -void CropHandler::colorPick (rtengine::Coord pickerPos, float &r, float &g, float &b, LockableColorPicker::Size size) +void CropHandler::colorPick (const rtengine::Coord &pickerPos, float &r, float &g, float &b, float &rpreview, float &gpreview, float &bpreview, LockableColorPicker::Size size) { + if (!cropPixbuf || !cropPixbuftrue) { + r = g = b = 0.f; + rpreview = gpreview = bpreview = 0.f; + return; + } + int xSize = (int)size; int ySize = (int)size; int pixbufW = cropPixbuftrue->get_width(); + int pixbufH = cropPixbuftrue->get_height(); rtengine::Coord topLeftPos(pickerPos.x - xSize/2, pickerPos.y - ySize/2); - if (topLeftPos.x > pixbufW || topLeftPos.y > pixbufW || topLeftPos.x + xSize < 0 || topLeftPos.y + ySize < 0) { + if (topLeftPos.x > pixbufW || topLeftPos.y > pixbufH || topLeftPos.x + xSize < 0 || topLeftPos.y + ySize < 0) { return; } @@ -503,8 +510,8 @@ void CropHandler::colorPick (rtengine::Coord pickerPos, float &r, float &g, floa ySize += topLeftPos.y; topLeftPos.y = 0; } - if (topLeftPos.y + ySize > cropimg_height) { - ySize = cropimg_height - topLeftPos.y; + if (topLeftPos.y + ySize > pixbufH) { + ySize = pixbufH - topLeftPos.y; } // Accumulating the data @@ -526,10 +533,35 @@ void CropHandler::colorPick (rtengine::Coord pickerPos, float &r, float &g, floa } } } + // Averaging r = (float)r2 / (float)count / 255.f; g = (float)g2 / (float)count / 255.f; b = (float)b2 / (float)count / 255.f; + + // Accumulating the data + r2=0, g2=0, b2=0; + count = 0; + data = cropPixbuf->get_pixels(); + for (int j = topLeftPos.y ; j < topLeftPos.y + ySize ; ++j) { + const guint8* data2 = data + cropPixbuf->get_rowstride()*j; + for (int i = topLeftPos.x ; i < topLeftPos.x + xSize ; ++i) { + const guint8* data3 = data2 + i*3; + rtengine::Coord currPos(i, j); + rtengine::Coord delta = pickerPos - currPos; + rtengine::PolarCoord p(delta); + if (p.radius <= radius) { + r2 += *data3; + g2 += *(data3+1); + b2 += *(data3+2); + ++count; + } + } + } + // Averaging + rpreview = (float)r2 / (float)count / 255.f; + gpreview = (float)g2 / (float)count / 255.f; + bpreview = (float)b2 / (float)count / 255.f; } void CropHandler::getSize (int& w, int& h) diff --git a/rtgui/crophandler.h b/rtgui/crophandler.h index 150b256f4..1350df27e 100644 --- a/rtgui/crophandler.h +++ b/rtgui/crophandler.h @@ -113,7 +113,7 @@ public: void setEnabled (bool e); bool getEnabled (); - void colorPick (rtengine::Coord pickerPos, float &r, float &g, float &b, LockableColorPicker::Size size); + void colorPick (const rtengine::Coord &pickerPos, float &r, float &g, float &b, float &rpreview, float &gpreview, float &bpreview, LockableColorPicker::Size size); rtengine::DetailedCrop* getCrop() { diff --git a/rtgui/cropwindow.cc b/rtgui/cropwindow.cc index df9cb9f86..aa1e8c859 100644 --- a/rtgui/cropwindow.cc +++ b/rtgui/cropwindow.cc @@ -66,13 +66,13 @@ ZoomStep zoomSteps[] = { #define MAXZOOMSTEPS 20 #define ZOOM11INDEX 13 -CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow) +CropWindow::CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow) : ObjectMOBuffer(parent), state(SNormal), press_x(0), press_y(0), action_x(0), action_y(0), pickedObject(-1), pickModifierKey(0), rot_deg(0), onResizeArea(false), deleted(false), fitZoomEnabled(true), fitZoom(false), isLowUpdatePriority(isLowUpdatePriority_), hoveredPicker(nullptr), cropLabel(Glib::ustring("100%")), backColor(options.bgcolor), decorated(true), isFlawnOver(false), titleHeight(30), sideBorderWidth(3), lowerBorderWidth(3), upperBorderWidth(1), sepWidth(2), xpos(30), ypos(30), width(0), height(0), imgAreaX(0), imgAreaY(0), imgAreaW(0), imgAreaH(0), imgX(-1), imgY(-1), imgW(1), imgH(1), iarea(parent), cropZoom(0), zoomVersion(0), exposeVersion(0), cropgl(NULL), - pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL), ipc(ipc_) + pmlistener(NULL), pmhlistener(NULL), observedCropWin(NULL) { Glib::RefPtr context = parent->get_pango_context () ; Pango::FontDescription fontd = context->get_font_description (); @@ -110,7 +110,7 @@ CropWindow::CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, minWidth = bsw + iw + 2 * sideBorderWidth; cropHandler.setDisplayHandler(this); - cropHandler.newImage (ipc_, isDetailWindow); + cropHandler.newImage (parent->getImProcCoordinator(), isDetailWindow); } CropWindow::~CropWindow () @@ -904,22 +904,23 @@ void CropWindow::pointerMoved (int bstate, int x, int y) screenCoordToImage (x, y, imgPos.x, imgPos.y); if (imgPos.x < 0) { imgPos.x = 0; - }else if (imgPos.x >= ipc->getFullWidth()) { - imgPos.x = ipc->getFullWidth()-1; + }else if (imgPos.x >= iarea->getImProcCoordinator()->getFullWidth()) { + imgPos.x = iarea->getImProcCoordinator()->getFullWidth()-1; } if (imgPos.y < 0) { imgPos.y = 0; - }else if (imgPos.y >= ipc->getFullHeight()) { - imgPos.y = ipc->getFullHeight()-1; + }else if (imgPos.y >= iarea->getImProcCoordinator()->getFullHeight()) { + imgPos.y = iarea->getImProcCoordinator()->getFullHeight()-1; } imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y); float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; LockableColorPicker::Validity validity = checkValidity (hoveredPicker, cropPos); hoveredPicker->setValidity (validity); if (validity == LockableColorPicker::Validity::INSIDE) { - cropHandler.colorPick(cropPos, r, g, b, hoveredPicker->getSize()); + cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize()); } - hoveredPicker->setPosition (imgPos, r, g, b); + hoveredPicker->setPosition (imgPos, r, g, b, rpreview, gpreview, bpreview); iarea->redraw (); } else if (state == SNormal && iarea->getToolMode () == TMColorPicker && onArea(ColorPicker, x, y)) { // TODO: we could set the hovered picker as Highlighted here @@ -2056,10 +2057,10 @@ void CropWindow::buttonPressed (LWButton* button, int actionCode, void* actionDa } else if (button == bZoom100) { // zoom 100 zoom11 (); } else if (button == bClose) { // close - if(ipc->updateTryLock()) { + if(iarea->getImProcCoordinator()->updateTryLock()) { deleted = true; iarea->cropWindowClosed (this); - ipc->updateUnLock(); + iarea->getImProcCoordinator()->updateUnLock(); } } } @@ -2080,11 +2081,12 @@ void CropWindow::updateHoveredPicker (rtengine::Coord &imgPos) rtengine::Coord cropPos; imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y); float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; LockableColorPicker::Validity validity = checkValidity (hoveredPicker, cropPos); hoveredPicker->setValidity (validity); if (validity == LockableColorPicker::Validity::INSIDE) { - cropHandler.colorPick(cropPos, r, g, b, hoveredPicker->getSize()); - hoveredPicker->setRGB (r, g, b); + cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, hoveredPicker->getSize()); + hoveredPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); } } void CropWindow::changeZoom (int zoom, bool notify, int centerx, int centery) @@ -2455,9 +2457,10 @@ void CropWindow::cropImageUpdated () colorPicker->getImagePosition(imgPos); imageCoordToCropImage(imgPos.x, imgPos.y, cropPos.x, cropPos.y); float r=0.f, g=0.f, b=0.f; + float rpreview=0.f, gpreview=0.f, bpreview=0.f; colorPicker->setValidity (checkValidity (colorPicker, cropPos)); - cropHandler.colorPick(cropPos, r, g, b, colorPicker->getSize()); - colorPicker->setRGB (r, g, b); + cropHandler.colorPick(cropPos, r, g, b, rpreview, gpreview, bpreview, colorPicker->getSize()); + colorPicker->setRGB (r, g, b, rpreview, gpreview, bpreview); } iarea->redraw (); } @@ -2524,3 +2527,55 @@ ImageArea* CropWindow::getImageArea() { return iarea; } + +void CropWindow::setCropGUIListener (CropGUIListener* cgl) +{ + cropgl = cgl; +} + +void CropWindow::setPointerMotionListener (PointerMotionListener* pml) +{ + pmlistener = pml; + pml->signal_cycle_rgb().connect( sigc::mem_fun(*this, &CropWindow::cycleRGB) ); + pml->signal_cycle_hsv().connect( sigc::mem_fun(*this, &CropWindow::cycleHSV) ); +} + +PointerMotionListener* CropWindow::getPointerMotionListener () +{ + return pmlistener; +} + +void CropWindow::setPointerMotionHListener (PointerMotionListener* pml) +{ + pmhlistener = pml; +} + +// crop window listeners +void CropWindow::addCropWindowListener (CropWindowListener* l) +{ + listeners.push_back (l); +} + +void CropWindow::cycleRGB () +{ + bool redraw = false; + for (auto colorPicker : colorPickers) { + redraw |= colorPicker->cycleRGB (); + } + + if (redraw) { + iarea->redraw (); + } +} + +void CropWindow::cycleHSV () +{ + bool redraw = false; + for (auto colorPicker : colorPickers) { + redraw |= colorPicker->cycleHSV (); + } + + if (redraw) { + iarea->redraw (); + } +} diff --git a/rtgui/cropwindow.h b/rtgui/cropwindow.h index 089fcb8a4..f976c98b1 100644 --- a/rtgui/cropwindow.h +++ b/rtgui/cropwindow.h @@ -94,7 +94,6 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed std::list listeners; CropWindow* observedCropWin; // Pointer to the currently active detail CropWindow - rtengine::StagedImageProcessor* ipc; bool onArea (CursorArea a, int x, int y); void updateCursor (int x, int y); @@ -105,6 +104,8 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed void drawObservedFrame (Cairo::RefPtr cr, int rw = 0, int rh = 0); void changeZoom (int zoom, bool notify = true, int centerx = -1, int centery = -1); void updateHoveredPicker (rtengine::Coord &imgPos); + void cycleRGB (); + void cycleHSV (); LockableColorPicker::Validity checkValidity (LockableColorPicker* picker, const rtengine::Coord &pos); @@ -113,7 +114,7 @@ class CropWindow : public LWButtonListener, public CropDisplayHandler, public Ed public: CropHandler cropHandler; - CropWindow (ImageArea* parent, rtengine::StagedImageProcessor* ipc_, bool isLowUpdatePriority_, bool isDetailWindow); + CropWindow (ImageArea* parent, bool isLowUpdatePriority_, bool isDetailWindow); ~CropWindow (); void setDecorated (bool decorated) @@ -190,24 +191,13 @@ public: void setCropAnchorPosition (int& w, int& h); // listeners - void setCropGUIListener (CropGUIListener* cgl) - { - cropgl = cgl; - } - void setPointerMotionListener (PointerMotionListener* pml) - { - pmlistener = pml; - } - void setPointerMotionHListener (PointerMotionListener* pml) - { - pmhlistener = pml; - } + void setCropGUIListener (CropGUIListener* cgl); + void setPointerMotionListener (PointerMotionListener* pml); + PointerMotionListener* getPointerMotionListener (); + void setPointerMotionHListener (PointerMotionListener* pml); // crop window listeners - void addCropWindowListener (CropWindowListener* l) - { - listeners.push_back (l); - } + void addCropWindowListener (CropWindowListener* l); void delCropWindowListener (CropWindowListener* l); // crophandlerlistener interface diff --git a/rtgui/imagearea.cc b/rtgui/imagearea.cc index c09051e4f..125968b8e 100644 --- a/rtgui/imagearea.cc +++ b/rtgui/imagearea.cc @@ -88,7 +88,7 @@ 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 (!mainCropWindow) { - mainCropWindow = new CropWindow (this, ipc, false, false); + mainCropWindow = new CropWindow (this, false, false); mainCropWindow->setDecorated (false); mainCropWindow->setFitZoomEnabled (true); mainCropWindow->addCropWindowListener (this); @@ -106,7 +106,12 @@ void ImageArea::on_resized (Gtk::Allocation& req) } } -void ImageArea::setImProcCoordinator (rtengine::StagedImageProcessor* ipc_) +rtengine::StagedImageProcessor* ImageArea::getImProcCoordinator() const +{ + return ipc; +} + +void ImageArea::setImProcCoordinator(rtengine::StagedImageProcessor* ipc_) { if( !ipc_ ) { focusGrabber = NULL; @@ -398,7 +403,7 @@ void ImageArea::addCropWindow () return; // if called but no image is loaded, it would crash } - CropWindow* cw = new CropWindow (this, ipc, true, true); + CropWindow* cw = new CropWindow (this, true, true); cw->zoom11(); cw->setCropGUIListener (cropgl); cw->setPointerMotionListener (pmlistener); diff --git a/rtgui/imagearea.h b/rtgui/imagearea.h index deabe8aa7..71d4007d1 100644 --- a/rtgui/imagearea.h +++ b/rtgui/imagearea.h @@ -73,7 +73,8 @@ public: ImageArea (ImageAreaPanel* p); ~ImageArea (); - void setImProcCoordinator (rtengine::StagedImageProcessor* ipc_); + rtengine::StagedImageProcessor* getImProcCoordinator() const; + void setImProcCoordinator(rtengine::StagedImageProcessor* ipc_); void setPreviewModePanel(PreviewModePanel* previewModePanel_) { previewModePanel = previewModePanel_; diff --git a/rtgui/lockablecolorpicker.cc b/rtgui/lockablecolorpicker.cc index 1d1da9b5c..896bdaa2a 100644 --- a/rtgui/lockablecolorpicker.cc +++ b/rtgui/lockablecolorpicker.cc @@ -23,26 +23,22 @@ #include "../rtengine/rt_math.h" #include "imagearea.h" #include "multilangmgr.h" +#include "navigator.h" extern Options options; LockableColorPicker::LockableColorPicker (CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile) : cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(0, 0), size(Size::S20), outputProfile(oProfile), workingProfile(wProfile), validity(Validity::OUTSIDE), - r(0.f), g(0.f), b(0.f), h(0.f), s(0.f), v(0.f), L(0.f), a(0.f), bb(0.f) + r(0.f), g(0.f), b(0.f), rpreview(0.f), gpreview(0.f), bpreview(0.f), h(0.f), s(0.f), v(0.f), L(0.f), a(0.f), bb(0.f) {} LockableColorPicker::LockableColorPicker (int x, int y, Size size, const float R, const float G, const float B, CropWindow* cropWindow, Glib::ustring *oProfile, Glib::ustring *wProfile) : cropWindow(cropWindow), displayedValues(ColorPickerType::RGB), position(x, y), size(size), outputProfile(oProfile), workingProfile(wProfile), validity(Validity::OUTSIDE), - r(R), g(G), b(B), L(0.f), a(0.f), bb(0.f) + r(R), g(G), b(B), rpreview(R), gpreview(G), bpreview(B), L(0.f), a(0.f), bb(0.f) { - float h_, s_, v_; - rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h_, s_, v_); - h = (int)(h_*255.f); - s = (int)(s_*255.f); - v = (int)(v_*255.f); - + rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h, s, v); rtengine::Color::rgb2lab (*outputProfile, *workingProfile, r * 65535.f, g * 65535.f, b * 65535.f, L, a, bb, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? } @@ -52,6 +48,7 @@ void LockableColorPicker::updateBackBuffer () // -------------------- setting some key constants --------------------- const float circlePadding = 3.f; // keep this value odd + const double opacity = 0.62; // --------------------------------------------------------------------- if (validity == Validity::INSIDE) { @@ -63,32 +60,37 @@ void LockableColorPicker::updateBackBuffer () pangoContext->set_font_description (fontd); Glib::RefPtr layout[3][2]; + Glib::ustring s1, s2, s3; + PointerMotionListener* navigator = cropWindow->getPointerMotionListener (); switch (displayedValues) { case ColorPickerType::RGB: + navigator->getRGBText ((int)(r*255.f), (int)(g*255.f), (int)(b*255.f), s1, s2, s3); layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_R")); - layout[0][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(r*255.f))); + layout[0][1] = iArea->create_pango_layout(s1); layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_G")); - layout[1][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(g*255.f))); + layout[1][1] = iArea->create_pango_layout(s2); layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_B")); - layout[2][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(b*255.f))); + layout[2][1] = iArea->create_pango_layout(s3); break; case ColorPickerType::HSV: + navigator->getHSVText (h, s, v, s1, s2, s3); layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_H")); - layout[0][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(h*255.f))); + layout[0][1] = iArea->create_pango_layout(s1); layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_S")); - layout[1][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(s*255.f))); + layout[1][1] = iArea->create_pango_layout(s2); layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_V")); - layout[2][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(0), (int)(v*255.f))); + layout[2][1] = iArea->create_pango_layout(s3); break; case ColorPickerType::LAB: default: + navigator->getLABText (L, a, bb, s1, s2, s3); layout[0][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_L")); - layout[0][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(1), L)); + layout[0][1] = iArea->create_pango_layout(s1); layout[1][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_A")); - layout[1][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(1), a)); + layout[1][1] = iArea->create_pango_layout(s2); layout[2][0] = iArea->create_pango_layout(M("NAVIGATOR_LAB_B")); - layout[2][1] = iArea->create_pango_layout(Glib::ustring::format(std::fixed, std::setprecision(1), bb)); + layout[2][1] = iArea->create_pango_layout(s3); } int w00, w01, w10, w11, w20, w21, h00, h01, h10, h11, h20, h21; @@ -108,7 +110,6 @@ void LockableColorPicker::updateBackBuffer () const int textPadding = 3; const int textWidth = maxWCol0 + maxWCol1 + textPadding; const int textHeight = maxHRow0 + maxHRow1 + maxHRow2 + 2*textPadding; - const double opacity = 0.62; // --------------------------------------------------------------------- newW = rtengine::max((int)size + 2 * circlePadding, textWidth + 2 * textPadding); @@ -124,7 +125,6 @@ void LockableColorPicker::updateBackBuffer () bbcr->paint (); bbcr->set_operator (Cairo::OPERATOR_OVER); - // for drawing text bbcr->set_antialias (Cairo::ANTIALIAS_SUBPIXEL); bbcr->set_line_width (0.); @@ -154,7 +154,7 @@ void LockableColorPicker::updateBackBuffer () // spot disc with picked color bbcr->arc (center, center, center - circlePadding, 0., 2. * (double)M_PI); - bbcr->set_source_rgb (r, g, b); // <- set the picker color here + bbcr->set_source_rgb (rpreview, gpreview, bpreview); // <- set the picker color here bbcr->set_line_width (0.); bbcr->fill(); @@ -220,15 +220,24 @@ void LockableColorPicker::updateBackBuffer () setDrawRectangle(Cairo::FORMAT_ARGB32, 0, 0, newW, newH, true); Cairo::RefPtr bbcr = BackBuffer::getContext(); + + // cleaning the back buffer + bbcr->set_source_rgba (0., 0., 0., 0.); + bbcr->set_operator (Cairo::OPERATOR_CLEAR); + bbcr->paint (); + bbcr->set_operator (Cairo::OPERATOR_OVER); + bbcr->set_antialias(Cairo::ANTIALIAS_SUBPIXEL); float center = (float)size / 2.f + circlePadding; + + // light grey circle around the color mark bbcr->arc (center, center, center - circlePadding / 2., 0., 2. * (double)M_PI); - bbcr->set_source_rgb (0., 0., 0.); + bbcr->set_source_rgba (0., 0., 0., opacity); bbcr->set_line_width(circlePadding); bbcr->stroke_preserve(); - bbcr->set_source_rgb (1., 1., 1.); - bbcr->set_line_width(circlePadding - 2.); + bbcr->set_source_rgb (0.75, 0.75, 0.75); + bbcr->set_line_width (circlePadding - 2.); bbcr->stroke (); anchorOffset.set (center, center); @@ -254,7 +263,7 @@ void LockableColorPicker::draw (Cairo::RefPtr &cr) copySurface(cr); } -void LockableColorPicker::setPosition (const rtengine::Coord &newPos, const float R, const float G, const float B) +void LockableColorPicker::setPosition (const rtengine::Coord &newPos, const float R, const float G, float B, const float previewR, const float previewG, const float previewB) { // we're not checking bounds here, this will be done at rendering time position = newPos; @@ -263,12 +272,11 @@ void LockableColorPicker::setPosition (const rtengine::Coord &newPos, const floa g = G; b = B; - float h_, s_, v_; - rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h_, s_, v_); - h = (float)h_; - s = (float)s_; - v = (float)v_; + rpreview = previewR; + gpreview = previewG; + bpreview = previewB; + rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h, s, v); rtengine::Color::rgb2lab (*outputProfile, *workingProfile, r * 65535.f, g * 65535.f, b * 65535.f, L, a, bb, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? if (validity != Validity::OUTSIDE) { @@ -276,7 +284,7 @@ void LockableColorPicker::setPosition (const rtengine::Coord &newPos, const floa } } -void LockableColorPicker::setRGB (const float R, const float G, const float B) +void LockableColorPicker::setRGB (const float R, const float G, const float B, const float previewR, const float previewG, const float previewB) { if (r==R && g==G && b==B) { return; @@ -286,12 +294,11 @@ void LockableColorPicker::setRGB (const float R, const float G, const float B) g = G; b = B; - float h_, s_, v_; - rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h_, s_, v_); - h = (float)h_; - s = (float)s_; - v = (float)v_; + rpreview = previewR; + gpreview = previewG; + bpreview = previewB; + rtengine::Color::rgb2hsv(r*65535.f, g*65535.f, b*65535.f, h, s, v); rtengine::Color::rgb2lab (*outputProfile, *workingProfile, r * 65535.f, g * 65535.f, b * 65535.f, L, a, bb, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? if (validity != Validity::OUTSIDE) { @@ -374,3 +381,23 @@ void LockableColorPicker::decSize () setDirty(true); } } + +// return true if the picker has to be redrawn +bool LockableColorPicker::cycleRGB () +{ + if (displayedValues == ColorPickerType::RGB) { + setDirty (true); + return true; + } + return false; +} + +// return true if the picker has to be redrawn +bool LockableColorPicker::cycleHSV () +{ + if (displayedValues == ColorPickerType::HSV) { + setDirty (true); + return true; + } + return false; +} diff --git a/rtgui/lockablecolorpicker.h b/rtgui/lockablecolorpicker.h index c42f742c4..467df2d87 100644 --- a/rtgui/lockablecolorpicker.h +++ b/rtgui/lockablecolorpicker.h @@ -66,6 +66,7 @@ private: Glib::ustring *workingProfile; Validity validity; float r, g, b; // red green blue in [0;1] range + float rpreview, gpreview, bpreview; float h, s, v; // hue saturation value in [0;1] range float L, a, bb; // L*a*b value in [0;1] range @@ -79,8 +80,8 @@ public: void draw (Cairo::RefPtr &cr); // Used to update the RGB color, the HSV values will be updated accordingly - void setPosition (const rtengine::Coord &newPos, const float R, const float G, const float B); - void setRGB (const float R, const float G, const float B); + void setPosition (const rtengine::Coord &newPos, const float R, const float G, float B, const float previewR, const float previewG, const float previewB); + void setRGB (const float R, const float G, const float B, const float previewR, const float previewG, const float previewB); void getImagePosition (rtengine::Coord &imgPos); void getScreenPosition (rtengine::Coord &screenPos); Size getSize (); @@ -90,6 +91,8 @@ public: void rollDisplayedValues (); void incSize (); void decSize (); + bool cycleRGB (); + bool cycleHSV (); }; #endif diff --git a/rtgui/navigator.cc b/rtgui/navigator.cc index 0142df49f..2c724ee4c 100644 --- a/rtgui/navigator.cc +++ b/rtgui/navigator.cc @@ -215,6 +215,55 @@ void Navigator::setInvalid (int fullWidth, int fullHeight) LAB_L->set_text (M("NAVIGATOR_NA")); } +void Navigator::getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB) +{ + switch (currentRGBUnit) { + case (Options::NavigatorUnit::R0_1): + sR = Glib::ustring::format(std::fixed, std::setprecision(4), r / 255.f); + sG = Glib::ustring::format(std::fixed, std::setprecision(4), g / 255.f); + sB = Glib::ustring::format(std::fixed, std::setprecision(4), b / 255.f); + break; + case (Options::NavigatorUnit::R0_255): + sR = Glib::ustring::format(std::fixed, std::setprecision(0), r); + sG = Glib::ustring::format(std::fixed, std::setprecision(0), g); + sB = Glib::ustring::format(std::fixed, std::setprecision(0), b); + break; + case (Options::NavigatorUnit::PERCENT): + default: + sR = Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.f / 255.f) + Glib::ustring("%"); + sG = Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.f / 255.f) + Glib::ustring("%"); + sB = Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.f / 255.f) + Glib::ustring("%"); + } +} + +void Navigator::getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV) +{ + switch (currentHSVUnit) { + case (Options::NavigatorUnit::R0_1): + sH = Glib::ustring::format(std::fixed, std::setprecision(4), h); + sS = Glib::ustring::format(std::fixed, std::setprecision(4), s); + sV = Glib::ustring::format(std::fixed, std::setprecision(4), v); + break; + case (Options::NavigatorUnit::R0_255): + sH = Glib::ustring::format(std::fixed, std::setprecision(0), h * 255); + sS = Glib::ustring::format(std::fixed, std::setprecision(0), s * 255); + sV = Glib::ustring::format(std::fixed, std::setprecision(0), v * 255); + break; + case (Options::NavigatorUnit::PERCENT): + default: + sH = Glib::ustring::format(std::fixed, std::setprecision(1), h * 360.f) + Glib::ustring("\xc2\xb0"); + sS = Glib::ustring::format(std::fixed, std::setprecision(1), s * 100.f) + Glib::ustring("%"); + sV = Glib::ustring::format(std::fixed, std::setprecision(1), v * 100.f) + Glib::ustring("%"); + } +} + +void Navigator::getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB) +{ + sL = Glib::ustring::format(std::fixed, std::setprecision(1), l); + sA = Glib::ustring::format(std::fixed, std::setprecision(1), a); + sB = Glib::ustring::format(std::fixed, std::setprecision(1), b); +} + // if !validPos then x/y contain the full image size void Navigator::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) { @@ -222,54 +271,28 @@ void Navigator::pointerMoved (bool validPos, Glib::ustring profile, Glib::ustrin if (!validPos) { setInvalid (x, y); } else { + Glib::ustring s1, s2, s3; + float h, s, v; + float LAB_a, LAB_b, LAB_l; + position->set_text (Glib::ustring::compose ("x: %1, y: %2", x, y)); - switch (currentRGBUnit) { - case (Options::NavigatorUnit::R0_1): - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), r / 255.f)); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), g / 255.f)); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), b / 255.f)); - break; - case (Options::NavigatorUnit::R0_255): - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), r)); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), g)); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), b)); - break; - case (Options::NavigatorUnit::PERCENT): - default: - R->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), r * 100.f / 255.f) + Glib::ustring("%")); - G->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), g * 100.f / 255.f) + Glib::ustring("%")); - B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), b * 100.f / 255.f) + Glib::ustring("%")); - break; - } + getRGBText (r, g, b, s1, s2, s3); + R->set_text (s1); + G->set_text (s2); + B->set_text (s3); - float h, s, v; Color::rgb2hsv (r * 0xffff / 0xff, g * 0xffff / 0xff, b * 0xffff / 0xff, h, s, v); - switch (currentHSVUnit) { - case (Options::NavigatorUnit::R0_1): - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), h)); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), s)); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(4), v)); - break; - case (Options::NavigatorUnit::R0_255): - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), h * 255)); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), s * 255)); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(0), v * 255)); - break; - case (Options::NavigatorUnit::PERCENT): - default: - H->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), h * 360.f) + Glib::ustring("\xc2\xb0")); - S->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), s * 100.f) + Glib::ustring("%")); - V->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), v * 100.f) + Glib::ustring("%")); - break; - } + getHSVText (h, s, v, s1, s2, s3); + H->set_text (s1); + S->set_text (s2); + V->set_text (s3); - float LAB_a, LAB_b, LAB_l; - //rgb2lab (r, g, b, LAB_l, LAB_a, LAB_b); Color::rgb2lab (profile, profileW, r * 0xffff / 0xff, g * 0xffff / 0xff, b * 0xffff / 0xff, LAB_l, LAB_a, LAB_b, options.rtSettings.HistogramWorking); // TODO: Really sure this function works? - LAB_A->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_a)); - LAB_B->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_b)); - LAB_L->set_text (Glib::ustring::format(std::fixed, std::setprecision(1), LAB_l)); + getLABText (LAB_l, LAB_a, LAB_b, s1, s2, s3); + LAB_L->set_text (s1); + LAB_A->set_text (s2); + LAB_B->set_text (s3); } } @@ -299,6 +322,7 @@ void Navigator::cycleUnitsRGB (GdkEventButton *event) { B->set_text ("[%]"); break; } + sig_cycle_rgb.emit(); } void Navigator::cycleUnitsHSV (GdkEventButton *event) { @@ -327,4 +351,5 @@ void Navigator::cycleUnitsHSV (GdkEventButton *event) { V->set_text ("[%]"); break; } + sig_cycle_hsv.emit(); } diff --git a/rtgui/navigator.h b/rtgui/navigator.h index d7b9d2bae..647df7a34 100644 --- a/rtgui/navigator.h +++ b/rtgui/navigator.h @@ -57,6 +57,10 @@ public: // void pointerMoved (bool validPos, int x, int y, int r, int g, int b); void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b); + void getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB); + void getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV); + void getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB); + }; #endif diff --git a/rtgui/pointermotionlistener.h b/rtgui/pointermotionlistener.h index 46eb42476..09a9b3b4f 100644 --- a/rtgui/pointermotionlistener.h +++ b/rtgui/pointermotionlistener.h @@ -21,11 +21,26 @@ class PointerMotionListener { +protected: + sigc::signal sig_cycle_rgb; + sigc::signal sig_cycle_hsv; public: -// virtual void pointerMoved (bool validPos, int x, int y, int r, int g, int b) {} + virtual ~PointerMotionListener() {} virtual void pointerMoved (bool validPos, Glib::ustring profile, Glib::ustring profileW, int x, int y, int r, int g, int b) {} virtual void toggleFreeze () {} + virtual void getRGBText (int r, int g, int b, Glib::ustring &sR, Glib::ustring &sG, Glib::ustring &sB) { sR = "--"; sG = "--"; sB = "--"; } + virtual void getHSVText (float h, float s, float v, Glib::ustring &sH, Glib::ustring &sS, Glib::ustring &sV) { sH = "--"; sS = "--"; sV = "--"; } + virtual void getLABText (float l, float a, float b, Glib::ustring &sL, Glib::ustring &sA, Glib::ustring &sB) { sL = "--"; sA = "--"; sB = "--"; } + + sigc::signal signal_cycle_rgb() + { + return sig_cycle_rgb; + } + sigc::signal signal_cycle_hsv() + { + return sig_cycle_hsv; + } }; #endif