Commit 563269c9 authored by Miguel Lopez's avatar Miguel Lopez Committed by Andrey Kamakin

Quadratic Blending Modes

During the creation of Quadratic Blending Modes, I have did the following:

  - Add new category suitable for quadratic blending modes
 -  I copied and paste existing codes, and created new codes used to calculate blending of images accordingly to the Pegtop formula reference sheet
- I have tested the 4 new blending modes, and keep adjusting until the blending modes matches that of the Pegtop blending modes

- Before the testing plan, find a way to make freeze and heat with acceptable coding. Reflect Blend Mode has now been solved.

Test Plan:
- Have artists find usage of quadratic blend modes, and see if they find the blending modes useful
- Test results of quadratic blend modes with existing programs (As far as I"m concerned, only reflect and glow are available for testing)
-If all seem sounds, and ready to go, then maybe it can be patched in Krita

Reviewers: #krita, dkazakov

Subscribers: dkazakov

Tags: #krita

Differential Revision:
parent fb2056e7
......@@ -41,6 +41,7 @@ QString KoCompositeOp::categoryHSL() { return i18n("HSL"); }
QString KoCompositeOp::categoryHSV() { return i18n("HSV"); }
QString KoCompositeOp::categoryMix() { return i18n("Mix"); }
QString KoCompositeOp::categoryMisc() { return i18n("Misc"); }
QString KoCompositeOp::categoryQuadratic() { return i18n("Quadratic"); }
: opacity(1.0f),
......@@ -51,6 +51,7 @@ public:
static QString categoryHSV();
static QString categoryMix();
static QString categoryMisc();
static QString categoryQuadratic();
struct KRITAPIGMENT_EXPORT ParameterInfo
......@@ -43,7 +43,8 @@ KoCompositeOpRegistry::KoCompositeOpRegistry()
<< KoID("hsy" , i18n("HSY"))
<< KoID("hsi" , i18n("HSI"))
<< KoID("hsl" , i18n("HSL"))
<< KoID("hsv" , i18n("HSV"));
<< KoID("hsv" , i18n("HSV"))
<< KoID("quadratic" , i18n("Quadratic"));
m_map.insert(m_categories[0], KoID(COMPOSITE_ADD , i18n("Addition")));
m_map.insert(m_categories[0], KoID(COMPOSITE_SUBTRACT , i18n("Subtract")));
......@@ -137,6 +138,11 @@ KoCompositeOpRegistry::KoCompositeOpRegistry()
m_map.insert(m_categories[9], KoID(COMPOSITE_INC_SATURATION_HSV, i18n("Increase Saturation HSV")));
m_map.insert(m_categories[9], KoID(COMPOSITE_DEC_VALUE , i18n("Decrease Value")));
m_map.insert(m_categories[9], KoID(COMPOSITE_INC_VALUE , i18n("Increase Value")));
m_map.insert(m_categories[10], KoID(COMPOSITE_REFLECT , i18n("Reflect")));
m_map.insert(m_categories[10], KoID(COMPOSITE_GLOW , i18n("Glow")));
m_map.insert(m_categories[10], KoID(COMPOSITE_FREEZE , i18n("Freeze")));
m_map.insert(m_categories[10], KoID(COMPOSITE_HEAT , i18n("Heat")));
const KoCompositeOpRegistry& KoCompositeOpRegistry::instance()
......@@ -138,6 +138,12 @@ const QString COMPOSITE_DARKER_COLOR = "darker color";
const QString COMPOSITE_LIGHTER_COLOR = "lighter color";
const QString COMPOSITE_UNDEF = "undefined";
const QString COMPOSITE_REFLECT = "reflect";
const QString COMPOSITE_GLOW = "glow";
const QString COMPOSITE_FREEZE = "freeze";
const QString COMPOSITE_HEAT = "heat";
class KRITAPIGMENT_EXPORT KoCompositeOpRegistry
......@@ -453,4 +453,51 @@ inline T cfDarkenOnly(T src, T dst) { return qMin(src, dst); }
template<class T>
inline T cfLightenOnly(T src, T dst) { return qMax(src, dst); }
template<class T>
inline T cfGlow(T src, T dst) {
using namespace Arithmetic;
// see for formulas of Quadratic Blending Modes like Glow, Reflect, Freeze, and Heat
if(dst == unitValue<T>()) {
return unitValue<T>();
if(src == zeroValue<T>()) {
return zeroValue<T>();
return clamp<T>(div(mul(src, src), inv(dst)));
template<class T>
inline T cfReflect(T src, T dst) {
using namespace Arithmetic;
return (cfGlow(dst,src));
template<class T>
inline T cfHeat(T src, T dst) {
using namespace Arithmetic;
// Heat, and Freeze only works properly on 8-bit images. It does not work properly on any other color depth. For now, if Heat and Freeze are proven useful for 8-bit painting, then there should be some way of solving this issue.
if(dst == zeroValue<T>()) {
return zeroValue<T>();
if(src == unitValue<T>()) {
return unitValue<T>();
return inv(clamp<T>(div(mul(inv(src), inv(src)),dst)));
template<class T>
inline T cfFreeze(T src, T dst) {
using namespace Arithmetic;
return clamp<T>(cfHeat(dst,src));
......@@ -153,6 +153,11 @@ struct AddGeneralOps<Traits, true>
add<&cfExclusion<Arg> >(cs, COMPOSITE_EXCLUSION , i18n("Exclusion") , KoCompositeOp::categoryNegative());
add<&cfEquivalence<Arg> >(cs, COMPOSITE_EQUIVALENCE , i18n("Equivalence") , KoCompositeOp::categoryNegative());
add<&cfAdditiveSubtractive<Arg> >(cs, COMPOSITE_ADDITIVE_SUBTRACTIVE , i18n("Additive-Subtractive") , KoCompositeOp::categoryNegative());
add<&cfReflect<Arg> >(cs, COMPOSITE_REFLECT , i18n("Reflect") , KoCompositeOp::categoryQuadratic());
add<&cfGlow<Arg> >(cs, COMPOSITE_GLOW , i18n("Glow") , KoCompositeOp::categoryQuadratic());
add<&cfFreeze<Arg> >(cs, COMPOSITE_FREEZE , i18n("Freeze") , KoCompositeOp::categoryQuadratic());
add<&cfHeat<Arg> >(cs, COMPOSITE_HEAT , i18n("Heat") , KoCompositeOp::categoryQuadratic());
cs->addCompositeOp(new KoCompositeOpDissolve<Traits>(cs, KoCompositeOp::categoryMisc()));
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