diff --git a/src/qml/filters/color/ui.qml b/src/qml/filters/color/ui.qml index 89c599b703..4f55b81d80 100644 --- a/src/qml/filters/color/ui.qml +++ b/src/qml/filters/color/ui.qml @@ -28,7 +28,7 @@ Item { property bool blockUpdate: true width: 455 height: 280 - + Component.onCompleted: { if (filter.isNew) { // Set default parameter values @@ -49,22 +49,69 @@ Item { function loadValues() { var position = getPosition() blockUpdate = true + // Force a color change to make sure the color wheel is updated. + liftRedSpinner.value = 1.0 + gammaRedSpinner.value = 1.0 + gainRedSpinner.value = 1.0 liftRedSpinner.value = filter.getDouble("lift_r", position) * 100.0 liftGreenSpinner.value = filter.getDouble("lift_g", position) * 100.0 liftBlueSpinner.value = filter.getDouble("lift_b", position) * 100.0 - gammaRedSpinner.value = filter.getDouble("gamma_r", position) * 100.0 / gammaFactor - gammaGreenSpinner.value = filter.getDouble("gamma_g", position) * 100.0 / gammaFactor - gammaBlueSpinner.value = filter.getDouble("gamma_b", position) * 100.0 / gammaFactor - gainRedSpinner.value = filter.getDouble("gain_r", position) * 100.0 / gainFactor - gainGreenSpinner.value = filter.getDouble("gain_g", position) * 100.0 / gainFactor - gainBlueSpinner.value = filter.getDouble("gain_b", position) * 100.0 / gainFactor + gammaRedSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gamma_r", position), gammaFactor)) + gammaGreenSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gamma_g", position), gammaFactor)) + gammaBlueSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gamma_b", position), gammaFactor)) + gainRedSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gain_r", position), gainFactor)) + gainGreenSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gain_g", position), gainFactor)) + gainBlueSpinner.value = wheelToSpinner(scaleValueToWheel(filter.getDouble("gain_b", position), gainFactor)) blockUpdate = false } - + function getPosition() { return Math.max(producer.position - (filter.in - producer.in), 0) } + function scaleWheelToValue(w, f) { + // The color wheel value (w) range is [0.0 - 1.0]. For the gamma and gain + // gain parameters, we want to scale that to [0.0 - f] where (f) is the + // maximum scaling factor. The middle of the wheel (0.5) needs to map to + // a filter value of 1.0 (no change). Since this could be a non-linear + // scaling, we use the quadratic equation: + // f(x) = ax**2 + bx + c + // With the following point mappings: + // f(0) = 0 + // f(0.5) = 1 + // f(1) = f (scaling factor) + // This reduces to: + // a = 2f - 4 + // b = f - a + // c = 0 + var a = (2*f) - 4 + var b = f - a + return a * (w*w) + b*w + } + + function scaleValueToWheel(v, f) { + // Do the opposite of scaleWheelToValue + var a = (2*f) - 4 + var b = f - a + if (a == 0) { + // For a = 0, the function is linear + return v / f + } else { + // The solution to the quadratic formula reduces to: + return ((b*-1.0) + Math.sqrt((b*b) + (4*a*v))) / (2*a) + } + } + + function wheelToSpinner(w) { + // Convert a wheel value [0.0 - 1.0] to a spinner value [-100.0 - 100.0] + return (w * 2.0 - 1.0) * 100.0 + } + + function spinnerToWheel(s) { + // Convert a spinner value [-100.0 - 100.0] to wheel value [0.0 - 1.0] + return (s / 100.0 + 1.0) / 2.0 + } + GridLayout { columns: 9 anchors.fill: parent @@ -112,16 +159,16 @@ Item { Layout.alignment: Qt.AlignLeft onToggled: { if (checked) { - filter.set('lift_r', liftwheel.redF, getPosition()) - filter.set('lift_g', liftwheel.greenF, getPosition()) - filter.set('lift_b', liftwheel.blueF, getPosition()) + filter.set('lift_r', liftwheel.redF * 2.0 - 1.0, getPosition()) + filter.set('lift_g', liftwheel.greenF * 2.0 - 1.0, getPosition()) + filter.set('lift_b', liftwheel.blueF * 2.0 - 1.0, getPosition()) } else { filter.resetProperty('lift_r') filter.resetProperty('lift_g') filter.resetProperty('lift_b') - filter.set('lift_r', liftwheel.redF) - filter.set('lift_g', liftwheel.greenF) - filter.set('lift_b', liftwheel.blueF) + filter.set('lift_r', liftwheel.redF * 2.0 - 1.0) + filter.set('lift_g', liftwheel.greenF * 2.0 - 1.0) + filter.set('lift_b', liftwheel.blueF * 2.0 - 1.0) } } } @@ -130,10 +177,10 @@ Item { Layout.alignment: Qt.AlignRight onClicked: { // Force a color change to make sure the color wheel is updated. - gammaRedSpinner.value = 1.0 / gammaFactor - gammaRedSpinner.value = 100.0 / gammaFactor - gammaGreenSpinner.value = 100.0 / gammaFactor - gammaBlueSpinner.value = 100.0 / gammaFactor + gammaRedSpinner.value = 100.0 + gammaRedSpinner.value = 0.0 + gammaGreenSpinner.value = 0.0 + gammaBlueSpinner.value = 0.0 } } KeyframesButton { @@ -142,16 +189,16 @@ Item { Layout.alignment: Qt.AlignLeft onToggled: { if (checked) { - filter.set('gamma_r', gammawheel.redF * gammaFactor, getPosition()) - filter.set('gamma_g', gammawheel.greenF * gammaFactor, getPosition()) - filter.set('gamma_b', gammawheel.blueF * gammaFactor, getPosition()) + filter.set('gamma_r', scaleWheelToValue(gammawheel.redF, gammaFactor), getPosition()) + filter.set('gamma_g', scaleWheelToValue(gammawheel.greenF, gammaFactor), getPosition()) + filter.set('gamma_b', scaleWheelToValue(gammawheel.blueF, gammaFactor), getPosition()) } else { filter.resetProperty('gamma_r') filter.resetProperty('gamma_g') filter.resetProperty('gamma_b') - filter.set('gamma_r', gammawheel.redF * gammaFactor) - filter.set('gamma_g', gammawheel.greenF * gammaFactor) - filter.set('gamma_b', gammawheel.blueF * gammaFactor) + filter.set('gamma_r', scaleWheelToValue(gammawheel.redF, gammaFactor)) + filter.set('gamma_g', scaleWheelToValue(gammawheel.greenF, gammaFactor)) + filter.set('gamma_b', scaleWheelToValue(gammawheel.blueF, gammaFactor)) } } } @@ -160,10 +207,10 @@ Item { Layout.alignment: Qt.AlignRight onClicked: { // Force a color change to make sure the color wheel is updated. - gainRedSpinner.value = 1.0 / gainFactor - gainRedSpinner.value = 100.0 / gainFactor - gainGreenSpinner.value = 100.0 / gainFactor - gainBlueSpinner.value = 100.0 / gainFactor + gainRedSpinner.value = 100.0 + gainRedSpinner.value = 0.0 + gainGreenSpinner.value = 0.0 + gainBlueSpinner.value = 0.0 } } KeyframesButton { @@ -172,16 +219,16 @@ Item { Layout.alignment: Qt.AlignLeft onToggled: { if (checked) { - filter.set('gain_r', gainwheel.redF * gainFactor, getPosition()) - filter.set('gain_g', gainwheel.greenF * gainFactor, getPosition()) - filter.set('gain_b', gainwheel.blueF * gainFactor, getPosition()) + filter.set('gain_r', scaleWheelToValue(gainwheel.redF, gainFactor), getPosition()) + filter.set('gain_g', scaleWheelToValue(gainwheel.greenF, gainFactor), getPosition()) + filter.set('gain_b', scaleWheelToValue(gainwheel.blueF, gainFactor), getPosition()) } else { filter.resetProperty('gain_r') filter.resetProperty('gain_g') filter.resetProperty('gain_b') - filter.set('gain_r', gainwheel.redF * gainFactor) - filter.set('gain_g', gainwheel.greenF * gainFactor) - filter.set('gain_b', gainwheel.blueF * gainFactor) + filter.set('gain_r', scaleWheelToValue(gainwheel.redF, gainFactor)) + filter.set('gain_g', scaleWheelToValue(gainwheel.greenF, gainFactor)) + filter.set('gain_b', scaleWheelToValue(gainwheel.blueF, gainFactor)) } } } @@ -195,29 +242,30 @@ Item { Layout.alignment : Qt.AlignCenter | Qt.AlignTop Layout.minimumHeight: 75 Layout.maximumHeight: 300 + step: 0.0005 onColorChanged: { - if( liftRedSpinner.value != liftwheel.redF * 100.0 ) { - liftRedSpinner.value = liftwheel.redF * 100.0 + if( liftRedSpinner.value != wheelToSpinner(liftwheel.redF) ) { + liftRedSpinner.value = wheelToSpinner(liftwheel.redF) } - if( liftGreenSpinner.value != liftwheel.greenF * 100.0 ) { - liftGreenSpinner.value = liftwheel.greenF * 100.0 + if( liftGreenSpinner.value != wheelToSpinner(liftwheel.greenF) ) { + liftGreenSpinner.value = wheelToSpinner(liftwheel.greenF) } - if( liftBlueSpinner.value != liftwheel.blueF * 100.0 ) { - liftBlueSpinner.value = liftwheel.blueF * 100.0 + if( liftBlueSpinner.value != wheelToSpinner(liftwheel.blueF) ) { + liftBlueSpinner.value = wheelToSpinner(liftwheel.blueF) } if (!blockUpdate) { if (!liftKeyframesButton.checked) { filter.resetProperty('lift_r') filter.resetProperty('lift_g') filter.resetProperty('lift_b') - filter.set('lift_r', liftwheel.redF) - filter.set('lift_g', liftwheel.greenF) - filter.set('lift_b', liftwheel.blueF) + filter.set('lift_r', liftwheel.redF * 2.0 - 1.0) + filter.set('lift_g', liftwheel.greenF * 2.0 - 1.0) + filter.set('lift_b', liftwheel.blueF * 2.0 - 1.0) } else { var position = getPosition() - filter.set('lift_r', liftwheel.redF, position) - filter.set('lift_g', liftwheel.greenF, position) - filter.set('lift_b', liftwheel.blueF, position) + filter.set('lift_r', liftwheel.redF * 2.0 - 1.0, position) + filter.set('lift_g', liftwheel.greenF * 2.0 - 1.0, position) + filter.set('lift_b', liftwheel.blueF * 2.0 - 1.0, position) } } } @@ -230,29 +278,30 @@ Item { Layout.alignment : Qt.AlignCenter | Qt.AlignTop Layout.minimumHeight: 75 Layout.maximumHeight: 300 + step: 0.0005 onColorChanged: { - if( gammaRedSpinner.value != gammawheel.redF * 100.0 ) { - gammaRedSpinner.value = gammawheel.redF * 100.0 + if( gammaRedSpinner.value != wheelToSpinner(gammawheel.redF) ) { + gammaRedSpinner.value = wheelToSpinner(gammawheel.redF) } - if( gammaGreenSpinner.value != gammawheel.greenF * 100.0 ) { - gammaGreenSpinner.value = gammawheel.greenF * 100.0 + if( gammaGreenSpinner.value != wheelToSpinner(gammawheel.greenF) ) { + gammaGreenSpinner.value = wheelToSpinner(gammawheel.greenF) } - if( gammaBlueSpinner.value != gammawheel.blueF * 100.0 ) { - gammaBlueSpinner.value = gammawheel.blueF * 100.0 + if( gammaBlueSpinner.value != wheelToSpinner(gammawheel.blueF) ) { + gammaBlueSpinner.value = wheelToSpinner(gammawheel.blueF) } if (!blockUpdate) { if (!gammaKeyframesButton.checked) { filter.resetProperty('gamma_r') filter.resetProperty('gamma_g') filter.resetProperty('gamma_b') - filter.set('gamma_r', gammawheel.redF * gammaFactor) - filter.set('gamma_g', gammawheel.greenF * gammaFactor) - filter.set('gamma_b', gammawheel.blueF * gammaFactor) + filter.set('gamma_r', scaleWheelToValue(gammawheel.redF, gammaFactor)) + filter.set('gamma_g', scaleWheelToValue(gammawheel.greenF, gammaFactor)) + filter.set('gamma_b', scaleWheelToValue(gammawheel.blueF, gammaFactor)) } else { var position = getPosition() - filter.set('gamma_r', gammawheel.redF * gammaFactor, position) - filter.set('gamma_g', gammawheel.greenF * gammaFactor, position) - filter.set('gamma_b', gammawheel.blueF * gammaFactor, position) + filter.set('gamma_r', scaleWheelToValue(gammawheel.redF, gammaFactor), position) + filter.set('gamma_g', scaleWheelToValue(gammawheel.greenF, gammaFactor), position) + filter.set('gamma_b', scaleWheelToValue(gammawheel.blueF, gammaFactor), position) } } } @@ -265,29 +314,30 @@ Item { Layout.alignment : Qt.AlignCenter | Qt.AlignTop Layout.minimumHeight: 75 Layout.maximumHeight: 300 + step: 0.0005 onColorChanged: { - if( gainRedSpinner.value != gainwheel.redF * 100.0 ) { - gainRedSpinner.value = gainwheel.redF * 100.0 + if( gainRedSpinner.value != wheelToSpinner(gainwheel.redF) ) { + gainRedSpinner.value = wheelToSpinner(gainwheel.redF) } - if( gainGreenSpinner.value != gainwheel.greenF * 100.0 ) { - gainGreenSpinner.value = gainwheel.greenF * 100.0 + if( gainGreenSpinner.value != wheelToSpinner(gainwheel.greenF) ) { + gainGreenSpinner.value = wheelToSpinner(gainwheel.greenF) } - if( gainBlueSpinner.value != gainwheel.blueF * 100.0 ) { - gainBlueSpinner.value = gainwheel.blueF * 100.0 + if( gainBlueSpinner.value != wheelToSpinner(gainwheel.blueF) ) { + gainBlueSpinner.value = wheelToSpinner(gainwheel.blueF) } if (!blockUpdate) { if (!gainKeyframesButton.checked) { filter.resetProperty('gain_r') filter.resetProperty('gain_g') filter.resetProperty('gain_b') - filter.set('gain_r', gainwheel.redF * gainFactor) - filter.set('gain_g', gainwheel.greenF * gainFactor) - filter.set('gain_b', gainwheel.blueF * gainFactor) + filter.set('gain_r', scaleWheelToValue(gainwheel.redF, gainFactor)) + filter.set('gain_g', scaleWheelToValue(gainwheel.greenF, gainFactor)) + filter.set('gain_b', scaleWheelToValue(gainwheel.blueF, gainFactor)) } else { var position = getPosition() - filter.set('gain_r', gainwheel.redF * gainFactor, position) - filter.set('gain_g', gainwheel.greenF * gainFactor, position) - filter.set('gain_b', gainwheel.blueF * gainFactor, position) + filter.set('gain_r', scaleWheelToValue(gainwheel.redF, gainFactor), position) + filter.set('gain_g', scaleWheelToValue(gainwheel.greenF, gainFactor), position) + filter.set('gain_b', scaleWheelToValue(gainwheel.blueF, gainFactor), position) } } } @@ -301,14 +351,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: liftRedSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( liftwheel.redF != value / 100.0 ) { - liftwheel.redF = value / 100.0 + if( liftwheel.redF != spinnerToWheel(value) ) { + liftwheel.redF = spinnerToWheel(value) } } } @@ -320,14 +370,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gammaRedSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gammawheel.redF != value / 100.0 ) { - gammawheel.redF = value / 100.0 + if( gammawheel.redF != spinnerToWheel(value) ) { + gammawheel.redF = spinnerToWheel(value) } } } @@ -339,14 +389,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gainRedSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gainwheel.redF != value / 100.0 ) { - gainwheel.redF = value / 100.0 + if( gainwheel.redF != spinnerToWheel(value) ) { + gainwheel.redF = spinnerToWheel(value) } } } @@ -360,14 +410,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: liftGreenSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( liftwheel.greenF != value / 100.0 ) { - liftwheel.greenF = value / 100.0 + if( liftwheel.greenF != spinnerToWheel(value) ) { + liftwheel.greenF = spinnerToWheel(value) } } } @@ -379,14 +429,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gammaGreenSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gammawheel.greenF != value / 100.0 ) { - gammawheel.greenF = value / 100.0 + if( gammawheel.greenF != spinnerToWheel(value) ) { + gammawheel.greenF = spinnerToWheel(value) } } } @@ -398,14 +448,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gainGreenSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gainwheel.greenF != value / 100.0 ) { - gainwheel.greenF = value / 100.0 + if( gainwheel.greenF != spinnerToWheel(value) ) { + gainwheel.greenF = spinnerToWheel(value) } } } @@ -419,14 +469,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: liftBlueSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( liftwheel.blueF != value / 100.0 ) { - liftwheel.blueF = value / 100.0 + if( liftwheel.blueF != spinnerToWheel(value) ) { + liftwheel.blueF = spinnerToWheel(value) } } } @@ -438,14 +488,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gammaBlueSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gammawheel.blueF != value / 100.0 ) { - gammawheel.blueF = value / 100.0 + if( gammawheel.blueF != spinnerToWheel(value) ) { + gammawheel.blueF = spinnerToWheel(value) } } } @@ -457,14 +507,14 @@ Item { SpinBox { Layout.alignment: Qt.AlignHCenter | Qt.AlignVCenter id: gainBlueSpinner - minimumValue: 0 + minimumValue: -100 maximumValue: 100 decimals: 1 stepSize: 0.1 suffix: ' %' onValueChanged: { - if( gainwheel.blueF != value / 100.0 ) { - gainwheel.blueF = value / 100.0 + if( gainwheel.blueF != spinnerToWheel(value) ) { + gainwheel.blueF = spinnerToWheel(value) } } } diff --git a/src/qmltypes/colorwheelitem.cpp b/src/qmltypes/colorwheelitem.cpp index 1b29e4d4e5..94b9e50175 100644 --- a/src/qmltypes/colorwheelitem.cpp +++ b/src/qmltypes/colorwheelitem.cpp @@ -38,6 +38,7 @@ ColorWheelItem::ColorWheelItem(QQuickItem *parent) , m_color(0, 0, 0, 0) , m_isInWheel(false) , m_isInSquare(false) + , m_step(1/256) { setAcceptedMouseButtons(Qt::LeftButton); setAcceptHoverEvents(true); @@ -141,6 +142,16 @@ void ColorWheelItem::setBlueF(qreal blue) } } +qreal ColorWheelItem::step() +{ + return m_step; +} + +void ColorWheelItem::setStep(qreal step) +{ + m_step = step; +} + int ColorWheelItem::wheelSize() const { qreal ws = (qreal)width() / (1.0 + 1.0 / WHEEL_SLIDER_RATIO); @@ -222,28 +233,28 @@ void ColorWheelItem::hoverMoveEvent(QHoverEvent * event) void ColorWheelItem::wheelEvent(QWheelEvent *event) { QPoint steps = event->angleDelta() / 8 / 15; - int delta = steps.y(); + qreal delta = (qreal)steps.y() * m_step; QColor currentColor = color(); - int c; + qreal c; // Increment/decrement RGB values by delta - c = currentColor.red(); + c = currentColor.redF(); c += delta; if(c < 0) c = 0; - if(c > 255) c = 255; - currentColor.setRed(c); + if(c > 1) c = 1; + currentColor.setRedF(c); - c = currentColor.green(); + c = currentColor.greenF(); c += delta; if(c < 0) c = 0; - if(c > 255) c = 255; - currentColor.setGreen(c); + if(c > 1) c = 1; + currentColor.setGreenF(c); - c = currentColor.blue(); + c = currentColor.blueF(); c += delta; if(c < 0) c = 0; - if(c > 255) c = 255; - currentColor.setBlue(c); + if(c > 1) c = 1; + currentColor.setBlueF(c); setColor(currentColor); diff --git a/src/qmltypes/colorwheelitem.h b/src/qmltypes/colorwheelitem.h index 8d88cbad66..cd8572d8d0 100644 --- a/src/qmltypes/colorwheelitem.h +++ b/src/qmltypes/colorwheelitem.h @@ -33,6 +33,7 @@ class ColorWheelItem : public QQuickPaintedItem Q_PROPERTY(qreal redF READ redF WRITE setRedF) Q_PROPERTY(qreal greenF READ greenF WRITE setGreenF) Q_PROPERTY(qreal blueF READ blueF WRITE setBlueF) + Q_PROPERTY(qreal step READ step WRITE setStep) public: explicit ColorWheelItem(QQuickItem *parent = 0); QColor color(); @@ -49,6 +50,9 @@ class ColorWheelItem : public QQuickPaintedItem void setGreenF(qreal green); qreal blueF(); void setBlueF(qreal blue); + qreal step(); + void setStep(qreal blue); + signals: void colorChanged(const QColor &color); @@ -72,6 +76,7 @@ class ColorWheelItem : public QQuickPaintedItem QColor m_color; bool m_isInWheel; bool m_isInSquare; + qreal m_step; int wheelSize() const; QColor colorForPoint(const QPoint &point);