Commit 3a3010ca authored by Boudewijn Rempt's avatar Boudewijn Rempt

Add an invert button to the level filter widget

Differential Revision: https://phabricator.kde.org/D9052
BUG:375842
CCMAIL:vincentl13x@gmail.com

Patch by Wu Weilin -- thanks!
parent 5077699b
......@@ -53,6 +53,7 @@ KisGradientSlider::KisGradientSlider(QWidget *parent)
, m_gammaEnabled(false)
, m_whiteEnabled(true)
, m_feedback(false)
, m_inverted(false)
{
m_grabCursor = None;
......@@ -90,25 +91,31 @@ void KisGradientSlider::paintEvent(QPaintEvent *e)
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,17 +134,17 @@ void KisGradientSlider::paintEvent(QPaintEvent *e)
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);
}
......@@ -145,12 +152,12 @@ void KisGradientSlider::paintEvent(QPaintEvent *e)
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;
......@@ -159,25 +166,25 @@ void KisGradientSlider::mousePressEvent(QMouseEvent * e)
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 @@ void KisGradientSlider::mousePressEvent(QMouseEvent * e)
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 @@ void KisGradientSlider::mouseReleaseEvent(QMouseEvent * e)
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::mouseReleaseEvent(QMouseEvent * e)
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,7 +326,7 @@ void KisGradientSlider::mouseMoveEvent(QMouseEvent * e)
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();
}
......@@ -317,8 +334,8 @@ void KisGradientSlider::calculateCursorPositions()
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 @@ void KisGradientSlider::enableWhite(bool b)
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) {
......
......@@ -76,6 +76,8 @@ public:
void enableWhite(bool b);
void setInverted(bool b);
private:
int m_leftmost;
int m_rightmost;
......@@ -93,6 +95,7 @@ private:
bool m_gammaEnabled;
bool m_whiteEnabled;
bool m_feedback;
bool m_inverted;
};
#endif /* KIS_GRADIENT_SLIDER_H */
......@@ -134,6 +134,7 @@ KisLevelConfigWidget::KisLevelConfigWidget(QWidget * parent, KisPaintDeviceSP de
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)));
......@@ -141,6 +142,7 @@ KisLevelConfigWidget::KisLevelConfigWidget(QWidget * parent, KisPaintDeviceSP de
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,20 @@ void KisLevelConfigWidget::slotModifyInWhiteLimit(int limit)
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 +283,18 @@ void KisLevelConfigWidget::slotAutoLevel(void)
}
}
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 +332,13 @@ void KisLevelConfigWidget::setConfiguration(const KisPropertiesConfigurationSP
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);
}
}
......@@ -75,10 +75,14 @@ protected Q_SLOTS:
void slotModifyOutWhiteLimit(int);
void slotAutoLevel(void);
void slotInvert(void);
void resetOutSpinLimit();
protected:
QScopedPointer<KisHistogram> m_histogram;
bool m_histlog;
bool m_inverted;
};
#endif
......@@ -288,6 +288,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="butinvert">
<property name="text">
<string>&amp;Invert</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment