diff --git a/libs/ui/widgets/kis_gradient_slider.h b/libs/ui/widgets/kis_gradient_slider.h --- a/libs/ui/widgets/kis_gradient_slider.h +++ b/libs/ui/widgets/kis_gradient_slider.h @@ -76,6 +76,8 @@ void enableWhite(bool b); + void setInverted(bool b); + private: int m_leftmost; int m_rightmost; @@ -93,6 +95,7 @@ bool m_gammaEnabled; bool m_whiteEnabled; bool m_feedback; + bool m_inverted; }; #endif /* KIS_GRADIENT_SLIDER_H */ diff --git a/libs/ui/widgets/kis_gradient_slider.cpp b/libs/ui/widgets/kis_gradient_slider.cpp --- a/libs/ui/widgets/kis_gradient_slider.cpp +++ b/libs/ui/widgets/kis_gradient_slider.cpp @@ -53,6 +53,7 @@ , m_gammaEnabled(false) , m_whiteEnabled(true) , m_feedback(false) + , m_inverted(false) { m_grabCursor = None; @@ -90,25 +91,31 @@ p1.drawRect(MARGIN, MARGIN, wWidth, height() - 2 * MARGIN - HANDLE_SIZE); // Draw first gradient - QLinearGradient grayGradient(MARGIN, 0, wWidth, gradientHeight); - grayGradient.setColorAt(0, Qt::black); - grayGradient.setColorAt(1, Qt::white); + QLinearGradient grayGradient(MARGIN, y, wWidth, gradientHeight); + grayGradient.setColorAt(0, m_inverted ? Qt::white : Qt::black); + grayGradient.setColorAt(1, m_inverted ? Qt::black : Qt::white); p1.fillRect(MARGIN, 0, wWidth, gradientHeight, QBrush(grayGradient)); // Draw second gradient y = gradientHeight; p1.fillRect(MARGIN, y, wWidth, gradientHeight, Qt::white); - if (m_blackCursor > 0) { + if (m_blackCursor > 0 && !m_inverted) { p1.fillRect(MARGIN, y, m_blackCursor, gradientHeight, Qt::black); + } else if (m_blackCursor < wWidth && m_inverted) { + p1.fillRect(MARGIN + m_blackCursor, y, wWidth - m_blackCursor, gradientHeight, Qt::black); } - for (x = (int)m_blackCursor + MARGIN; x < (int)m_whiteCursor - MARGIN; ++x) { - double inten = (double)(x - (m_blackCursor + MARGIN)) / (double)((m_whiteCursor - MARGIN) - (m_blackCursor + MARGIN)); + + int left = qMin(m_blackCursor, m_whiteCursor); + int right = qMax(m_blackCursor, m_whiteCursor); + for (x = left; x <= right; ++x) { + double inten = (double)(x - m_blackCursor) / + (double)(m_whiteCursor - m_blackCursor); inten = pow(inten, (1.0 / m_gamma)); int gray = (int)(255 * inten); p1.setPen(QColor(gray, gray, gray)); - p1.drawLine(x, y, x, y + gradientHeight - 1); + p1.drawLine(x + MARGIN, y, x + MARGIN, y + gradientHeight - 1); } // Draw cursors @@ -127,57 +134,57 @@ p1.setPen(Qt::black); if (m_gammaEnabled) { - a[0] = QPoint(m_gammaCursor, y); - a[1] = QPoint(m_gammaCursor + cursorHalfBase, wHeight - 1); - a[2] = QPoint(m_gammaCursor - cursorHalfBase, wHeight - 1); + a[0] = QPoint(m_gammaCursor + MARGIN, y); + a[1] = QPoint(m_gammaCursor + MARGIN + cursorHalfBase, wHeight - 1); + a[2] = QPoint(m_gammaCursor + MARGIN - cursorHalfBase, wHeight - 1); p1.setBrush(Qt::gray); p1.drawPolygon(a, 3); } if (m_whiteEnabled) { - a[0] = QPoint(m_whiteCursor - MARGIN, y); - a[1] = QPoint(m_whiteCursor - MARGIN + cursorHalfBase, wHeight - 1); - a[2] = QPoint(m_whiteCursor - MARGIN - cursorHalfBase, wHeight - 1); + a[0] = QPoint(m_whiteCursor + MARGIN, y); + a[1] = QPoint(m_whiteCursor + MARGIN + cursorHalfBase, wHeight - 1); + a[2] = QPoint(m_whiteCursor + MARGIN - cursorHalfBase, wHeight - 1); p1.setBrush(Qt::white); p1.drawPolygon(a, 3); } } void KisGradientSlider::resizeEvent(QResizeEvent *) { - m_scalingFactor = (double)(width() - MARGIN) / 255; + m_scalingFactor = (double)(width() - 2 * MARGIN) / 255; calculateCursorPositions(); update(); } -void KisGradientSlider::mousePressEvent(QMouseEvent * e) +void KisGradientSlider::mousePressEvent(QMouseEvent *e) { eCursor closest_cursor; int distance; if (e->button() != Qt::LeftButton) return; unsigned int x = e->pos().x(); - int xPlusMargin = x + MARGIN; + int xMinusMargin = x - MARGIN; distance = width() + 1; // just a big number - if (abs((int)(xPlusMargin - m_blackCursor)) < distance) { - distance = abs((int)(xPlusMargin - m_blackCursor)); + if (abs((int)(xMinusMargin - m_blackCursor)) < distance) { + distance = abs((int)(xMinusMargin - m_blackCursor)); closest_cursor = BlackCursor; } - if (abs((int)(xPlusMargin - m_whiteCursor)) < distance) { - distance = abs((int)(xPlusMargin - m_whiteCursor)); + if (abs((int)(xMinusMargin - m_whiteCursor)) < distance) { + distance = abs((int)(xMinusMargin - m_whiteCursor)); closest_cursor = WhiteCursor; } if (m_gammaEnabled) { - int gammaDistance = (int)xPlusMargin - m_gammaCursor; + int gammaDistance = (int)xMinusMargin - m_gammaCursor; if (abs(gammaDistance) < distance) { - distance = abs((int)xPlusMargin - m_gammaCursor); + distance = abs((int)xMinusMargin - m_gammaCursor); closest_cursor = GammaCursor; } else if (abs(gammaDistance) == distance) { if ((closest_cursor == BlackCursor) && (gammaDistance > 0)) { @@ -199,30 +206,40 @@ switch (closest_cursor) { case BlackCursor: - m_blackCursor = x - MARGIN; + m_blackCursor = xMinusMargin; m_grabCursor = closest_cursor; - m_leftmost = 0; - m_rightmost = m_whiteCursor - ((MARGIN + 1) * m_scalingFactor); + if (m_inverted) { + m_leftmost = m_whiteCursor + 1; + m_rightmost = width() - 2 * MARGIN - 1; + } else { + m_leftmost = 0; + m_rightmost = m_whiteCursor - 1; + } if (m_gammaEnabled) m_gammaCursor = calculateGammaCursor(); break; case WhiteCursor: - m_whiteCursor = x + MARGIN; + m_whiteCursor = xMinusMargin; m_grabCursor = closest_cursor; - m_leftmost = m_blackCursor + (MARGIN * m_scalingFactor); - m_rightmost = width() - MARGIN ; + if (m_inverted) { + m_leftmost = 0; + m_rightmost = m_blackCursor - 1; + } else { + m_leftmost = m_blackCursor + 1; + m_rightmost = width() - 2 * MARGIN - 1; + } if (m_gammaEnabled) m_gammaCursor = calculateGammaCursor(); break; case GammaCursor: m_gammaCursor = x; m_grabCursor = closest_cursor; - m_leftmost = m_blackCursor + (MARGIN * m_scalingFactor); - m_rightmost = m_whiteCursor - (MARGIN * m_scalingFactor); + m_leftmost = qMin(m_blackCursor, m_whiteCursor); + m_rightmost = qMax(m_blackCursor, m_whiteCursor); { double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0; double mid = (double)m_blackCursor + delta + MARGIN; - double tmp = (x - mid) / delta; + double tmp = (xMinusMargin - mid) / delta; m_gamma = 1.0 / pow(10, tmp); } break; @@ -241,12 +258,12 @@ switch (m_grabCursor) { case BlackCursor: - m_black = qRound( m_blackCursor / m_scalingFactor); + m_black = qRound(m_blackCursor / m_scalingFactor); m_feedback = true; emit sigModifiedBlack(m_black); break; case WhiteCursor: - m_white = qRound( (m_whiteCursor - MARGIN) / m_scalingFactor); + m_white = qRound(m_whiteCursor / m_scalingFactor); m_feedback = true; emit sigModifiedWhite(m_white); break; @@ -264,37 +281,37 @@ void KisGradientSlider::mouseMoveEvent(QMouseEvent * e) { int x = e->pos().x(); - + int xMinusMargin = x - MARGIN; if (m_grabCursor != None) { // Else, drag the selected point - if (x + MARGIN <= m_leftmost) - x = m_leftmost; + if (xMinusMargin <= m_leftmost) + xMinusMargin = m_leftmost; - if (x >= m_rightmost) - x = m_rightmost; + if (xMinusMargin >= m_rightmost) + xMinusMargin = m_rightmost; switch (m_grabCursor) { case BlackCursor: - if (m_blackCursor != x) { - m_blackCursor = x; + if (m_blackCursor != xMinusMargin) { + m_blackCursor = xMinusMargin; if (m_gammaEnabled) { m_gammaCursor = calculateGammaCursor(); } } break; case WhiteCursor: - if (m_whiteCursor != x) { - m_whiteCursor = x + MARGIN; + if (m_whiteCursor != xMinusMargin) { + m_whiteCursor = xMinusMargin; if (m_gammaEnabled) { m_gammaCursor = calculateGammaCursor(); } } break; case GammaCursor: - if (m_gammaCursor != x) { - m_gammaCursor = x; + if (m_gammaCursor != xMinusMargin) { + m_gammaCursor = xMinusMargin; double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0; double mid = (double)m_blackCursor + delta; - double tmp = (x - mid) / delta; + double tmp = (xMinusMargin - mid) / delta; m_gamma = 1.0 / pow(10, tmp); } break; @@ -309,16 +326,16 @@ void KisGradientSlider::calculateCursorPositions() { m_blackCursor = qRound(m_black * m_scalingFactor); - m_whiteCursor = qRound(m_white * m_scalingFactor + MARGIN); + m_whiteCursor = qRound(m_white * m_scalingFactor); m_gammaCursor = calculateGammaCursor(); } unsigned int KisGradientSlider::calculateGammaCursor() { double delta = (double)(m_whiteCursor - m_blackCursor) / 2.0; - double mid = (double)m_blackCursor + delta; - double tmp = log10(1.0 / m_gamma); + double mid = (double)m_blackCursor + delta; + double tmp = log10(1.0 / m_gamma); return (unsigned int)qRound(mid + delta * tmp); } @@ -341,24 +358,37 @@ update(); } +void KisGradientSlider::setInverted(bool b) +{ + m_inverted = b; + update(); +} + void KisGradientSlider::slotModifyBlack(int v) { - if (v >= 0 && v <= (int)m_white && !m_feedback) { - m_black = v; - m_blackCursor = qRound(m_black * m_scalingFactor); - m_gammaCursor = calculateGammaCursor(); - update(); - } + if ((m_inverted && (v < m_white || v > width())) || + (!m_inverted && (v < 0 || v > m_white)) || + m_feedback) + return; + + m_black = v; + m_blackCursor = qRound(m_black * m_scalingFactor); + m_gammaCursor = calculateGammaCursor(); + update(); } + void KisGradientSlider::slotModifyWhite(int v) { - if (v >= (int)m_black && v <= width() && !m_feedback) { - m_white = v; - m_whiteCursor = qRound(m_white * m_scalingFactor + MARGIN); - m_gammaCursor = calculateGammaCursor(); - update(); - } + if ((m_inverted && (v < 0 || v > m_white)) || + (!m_inverted && (v < m_black && v > width())) || + m_feedback) + return; + m_white = v; + m_whiteCursor = qRound(m_white * m_scalingFactor); + m_gammaCursor = calculateGammaCursor(); + update(); } + void KisGradientSlider::slotModifyGamma(double v) { if (m_gamma != v) { diff --git a/plugins/filters/levelfilter/kis_level_filter.h b/plugins/filters/levelfilter/kis_level_filter.h --- a/plugins/filters/levelfilter/kis_level_filter.h +++ b/plugins/filters/levelfilter/kis_level_filter.h @@ -75,10 +75,14 @@ void slotModifyOutWhiteLimit(int); void slotAutoLevel(void); + void slotInvert(void); + + void resetOutSpinLimit(); protected: QScopedPointer m_histogram; bool m_histlog; + bool m_inverted; }; #endif diff --git a/plugins/filters/levelfilter/kis_level_filter.cpp b/plugins/filters/levelfilter/kis_level_filter.cpp --- a/plugins/filters/levelfilter/kis_level_filter.cpp +++ b/plugins/filters/levelfilter/kis_level_filter.cpp @@ -134,13 +134,15 @@ connect(m_page.outgradient, SIGNAL(sigModifiedWhite(int)), m_page.outwhitespin, SLOT(setValue(int))); connect(m_page.butauto, SIGNAL(clicked(bool)), this, SLOT(slotAutoLevel(void))); + connect(m_page.butinvert, SIGNAL(clicked(bool)), this, SLOT(slotInvert(void))); connect((QObject*)(m_page.chkLogarithmic), SIGNAL(toggled(bool)), this, SLOT(slotDrawHistogram(bool))); KoHistogramProducer *producer = new KoGenericLabHistogramProducer(); m_histogram.reset( new KisHistogram(dev, dev->exactBounds(), producer, LINEAR) ); m_histlog = false; m_page.histview->resize(288,100); + m_inverted = false; slotDrawHistogram(); } @@ -207,12 +209,18 @@ void KisLevelConfigWidget::slotModifyOutBlackLimit(int limit) { - m_page.outblackspin->setMaximum(limit - 1); + if (m_inverted) { + m_page.outblackspin->setMinimum(limit + 1); + }else + m_page.outblackspin->setMaximum(limit - 1); } void KisLevelConfigWidget::slotModifyOutWhiteLimit(int limit) { - m_page.outwhitespin->setMinimum(limit + 1); + if (m_inverted) + m_page.outwhitespin->setMaximum(limit - 1); + else + m_page.outwhitespin->setMinimum(limit + 1); } void KisLevelConfigWidget::slotAutoLevel(void) @@ -273,6 +281,18 @@ } } +void KisLevelConfigWidget::slotInvert(void) +{ + m_inverted = !m_inverted; + int white = m_page.outwhitespin->value(); + int black = m_page.outblackspin->value(); + + resetOutSpinLimit(); + m_page.outgradient->setInverted(m_inverted); + m_page.outwhitespin->setValue(black); + m_page.outblackspin->setValue(white); +} + KisPropertiesConfigurationSP KisLevelConfigWidget::configuration() const { KisColorTransformationConfiguration * config = new KisColorTransformationConfiguration(KisLevelFilter::id().id(), 1); @@ -310,3 +330,13 @@ m_page.outgradient->slotModifyWhite(value.toUInt()); } } + +void KisLevelConfigWidget::resetOutSpinLimit() { + if (m_inverted) { + m_page.outblackspin->setMaximum(255); + m_page.outwhitespin->setMinimum(0); + } else { + m_page.outblackspin->setMinimum(0); + m_page.outwhitespin->setMaximum(255); + } +} diff --git a/plugins/filters/levelfilter/wdg_level.ui b/plugins/filters/levelfilter/wdg_level.ui --- a/plugins/filters/levelfilter/wdg_level.ui +++ b/plugins/filters/levelfilter/wdg_level.ui @@ -289,6 +289,13 @@ + + + &Invert + + + + Qt::Horizontal