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; };
79inline QPolygon::iterator range_begin(QPolygon&
p)
80{
return QPolygon::iterator(
p.begin());}
82inline QPolygon::const_iterator range_begin(
const QPolygon&
p)
83{
return QPolygon::const_iterator(
p.begin());}
85inline QPolygon::iterator range_end(QPolygon&
p)
86{
return QPolygon::iterator(
p.end());}
88inline QPolygon::const_iterator range_end(
const QPolygon&
p)
89{
return QPolygon::const_iterator(
p.end());}
94 boost::geometry::convex_hull(QPolygon(points), hull);
99struct CheckFullyTransparent {
101 : m_colorSpace(colorSpace)
105 bool isPixelEmpty(
const quint8 *pixelData)
114struct CheckNonDefault {
115 CheckNonDefault(
int pixelSize,
const quint8 *defaultPixel)
116 : m_pixelSize(pixelSize),
117 m_defaultPixel(defaultPixel)
121 bool isPixelEmpty(
const quint8 *pixelData)
123 return memcmp(m_defaultPixel, pixelData, m_pixelSize) == 0;
128 const quint8 *m_defaultPixel;
131struct CheckDeselected {
133 : m_colorSpace(colorSpace),
134 m_deselectedColor(Qt::black, colorSpace),
135 m_pixelSize(colorSpace->pixelSize())
141 bool isPixelEmpty(
const quint8 *pixelData)
144 memcmp(m_deselectedColor.data(), pixelData, m_pixelSize) == 0;
149 const KoColor m_deselectedColor;
150 const int m_pixelSize;
153template <
class ComparePixelOp>
157 int defaultMin =
rect.x() +
rect.width() + 1;
158 int defaultMax =
rect.x() - 1;
161 int base =
rect.top();
162 if (!skip.isEmpty()) {
163 for (
int y = skip.top();
y <= skip.bottom();
y++) {
164 minX[
y - base] = skip.left();
165 maxX[
y - base] = skip.right();
171 for (
int y =
rect.top();
y <=
rect.bottom();) {
173 for (
int x =
rect.left();
x <=
rect.right();) {
176 int strideBytes = accessor->
rowStride(x, y);
178 for (
int r = 0;
r < rows;
r++) {
179 for (
int c = 0; c < columns; c++) {
180 if (!compareOp.isPixelEmpty(data + c * pixelSize)) {
181 int index =
y +
r - base;
182 minX[index] = std::min(minX[index], x + c);
183 maxX[index] = std::max(maxX[index], x + c);
193 for (
int y =
rect.top();
y <=
rect.bottom();
y++) {
194 int index =
y - base;
195 if (minX[index] < defaultMin) {
196 points << QPoint(minX[index], y);
197 points << QPoint(minX[index], y + 1);
199 if (maxX[index] > defaultMax) {
200 points << QPoint(maxX[index] + 1, y);
201 points << QPoint(maxX[index] + 1, y + 1);
212 const quint8 defaultOpacity = defaultPixel.
opacityU8();
218 CheckNonDefault compareOp(device->
pixelSize(), defaultPixel.
data());
220 points = retrieveAllBoundaryPointsImpl(device,
rect, skip, compareOp);
221 if (!skip.isEmpty()) {
223 skip.getRect(&x, &y, &w, &h);
224 points << QPoint(x, y) << QPoint(x + w, y) << QPoint(x + w, y + h) << QPoint(x, y + h);
227 CheckFullyTransparent compareOp(device->
colorSpace());
228 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
237 const quint8 defaultOpacity = defaultPixel.
opacityU8();
245 CheckNonDefault compareOp(device->
pixelSize(), defaultPixel.
data());
247 points = retrieveAllBoundaryPointsImpl(device,
rect, skip, compareOp);
248 if (!skip.isEmpty()) {
250 skip.getRect(&x, &y, &w, &h);
251 points << QPoint(x, y) << QPoint(x + w, y) << QPoint(x + w, y + h) << QPoint(x, y + h);
254 CheckFullyTransparent compareOp(device->
colorSpace());
255 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
261 CheckDeselected compareOp(device->
colorSpace());
262 points = retrieveAllBoundaryPointsImpl(device,
rect, QRect(), compareOp);
273 QPolygon hull = convexHull(points);
281 auto ps = retrieveAllBoundaryPoints(device);
290 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