Commit 5255a67f authored by Jouni Pentikäinen's avatar Jouni Pentikäinen

Extend cubic curves for use as relative adjustments

This consists of allowing separate input and output ranges in
KisCurveWidget and extending the "no-op" checks in KisCubicCurve
to allow checking for constant output curves.
parent 10f84748
......@@ -408,7 +408,7 @@ void KisCubicCurve::removePoint(int idx)
d->data->invalidate();
}
bool KisCubicCurve::isNull() const
bool KisCubicCurve::isIdentity() const
{
const QList<QPointF> &points = d->data->points;
......@@ -421,6 +421,19 @@ bool KisCubicCurve::isNull() const
return true;
}
bool KisCubicCurve::isConstant(qreal c) const
{
const QList<QPointF> &points = d->data->points;
Q_FOREACH (const QPointF &pt, points) {
if (!qFuzzyCompare(c, pt.y())) {
return false;
}
}
return true;
}
const QString& KisCubicCurve::name() const
{
return d->data->name;
......
......@@ -54,7 +54,15 @@ public:
int addPoint(const QPointF& point);
void removePoint(int idx);
bool isNull() const;
/*
* Check whether the curve maps all values to themselves.
*/
bool isIdentity() const;
/*
* Check whether the curve maps all values to given constant.
*/
bool isConstant(qreal c) const;
/**
* This allows us to carry around a display name for the curve internally. It is used
......
......@@ -142,10 +142,10 @@ void KisCubicCurveTest::testValue()
void KisCubicCurveTest::testNull()
{
KisCubicCurve cc;
QVERIFY(cc.isNull());
QVERIFY(cc.isIdentity());
cc.addPoint(QPointF(0.2, 0.3));
QVERIFY(!cc.isNull());
QVERIFY(!cc.isIdentity());
QList<QPointF> points;
points << QPointF();
......@@ -153,7 +153,7 @@ void KisCubicCurveTest::testNull()
points << QPointF(1.0,1.0);
cc.setPoints(points);
QVERIFY(cc.isNull());
QVERIFY(cc.isIdentity());
}
......
......@@ -90,7 +90,7 @@ KisCurveWidget::~KisCurveWidget()
delete d;
}
void KisCurveWidget::setupInOutControls(QSpinBox *in, QSpinBox *out, int min, int max)
void KisCurveWidget::setupInOutControls(QSpinBox *in, QSpinBox *out, int inMin, int inMax, int outMin, int outMax)
{
d->m_intIn = in;
d->m_intOut = out;
......@@ -98,12 +98,13 @@ void KisCurveWidget::setupInOutControls(QSpinBox *in, QSpinBox *out, int min, in
if (!d->m_intIn || !d->m_intOut)
return;
d->m_inOutMin = min;
d->m_inOutMax = max;
d->m_intIn->setRange(d->m_inOutMin, d->m_inOutMax);
d->m_intOut->setRange(d->m_inOutMin, d->m_inOutMax);
d->m_inMin = inMin;
d->m_inMax = inMax;
d->m_outMin = outMin;
d->m_outMax = outMax;
d->m_intIn->setRange(d->m_inMin, d->m_inMax);
d->m_intOut->setRange(d->m_outMin, d->m_outMax);
connect(d->m_intIn, SIGNAL(valueChanged(int)), this, SLOT(inOutChanged(int)));
connect(d->m_intOut, SIGNAL(valueChanged(int)), this, SLOT(inOutChanged(int)));
......@@ -128,8 +129,8 @@ void KisCurveWidget::inOutChanged(int)
Q_ASSERT(d->m_grab_point_index >= 0);
pt.setX(d->io2sp(d->m_intIn->value()));
pt.setY(d->io2sp(d->m_intOut->value()));
pt.setX(d->io2sp(d->m_intIn->value(), d->m_inMin, d->m_inMax));
pt.setY(d->io2sp(d->m_intOut->value(), d->m_outMin, d->m_outMax));
if (d->jumpOverExistingPoints(pt, d->m_grab_point_index)) {
d->m_curve.setPoint(d->m_grab_point_index, pt);
......@@ -142,8 +143,8 @@ void KisCurveWidget::inOutChanged(int)
d->m_intIn->blockSignals(true);
d->m_intOut->blockSignals(true);
d->m_intIn->setValue(d->sp2io(pt.x()));
d->m_intOut->setValue(d->sp2io(pt.y()));
d->m_intIn->setValue(d->sp2io(pt.x(), d->m_inMin, d->m_inMax));
d->m_intOut->setValue(d->sp2io(pt.y(), d->m_outMin, d->m_outMax));
d->m_intIn->blockSignals(false);
d->m_intOut->blockSignals(false);
......
......@@ -137,9 +137,10 @@ public:
/**
* Connect/disconnect external spinboxes to the curve
* @min/@max - is the range for their values
* @inMin/@inMax - is the range for input values
* @outMin/@outMax - is the range for output values
*/
void setupInOutControls(QSpinBox *in, QSpinBox *out, int min, int max);
void setupInOutControls(QSpinBox *in, QSpinBox *out, int inMin, int inMax, int outMin, int outMax);
void dropInOutControls();
/**
......
......@@ -67,8 +67,10 @@ public:
QSpinBox *m_intOut;
/* Working range of them */
int m_inOutMin;
int m_inOutMax;
int m_inMin;
int m_inMax;
int m_outMin;
int m_outMax;
/**
* State functions.
......@@ -95,8 +97,8 @@ public:
* In/Out controls to normalized
* range of spline (and reverse)
*/
double io2sp(int x);
int sp2io(double x);
double io2sp(int x, int min, int max);
int sp2io(double x, int min, int max);
/**
......@@ -135,16 +137,16 @@ KisCurveWidget::Private::Private(KisCurveWidget *parent)
m_curveWidget = parent;
}
double KisCurveWidget::Private::io2sp(int x)
double KisCurveWidget::Private::io2sp(int x, int min, int max)
{
int rangeLen = m_inOutMax - m_inOutMin;
return double(x - m_inOutMin) / rangeLen;
int rangeLen = max - min;
return double(x - min) / rangeLen;
}
int KisCurveWidget::Private::sp2io(double x)
int KisCurveWidget::Private::sp2io(double x, int min, int max)
{
int rangeLen = m_inOutMax - m_inOutMin;
return int(x*rangeLen + 0.5) + m_inOutMin;
int rangeLen = max - min;
return int(x*rangeLen + 0.5) + min;
}
......@@ -231,8 +233,8 @@ void KisCurveWidget::Private::syncIOControls()
m_intIn->blockSignals(true);
m_intOut->blockSignals(true);
m_intIn->setValue(sp2io(m_curve.points()[m_grab_point_index].x()));
m_intOut->setValue(sp2io(m_curve.points()[m_grab_point_index].y()));
m_intIn->setValue(sp2io(m_curve.points()[m_grab_point_index].x(), m_inMin, m_inMax));
m_intOut->setValue(sp2io(m_curve.points()[m_grab_point_index].y(), m_outMin, m_outMax));
m_intIn->blockSignals(false);
m_intOut->blockSignals(false);
......
......@@ -11,7 +11,8 @@ public:
void setPoint(int idx, const QPointF& point);
int addPoint(const QPointF& point);
void removePoint(int idx);
bool isNull() const;
bool isIdentity() const;
bool isConstant(qreal x) const;
void setName(const QString& name);
const QString& name() const;
QString toString() const;
......
......@@ -100,7 +100,7 @@ void KisPerChannelConfigWidget::updateChannelControls()
break;
}
m_page->curveWidget->setupInOutControls(m_page->intIn, m_page->intOut, min, max);
m_page->curveWidget->setupInOutControls(m_page->intIn, m_page->intOut, min, max, min, max);
}
......@@ -198,35 +198,35 @@ KoColorTransformation* KisPerChannelFilter::createTransformation(const KoColorSp
alphaIndexInReal = realTransfers.size() - 1;
}
if (colorsNull && !originalCurves[i].isNull()) {
if (colorsNull && !originalCurves[i].isIdentity()) {
colorsNull = false;
}
} else if (virtualChannels[i].type() == VirtualChannelInfo::HUE) {
KIS_ASSERT_RECOVER_NOOP(hueTransfer.isEmpty());
hueTransfer = originalTransfers[i];
if (hueNull && !originalCurves[i].isNull()) {
if (hueNull && !originalCurves[i].isIdentity()) {
hueNull = false;
}
} else if (virtualChannels[i].type() == VirtualChannelInfo::SATURATION) {
KIS_ASSERT_RECOVER_NOOP(saturationTransfer.isEmpty());
saturationTransfer = originalTransfers[i];
if (saturationNull && !originalCurves[i].isNull()) {
if (saturationNull && !originalCurves[i].isIdentity()) {
saturationNull = false;
}
} else if (virtualChannels[i].type() == VirtualChannelInfo::LIGHTNESS) {
KIS_ASSERT_RECOVER_NOOP(lightnessTransfer.isEmpty());
lightnessTransfer = originalTransfers[i];
if (lightnessNull && !originalCurves[i].isNull()) {
if (lightnessNull && !originalCurves[i].isIdentity()) {
lightnessNull = false;
}
} else if (virtualChannels[i].type() == VirtualChannelInfo::ALL_COLORS) {
KIS_ASSERT_RECOVER_NOOP(allColorsTransfer.isEmpty());
allColorsTransfer = originalTransfers[i];
if (allColorsNull && !originalCurves[i].isNull()) {
if (allColorsNull && !originalCurves[i].isIdentity()) {
allColorsNull = false;
}
}
......
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