Krita

ColorizeMask.cpp
1/*
2 * SPDX-FileCopyrightText: 2017 Wolthera van Hövell tot Westerflier <griffinvalley@gmail.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6#include "ColorizeMask.h"
7#include <lazybrush/kis_colorize_mask.h>
8#include <lazybrush/kis_lazy_fill_tools.h>
9#include <kis_image.h>
10#include "Selection.h"
11#include <kis_selection.h>
12#include <KoColor.h>
13#include "kis_layer_properties_icons.h"
14#include <kis_transaction.h>
15#include <kis_update_scheduler.h>
16#include <kis_undo_stores.h>
17#include <kis_default_bounds.h>
18
19
20
21ColorizeMask::ColorizeMask(KisImageSP image, QString name, QObject *parent) :
22 Node(image, new KisColorizeMask(image,name), parent)
23{
24
25}
26
27ColorizeMask::ColorizeMask(KisImageSP image, KisColorizeMaskSP mask, QObject *parent):
28 Node(image, mask, parent)
29{
30}
31
32ColorizeMask::~ColorizeMask()
33{
34
35}
36
37
39{
40 QList<ManagedColor*> colorList;
41 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
42 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, colorList);
43
44 for (KoColor color : mask->keyStrokesColors().colors) {
45 colorList.append(new ManagedColor(color));
46 }
47
48 return colorList;
49}
50
52{
53 KisColorizeMaskSP mask = qobject_cast<KisColorizeMask*>(this->node().data());
54 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
55
56 /**
57 * This method is supposed to to initial initialization only!
58 *
59 * It is necessary because the function also changes the color
60 * space and blending mode of the mask
61 *
62 * TODO: implement a proper API that modifies key strokes
63 * of a colorize mask without breaking undo history
64 */
65 KIS_SAFE_ASSERT_RECOVER_RETURN(mask->keyStrokesColors().colors.size() == 0);
66
67 mask->initializeCompositeOp();
68 delete mask->setColorSpace(mask->parent()->colorSpace());
69
71
72 for (int i = 0; i < colors.size(); i++) {
73 KisLazyFillTools::KeyStroke keyStroke;
74 keyStroke.color = colors[i]->color();
75 keyStroke.dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
76 keyStroke.dev->setDefaultBounds(new KisDefaultBounds(this->node()->image()));
77 keyStroke.isTransparent = transparentIndex == i;
78 // NOTE: the parent node link is initialized in
79 // setKeyStrokesDirect
80
81 keyStrokes.append(keyStroke);
82 }
83
84 mask->setKeyStrokesDirect(keyStrokes);
85}
86
87
89{
90 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
91 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, -1);
92
93 return mask->keyStrokesColors().transparentIndex;
94}
95
97{
98 const KoColor kc = color->color();
99 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
100 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
101
102 mask->removeKeyStroke(kc);
103}
104
105QByteArray ColorizeMask::keyStrokePixelData(ManagedColor* color, int x, int y, int w, int h) const
106{
107 QByteArray ba;
108
109 if (!this->node()) return ba;
110
111 const KoColor kc = color->color();
112 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
113 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, QByteArray());
114
115 for (KisLazyFillTools::KeyStroke keystroke : mask->fetchKeyStrokesDirect()) {
116 if (kc == keystroke.color) {
117 KisPaintDeviceSP dev = keystroke.dev;
118
119 if (!dev) return ba;
120
121 ba.resize(w * h * dev->pixelSize());
122 dev->readBytes(reinterpret_cast<quint8*>(ba.data()), x, y, w, h);
123 return ba;
124 }
125 }
126
127 return ba;
128}
129
130bool ColorizeMask::setKeyStrokePixelData(QByteArray value, ManagedColor* color, int x, int y, int w, int h)
131{
132 if (!this->node()) return false;
133
134 const KoColor kc = color->color();
135 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
136 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, false);
137
138 for (KisLazyFillTools::KeyStroke keystroke : mask->fetchKeyStrokesDirect()) {
139 if (kc == keystroke.color) {
140 KisPaintDeviceSP dev = keystroke.dev;
141
142 if (!dev) return false;
143 if (value.length() < w * h * (int)dev->colorSpace()->pixelSize()) {
144 qWarning() << "ColorizeMask::setKeyStrokePixelData: not enough data to write to the paint device";
145 return false;
146 }
147 dev->writeBytes((const quint8*)value.constData(), x, y, w, h);
148 return true;
149 }
150 }
151
152 return false;
153}
154
156{
157 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
158 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
159
160 mask->setUseEdgeDetection(value);
161}
162
164{
165 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
166 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, false);
167
168 return mask->useEdgeDetection();
169}
170
172{
173 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
174 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
175
176 mask->setEdgeDetectionSize(value);
177}
178
180{
181 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
182 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, -1);
183
184 return mask->edgeDetectionSize();
185}
186
188{
189 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
190 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
191
192 mask->setCleanUpAmount(value);
193}
194
196{
197 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
198 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, -1);
199
200 return mask->cleanUpAmount();
201}
202
204{
205 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
206 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
207
208 mask->setLimitToDeviceBounds(value);
209}
210
212{
213 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
214 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, false);
215
216 return mask->limitToDeviceBounds();
217}
218
220{
221 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
222 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
223
224 if (force) {
225 mask->forceRegenerateMask();
226 } else {
227 KisLayerPropertiesIcons::setNodePropertyAutoUndo(mask, KisLayerPropertiesIcons::colorizeNeedsUpdate, false, this->node()->image());
228 }
229}
230
231void ColorizeMask::resetCache()
232{
233 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
234 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
235
236 mask->resetCache();
237}
238
240{
241 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
242 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
243
244 KisLayerPropertiesIcons::setNodePropertyAutoUndo(mask, KisLayerPropertiesIcons::colorizeShowColoring, enabled, this->node()->image());
245}
246
248{
249 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
250 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, false);
251
252 const KisBaseNode::PropertyList props = mask->sectionModelProperties();
253
254 for (const KisBaseNode::Property &prop : props) {
255 if (prop.id == KisLayerPropertiesIcons::colorizeShowColoring.id()) {
256 return prop.state.toBool();
257 }
258 }
259
260 return false;
261}
262
264{
265 KisColorizeMask *mask = qobject_cast<KisColorizeMask*>(this->node().data());
266 KIS_SAFE_ASSERT_RECOVER_RETURN(mask);
267
268 KisLayerPropertiesIcons::setNodePropertyAutoUndo(mask, KisLayerPropertiesIcons::colorizeEditKeyStrokes, enabled, this->node()->image());
269}
270
272{
273 const KisColorizeMask *mask = qobject_cast<const KisColorizeMask*>(this->node());
274 KIS_SAFE_ASSERT_RECOVER_RETURN_VALUE(mask, false);
275
276 const KisBaseNode::PropertyList props = mask->sectionModelProperties();
277
278 for (const KisBaseNode::Property &prop : props) {
279 if (prop.id == KisLayerPropertiesIcons::colorizeEditKeyStrokes.id()) {
280 return prop.state.toBool();
281 }
282 }
283
284 return false;
285}
286
288{
289 return "colorizemask";
290}
bool useEdgeDetection() const
useEdgeDetection
QByteArray keyStrokePixelData(ManagedColor *color, int x, int y, int w, int h) const
keyStrokePixelData reads the given rectangle from the keystroke image data and returns it as a byte a...
void setEditKeyStrokes(bool enabled)
setEditKeyStrokes Toggle Colorize Mask's edit keystrokes mode.
bool showOutput() const
showOutput Show output mode allows the user to see the result of the Colorize Mask's algorithm.
bool editKeyStrokes() const
editKeyStrokes Edit keystrokes mode allows the user to modify keystrokes on the active Colorize Mask.
void setEdgeDetectionSize(qreal value)
setEdgeDetectionSize Set the value to the thinnest line on the image.
int transparencyIndex() const
transparencyIndex Index of the transparent color.
qreal cleanUpAmount() const
cleanUpAmount
qreal edgeDetectionSize() const
edgeDetectionSize
void setShowOutput(bool enabled)
setShowOutput Toggle Colorize Mask's show output mode.
void setCleanUpAmount(qreal value)
setCleanUpAmount This will attempt to handle messy strokes that overlap the line art where they shoul...
QList< ManagedColor * > keyStrokesColors() const
keyStrokesColors Colors used in the Colorize Mask's keystrokes.
bool setKeyStrokePixelData(QByteArray value, ManagedColor *color, int x, int y, int w, int h)
setKeyStrokePixelData writes the given bytes, of which there must be enough, into the keystroke,...
void setLimitToDeviceBounds(bool value)
setLimitToDeviceBounds Limit the colorize mask to the combined layer bounds of the strokes and the li...
void updateMask(bool force=false)
updateMask Process the Colorize Mask's keystrokes and generate a projection of the computed colors.
bool limitToDeviceBounds() const
limitToDeviceBounds
void setUseEdgeDetection(bool value)
setUseEdgeDetection Activate this for line art with large solid areas, for example shadows on an obje...
void initializeKeyStrokeColors(QList< ManagedColor * > colors, int transparentIndex=-1)
initializeKeyStrokeColors Set the colors to use for the Colorize Mask's keystrokes.
virtual QString type() const override
type Krita has several types of nodes, split in layers and masks.
void removeKeyStroke(ManagedColor *color)
removeKeyStroke Remove a color from the Colorize Mask's keystrokes.
The ManagedColor class is a class to handle colors that are color managed.
Node represents a layer or mask in a Krita image's Node hierarchy.
Definition Node.h:24
QString name(GameStandardAction id)
const char * constData() const const
char * data()
qsizetype length() const const
void resize(qsizetype newSize, char c)
void append(QList< T > &&value)
qsizetype size() const const
T qobject_cast(QObject *object)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 4 2024 16:35:00 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.