Krita Source Code Documentation
Loading...
Searching...
No Matches
KisColorSmudgeStrategyLightness.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2021 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
10
11#include "kis_painter.h"
12#include "kis_paint_device.h"
14#include "kis_selection.h"
15
17#include "kis_algebra_2d.h"
19
21 bool useDullingMode, KisPaintThicknessOptionData::ThicknessMode thicknessMode)
22 : KisColorSmudgeStrategyBase(useDullingMode)
23 , m_maskDab(new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->alpha8()))
24 , m_origDab(new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->rgb8()))
25 , m_smearAlpha(smearAlpha)
26 , m_initializationPainter(painter)
27 , m_thicknessMode(thicknessMode)
28{
29 KIS_SAFE_ASSERT_RECOVER(thicknessMode == KisPaintThicknessOptionData::OVERLAY ||
30 thicknessMode == KisPaintThicknessOptionData::OVERWRITE) {
31
32 thicknessMode = KisPaintThicknessOptionData::OVERLAY;
33 }
34}
35
37{
38 KisColorSmudgeInterstrokeData *colorSmudgeData =
40
41 if (colorSmudgeData) {
42 m_projectionDevice = colorSmudgeData->projectionDevice;
43 m_colorOnlyDevice = colorSmudgeData->colorBlendDevice;
44 m_heightmapDevice = colorSmudgeData->heightmapDevice;
46 }
47
48 KIS_SAFE_ASSERT_RECOVER(colorSmudgeData) {
50
54 cs->colorModelId().id(),
56 cs->profile()));
57
62 }
63
67
69
70 // we should read data from the color layer, not from the final projection layer
72
78
82
83}
84
89
91 const KisDabShape &shape, const QPointF &cursorPoint,
92 QRect *dstDabRect, qreal paintThickness)
93{
95 cursorPoint,
96 shape,
97 info,
98 1.0,
99 dstDabRect);
100
102
103 const int numPixels = m_origDab->bounds().width() * m_origDab->bounds().height();
104
105 if (paintThickness < 1.0) {
109 }
110
111 const int denormedPaintThickness = qRound(paintThickness * 255.0);
112 KoBgrU8Traits::Pixel *pixelPtr = reinterpret_cast<KoBgrU8Traits::Pixel *>(m_origDab->data());
113 for (int i = 0; i < numPixels; i++) {
114 int gray = pixelPtr->red - 127;
115
116 if (gray >= 0) {
117 gray = KoColorSpaceMaths<quint8>::multiply(gray, denormedPaintThickness);
118 } else {
119 gray = -KoColorSpaceMaths<quint8>::multiply(-gray, denormedPaintThickness);
120 }
121
122 gray = qBound(0, gray + 127, 255);
123
124 pixelPtr->red = gray;
125 pixelPtr->green = gray;
126 pixelPtr->blue = gray;
127
128 pixelPtr++;
129 }
130 }
131
135}
136
138KisColorSmudgeStrategyLightness::paintDab(const QRect &srcRect, const QRect &dstRect, const KoColor &currentPaintColor,
139 qreal opacity, qreal colorRateValue, qreal smudgeRateValue,
140 qreal maxPossibleSmudgeRateValue, qreal paintThicknessValue,
141 qreal smudgeRadiusValue)
142{
143 const int numPixels = dstRect.width() * dstRect.height();
144
145 const QVector<QRect> mirroredRects = m_finalPainter.calculateAllMirroredRects(dstRect);
146
147 QVector<QRect> readRects;
148 readRects << mirroredRects;
149 readRects << srcRect;
150 m_sourceWrapperDevice->readRects(readRects);
151
152
156 srcRect, dstRect,
157 currentPaintColor,
158 opacity,
159 smudgeRateValue,
160 maxPossibleSmudgeRateValue,
161 colorRateValue,
162 smudgeRadiusValue);
163
164
165 const qreal overlaySmearRate = smudgeRateValue - 0.01; //adjust so minimum value is 0 instead of 1%
166 const qreal overlayAdjustment =
167 (m_thicknessMode == KisPaintThicknessOptionData::ThicknessMode::OVERWRITE) ?
168 1.0 : KisAlgebra2D::lerp(overlaySmearRate, 1.0, paintThicknessValue);
169 const qreal brushHeightmapOpacity = opacity * overlayAdjustment;
170 m_heightmapPainter.setOpacityF(brushHeightmapOpacity);
171 m_heightmapPainter.bltFixed(dstRect.topLeft(), m_origDab, m_origDab->bounds());
173
174
175 KisFixedPaintDeviceSP tempColorDevice =
177
178 KisFixedPaintDeviceSP tempHeightmapDevice =
180
181 Q_FOREACH(const QRect& rc, mirroredRects) {
182 tempColorDevice->setRect(rc);
183 tempColorDevice->lazyGrowBufferWithoutInitialization();
184
185 tempHeightmapDevice->setRect(rc);
186 tempHeightmapDevice->lazyGrowBufferWithoutInitialization();
187
188 m_colorOnlyDevice->readBytes(tempColorDevice->data(), rc);
189 m_heightmapDevice->readBytes(tempHeightmapDevice->data(), rc);
190 tempColorDevice->colorSpace()->
191 modulateLightnessByGrayBrush(tempColorDevice->data(),
192 reinterpret_cast<const QRgb*>(tempHeightmapDevice->data()),
193 1.0,
194 numPixels);
195 m_projectionDevice->writeBytes(tempColorDevice->data(), tempColorDevice->bounds());
196 }
197
198 m_layerOverlayDevice->writeRects(mirroredRects);
199
200 return mirroredRects;
201}
const KoID Integer16BitsColorDepthID("U16", ki18n("16-bit integer/channel"))
const QString COMPOSITE_OVER
const QString COMPOSITE_COPY
PythonPluginManager * instance
void blendBrush(const QVector< KisPainter * > dstPainters, KisColorSmudgeSourceSP srcSampleDevice, KisFixedPaintDeviceSP maskDab, bool preserveMaskDab, const QRect &srcRect, const QRect &dstRect, const KoColor &currentPaintColor, qreal opacity, qreal smudgeRateValue, qreal maxPossibleSmudgeRateValue, qreal colorRateValue, qreal smudgeRadiusValue)
void initializePaintingImpl(const KoColorSpace *dstColorSpace, bool smearAlpha, const QString &colorRateCompositeOpId)
DabColoringStrategy & coloringStrategy() override
void updateMask(KisDabCache *dabCache, const KisPaintInformation &info, const KisDabShape &shape, const QPointF &cursorPoint, QRect *dstDabRect, qreal lightnessStrength) override
QVector< QRect > paintDab(const QRect &srcRect, const QRect &dstRect, const KoColor &currentPaintColor, qreal opacity, qreal colorRateValue, qreal smudgeRateValue, qreal maxPossibleSmudgeRateValue, qreal lightnessStrengthValue, qreal smudgeRadiusValue) override
KisColorSmudgeStrategyLightness(KisPainter *painter, bool smearAlpha, bool useDullingMode, KisPaintThicknessOptionData::ThicknessMode thicknessMode)
KisOverlayPaintDeviceWrapper * m_layerOverlayDevice
KisPaintThicknessOptionData::ThicknessMode m_thicknessMode
KisOptimizedByteArray::MemoryAllocatorSP m_memoryAllocator
The KisDabCache class provides caching for dabs into the brush paintop.
bool needSeparateOriginal() const
KisFixedPaintDeviceSP fetchNormalizedImageDab(const KoColorSpace *cs, const QPointF &cursorPoint, KisDabShape const &shape, const KisPaintInformation &info, qreal softnessFactor, QRect *dstDabRect)
void setRect(const QRect &rc)
const KoColorSpace * colorSpace() const
void writeRects(const QVector< QRect > &rects, int index=0)
bool supportsWraproundMode() const
void setDefaultBounds(KisDefaultBoundsBaseSP bounds)
KisInterstrokeDataSP interstrokeData() const
const KoColorSpace * colorSpace() const
void setSupportsWraparoundMode(bool value)
KisDefaultBoundsBaseSP defaultBounds() const
void convertTo(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent=KoColorConversionTransformation::internalRenderingIntent(), KoColorConversionTransformation::ConversionFlags conversionFlags=KoColorConversionTransformation::internalConversionFlags(), KUndo2Command *parentCommand=nullptr, KoUpdater *progressUpdater=nullptr)
void readBytes(quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h) const
void writeBytes(const quint8 *data, qint32 x, qint32 y, qint32 w, qint32 h)
QString compositeOpId
const QVector< QRect > calculateAllMirroredRects(const QRect &rc)
void copyMirrorInformationFrom(const KisPainter *other)
QBitArray channelFlags()
void setSelection(KisSelectionSP selection)
KisSelectionSP selection
void setOpacityF(qreal opacity)
void begin(KisPaintDeviceSP device)
void renderMirrorMaskSafe(QRect rc, KisFixedPaintDeviceSP dab, bool preserveDab)
KisPaintDeviceSP device
void bltFixed(qint32 dstX, qint32 dstY, const KisFixedPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
void setChannelFlags(QBitArray channelFlags)
void setCompositeOpId(const KoCompositeOp *op)
static _Tdst multiply(_T a, _Tdst b)
virtual void copyOpacityU8(quint8 *src, quint8 *dst, qint32 nPixels) const =0
virtual KoID colorModelId() const =0
virtual const KoColorProfile * profile() const =0
QString id() const
Definition KoID.cpp:63
#define KIS_SAFE_ASSERT_RECOVER(cond)
Definition kis_assert.h:126
unsigned int QRgb
QSharedPointer< T > toQShared(T *ptr)
Point lerp(const Point &pt1, const Point &pt2, qreal t)
KisOverlayPaintDeviceWrapper overlayDeviceWrapper
static KoColorSpaceRegistry * instance()