[PATCH 10/10] Made the KoCompositeOpCopy2 work properly and used this mode for the smudge brush.
Silvio Heinrich
plassy at web.de
Tue Jan 11 18:45:55 CET 2011
The COMPOSITE_COPY mode didn't work right because it blended between the
destination and source pixel even if the source's pixel had undefined
color (zero opacy).
I also did some fine tuning on the rate values of the smudge brush and
did some minor fixes.
---
.../defaultpaintops/smudge/kis_smudgeop.cpp | 17 +--
.../paintops/defaultpaintops/smudge/kis_smudgeop.h | 1 -
.../libpaintop/kis_pressure_composite_option.cpp | 4 +-
.../libpaintop/kis_pressure_rate_option.cpp | 11 +-
.../paintops/libpaintop/kis_pressure_rate_option.h | 4 +-
libs/pigment/compositeops/KoCompositeOpCopy2.h | 140 +++++++++-----------
6 files changed, 78 insertions(+), 99 deletions(-)
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
index d8bbd14..8abeb97 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.cpp
@@ -110,19 +110,12 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
const KoCompositeOp* oldMode = painter()->compositeOp();
if(!m_firstRun) {
- // set opacity calculated by the rate option (but fit the rate inbetween the range 0.0 - 0.25)
- m_rateOption.apply(painter(), info, 0.0, 0.25);
+ // set opacity calculated by the rate option
+ m_rateOption.apply(painter(), info);
// then blit the temporary painting device on the canvas at the current brush position
// the alpha mask (maskDab) will be used here to only blit the pixels that are in the area (shape) of the brush
- painter()->setCompositeOp(COMPOSITE_OVER);
- painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, maskDab->bounds().width(), maskDab->bounds().height());
-
- // apply the opacity rate calculated by the rate option for smudging the alpha channel
- // (this time we use the full range of the rate value)
- m_rateOption.apply(painter(), info);
-
- painter()->setCompositeOp(COMPOSITE_COPY_OPACITY);
+ painter()->setCompositeOp(COMPOSITE_COPY);
painter()->bitBltWithFixedSelection(x, y, m_tempDev, maskDab, maskDab->bounds().width(), maskDab->bounds().height());
}
else m_firstRun = false;
@@ -144,7 +137,9 @@ qreal KisSmudgeOp::paintAt(const KisPaintInformation& info)
// we will mix some color into the temorary painting device (m_tempDev)
if(m_compositeOption.isChecked()) {
// this will apply the opacy and the composite mode (selected by the user) to copyPainter
- m_compositeOption.applyOpacityRate(©Painter, info, 0.0, 0.5);
+ // (but fit the rate inbetween the range 0.0 to (1.0-SmudgeRate))
+ qreal maxColorRate = qMax<qreal>(1.0-m_rateOption.rate(), 0.2);
+ m_compositeOption.applyOpacityRate(©Painter, info, 0.0, maxColorRate);
m_compositeOption.applyCompositeOp(©Painter);
// paint a rectangle with the current color (foreground color)
diff --git a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
index 333df09..63346bd 100644
--- a/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
+++ b/krita/plugins/paintops/defaultpaintops/smudge/kis_smudgeop.h
@@ -29,7 +29,6 @@
#include "kis_brush_based_paintop.h"
#include <kis_types.h>
-#include <kis_pressure_opacity_option.h>
#include <kis_pressure_size_option.h>
#include <kis_pressure_rate_option.h>
#include <kis_pressure_composite_option.h>
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
index 510768f..36d9062 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_composite_option.cpp
@@ -56,8 +56,10 @@ void KisPressureCompositeOption::readOptionSetting(const KisPropertiesConfigurat
void KisPressureCompositeOption::applyOpacityRate(KisPainter* painter, const KisPaintInformation& info, qreal scaleMin, qreal scaleMax) const
{
- if(!isChecked())
+ if(!isChecked()) {
+ painter->setOpacity((quint8)(scaleMax * 255.0));
return;
+ }
qreal rate = scaleMin + (scaleMax - scaleMin) * m_rate; // scale m_rate into the range scaleMin - scaleMax
quint8 opacity = qBound(OPACITY_TRANSPARENT_U8, (quint8)(rate * computeValue(info) * 255.0), OPACITY_OPAQUE_U8);
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.cpp b/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.cpp
index bd643d1..b40d88b 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.cpp
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.cpp
@@ -1,5 +1,6 @@
/* This file is part of the KDE project
- * Copyright (C) Boudewijn Rempt <boud at valdyas.org>, (C) 2008
+ * Copyright (C) 2008 Boudewijn Rempt <boud at valdyas.org>
+ * Copyright (C) 2011 Silvio Heinrich <plassy at web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -47,11 +48,13 @@ void KisPressureRateOption::readOptionSetting(const KisPropertiesConfiguration*
void KisPressureRateOption::apply(KisPainter* painter, const KisPaintInformation& info, qreal scaleMin, qreal scaleMax) const
{
- if(!isChecked())
+ if(!isChecked()) {
+ painter->setOpacity((quint8)(scaleMax * 255.0));
return;
+ }
- qreal rate = scaleMin + (scaleMax - scaleMin) * m_rate;
- quint8 opacity = qBound(OPACITY_TRANSPARENT_U8, (quint8)(m_rate * computeValue(info) * 255.0), OPACITY_OPAQUE_U8);
+ qreal rate = scaleMin + (scaleMax - scaleMin) * m_rate; // scale m_rate into the range scaleMin - scaleMax
+ quint8 opacity = qBound(OPACITY_TRANSPARENT_U8, (quint8)(rate * computeValue(info) * 255.0), OPACITY_OPAQUE_U8);
painter->setOpacity(opacity);
}
diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.h
index c0d9d66..e71102e 100644
--- a/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.h
+++ b/krita/plugins/paintops/libpaintop/kis_pressure_rate_option.h
@@ -1,5 +1,6 @@
/* This file is part of the KDE project
* Copyright (C) Boudewijn Rempt <boud at valdyas.org>, (C) 2008
+ * Copyright (C) Silvio Heinrich <plassy at web.de>, (C) 2011
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -45,10 +46,9 @@ public:
void apply(KisPainter* painter, const KisPaintInformation& info, qreal scaleMin=0.0, qreal scaleMax=1.0) const;
void writeOptionSetting(KisPropertiesConfiguration* setting) const;
-
void readOptionSetting(const KisPropertiesConfiguration* setting);
- void setRate(qreal rate) { m_rate = rate; }
+ void setRate(qreal rate) { m_rate = qBound<qreal>(0.0, rate, 1.0); }
qreal rate() const { return m_rate; }
private:
diff --git a/libs/pigment/compositeops/KoCompositeOpCopy2.h b/libs/pigment/compositeops/KoCompositeOpCopy2.h
index 5257d1a..1d8b04a 100644
--- a/libs/pigment/compositeops/KoCompositeOpCopy2.h
+++ b/libs/pigment/compositeops/KoCompositeOpCopy2.h
@@ -2,6 +2,7 @@
* Copyright (c) 2006, 2010 Cyrille Berger <cberger at cberger.net>
* Copyright (c) 2007 Emanuele Tamponi <emanuele at valinor.it>
* Copyright (c) 2010 Lukáš Tvrdý <lukast.dev at gmail.com>
+ * Copyright (c) 2011 Silvio Heinrich <plassy at web.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -24,102 +25,81 @@
#include <KoColorSpaceMaths.h>
-#define NATIVE_OPACITY_OPAQUE KoColorSpaceMathsTraits<channels_type>::unitValue
-#define NATIVE_OPACITY_TRANSPARENT KoColorSpaceMathsTraits<channels_type>::zeroValue
-
/**
* Generic implementation of the COPY composite op. That respect selection.
*/
template<class _CSTraits>
class KoCompositeOpCopy2 : 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;
+
+ template<class T>
+ inline static T mul(T a, T b) { return T(KoColorSpaceMaths<T>::multiply(a, b)); }
+
+ template<class T>
+ inline static T mul(T a, T b, T c) { return T(KoColorSpaceMaths<T>::multiply(a, b, c)); }
+
+ template<class T>
+ inline static T lerp(T a, T b, T alpha) { return KoColorSpaceMaths<T>::blend(b, a, alpha); }
+
+ template<class TRet, class T>
+ inline static TRet scale(T a) { return KoColorSpaceMaths<T,TRet>::scaleToA(a); }
public:
-
explicit KoCompositeOpCopy2(KoColorSpace * cs)
- : KoCompositeOp(cs, COMPOSITE_COPY, i18n("Copy"), KoCompositeOp::categoryMix(), false) {
- }
+ : KoCompositeOp(cs, COMPOSITE_COPY, i18n("Copy"), KoCompositeOp::categoryMix(), false) { }
-public:
using KoCompositeOp::composite;
-
- 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
- {
- Q_UNUSED(channelFlags);
- if(maskRowStart == 0 && U8_opacity == OPACITY_OPAQUE_U8)
- {
- quint8 *dst = dstRowStart;
- const quint8 *src = srcRowStart;
- quint8 bytesPerPixel = _CSTraits::pixelSize;
- while (rows > 0) {
- if (srcRowStride == 0) {
- quint8* dstN = dst;
- qint32 columns = cols;
- while (columns > 0) {
- memcpy(dstN, src, bytesPerPixel);
- dstN += bytesPerPixel;
- --columns;
- }
- } else {
- memcpy(dst, src, cols * bytesPerPixel);
- }
-
- dst += dstRowStride;
- src += srcRowStride;
- --rows;
- }
- } else {
- qint32 srcInc = (srcRowStride == 0) ? 0 : _CSTraits::channels_nb;
- channels_type opacity = KoColorSpaceMaths<quint8, channels_type>::scaleToA(U8_opacity);
- while (rows > 0)
- {
- const channels_type *srcN = reinterpret_cast<const channels_type *>(srcRowStart);
- channels_type *dstN = reinterpret_cast<channels_type *>(dstRowStart);
- const quint8 *mask = maskRowStart;
-
- qint32 columns = cols;
-
- while (columns > 0)
- {
- channels_type blend;
- // compute the blend
- if (!mask){
- blend = opacity;
- }else if (*mask == OPACITY_OPAQUE_U8){
- blend = opacity;
- ++mask;
- } else {
- blend = KoColorSpaceMaths<channels_type, quint8>::multiply(opacity, *mask);
- ++mask;
- }
-
- for (uint i = 0; i < _CSTraits::channels_nb; i++) {
- dstN[i] = KoColorSpaceMaths<channels_type>::blend(srcN[i], dstN[i], blend);
- }
- --columns;
- srcN += srcInc;
- dstN += _CSTraits::channels_nb;
+
+ 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 useMask = maskRowStart != 0;
+ qint32 srcInc = srcRowStride != 0 ? channels_nb : 0;
+ channels_type opacity = KoColorSpaceMaths<quint8,channels_type>::scaleToA(U8_opacity);
+
+ for(; rows>0; --rows) {
+ const quint8* msk = maskRowStart;
+ const channels_type* src = reinterpret_cast<const channels_type*>(srcRowStart);
+ channels_type* dst = reinterpret_cast<channels_type*>(dstRowStart);
+
+ for(qint32 c=cols; c>0; --c) {
+ channels_type srcAlpha = (alpha_pos != -1) ? scale<channels_type>(src[alpha_pos]) : KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type dstAlpha = (alpha_pos != -1) ? scale<channels_type>(dst[alpha_pos]) : KoColorSpaceMathsTraits<channels_type>::unitValue;
+ channels_type blendAlpha = useMask ? mul(opacity, scale<channels_type>(*msk)) : opacity;
+ channels_type blendColor = mul(srcAlpha, blendAlpha);
+
+ if(dstAlpha != KoColorSpaceMathsTraits<channels_type>::zeroValue) {
+ // blend the color channels
+ for(qint32 i=0; i<channels_nb; ++i)
+ if(i != alpha_pos && flags.testBit(i))
+ dst[i] = lerp(dst[i], src[i], blendColor);
}
-
- rows--;
- srcRowStart += srcRowStride;
- dstRowStart += dstRowStride;
- if (maskRowStart) {
- maskRowStart += maskRowStride;
+ else {
+ // don't blend if the color of the destination is undefined (has zero opacity)
+ // copy the source channel instead
+ for(qint32 i=0; i<channels_nb; ++i)
+ if(i != alpha_pos && flags.testBit(i))
+ dst[i] = src[i];
}
+
+ // blend the alpha channel if there exists one
+ if(alpha_pos != -1)
+ dst[alpha_pos] = lerp(dstAlpha, srcAlpha, blendAlpha);
+
+ src += srcInc;
+ dst += channels_nb;
+ ++msk;
}
+ srcRowStart += srcRowStride;
+ dstRowStart += dstRowStride;
+ maskRowStart += maskRowStride;
}
}
};
--
1.7.1
--------------080902090707010407080904--
More information about the kimageshop
mailing list