This is a multi-part message in MIME format.
--------------080501060900080908060607
Content-Type: multipart/alternative;
boundary="------------050209040906090300030902"
--------------050209040906090300030902
Content-Type: text/plain; charset=ISO-8859-1; format=flowed
Content-Transfer-Encoding: 7bit
Phew... I think I've gone a bit mad with the blending modes :D.
I added a few. When counting everything together there should be nearly
40 compositing modes now.
All modes should trait partly transparent layers as Photoshop is doing
it and all modes should
respect the channel flags.
But there are two problems with this patch:
1. I used a pretty generic approach. So it relies on the compiler to do
proper inlining. And i didn't use the optimized multiply functions. I
had a few problems with those functions, because it seems the give no
correct results but approximations. So I still need to check out which
composite modes will work with the optimized functions. I just want to
say that it could be that this is a bit/much slower then the current
implementation (i don't know how much time you spend in optimizing this).
I personally haven't noticed any speed impact but I've got a 3GHz quad
core, so i think i will be the last
who will notice this.
2. The "Hue" and "Saturation" modes are not working correctly but the
"Luminosity" and "Color" modes work exactly as in Photoshop. I coded the
algorithms after the ISO 3200-1 spec. Adobe released the texts they gave
to the ISO committee for specification. You can find them here:
http://www.adobe.com/devnet/pdf.html
http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
(direct link)
go to the category "Transparency" -> "Basic Composition Computations".
This spec is of course for PDFs but it seems that Photoshop uses the
same formulas.
Since "Luminosity" and "Color" modes are working i think i made some
mistake in implementing the
"setSat" function (on page 327). Maybe someone else has an
enlightenment, because I'm working in the dark right now :D.
But apart from this two problems everything else should work fine
(hopefully).
--------------050209040906090300030902
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
Phew... I think I've gone a bit mad with the blending modes :D.
I added a few. When counting everything together there should be
nearly 40 compositing modes now.
All modes should trait partly transparent layers as Photoshop is
doing it and all modes should
respect the channel flags.
But there are two problems with this patch:
1. I used a pretty generic approach. So it relies on the compiler to
do proper inlining. And i didn't use the optimized multiply
functions. I had a few problems with those functions, because it
seems the give no correct results but approximations. So I still
need to check out which composite modes will work with the optimized
functions. I just want to say that it could be that this is a
bit/much slower then the current implementation (i don't know how
much time you spend in optimizing this).
I personally haven't noticed any speed impact but I've got a 3GHz
quad core, so i think i will be the last
who will notice this.
2. The "Hue" and "Saturation" modes are not working correctly but
the "Luminosity" and "Color" modes work exactly as in Photoshop. I
coded the algorithms after the ISO 3200-1 spec. Adobe released the
texts they gave to the ISO committee for specification. You can find
them here:
http://www.adobe.com/devnet/pdf.html
http://www.adobe.com/content/dam/Adobe/en/devnet/acrobat/pdfs/PDF32000_2008.pdf
(direct link)
go to the category "Transparency" -> "Basic Composition
Computations". This spec is of course for PDFs but it seems that
Photoshop uses the same formulas.
Since "Luminosity" and "Color" modes are working i think i made some
mistake in implementing the
"setSat" function (on page 327). Maybe someone else has an
enlightenment, because I'm working in the dark right now :D.
But apart from this two problems everything else should work fine
(hopefully).
--------------050209040906090300030902--
--------------080501060900080908060607
Content-Type: text/x-diff;
name="BlendModes.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment;
filename="BlendModes.patch"
From a2f91b86e96919ca5ff5a506933d9d798218f93f Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Wed, 5 Jan 2011 00:43:52 +0100
Subject: [PATCH 01/15] Fixed the Burn composite option.
Should now work exactly like the Color burn mode in Photoshop
but only for fully opaque colors. Transparency is not considered jet.
---
libs/pigment/compositeops/KoCompositeOpBurn.h | 25 ++++++++++++++-----------
1 files changed, 14 insertions(+), 11 deletions(-)
diff --git a/libs/pigment/compositeops/KoCompositeOpBurn.h b/libs/pigment/compositeops/KoCompositeOpBurn.h
index 97feaa4..2a56e2f 100644
--- a/libs/pigment/compositeops/KoCompositeOpBurn.h
+++ b/libs/pigment/compositeops/KoCompositeOpBurn.h
@@ -29,7 +29,8 @@ template
class KoCompositeOpBurn : public KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpBurn<_CSTraits>, true >
{
typedef typename _CSTraits::channels_type channels_type;
- typedef typename KoColorSpaceMathsTraits::compositetype compositetype;
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+
public:
KoCompositeOpBurn(const KoColorSpace * cs)
@@ -48,20 +49,22 @@ public:
const QBitArray & channelFlags) {
for (uint i = 0; i < _CSTraits::channels_nb; i++) {
if ((int)i != _CSTraits::alpha_pos && (allChannelFlags || channelFlags.testBit(i))) {
- compositetype srcColor = src[i];
- compositetype dstColor = dst[i];
-
- srcColor = qMin(((NATIVE_MAX_VALUE - dstColor) * (NATIVE_MAX_VALUE + 1)) / (srcColor + 1), (compositetype)NATIVE_MAX_VALUE);
- if (NATIVE_MAX_VALUE - srcColor > NATIVE_MAX_VALUE) srcColor = NATIVE_MAX_VALUE;
-
- channels_type newColor = NATIVE_MAX_VALUE - KoColorSpaceMaths::blend(srcColor, dstColor, srcBlend);
-
- dst[i] = newColor;
+ composite_type unitValue = KoColorSpaceMathsTraits::unitValue;
+ composite_type invDst = unitValue - dst[i];
+
+ if(src[i] != KoColorSpaceMathsTraits::zeroValue) {
+ composite_type result = unitValue - qMin(invDst * unitValue / src[i], unitValue);
+ dst[i] = KoColorSpaceMaths::blend(result, dst[i], srcBlend);
+ }
+ else {
+ //composite_type result = KoColorSpaceMathsTraits::zeroValue;
+ composite_type result = unitValue - qMin(invDst * unitValue, unitValue);
+ dst[i] = KoColorSpaceMaths::blend(result, dst[i], srcBlend);
+ }
}
}
}
-
};
#endif
--
1.7.1
From dd43f07e61d643153e260875276f38f33ae1af03 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Fri, 7 Jan 2011 19:14:15 +0100
Subject: [PATCH 02/15] Made burn and dodge CompositeOs compatible with Adobe Photoshop (c)
Added a new generic base class for CompositeOps, currently only used by
KoCompositeOpBurn and KoCompositeOpDodge.
---
libs/pigment/compositeops/KoCompositeOpBurn.h | 49 ++---
libs/pigment/compositeops/KoCompositeOpDodge.h | 49 +++---
libs/pigment/compositeops/KoCompositeOpFunctions.h | 193 ++++++++++++++++++++
3 files changed, 236 insertions(+), 55 deletions(-)
create mode 100644 libs/pigment/compositeops/KoCompositeOpFunctions.h
diff --git a/libs/pigment/compositeops/KoCompositeOpBurn.h b/libs/pigment/compositeops/KoCompositeOpBurn.h
index 2a56e2f..3315373 100644
--- a/libs/pigment/compositeops/KoCompositeOpBurn.h
+++ b/libs/pigment/compositeops/KoCompositeOpBurn.h
@@ -20,51 +20,42 @@
#ifndef KOCOMPOSITEOPBURN_H_
#define KOCOMPOSITEOPBURN_H_
-#include "KoCompositeOpAlphaBase.h"
+#include "KoCompositeOpFunctions.h"
/**
* A template version of the burn composite operation to use in colorspaces.
*/
template
-class KoCompositeOpBurn : public KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpBurn<_CSTraits>, true >
+class KoCompositeOpBurn : public KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >
{
typedef typename _CSTraits::channels_type channels_type;
typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ static const qint32 channels_nb = _CSTraits::channels_nb;
+ static const qint32 alpha_pos = _CSTraits::alpha_pos;
public:
-
- KoCompositeOpBurn(const KoColorSpace * cs)
- : KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpBurn<_CSTraits>, true >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight()) {
- }
+ KoCompositeOpBurn(const KoColorSpace* cs)
+ : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight()) { }
public:
- inline static channels_type selectAlpha(channels_type srcAlpha, channels_type dstAlpha) {
- return qMin(srcAlpha, dstAlpha);
- }
-
- inline static void composeColorChannels(channels_type srcBlend,
- const channels_type* src,
- channels_type* dst,
- bool allChannelFlags,
- const QBitArray & channelFlags) {
- for (uint i = 0; i < _CSTraits::channels_nb; i++) {
- if ((int)i != _CSTraits::alpha_pos && (allChannelFlags || channelFlags.testBit(i))) {
- composite_type unitValue = KoColorSpaceMathsTraits::unitValue;
- composite_type invDst = unitValue - dst[i];
-
- if(src[i] != KoColorSpaceMathsTraits::zeroValue) {
- composite_type result = unitValue - qMin(invDst * unitValue / src[i], unitValue);
- dst[i] = KoColorSpaceMaths::blend(result, dst[i], srcBlend);
- }
- else {
- //composite_type result = KoColorSpaceMathsTraits::zeroValue;
- composite_type result = unitValue - qMin(invDst * unitValue, unitValue);
- dst[i] = KoColorSpaceMaths::blend(result, dst[i], srcBlend);
+ inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
+ channels_type* dst, channels_type dstAlpha,
+ channels_type opacity, const QBitArray& channelFlags) {
+ srcAlpha = mul(srcAlpha, opacity);
+
+ channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
+
+ if(newDstAlpha != KoColorSpaceMathsTraits::zeroValue) {
+ for(qint32 i=0; i );
+ dst[i] = div(result, newDstAlpha);
}
}
}
+
+ return newDstAlpha;
}
-
};
#endif
diff --git a/libs/pigment/compositeops/KoCompositeOpDodge.h b/libs/pigment/compositeops/KoCompositeOpDodge.h
index 368a26b..019695a 100644
--- a/libs/pigment/compositeops/KoCompositeOpDodge.h
+++ b/libs/pigment/compositeops/KoCompositeOpDodge.h
@@ -1,6 +1,7 @@
/*
* Copyright (c) 2007 Cyrille Berger
- *
+ * Copyright (c) 2011 Silvio Heinrich
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -20,44 +21,40 @@
#ifndef _KOCOMPOSITEOPDODGE_H_
#define _KOCOMPOSITEOPDODGE_H_
-#include "KoCompositeOpAlphaBase.h"
-
+#include "KoCompositeOpFunctions.h"
/**
* A template version of the dodge composite operation to use in colorspaces.
*/
template
-class KoCompositeOpDodge : public KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpDodge<_CSTraits>, true >
+class KoCompositeOpDodge : public KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >
{
typedef typename _CSTraits::channels_type channels_type;
- typedef typename KoColorSpaceMathsTraits::compositetype compositetype;
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ static const qint32 channels_nb = _CSTraits::channels_nb;
+ static const qint32 alpha_pos = _CSTraits::alpha_pos;
public:
-
KoCompositeOpDodge(const KoColorSpace * cs)
- : KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpDodge<_CSTraits>, true >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight()) {
- }
+ : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight()) { }
public:
- inline static channels_type selectAlpha(channels_type srcAlpha, channels_type dstAlpha) {
- return qMin(srcAlpha, dstAlpha);
- }
- inline static void composeColorChannels(channels_type srcBlend,
- const channels_type* src,
- channels_type* dst,
- bool allChannelFlags,
- const QBitArray & channelFlags) {
- for (uint channel = 0; channel < _CSTraits::channels_nb; channel++) {
- if ((int)channel != _CSTraits::alpha_pos && (allChannelFlags || channelFlags.testBit(channel))) {
- compositetype srcColor = src[channel];
- compositetype dstColor = dst[channel];
-
- srcColor = qMin((compositetype)(dstColor * (NATIVE_MAX_VALUE + 1)) / (NATIVE_MAX_VALUE + 1 - srcColor), (compositetype)NATIVE_MAX_VALUE);
-
- channels_type newColor = KoColorSpaceMaths::blend(srcColor, dstColor, srcBlend);
-
- dst[channel] = newColor;
+ inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
+ channels_type* dst, channels_type dstAlpha,
+ channels_type opacity, const QBitArray& channelFlags) {
+ srcAlpha = mul(srcAlpha, opacity);
+
+ channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
+
+ if(newDstAlpha != KoColorSpaceMathsTraits::zeroValue) {
+ for(qint32 i=0; i );
+ dst[i] = div(result, newDstAlpha);
+ }
}
}
+
+ return newDstAlpha;
}
};
diff --git a/libs/pigment/compositeops/KoCompositeOpFunctions.h b/libs/pigment/compositeops/KoCompositeOpFunctions.h
new file mode 100644
index 0000000..bdd3af7
--- /dev/null
+++ b/libs/pigment/compositeops/KoCompositeOpFunctions.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2011 Silvio Heinrich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KOCOMPOSITEOPFUNCTIONS_H_
+#define KOCOMPOSITEOPFUNCTIONS_H_
+
+#include
+#include
+#include
+
+/* --------------------- Arithmetic functions ----------------------------- /
+ * definitions of standard arithmetic functions. all computations are meant
+ * to be performed on normalized values (in the range of 0.0 - 1.0)
+ * if non floating point types are used, fixed point arithmetic is used
+ */
+
+template
+inline T mul(T a, T b) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return T(composite_type(a) * composite_type(b) / KoColorSpaceMathsTraits::unitValue);
+}
+
+template
+inline T mul(T a, T b, T c) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return T((composite_type(a) * b * c) / (composite_type(KoColorSpaceMathsTraits::unitValue) * KoColorSpaceMathsTraits::unitValue));
+}
+
+template
+inline typename KoColorSpaceMathsTraits::compositetype
+div(T a, T b) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return composite_type(a) * KoColorSpaceMathsTraits::unitValue / composite_type(b);
+}
+
+template
+inline T inv(T a) {
+ return KoColorSpaceMathsTraits::unitValue - a;
+}
+
+template
+inline T clamp(typename KoColorSpaceMathsTraits::compositetype a) {
+ return (a > KoColorSpaceMathsTraits::unitValue) ? KoColorSpaceMathsTraits::unitValue : T(a);
+}
+
+template
+inline T lerp(T a, T b, T alpha) {
+ return KoColorSpaceMaths::blend(b, a, alpha);
+}
+
+template
+inline TRet scale(T a) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return TRet(composite_type(a) * KoColorSpaceMathsTraits::unitValue / KoColorSpaceMathsTraits::unitValue);
+}
+
+/* ---------------- Blending/Compositing functions ------------------------ /
+ * definitions of standard blending/compositing functions compatible
+ * to the ISO 32000-1 specification (for PDF filed) which also defines
+ * the compositing functions who are also used in Adobe Photoshop (c)
+ */
+
+template
+inline T unionShapeOpacy(T a, T b) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return T(composite_type(a) + b - mul(a,b));
+}
+
+template
+inline T blend(T src, T srcAlpha, T dst, T dstAlpha, TFunc blendFunc) {
+ return mul(inv(srcAlpha), dstAlpha, dst) + mul(inv(dstAlpha), srcAlpha, src) + mul(dstAlpha, srcAlpha, blendFunc(src, dst));
+}
+
+template
+inline T cfColorBurn(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+
+ if(src != KoColorSpaceMathsTraits::zeroValue)
+ return inv(clamp(div(inv(dst), src)));
+
+ return KoColorSpaceMathsTraits::zeroValue;
+}
+
+template
+inline T cfColorDodge(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+
+ if(src != KoColorSpaceMathsTraits::unitValue)
+ return clamp(div(dst, inv(src)));
+
+ return KoColorSpaceMathsTraits::unitValue;
+}
+
+/**
+ * A template base class that can be used for most composite modes/ops
+ *
+ * @param _compositeOp this template parameter is a class that must be
+ * derived fom KoCompositeOpBase and must define the static member function
+ * inline static channels_type composeColorChannels(
+ * const channels_type* src,
+ * channels_type srcAlpha,
+ * channels_type* dst,
+ * channels_type dstAlpha,
+ * channels_type opacity,
+ * const QBitArray& channelFlags
+ * )
+ *
+ * where channels_type is _CSTraits::channels_type
+ */
+template
+class KoCompositeOpBase : public KoCompositeOp
+{
+ typedef typename _CSTraits::channels_type channels_type;
+ static const qint32 channels_nb = _CSTraits::channels_nb;
+ static const qint32 alpha_pos = _CSTraits::alpha_pos;
+
+public:
+
+ KoCompositeOpBase(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category)
+ : KoCompositeOp(cs, id, description, category) { }
+
+private:
+ template
+ void genericComposite(quint8* dstRowStart , qint32 dstRowStride ,
+ const quint8* srcRowStart , qint32 srcRowStride ,
+ const quint8* maskRowStart, qint32 maskRowStride,
+ qint32 rows, qint32 cols, quint8 U8_opacity, const QBitArray& channelFlags) const {
+
+ qint32 srcInc = (srcRowStride == 0) ? 0 : channels_nb;
+ bool useMask = maskRowStart != 0;
+ channels_type unitValue = KoColorSpaceMathsTraits::unitValue;
+ channels_type opacity = KoColorSpaceMaths::scaleToA(U8_opacity);
+
+ for(; rows>0; --rows) {
+ const channels_type* src = reinterpret_cast(srcRowStart);
+ channels_type* dst = reinterpret_cast(dstRowStart);
+ const quint8* mask = maskRowStart;
+
+ for(qint32 c=cols; c>0; --c) {
+ channels_type srcAlpha = (alpha_pos == -1) ? unitValue : src[alpha_pos];
+ channels_type dstAlpha = (alpha_pos == -1) ? unitValue : dst[alpha_pos];
+ channels_type blend = useMask ? mul(opacity, scale(*mask)) : opacity;
+ channels_type newDstAlpha = _compositeOp::composeColorChannels(src, srcAlpha, dst, dstAlpha, blend, channelFlags);
+
+ if(alpha_pos != -1)
+ dst[alpha_pos] = alphaLocked ? dstAlpha : newDstAlpha;
+
+ src += srcInc;
+ dst += channels_nb;
+ ++mask;
+ }
+
+ srcRowStart += srcRowStride;
+ dstRowStart += dstRowStride;
+ maskRowStart += maskRowStride;
+ }
+ }
+
+public:
+ using KoCompositeOp::composite;
+
+ virtual void composite(quint8* dstRowStart , qint32 dstRowStride ,
+ const quint8* srcRowStart , qint32 srcRowStride ,
+ const quint8* maskRowStart, qint32 maskRowStride,
+ qint32 rows, qint32 cols, quint8 U8_opacity, const QBitArray& channelFlags) const {
+
+ const QBitArray& flags = channelFlags.isEmpty() ? QBitArray(channels_nb,true) : channelFlags;
+ bool alphaLocked = (alpha_pos != -1) && !flags.testBit(alpha_pos);
+
+ if(alphaLocked)
+ genericComposite(dstRowStart, dstRowStride, srcRowStart, srcRowStride, maskRowStart, maskRowStride, rows, cols, U8_opacity, flags);
+ else
+ genericComposite(dstRowStart, dstRowStride, srcRowStart, srcRowStride, maskRowStart, maskRowStride, rows, cols, U8_opacity, flags);
+ }
+};
+
+#endif // KOCOMPOSITEOPFUNCTIONS_H_
--
1.7.1
From 5ac8037cee855175f8448b9671b00db9d876f3dc Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Sat, 8 Jan 2011 03:46:10 +0100
Subject: [PATCH 03/15] Added KoCompositeOpGeneric class to easily create new composite modes by just defining a composition function.
The KoCompositeOpGeneric class is a template that takes a function pointer
to a composition function as a second template parameter.
So for the most composition modes it is not needed anymore
to derive a new class from KoCompositionOp (or from one of its derivates)
---
libs/pigment/KoCompositeOp.h | 2 +
libs/pigment/compositeops/KoCompositeOpBurn.h | 2 +-
libs/pigment/compositeops/KoCompositeOpDodge.h | 2 +-
libs/pigment/compositeops/KoCompositeOpFunctions.h | 64 +++++++++++++++++---
libs/pigment/compositeops/KoCompositeOpGeneric.h | 65 ++++++++++++++++++++
libs/pigment/compositeops/KoCompositeOps.h | 56 +++++++++++------
6 files changed, 162 insertions(+), 29 deletions(-)
create mode 100644 libs/pigment/compositeops/KoCompositeOpGeneric.h
diff --git a/libs/pigment/KoCompositeOp.h b/libs/pigment/KoCompositeOp.h
index f6fb236..73c923e 100644
--- a/libs/pigment/KoCompositeOp.h
+++ b/libs/pigment/KoCompositeOp.h
@@ -43,7 +43,9 @@ const QString COMPOSITE_DIFF = "diff";
const QString COMPOSITE_MULT = "multiply";
const QString COMPOSITE_DIVIDE = "divide";
const QString COMPOSITE_DODGE = "dodge";
+const QString COMPOSITE_LINEAR_DODGE = "linear_dodge";
const QString COMPOSITE_BURN = "burn";
+const QString COMPOSITE_LINEAR_BURN = "linear_burn";
const QString COMPOSITE_BUMPMAP = "bumpmap";
const QString COMPOSITE_CLEAR = "clear";
const QString COMPOSITE_DISSOLVE = "dissolve";
diff --git a/libs/pigment/compositeops/KoCompositeOpBurn.h b/libs/pigment/compositeops/KoCompositeOpBurn.h
index 3315373..857efea 100644
--- a/libs/pigment/compositeops/KoCompositeOpBurn.h
+++ b/libs/pigment/compositeops/KoCompositeOpBurn.h
@@ -35,7 +35,7 @@ class KoCompositeOpBurn : public KoCompositeOpBase< _CSTraits, KoCompositeOpBurn
public:
KoCompositeOpBurn(const KoColorSpace* cs)
- : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight()) { }
+ : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight(), true) { }
public:
inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
diff --git a/libs/pigment/compositeops/KoCompositeOpDodge.h b/libs/pigment/compositeops/KoCompositeOpDodge.h
index 019695a..815d273 100644
--- a/libs/pigment/compositeops/KoCompositeOpDodge.h
+++ b/libs/pigment/compositeops/KoCompositeOpDodge.h
@@ -35,7 +35,7 @@ class KoCompositeOpDodge : public KoCompositeOpBase< _CSTraits, KoCompositeOpDod
static const qint32 alpha_pos = _CSTraits::alpha_pos;
public:
KoCompositeOpDodge(const KoColorSpace * cs)
- : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight()) { }
+ : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight(), true) { }
public:
inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
diff --git a/libs/pigment/compositeops/KoCompositeOpFunctions.h b/libs/pigment/compositeops/KoCompositeOpFunctions.h
index bdd3af7..0656fa5 100644
--- a/libs/pigment/compositeops/KoCompositeOpFunctions.h
+++ b/libs/pigment/compositeops/KoCompositeOpFunctions.h
@@ -56,7 +56,8 @@ inline T inv(T a) {
template
inline T clamp(typename KoColorSpaceMathsTraits::compositetype a) {
- return (a > KoColorSpaceMathsTraits::unitValue) ? KoColorSpaceMathsTraits::unitValue : T(a);
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return qBound(KoColorSpaceMathsTraits::zeroValue, a, KoColorSpaceMathsTraits::unitValue);
}
template
@@ -89,24 +90,69 @@ inline T blend(T src, T srcAlpha, T dst, T dstAlpha, TFunc blendFunc) {
template
inline T cfColorBurn(T src, T dst) {
- typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
-
if(src != KoColorSpaceMathsTraits::zeroValue)
return inv(clamp(div(inv(dst), src)));
-
return KoColorSpaceMathsTraits::zeroValue;
}
template
-inline T cfColorDodge(T src, T dst) {
+inline T cfLinearBurn(T src, T dst) {
typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
-
+ return clamp(composite_type(src) + dst - KoColorSpaceMathsTraits::unitValue);
+}
+
+template
+inline T cfColorDodge(T src, T dst) {
if(src != KoColorSpaceMathsTraits::unitValue)
return clamp(div(dst, inv(src)));
-
return KoColorSpaceMathsTraits::unitValue;
}
+template
+inline T cfAddition(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return clamp(composite_type(src) + dst);
+}
+
+template
+inline T cfSubtract(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ return clamp(composite_type(dst) - src);
+}
+
+template
+inline T cfExclusion(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ composite_type x = mul(src, dst);
+ return clamp(composite_type(dst) + src - (x + x));
+}
+
+template
+inline T cfDivide(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ if(src == KoColorSpaceMathsTraits::zeroValue)
+ return dst;
+ return clamp(div(dst, src));
+}
+
+template
+inline T cfOver(T src, T dst) { Q_UNUSED(dst); return src; }
+
+template
+inline T cfMultiply(T src, T dst) { return mul(src, dst); }
+
+template
+inline T cfDifference(T src, T dst) { return qMax(src,dst) - qMin(src,dst); }
+
+template
+inline T cfScreen(T src, T dst) { return unionShapeOpacy(src, dst); }
+
+template
+inline T cfDarkenOnly(T src, T dst) { return qMin(src, dst); }
+
+template
+inline T cfLightenOnly(T src, T dst) { return qMax(src, dst); }
+
/**
* A template base class that can be used for most composite modes/ops
*
@@ -132,8 +178,8 @@ class KoCompositeOpBase : public KoCompositeOp
public:
- KoCompositeOpBase(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category)
- : KoCompositeOp(cs, id, description, category) { }
+ KoCompositeOpBase(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category, bool userVisible)
+ : KoCompositeOp(cs, id, description, category, userVisible) { }
private:
template
diff --git a/libs/pigment/compositeops/KoCompositeOpGeneric.h b/libs/pigment/compositeops/KoCompositeOpGeneric.h
new file mode 100644
index 0000000..805b017
--- /dev/null
+++ b/libs/pigment/compositeops/KoCompositeOpGeneric.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2011 Silvio Heinrich
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KOCOMPOSITEO_GENERIC_H_
+#define _KOCOMPOSITEO_GENERIC_H_
+
+#include "KoCompositeOpFunctions.h"
+
+/**
+ * A template version of the burn composite operation to use in colorspaces.
+ */
+template<
+ class Traits,
+ typename Traits::channels_type compositeFunc(typename Traits::channels_type, typename Traits::channels_type)
+>
+class KoCompositeOpGeneric : public KoCompositeOpBase< Traits, KoCompositeOpGeneric >
+{
+ typedef KoCompositeOpBase< Traits, KoCompositeOpGeneric > base_class;
+ typedef typename Traits::channels_type channels_type;
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+
+ static const qint32 channels_nb = Traits::channels_nb;
+ static const qint32 alpha_pos = Traits::alpha_pos;
+
+public:
+ KoCompositeOpGeneric(const KoColorSpace* cs, const QString& id, const QString& description, const QString& category, bool userVisible=true)
+ : base_class(cs, id, description, category, userVisible) { }
+
+public:
+ inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
+ channels_type* dst, channels_type dstAlpha,
+ channels_type opacity, const QBitArray& channelFlags) {
+ srcAlpha = mul(srcAlpha, opacity);
+ channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
+
+ if(newDstAlpha != KoColorSpaceMathsTraits::zeroValue) {
+ for(qint32 i=0; i
+ * Copyright (c) 2011 Silvio Heinrich
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -22,21 +23,22 @@
#include "KoColorSpace.h"
-#include "compositeops/KoCompositeOpAdd.h"
+// #include "compositeops/KoCompositeOpAdd.h"
#include "compositeops/KoCompositeOpAlphaDarken.h"
-#include "compositeops/KoCompositeOpBurn.h"
+// #include "compositeops/KoCompositeOpBurn.h"
#include "compositeops/KoCompositeOpDivide.h"
-#include "compositeops/KoCompositeOpDodge.h"
+// #include "compositeops/KoCompositeOpDodge.h"
#include "compositeops/KoCompositeOpErase.h"
-#include "compositeops/KoCompositeOpMultiply.h"
-#include "compositeops/KoCompositeOpOver.h"
+// #include "compositeops/KoCompositeOpMultiply.h"
+// #include "compositeops/KoCompositeOpOver.h"
#include "compositeops/KoCompositeOpOverlay.h"
-#include "compositeops/KoCompositeOpScreen.h"
-#include "compositeops/KoCompositeOpSubtract.h"
+// #include "compositeops/KoCompositeOpScreen.h"
+// #include "compositeops/KoCompositeOpSubtract.h"
#include "compositeops/KoCompositeOpInversedSubtract.h"
#include "compositeops/KoCompositeOpSoftlight.h"
#include "compositeops/KoCompositeOpHardlight.h"
#include "compositeops/KoCompositeOpCopy2.h"
+#include "compositeops/KoCompositeOpGeneric.h"
/**
* This function add to the colorspace all the composite ops defined by
@@ -45,20 +47,38 @@
template
void addStandardCompositeOps(KoColorSpace* cs)
{
- cs->addCompositeOp(new KoCompositeOpAdd<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpAdd<_Traits_>(cs));
cs->addCompositeOp(new KoCompositeOpAlphaDarken<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpBurn<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpBurn<_Traits_>(cs));
cs->addCompositeOp(new KoCompositeOpCopy2<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpDivide<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpDodge<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpDivide<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpDodge<_Traits_>(cs));
cs->addCompositeOp(new KoCompositeOpErase<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpMultiply<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpOver<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpMultiply<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpOver<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+
+ typedef typename _Traits_::channels_type type;
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfOver >(cs, COMPOSITE_OVER, i18n("Normal"), KoCompositeOp::categoryMix()));
+
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorBurn >(cs, COMPOSITE_BURN , i18n("Color Burn"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorDodge >(cs, COMPOSITE_DODGE , i18n("Color Dodge"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLinearBurn >(cs, COMPOSITE_LINEAR_BURN , i18n("Linear Burn"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition >(cs, COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDarkenOnly >(cs, COMPOSITE_DARKEN , i18n("Darken"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLightenOnly >(cs, COMPOSITE_LIGHTEN , i18n("Lighten"), KoCompositeOp::categoryLight()));
+
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition >(cs, COMPOSITE_ADD , i18n("Addition"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfSubtract >(cs, COMPOSITE_SUBTRACT , i18n("Subtract"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDifference >(cs, COMPOSITE_DIFF , i18n("Difference"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfMultiply >(cs, COMPOSITE_MULT , i18n("Multiply"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDivide >(cs, COMPOSITE_DIVIDE , i18n("Divide"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfExclusion >(cs, COMPOSITE_EXCLUSION, i18n("Exclusion"), KoCompositeOp::categoryArithmetic()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfScreen >(cs, COMPOSITE_SCREEN , i18n("Screen"), KoCompositeOp::categoryArithmetic()));
}
#endif
--
1.7.1
From 2dec28d893b4f63e21f76b8039a4dd9ab236c1bc Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Sat, 8 Jan 2011 03:54:09 +0100
Subject: [PATCH 04/15] Enable the Soft Light and Hard Light CompositeOps again.
---
libs/pigment/compositeops/KoCompositeOps.h | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/libs/pigment/compositeops/KoCompositeOps.h b/libs/pigment/compositeops/KoCompositeOps.h
index 7949865..b662f3a 100644
--- a/libs/pigment/compositeops/KoCompositeOps.h
+++ b/libs/pigment/compositeops/KoCompositeOps.h
@@ -59,8 +59,8 @@ void addStandardCompositeOps(KoColorSpace* cs)
//cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
//cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
//cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
- //cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
- //cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+ cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
+ cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
typedef typename _Traits_::channels_type type;
cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfOver >(cs, COMPOSITE_OVER, i18n("Normal"), KoCompositeOp::categoryMix()));
--
1.7.1
From 924c71e117c2f7ffb3151b2211fc6b7cd16f2b77 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Sat, 8 Jan 2011 13:09:59 +0100
Subject: [PATCH 05/15] Reset the Burn and Dodge CompositeOps files to their original state.
This files are not needed anymore KoCompositeOpGeneric is used instead
---
libs/pigment/compositeops/KoCompositeOpBurn.h | 52 +++++++++++++----------
libs/pigment/compositeops/KoCompositeOpDodge.h | 49 ++++++++++++----------
2 files changed, 55 insertions(+), 46 deletions(-)
diff --git a/libs/pigment/compositeops/KoCompositeOpBurn.h b/libs/pigment/compositeops/KoCompositeOpBurn.h
index 857efea..97feaa4 100644
--- a/libs/pigment/compositeops/KoCompositeOpBurn.h
+++ b/libs/pigment/compositeops/KoCompositeOpBurn.h
@@ -20,42 +20,48 @@
#ifndef KOCOMPOSITEOPBURN_H_
#define KOCOMPOSITEOPBURN_H_
-#include "KoCompositeOpFunctions.h"
+#include "KoCompositeOpAlphaBase.h"
/**
* A template version of the burn composite operation to use in colorspaces.
*/
template
-class KoCompositeOpBurn : public KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >
+class KoCompositeOpBurn : public KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpBurn<_CSTraits>, true >
{
typedef typename _CSTraits::channels_type channels_type;
- typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
- static const qint32 channels_nb = _CSTraits::channels_nb;
- static const qint32 alpha_pos = _CSTraits::alpha_pos;
-
+ typedef typename KoColorSpaceMathsTraits::compositetype compositetype;
public:
- KoCompositeOpBurn(const KoColorSpace* cs)
- : KoCompositeOpBase< _CSTraits, KoCompositeOpBurn<_CSTraits> >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight(), true) { }
+
+ KoCompositeOpBurn(const KoColorSpace * cs)
+ : KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpBurn<_CSTraits>, true >(cs, COMPOSITE_BURN, i18n("Burn"), KoCompositeOp::categoryLight()) {
+ }
public:
- inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
- channels_type* dst, channels_type dstAlpha,
- channels_type opacity, const QBitArray& channelFlags) {
- srcAlpha = mul(srcAlpha, opacity);
-
- channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
-
- if(newDstAlpha != KoColorSpaceMathsTraits::zeroValue) {
- for(qint32 i=0; i );
- dst[i] = div(result, newDstAlpha);
- }
+ inline static channels_type selectAlpha(channels_type srcAlpha, channels_type dstAlpha) {
+ return qMin(srcAlpha, dstAlpha);
+ }
+
+ inline static void composeColorChannels(channels_type srcBlend,
+ const channels_type* src,
+ channels_type* dst,
+ bool allChannelFlags,
+ const QBitArray & channelFlags) {
+ for (uint i = 0; i < _CSTraits::channels_nb; i++) {
+ if ((int)i != _CSTraits::alpha_pos && (allChannelFlags || channelFlags.testBit(i))) {
+ compositetype srcColor = src[i];
+ compositetype dstColor = dst[i];
+
+ srcColor = qMin(((NATIVE_MAX_VALUE - dstColor) * (NATIVE_MAX_VALUE + 1)) / (srcColor + 1), (compositetype)NATIVE_MAX_VALUE);
+ if (NATIVE_MAX_VALUE - srcColor > NATIVE_MAX_VALUE) srcColor = NATIVE_MAX_VALUE;
+
+ channels_type newColor = NATIVE_MAX_VALUE - KoColorSpaceMaths::blend(srcColor, dstColor, srcBlend);
+
+ dst[i] = newColor;
}
}
-
- return newDstAlpha;
}
+
+
};
#endif
diff --git a/libs/pigment/compositeops/KoCompositeOpDodge.h b/libs/pigment/compositeops/KoCompositeOpDodge.h
index 815d273..368a26b 100644
--- a/libs/pigment/compositeops/KoCompositeOpDodge.h
+++ b/libs/pigment/compositeops/KoCompositeOpDodge.h
@@ -1,7 +1,6 @@
/*
* Copyright (c) 2007 Cyrille Berger
- * Copyright (c) 2011 Silvio Heinrich
- *
+ *
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
@@ -21,40 +20,44 @@
#ifndef _KOCOMPOSITEOPDODGE_H_
#define _KOCOMPOSITEOPDODGE_H_
-#include "KoCompositeOpFunctions.h"
+#include "KoCompositeOpAlphaBase.h"
+
/**
* A template version of the dodge composite operation to use in colorspaces.
*/
template
-class KoCompositeOpDodge : public KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >
+class KoCompositeOpDodge : public KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpDodge<_CSTraits>, true >
{
typedef typename _CSTraits::channels_type channels_type;
- typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
- static const qint32 channels_nb = _CSTraits::channels_nb;
- static const qint32 alpha_pos = _CSTraits::alpha_pos;
+ typedef typename KoColorSpaceMathsTraits::compositetype compositetype;
public:
+
KoCompositeOpDodge(const KoColorSpace * cs)
- : KoCompositeOpBase< _CSTraits, KoCompositeOpDodge<_CSTraits> >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight(), true) { }
+ : KoCompositeOpAlphaBase<_CSTraits, KoCompositeOpDodge<_CSTraits>, true >(cs, COMPOSITE_DODGE, i18n("Dodge"), KoCompositeOp::categoryLight()) {
+ }
public:
- inline static channels_type composeColorChannels(const channels_type* src, channels_type srcAlpha,
- channels_type* dst, channels_type dstAlpha,
- channels_type opacity, const QBitArray& channelFlags) {
- srcAlpha = mul(srcAlpha, opacity);
-
- channels_type newDstAlpha = unionShapeOpacy(srcAlpha, dstAlpha);
-
- if(newDstAlpha != KoColorSpaceMathsTraits::zeroValue) {
- for(qint32 i=0; i );
- dst[i] = div(result, newDstAlpha);
- }
+ inline static channels_type selectAlpha(channels_type srcAlpha, channels_type dstAlpha) {
+ return qMin(srcAlpha, dstAlpha);
+ }
+ inline static void composeColorChannels(channels_type srcBlend,
+ const channels_type* src,
+ channels_type* dst,
+ bool allChannelFlags,
+ const QBitArray & channelFlags) {
+ for (uint channel = 0; channel < _CSTraits::channels_nb; channel++) {
+ if ((int)channel != _CSTraits::alpha_pos && (allChannelFlags || channelFlags.testBit(channel))) {
+ compositetype srcColor = src[channel];
+ compositetype dstColor = dst[channel];
+
+ srcColor = qMin((compositetype)(dstColor * (NATIVE_MAX_VALUE + 1)) / (NATIVE_MAX_VALUE + 1 - srcColor), (compositetype)NATIVE_MAX_VALUE);
+
+ channels_type newColor = KoColorSpaceMaths::blend(srcColor, dstColor, srcBlend);
+
+ dst[channel] = newColor;
}
}
-
- return newDstAlpha;
}
};
--
1.7.1
From 715a106a266b5b1fda71b1fd64acc2084f411483 Mon Sep 17 00:00:00 2001
From: Silvio Heinrich
Date: Sat, 8 Jan 2011 16:10:09 +0100
Subject: [PATCH 06/15] Added "Soft Light", "Hard Light" and "Overlay" blending functions.
---
libs/pigment/KoColorSpaceMaths.cpp | 3 +
libs/pigment/KoColorSpaceMaths.h | 7 ++
libs/pigment/compositeops/KoCompositeOpFunctions.h | 70 +++++++++++++++-----
libs/pigment/compositeops/KoCompositeOps.h | 47 +++++++------
4 files changed, 88 insertions(+), 39 deletions(-)
diff --git a/libs/pigment/KoColorSpaceMaths.cpp b/libs/pigment/KoColorSpaceMaths.cpp
index 891c8a2..b2f82ed 100644
--- a/libs/pigment/KoColorSpaceMaths.cpp
+++ b/libs/pigment/KoColorSpaceMaths.cpp
@@ -26,6 +26,7 @@
#ifdef HAVE_OPENEXR
const half KoColorSpaceMathsTraits::zeroValue = 0.0;
const half KoColorSpaceMathsTraits::unitValue = 1.0;
+const half KoColorSpaceMathsTraits::halfValue = 0.5;
const half KoColorSpaceMathsTraits::max = HALF_MAX;
const half KoColorSpaceMathsTraits::min = -HALF_MAX;
const half KoColorSpaceMathsTraits::epsilon = HALF_EPSILON;
@@ -34,6 +35,7 @@ const KoChannelInfo::enumChannelValueType KoColorSpaceMathsTraits::channel
const float KoColorSpaceMathsTraits::zeroValue = 0.0;
const float KoColorSpaceMathsTraits::unitValue = 1.0;
+const float KoColorSpaceMathsTraits::halfValue = 0.5;
const float KoColorSpaceMathsTraits::max = FLT_MAX;
const float KoColorSpaceMathsTraits::min = -FLT_MAX;
const float KoColorSpaceMathsTraits::epsilon = FLT_EPSILON;
@@ -41,6 +43,7 @@ const KoChannelInfo::enumChannelValueType KoColorSpaceMathsTraits::channe
const double KoColorSpaceMathsTraits::zeroValue = 0.0;
const double KoColorSpaceMathsTraits::unitValue = 1.0;
+const double KoColorSpaceMathsTraits::halfValue = 0.5;
const double KoColorSpaceMathsTraits::max = DBL_MAX;
const double KoColorSpaceMathsTraits::min = -DBL_MAX;
const double KoColorSpaceMathsTraits::epsilon = DBL_EPSILON;
diff --git a/libs/pigment/KoColorSpaceMaths.h b/libs/pigment/KoColorSpaceMaths.h
index a0ba9cf..f577a7d 100644
--- a/libs/pigment/KoColorSpaceMaths.h
+++ b/libs/pigment/KoColorSpaceMaths.h
@@ -56,6 +56,7 @@ public:
typedef qint32 compositetype;
static const quint8 zeroValue = 0;
static const quint8 unitValue = 0x00FF;
+ static const quint8 halfValue = 0x00FF / 2;
static const quint8 max = 0x00FF;
static const quint8 min = 0;
static const quint8 epsilon = 1;
@@ -70,6 +71,7 @@ public:
typedef qint64 compositetype;
static const quint16 zeroValue = 0;
static const quint16 unitValue = 0xFFFF;
+ static const quint16 halfValue = 0xFFFF / 2;
static const quint16 max = 0xFFFF;
static const quint16 min = 0;
static const quint16 epsilon = 1;
@@ -84,6 +86,7 @@ public:
typedef qint64 compositetype;
static const qint16 zeroValue = 0;
static const qint16 unitValue = 32767;
+ static const qint16 halfValue = 32767 / 2;
static const qint16 max = 32767;
static const qint16 min = -32768;
static const qint16 epsilon = 1;
@@ -98,6 +101,7 @@ public:
typedef qint64 compositetype;
static const quint32 zeroValue = 0;
static const quint32 unitValue = 0xFFFFFFFF;
+ static const quint32 halfValue = 0xFFFFFFFF / 2;
static const quint32 max = 0xFFFFFFFF;
static const quint32 min = 0;
static const quint32 epsilon = 1;
@@ -116,6 +120,7 @@ public:
typedef double compositetype;
static const half zeroValue;
static const half unitValue;
+ static const half halfValue;
static const half max;
static const half min;
static const half epsilon;
@@ -131,6 +136,7 @@ public:
typedef double compositetype;
static const float zeroValue;
static const float unitValue;
+ static const float halfValue;
static const float max;
static const float min;
static const float epsilon;
@@ -145,6 +151,7 @@ public:
typedef double compositetype;
static const double zeroValue;
static const double unitValue;
+ static const double halfValue;
static const double max;
static const double min;
static const double epsilon;
diff --git a/libs/pigment/compositeops/KoCompositeOpFunctions.h b/libs/pigment/compositeops/KoCompositeOpFunctions.h
index 0656fa5..de41921 100644
--- a/libs/pigment/compositeops/KoCompositeOpFunctions.h
+++ b/libs/pigment/compositeops/KoCompositeOpFunctions.h
@@ -30,10 +30,16 @@
* if non floating point types are used, fixed point arithmetic is used
*/
+// template
+// inline T mul(T a, T b) { T(KoColorSpaceMaths::multiply(a, b)); }
+
+// template
+// inline T mul(T a, T b, T c) { T(KoColorSpaceMaths::multiply(a, b, c)); }
+
template
inline T mul(T a, T b) {
typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
- return T(composite_type(a) * composite_type(b) / KoColorSpaceMathsTraits::unitValue);
+ return T(composite_type(a) * b / KoColorSpaceMathsTraits::unitValue);
}
template
@@ -43,6 +49,21 @@ inline T mul(T a, T b, T c) {
}
template
+inline T inv(T a) { return KoColorSpaceMathsTraits::unitValue - a; }
+
+template
+inline T lerp(T a, T b, T alpha) { return KoColorSpaceMaths::blend(b, a, alpha); }
+
+template
+inline TRet scale(T a) { return KoColorSpaceMaths::scaleToA(a); }
+
+// template
+// inline TRet scale(T a) {
+// typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+// return TRet(composite_type(a) * KoColorSpaceMathsTraits::unitValue / KoColorSpaceMathsTraits::unitValue);
+// }
+
+template
inline typename KoColorSpaceMathsTraits::compositetype
div(T a, T b) {
typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
@@ -50,27 +71,11 @@ div(T a, T b) {
}
template
-inline T inv(T a) {
- return KoColorSpaceMathsTraits::unitValue - a;
-}
-
-template
inline T clamp(typename KoColorSpaceMathsTraits::compositetype a) {
typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
return qBound(KoColorSpaceMathsTraits::zeroValue, a, KoColorSpaceMathsTraits::unitValue);
}
-template
-inline T lerp(T a, T b, T alpha) {
- return KoColorSpaceMaths::blend(b, a, alpha);
-}
-
-template
-inline TRet scale(T a) {
- typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
- return TRet(composite_type(a) * KoColorSpaceMathsTraits::unitValue / KoColorSpaceMathsTraits::unitValue);
-}
-
/* ---------------- Blending/Compositing functions ------------------------ /
* definitions of standard blending/compositing functions compatible
* to the ISO 32000-1 specification (for PDF filed) which also defines
@@ -136,9 +141,40 @@ inline T cfDivide(T src, T dst) {
}
template
+inline T cfHardLight(T src, T dst) {
+ typedef typename KoColorSpaceMathsTraits::compositetype composite_type;
+ composite_type src2 = composite_type(src) + src;
+
+ if(src > KoColorSpaceMathsTraits::halfValue) {
+ // screen(src*2.0 - 1.0, dst)
+ src2 -= KoColorSpaceMathsTraits::unitValue;
+ return T((src2+dst) - (src2*dst / KoColorSpaceMathsTraits::unitValue));
+ }
+
+ // multiply(src*2.0, dst)
+ return clamp(src2*dst / KoColorSpaceMathsTraits::unitValue);
+}
+
+template
+inline T cfSoftLight(T src, T dst) {
+ qreal fsrc = scale(src);
+ qreal fdst = scale(dst);
+
+ if(fsrc > 0.5f) {
+ qreal D = (fdst > 0.25f) ? sqrt(fdst) : ((16.0f*fdst - 12.0)*fdst + 4.0f)*fdst;
+ return scale(fdst + (2.0f*fsrc - 1.0f) * (D - fdst));
+ }
+
+ return scale(fdst - (1.0f - 2.0f*fsrc) * fdst * (1.0f - fdst));
+}
+
+template
inline T cfOver(T src, T dst) { Q_UNUSED(dst); return src; }
template
+inline T cfOverlay(T src, T dst) { return cfHardLight(dst, src); }
+
+template
inline T cfMultiply(T src, T dst) { return mul(src, dst); }
template
diff --git a/libs/pigment/compositeops/KoCompositeOps.h b/libs/pigment/compositeops/KoCompositeOps.h
index b662f3a..b563261 100644
--- a/libs/pigment/compositeops/KoCompositeOps.h
+++ b/libs/pigment/compositeops/KoCompositeOps.h
@@ -26,17 +26,17 @@
// #include "compositeops/KoCompositeOpAdd.h"
#include "compositeops/KoCompositeOpAlphaDarken.h"
// #include "compositeops/KoCompositeOpBurn.h"
-#include "compositeops/KoCompositeOpDivide.h"
+// #include "compositeops/KoCompositeOpDivide.h"
// #include "compositeops/KoCompositeOpDodge.h"
#include "compositeops/KoCompositeOpErase.h"
// #include "compositeops/KoCompositeOpMultiply.h"
// #include "compositeops/KoCompositeOpOver.h"
-#include "compositeops/KoCompositeOpOverlay.h"
+// #include "compositeops/KoCompositeOpOverlay.h"
// #include "compositeops/KoCompositeOpScreen.h"
// #include "compositeops/KoCompositeOpSubtract.h"
-#include "compositeops/KoCompositeOpInversedSubtract.h"
-#include "compositeops/KoCompositeOpSoftlight.h"
-#include "compositeops/KoCompositeOpHardlight.h"
+// #include "compositeops/KoCompositeOpInversedSubtract.h"
+// #include "compositeops/KoCompositeOpSoftlight.h"
+// #include "compositeops/KoCompositeOpHardlight.h"
#include "compositeops/KoCompositeOpCopy2.h"
#include "compositeops/KoCompositeOpGeneric.h"
@@ -59,26 +59,29 @@ void addStandardCompositeOps(KoColorSpace* cs)
//cs->addCompositeOp(new KoCompositeOpOverlay<_Traits_>(cs));
//cs->addCompositeOp(new KoCompositeOpScreen<_Traits_>(cs));
//cs->addCompositeOp(new KoCompositeOpSubtract<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
- cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpSoftlight<_Traits_>(cs));
+ //cs->addCompositeOp(new KoCompositeOpHardlight<_Traits_>(cs));
- typedef typename _Traits_::channels_type type;
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfOver >(cs, COMPOSITE_OVER, i18n("Normal"), KoCompositeOp::categoryMix()));
+ typedef typename _Traits_::channels_type T;
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfOver >(cs, COMPOSITE_OVER, i18n("Normal"), KoCompositeOp::categoryMix()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorBurn >(cs, COMPOSITE_BURN , i18n("Color Burn"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorDodge >(cs, COMPOSITE_DODGE , i18n("Color Dodge"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLinearBurn >(cs, COMPOSITE_LINEAR_BURN , i18n("Linear Burn"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition >(cs, COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDarkenOnly >(cs, COMPOSITE_DARKEN , i18n("Darken"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLightenOnly >(cs, COMPOSITE_LIGHTEN , i18n("Lighten"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorBurn >(cs, COMPOSITE_BURN , i18n("Color Burn"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfColorDodge >(cs, COMPOSITE_DODGE , i18n("Color Dodge"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLinearBurn >(cs, COMPOSITE_LINEAR_BURN , i18n("Linear Burn"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition >(cs, COMPOSITE_LINEAR_DODGE, i18n("Linear Dodge"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfDarkenOnly >(cs, COMPOSITE_DARKEN , i18n("Darken"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfLightenOnly >(cs, COMPOSITE_LIGHTEN , i18n("Lighten"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfHardLight >(cs, COMPOSITE_HARD_LIGHT , i18n("Hard Light"), KoCompositeOp::categoryLight()));
+ cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfSoftLight >(cs, COMPOSITE_SOFT_LIGHT , i18n("Soft Light"), KoCompositeOp::categoryLight()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfAddition >(cs, COMPOSITE_ADD , i18n("Addition"), KoCompositeOp::categoryArithmetic()));
- cs->addCompositeOp(new KoCompositeOpGeneric< _Traits_, &cfSubtract