Krita Source Code Documentation
Loading...
Searching...
No Matches
kis_multiway_cut.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#include "kis_multiway_cut.h"
8
10#include <KoColorSpace.h>
11#include <KoColor.h>
12
13#include "KisRegion.h"
14#include "kis_paint_device.h"
15#include "kis_painter.h"
16#include "kis_lazy_fill_tools.h"
19
20
21using namespace KisLazyFillTools;
22
34
37 const QRect &boundingRect)
38 : m_d(new Private)
39{
40 m_d->src = src;
41 m_d->dst = dst;
42 m_d->mask = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8());
43 m_d->boundingRect = boundingRect;
44}
45
49
51{
52 m_d->keyStrokes << KeyStroke(dev, color);
53}
54
55
56void KisMultiwayCut::Private::maskOutKeyStroke(KisPaintDeviceSP keyStrokeDevice, KisPaintDeviceSP mask, const QRect &boundingRect)
57{
58 KIS_ASSERT_RECOVER_RETURN(keyStrokeDevice->pixelSize() == 1);
60
61 KisRegion region =
62 keyStrokeDevice->region() &
64
65 Q_FOREACH (const QRect &rc, region.rects()) {
66 KisSequentialIterator dstIt(keyStrokeDevice, rc);
68
69 while (dstIt.nextPixel() && mskIt.nextPixel()) {
70 if (*mskIt.rawDataConst() > 0) {
71 *dstIt.rawData() = 0;
72 }
73 }
74 }
75}
76
77bool keyStrokesOrder(const KeyStroke &a, const KeyStroke &b)
78{
79 const bool aTransparent = a.color.opacityU8() == OPACITY_TRANSPARENT_U8;
80 const bool bTransparent = b.color.opacityU8() == OPACITY_TRANSPARENT_U8;
81
82 if (aTransparent && !bTransparent) return true;
83 if (!aTransparent && bTransparent) return false;
84
85 const QRect aRect = a.dev->extent();
86 const QRect bRect = b.dev->extent();
87
88 const int aArea = aRect.width() * aRect.height();
89 const int bArea = bRect.width() * bRect.height();
90
91 return aArea > bArea;
92}
93
95{
97
108 std::stable_sort(m_d->keyStrokes.begin(), m_d->keyStrokes.end(), keyStrokesOrder);
109
110 while (m_d->keyStrokes.size() > 1) {
111 KeyStroke current = m_d->keyStrokes.takeFirst();
112
113 // if current scribble is empty, it just has no effect
114 if (current.dev->exactBounds().isEmpty()) continue;
115
116 KisPainter gc(other);
117
118 Q_FOREACH (const KeyStroke &s, m_d->keyStrokes) {
119 const QRect rc = s.dev->extent() & m_d->boundingRect;
120 gc.bitBlt(rc.topLeft(), s.dev, rc);
121 }
122
123 // if other is empty, it means that *all* other strokes are
124 // empty, so there is no reason to continue the process
125 if (other->exactBounds().isEmpty()) {
126 m_d->keyStrokes.clear();
127 m_d->keyStrokes << current;
128 break;
129 }
130
132 m_d->src,
133 current.dev,
134 other,
135 m_d->dst,
136 m_d->mask,
137 m_d->boundingRect);
138
139 other->clear();
140 }
141
142 // TODO: check if one can use the last cut for this purpose!
143
144 if (m_d->keyStrokes.size() == 1) {
145 KeyStroke current = m_d->keyStrokes.takeLast();
146
147 m_d->maskOutKeyStroke(current.dev, m_d->mask, m_d->boundingRect);
148
149 QVector<QPoint> points =
151
152 Q_FOREACH (const QPoint &pt, points) {
153 KisScanlineFill fill(m_d->mask, pt, m_d->boundingRect);
154 fill.fill(current.color, m_d->dst);
155 }
156 }
157}
158
160{
161 return m_d->src;
162}
163
165{
166 return m_d->dst;
167}
const quint8 OPACITY_TRANSPARENT_U8
KisMultiwayCut(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &boundingRect)
void addKeyStroke(KisPaintDeviceSP dev, const KoColor &color)
const QScopedPointer< Private > m_d
KisPaintDeviceSP dstDevice() const
KisPaintDeviceSP srcDevice() const
quint32 pixelSize() const
virtual void clear()
KisRegion region() const
QRect exactBounds() const
QRect extent() const
void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight)
QVector< QRect > rects() const
ALWAYS_INLINE quint8 * rawData()
ALWAYS_INLINE const quint8 * rawDataConst() const
quint8 opacityU8() const
Definition KoColor.cpp:341
#define KIS_ASSERT_RECOVER_RETURN(cond)
Definition kis_assert.h:75
bool keyStrokesOrder(const KeyStroke &a, const KeyStroke &b)
void cutOneWay(const KoColor &color, KisPaintDeviceSP src, KisPaintDeviceSP colorScribble, KisPaintDeviceSP backgroundScribble, KisPaintDeviceSP resultDevice, KisPaintDeviceSP maskDevice, const QRect &boundingRect)
QVector< QPoint > splitIntoConnectedComponents(KisPaintDeviceSP dev, const QRect &boundingRect)
static void maskOutKeyStroke(KisPaintDeviceSP keyStrokeDevice, KisPaintDeviceSP mask, const QRect &boundingRect)
QVector< KeyStroke > keyStrokes
void fill(const KoColor &fillColor)
static KoColorSpaceRegistry * instance()