9#include <boost/geometry.hpp>
11#include <QElapsedTimer>
21 template<>
struct tag<QPoint>
22 {
typedef point_tag
type; };
24 template<>
struct coordinate_type<QPoint>
27 template<>
struct coordinate_system<QPoint>
28 {
typedef cs::cartesian
type; };
30 template<>
struct dimension<QPoint> : boost::mpl::int_<2> {};
33 struct access<QPoint, 0>
35 static int get(QPoint
const&
p)
47 struct access<QPoint, 1>
49 static int get(QPoint
const&
p)
62 template<>
struct tag<QPolygon>
63 {
typedef linestring_tag
type; };
69 struct range_iterator<QPolygon>
70 {
typedef QPolygon::iterator
type; };
73 struct range_const_iterator<QPolygon>
74 {
typedef QPolygon::const_iterator
type; };
82 boost::geometry::convex_hull(QPolygon(points), hull);
87struct CheckFullyTransparent {
89 : m_colorSpace(colorSpace)
93 bool isPixelEmpty(
const quint8 *pixelData)
102struct CheckNonDefault {
103 CheckNonDefault(
int pixelSize,
const quint8 *defaultPixel)
104 : m_pixelSize(pixelSize),
105 m_defaultPixel(defaultPixel)
109 bool isPixelEmpty(
const quint8 *pixelData)
111 return memcmp(m_defaultPixel, pixelData, m_pixelSize) == 0;
116 const quint8 *m_defaultPixel;
119struct CheckDeselected {
121 : m_colorSpace(colorSpace),
122 m_deselectedColor(Qt::black, colorSpace),
123 m_pixelSize(colorSpace->pixelSize())
129 bool isPixelEmpty(
const quint8 *pixelData)
132 memcmp(m_deselectedColor.data(), pixelData, m_pixelSize) == 0;
137 const KoColor m_deselectedColor;
138 const int m_pixelSize;
141template <
class ComparePixelOp>
145 int defaultMin =
rect.x() +
rect.width() + 1;
146 int defaultMax =
rect.x() - 1;
149 int base =
rect.top();
150 if (!skip.isEmpty()) {
151 for (
int y = skip.top();
y <= skip.bottom();
y++) {
152 minX[
y - base] = skip.left();
153 maxX[
y - base] = skip.right();
159 for (
int y =
rect.top();
y <=
rect.bottom();) {
161 for (
int x =
rect.left();
x <=
rect.right();) {
164 int strideBytes = accessor->
rowStride(x, y);
166 for (
int r = 0;
r < rows;
r++) {
167 for (
int c = 0; c < columns; c++) {
168 if (!compareOp.isPixelEmpty(data + c * pixelSize)) {
169 int index =
y +
r - base;
170 minX[index] = std::min(minX[index], x + c);
171 maxX[index] = std::max(maxX[index], x + c);
181 for (
int y =
rect.top();
y <=
rect.bottom();
y++) {
182 int index =
y - base;
183 if (minX[index] < defaultMin) {
184 points << QPoint(minX[index], y);
185 points << QPoint(minX[index], y + 1);
187 if (maxX[index] > defaultMax) {
188 points << QPoint(maxX[index] + 1, y);
189 points << QPoint(maxX[index] + 1, y + 1);
200 const quint8 defaultOpacity = defaultPixel.
opacityU8();
206 CheckNonDefault compareOp(device->
pixelSize(), defaultPixel.
data());
208 points = retrieveAllBoundaryPointsImpl(device,
rect, skip, compareOp);
209 if (!skip.isEmpty()) {
211 skip.getRect(&x, &y, &w, &h);
212 points << QPoint(x, y) << QPoint(x + w, y) << QPoint(x + w, y + h) << QPoint(x, y + h);
215 CheckFullyTransparent compareOp(device->
colorSpace());
216 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
225 const quint8 defaultOpacity = defaultPixel.
opacityU8();
233 CheckNonDefault compareOp(device->
pixelSize(), defaultPixel.
data());
235 points = retrieveAllBoundaryPointsImpl(device,
rect, skip, compareOp);
236 if (!skip.isEmpty()) {
238 skip.getRect(&x, &y, &w, &h);
239 points << QPoint(x, y) << QPoint(x + w, y) << QPoint(x + w, y + h) << QPoint(x, y + h);
242 CheckFullyTransparent compareOp(device->
colorSpace());
243 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
249 CheckDeselected compareOp(device->
colorSpace());
250 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
261 QPolygon hull = convexHull(points);
269 auto ps = retrieveAllBoundaryPoints(device);
278 auto ps = retrieveAllBoundaryPointsSelectionLike(device);
float value(const T *src, size_t ch)
const KoID GrayAColorModelID("GRAYA", ki18n("Grayscale/Alpha"))
const KoID AlphaColorModelID("A", ki18n("Alpha mask"))
const quint8 OPACITY_TRANSPARENT_U8
virtual const quint8 * rawDataConst() const =0
virtual QRect bounds() const =0
quint32 pixelSize() const
KisRandomConstAccessorSP createRandomConstAccessorNG() const
const KoColorSpace * colorSpace() const
KoColor defaultPixel() const
KisDefaultBoundsBaseSP defaultBounds() const
virtual qint32 rowStride(qint32 x, qint32 y) const =0
virtual qint32 numContiguousRows(qint32 y) const =0
virtual void moveTo(qint32 x, qint32 y)=0
virtual qint32 numContiguousColumns(qint32 x) const =0
virtual KoID colorModelId() const =0
const KoColorSpace * colorSpace() const
return the current colorSpace
#define KIS_SAFE_ASSERT_RECOVER_NOOP(cond)
QPolygon findConvexHullSelectionLike(KisPaintDeviceSP device)
QPolygon findConvexHull(const QVector< QPoint > &points)
static void set(QPoint &p, int const &value)
static int get(QPoint const &p)
static int get(QPoint const &p)
static void set(QPoint &p, int const &value)
QPolygon::const_iterator type