Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_lazy_fill_tools.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2016 Dmitry Kazakov <dimula73@gmail.com>
3 *
4 * SPDX-License-Identifier: GPL-2.0-or-later
5 */
6
7#define BOOST_DISABLE_ASSERTS 1
8
10
11#include <numeric>
12#include <boost/limits.hpp>
13
14#include <boost/graph/graph_traits.hpp>
15#include <boost/graph/properties.hpp>
16#include <boost/iterator/counting_iterator.hpp>
17#include <boost/iterator/transform_iterator.hpp>
18
19// we use a forked version of the algorithm
20//#include <boost/graph/boykov_kolmogorov_max_flow.hpp>
22
23#include <boost/graph/iteration_macros.hpp>
24
27
30
31#include "krita_utils.h"
32
33namespace KisLazyFillTools {
34
36{
37 quint8 maxPixel = std::numeric_limits<quint8>::min();
38 quint8 minPixel = std::numeric_limits<quint8>::max();
40 [&minPixel, &maxPixel](quint8 pixel) {
41 if (pixel > maxPixel) {
42 maxPixel = pixel;
43 }
44 if (pixel < minPixel) {
45 minPixel = pixel;
46 }
47 });
48
49 const qreal scale = 255.0 / (maxPixel - minPixel);
51 [minPixel, scale](quint8 pixel) {
52 return pow2(255 - quint8((pixel - minPixel) * scale)) / 255;
53 });
54}
55
57{
58 quint8 maxPixel = std::numeric_limits<quint8>::min();
59 quint8 minPixel = std::numeric_limits<quint8>::max();
61 [&minPixel, &maxPixel](quint8 pixel) {
62 if (pixel > maxPixel) {
63 maxPixel = pixel;
64 }
65 if (pixel < minPixel) {
66 minPixel = pixel;
67 }
68 });
69
70 const qreal scale = 255.0 / (maxPixel - minPixel);
72 [minPixel, scale](quint8 pixel) {
73 return (quint8((pixel - minPixel) * scale));
74 });
75}
76
77void cutOneWay(const KoColor &color,
79 KisPaintDeviceSP colorScribble,
80 KisPaintDeviceSP backgroundScribble,
81 KisPaintDeviceSP resultDevice,
82 KisPaintDeviceSP maskDevice,
83 const QRect &boundingRect)
84{
85 using namespace boost;
86
87 KIS_ASSERT_RECOVER_RETURN(src->pixelSize() == 1);
88 KIS_ASSERT_RECOVER_RETURN(colorScribble->pixelSize() == 1);
89 KIS_ASSERT_RECOVER_RETURN(backgroundScribble->pixelSize() == 1);
90 KIS_ASSERT_RECOVER_RETURN(maskDevice->pixelSize() == 1);
91 KIS_ASSERT_RECOVER_RETURN(*resultDevice->colorSpace() == *color.colorSpace());
92
93 KisLazyFillCapacityMap capacityMap(src, colorScribble, backgroundScribble, maskDevice, boundingRect);
94 KisLazyFillGraph &graph = capacityMap.graph();
95
96 std::vector<default_color_type> groups(num_vertices(graph));
97 std::vector<int> residual_capacity(num_edges(graph), 0);
98
99 std::vector<typename graph_traits<KisLazyFillGraph>::vertices_size_type> distance_vec(num_vertices(graph), 0);
100 std::vector<typename graph_traits<KisLazyFillGraph>::edge_descriptor> predecessor_vec(num_vertices(graph));
101
102 auto vertexIndexMap = get(boost::vertex_index, graph);
103
105
106 Vertex s(Vertex::LABEL_A);
107 Vertex t(Vertex::LABEL_B);
108
109 float maxFlow =
111 capacityMap,
112 make_iterator_property_map(&residual_capacity[0], get(boost::edge_index, graph)),
113 get(boost::edge_reverse, graph),
114 make_iterator_property_map(&predecessor_vec[0], vertexIndexMap),
115 make_iterator_property_map(&groups[0], vertexIndexMap),
116 make_iterator_property_map(&distance_vec[0], vertexIndexMap),
117 vertexIndexMap,
118 s,
119 t);
120 Q_UNUSED(maxFlow);
121
122 KisSequentialIterator dstIt(resultDevice, graph.rect());
123 KisSequentialIterator mskIt(maskDevice, graph.rect());
124
125 const int pixelSize = resultDevice->pixelSize();
126
127 while (dstIt.nextPixel() && mskIt.nextPixel()) {
128 KisLazyFillGraph::vertex_descriptor v(dstIt.x(), dstIt.y());
129 long vertex_idx = get(boost::vertex_index, graph, v);
130 default_color_type label = groups[vertex_idx];
131
132 if (label == black_color) {
133 memcpy(dstIt.rawData(), color.data(), pixelSize);
134 *mskIt.rawData() = 10 + (int(label) << 4);
135 }
136 }
137}
138
140 const QRect &boundingRect)
141{
142 QVector<QPoint> points;
143 const KoColorSpace *cs = dev->colorSpace();
144
145 const QRect rect = dev->exactBounds() & boundingRect;
146 if (rect.isEmpty()) return points;
147
154 KisSequentialIterator dstIt(dev, rect);
155
156 while (dstIt.nextPixel()) {
157 if (cs->opacityU8(dstIt.rawData()) > 0) {
158 const QPoint pt(dstIt.x(), dstIt.y());
159 points << pt;
160
161 KisScanlineFill fill(dev, pt, rect);
163 }
164 }
165
166 return points;
167}
168
169
171 : isTransparent(false)
172{
173}
174
175KeyStroke::KeyStroke(KisPaintDeviceSP _dev, const KoColor &_color, bool _isTransparent)
176 : dev(_dev), color(_color), isTransparent(_isTransparent)
177{
178}
179
180bool operator==(const KeyStroke& t1, const KeyStroke&t2)
181{
182 return
183 t1.dev == t2.dev &&
184 t1.color == t2.color &&
186}
187
188FilteringOptions::FilteringOptions(bool _useEdgeDetection, qreal _edgeDetectionSize, qreal _fuzzyRadius, qreal _cleanUpAmount)
189 : useEdgeDetection(_useEdgeDetection),
190 edgeDetectionSize(_edgeDetectionSize),
191 fuzzyRadius(_fuzzyRadius),
192 cleanUpAmount(_cleanUpAmount)
193{
194}
195
203
204}
qreal v
VertexDescriptor get(PredecessorMap const &m, VertexDescriptor v)
quint32 pixelSize() const
QRect exactBounds() const
const KoColorSpace * colorSpace() const
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE int x() const
ALWAYS_INLINE int y() const
virtual quint8 opacityU8(const quint8 *pixel) const =0
quint8 * data()
Definition KoColor.h:144
const KoColorSpace * colorSpace() const
return the current colorSpace
Definition KoColor.h:82
static bool qFuzzyCompare(half p1, half p2)
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
T pow2(const T &x)
Definition kis_global.h:166
bool operator==(const KeyStroke &t1, const KeyStroke &t2)
void cutOneWay(const KoColor &color, KisPaintDeviceSP src, KisPaintDeviceSP colorScribble, KisPaintDeviceSP backgroundScribble, KisPaintDeviceSP resultDevice, KisPaintDeviceSP maskDevice, const QRect &boundingRect)
void normalizeAndInvertAlpha8Device(KisPaintDeviceSP dev, const QRect &rect)
void normalizeAlpha8Device(KisPaintDeviceSP dev, const QRect &rect)
QVector< QPoint > splitIntoConnectedComponents(KisPaintDeviceSP dev, const QRect &boundingRect)
void filterAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function< quint8(quint8)> func)
void applyToAlpha8Device(KisPaintDeviceSP dev, const QRect &rc, std::function< void(quint8)> func)
property_traits< CapacityEdgeMap >::value_type boykov_kolmogorov_max_flow(Graph &g, CapacityEdgeMap cap, ResidualCapacityEdgeMap res_cap, ReverseEdgeMap rev_map, PredecessorMap pre_map, ColorMap color, DistanceMap dist, IndexMap idx, typename graph_traits< Graph >::vertex_descriptor src, typename graph_traits< Graph >::vertex_descriptor sink)