ImageMaskEditor.cpp
Go to the documentation of this file.
1 #include <QWidget>
2 #include <QMouseEvent>
3 #include <QPainter>
4 #include <QPen>
5 #include <QBrush>
6 
7 #include "ImageMaskEditor.h"
8 
9 ImageMaskEditor::ImageMaskEditor(QSize size, QWidget* parent)
10  : QWidget(parent)
11 {
12  setMouseTracking(true);
13  resizeImage(size);
14 }
15 
16 ImageMaskEditor::ImageMaskEditor(int width, int height, QWidget* parent)
17  : ImageMaskEditor({width, height}, parent)
18 {}
19 
20 bool ImageMaskEditor::openMaskImage(const QString& fileName)
21 {
22  QImage loadedImage;
23  if (!loadedImage.load(fileName))
24  {
25  return false;
26  }
27  setMaskImage(loadedImage);
28  return true;
29 }
30 
31 bool ImageMaskEditor::openBackgroundImage(const QString& fileName)
32 {
33  QImage loadedImage;
34  if (!loadedImage.load(fileName))
35  {
36  return false;
37  }
38  setBackgroundImage(loadedImage);
39  return true;
40 }
41 
42 bool ImageMaskEditor::saveMaskImage(const QString& fileName, const char* fileFormat)
43 {
44  if (maskImage().save(fileName, fileFormat))
45  {
46  return true;
47  }
48  else
49  {
50  return false;
51  }
52 }
53 
54 bool ImageMaskEditor::saveBackgroundImage(const QString& fileName, const char* fileFormat)
55 {
56  if (backgroundImage().save(fileName, fileFormat))
57  {
58  return true;
59  }
60  else
61  {
62  return false;
63  }
64 }
65 
66 const QColor& ImageMaskEditor::maskColor() const
67 {
68  return _penColor;
69 }
70 
71 const QColor& ImageMaskEditor::transparentColor() const
72 {
73  return _maskTransparentColor;
74 }
75 
77 {
78  return _penWidth;
79 }
80 
81 const QImage& ImageMaskEditor::backgroundImage() const
82 {
83  return _backgroundImage;
84 }
85 
87 {
88  QImage i = _maskImage;
89  for (int x = 0; x < i.width(); ++x)
90  {
91  for (int y = 0; y < i.height(); ++y)
92  {
93  QColor color {i.pixel(x, y)};
94  if (color.alpha() == 0)
95  {
96  color = _maskTransparentColor;
97  }
98  else
99  {
100  color.setAlpha(255);
101  }
102  i.setPixel(x, y, color.rgba());
103  }
104  }
105  return i;
106 }
107 
109 {
110  return _backgroundImage.size();
111 }
112 
114 {
115  return imageSize();
116 }
117 
118 void ImageMaskEditor::setMaskColor(const QColor& newColor)
119 {
120  _penColor = newColor;
121  _penColor.setAlpha(255); // prevent blending of masks
122 }
123 
124 void ImageMaskEditor::setMaskColor(int r, int g, int b)
125 {
126  _penColor.setRed(r);
127  _penColor.setGreen(g);
128  _penColor.setBlue(b);
129  _penColor.setAlpha(255); // prevent blending of masks
130 }
131 
132 void ImageMaskEditor::setMaskColor(qreal r, qreal g, qreal b)
133 {
134  _penColor.setRedF(r);
135  _penColor.setGreenF(g);
136  _penColor.setBlueF(b);
137  _penColor.setAlpha(255); // prevent blending of masks
138 }
139 
140 
141 void ImageMaskEditor::setTransparentColor(const QColor& newColor)
142 {
143  _maskTransparentColor = newColor;
144  _maskTransparentColor.setAlpha(255); // prevent blending of masks
145 }
146 
147 void ImageMaskEditor::setTransparentColor(int r, int g, int b)
148 {
149  _maskTransparentColor.setRed(r);
150  _maskTransparentColor.setGreen(g);
151  _maskTransparentColor.setBlue(b);
152  _maskTransparentColor.setAlpha(255); // prevent blending of masks
153 }
154 
155 void ImageMaskEditor::setTransparentColor(qreal r, qreal g, qreal b)
156 {
157  _maskTransparentColor.setRedF(r);
158  _maskTransparentColor.setGreenF(g);
159  _maskTransparentColor.setBlueF(b);
160  _maskTransparentColor.setAlpha(255); // prevent blending of masks
161 }
162 
164 {
165  _maskImage.fill(qRgba(0, 0, 0, 0));
166  update();
167 }
168 
170 {
171  _penWidth = std::max(1, newWidth);
172 }
173 
175 {
176  _maskAlpha = std::max(1, std::min(255, newAlpha));
177  update();
178 }
179 
180 void ImageMaskEditor::setImageSize(QSize size, bool doNotShrink)
181 {
182  if (doNotShrink)
183  {
184  size = imageSize().expandedTo(size);
185  }
186  setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
187  setFixedSize(size);
188  resizeImage(&_backgroundImage, size, Qt::white);
189  resizeImage(&_maskImage, size, _maskTransparentColor);
190  update();
191 }
192 
193 void ImageMaskEditor::resizeImage(QSize size, bool doNotShrink)
194 {
195  setImageSize(size, doNotShrink);
196 }
197 
198 void ImageMaskEditor::setMaskImage(const QImage& i)
199 {
200  _maskImage = i.copy();
201  resizeImage(i.size(), true);
202  update();
203 }
204 
206 {
207  _backgroundImage = i.copy();
208  resizeImage(i.size(), false);
209  _maskModified = true;
210  update();
211 }
212 
213 void ImageMaskEditor::mousePressEvent(QMouseEvent* event)
214 {
215  if (event->button() == Qt::LeftButton)
216  {
217  _lastPoint = event->pos();
218  drawOnMask(_lastPoint);
219  _drawing = true;
220  }
221 }
222 
223 void ImageMaskEditor::mouseMoveEvent(QMouseEvent* event)
224 {
225  if ((event->buttons() & Qt::LeftButton) && _drawing)
226  {
227  drawOnMask(event->pos());
228  }
229  else if (_drawPenCircle)
230  {
231  int rad = (_penWidth / 2) + 2;
232  QPoint border{rad, rad};
233  update(QRect(event->pos() - border, event->pos() + border));
234  }
235 }
236 
237 void ImageMaskEditor::mouseReleaseEvent(QMouseEvent* event)
238 {
239  if (event->button() == Qt::LeftButton && _drawing)
240  {
241  drawOnMask(event->pos());
242  _drawing = false;
243  }
244 }
245 
246 void ImageMaskEditor::paintEvent(QPaintEvent* event)
247 {
248  QPainter painter(this);
249  QRect dirtyRect = event->rect();
250  painter.drawImage(dirtyRect, _backgroundImage, dirtyRect);
251  painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
252  for (
253  int x = std::max(0, dirtyRect.x());
254  x < std::min(dirtyRect.x() + dirtyRect.width(), _maskImage.width());
255  ++x
256  )
257  {
258  for (
259  int y = std::max(0, dirtyRect.y());
260  y < std::min(dirtyRect.y() + dirtyRect.height(), _maskImage.height()) ;
261  ++y
262  )
263  {
264  QColor clr {_maskImage.pixel(x, y)};
265  if (
266  clr.red() == _maskTransparentColor.red() &&
267  clr.green() == _maskTransparentColor.green() &&
268  clr.blue() == _maskTransparentColor.blue()
269  )
270  {
271  clr = QColor(0, 0, 0, 0);
272  }
273  else if (clr.alpha() != 0)
274  {
275  clr.setAlpha(_maskAlpha);
276  }
277  _maskImage.setPixel(x, y, clr.rgba());
278  }
279  }
280  painter.drawImage(dirtyRect, _maskImage, dirtyRect);
281  if (_maskModified)
282  {
283  _maskModified = false;
284  emit maskUpdated();
285  if (!_drawing)
286  {
287  emit maskUpdateFinished();
288  }
289  }
290  //draw brush circle
291  if (_drawPenCircle)
292  {
293  const auto pos = mapFromGlobal(QCursor::pos());
294  if (pos.x() >= 0 && pos.x() < width() && pos.y() >= 0 && pos.y() < height())
295  {
296  painter.setBrush(Qt::NoBrush);
297  {
298  QPen pen(Qt::white);
299  pen.setWidth(2);
300  painter.setPen(pen);
301  painter.drawEllipse(QPointF(pos), _penWidth / 2.0, _penWidth / 2.0);
302  }
303  {
304  QPen pen(Qt::black);
305  pen.setWidth(2);
306  painter.setPen(pen);
307  painter.drawEllipse(QPointF(pos), _penWidth / 2.0 - 2, _penWidth / 2.0 - 2);
308  }
309  }
310  }
311 }
312 
313 void ImageMaskEditor::drawOnMask(const QPoint& endPoint)
314 {
315  QPainter painter(&_maskImage);
316  if (_lastPoint == endPoint)
317  {
318  if (_penWidth > 1)
319  {
320  painter.setPen(Qt::NoPen);
321  painter.setBrush(_penColor);
322  const auto w = _penWidth / 2.0;
323  painter.drawEllipse(QPointF(_lastPoint), w, w);
324  }
325  else
326  {
327  painter.setPen(_penColor);
328  painter.drawPoint(_lastPoint); // fix for w = 1
329  }
330  }
331  else
332  {
333  painter.setPen(QPen(_penColor, _penWidth, Qt::SolidLine, Qt::RoundCap,
334  Qt::RoundJoin));
335  painter.drawLine(_lastPoint, endPoint);
336  }
337 
338  int rad = (_penWidth / 2) + 2;
339  update(QRect(_lastPoint, endPoint).normalized()
340  .adjusted(-rad, -rad, +rad, +rad));
341  _lastPoint = endPoint;
342  _maskModified = true;
343 }
344 
345 void ImageMaskEditor::resizeImage(QImage* image, const QSize& newSize, const QColor& fillcolor)
346 {
347  if (image->size() == newSize)
348  {
349  return;
350  }
351 
352  QImage newImage(newSize, QImage::Format_ARGB32);
353  newImage.fill(fillcolor);
354  QPainter painter(&newImage);
355  painter.drawImage(QPoint(0, 0), *image);
356  *image = newImage;
357 }
358 
360 {
361  _drawPenCircle = b;
362 }
ImageMaskEditor::imageSize
QSize imageSize() const
Definition: ImageMaskEditor.cpp:108
ImageMaskEditor::ImageMaskEditor
ImageMaskEditor(QSize size, QWidget *parent=nullptr)
Definition: ImageMaskEditor.cpp:9
ImageMaskEditor::mouseReleaseEvent
void mouseReleaseEvent(QMouseEvent *event) override
Definition: ImageMaskEditor.cpp:237
ImageMaskEditor::backgroundImage
const QImage & backgroundImage() const
Definition: ImageMaskEditor.cpp:81
ImageMaskEditor::openMaskImage
bool openMaskImage(const QString &fileName)
Definition: ImageMaskEditor.cpp:20
ImageMaskEditor::maskColor
const QColor & maskColor() const
Definition: ImageMaskEditor.cpp:66
ImageMaskEditor.h
ImageMaskEditor::setPenWidth
void setPenWidth(int newWidth)
Definition: ImageMaskEditor.cpp:169
ImageMaskEditor::maskImage
QImage maskImage() const
Definition: ImageMaskEditor.cpp:86
ImageMaskEditor::setBackgroundImage
void setBackgroundImage(const QImage &i)
Definition: ImageMaskEditor.cpp:205
ImageMaskEditor::saveBackgroundImage
bool saveBackgroundImage(const QString &fileName, const char *fileFormat)
Definition: ImageMaskEditor.cpp:54
ImageMaskEditor::maskUpdateFinished
void maskUpdateFinished()
ImageMaskEditor::saveMaskImage
bool saveMaskImage(const QString &fileName, const char *fileFormat)
Definition: ImageMaskEditor.cpp:42
ImageMaskEditor::openBackgroundImage
bool openBackgroundImage(const QString &fileName)
Definition: ImageMaskEditor.cpp:31
armarx::navigation::algorithms::save
bool save(const Costmap &costmap, const std::filesystem::path &directory)
Definition: persistence.cpp:101
ImageMaskEditor::setMaskImage
void setMaskImage(const QImage &i)
Definition: ImageMaskEditor.cpp:198
ImageMaskEditor::clearMaskImage
void clearMaskImage()
Definition: ImageMaskEditor.cpp:163
ImageMaskEditor::setImageSize
void setImageSize(QSize size, bool doNotShrink=false)
Definition: ImageMaskEditor.cpp:180
ImageMaskEditor::transparentColor
const QColor & transparentColor() const
Definition: ImageMaskEditor.cpp:71
ImageMaskEditor::maskUpdated
void maskUpdated()
ImageMaskEditor
Definition: ImageMaskEditor.h:8
ImageMaskEditor::mouseMoveEvent
void mouseMoveEvent(QMouseEvent *event) override
Definition: ImageMaskEditor.cpp:223
ImageMaskEditor::resizeImage
void resizeImage(QSize size, bool doNotShrink=false)
Definition: ImageMaskEditor.cpp:193
max
T max(T t1, T t2)
Definition: gdiam.h:48
armarx::armem::server::ltm::util::mongodb::detail::update
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
Definition: mongodb.cpp:67
ImageMaskEditor::setTransparentColor
void setTransparentColor(const QColor &newColor)
Definition: ImageMaskEditor.cpp:141
ImageMaskEditor::sizeHint
QSize sizeHint() const override
Definition: ImageMaskEditor.cpp:113
ImageMaskEditor::paintEvent
void paintEvent(QPaintEvent *event) override
Definition: ImageMaskEditor.cpp:246
ImageMaskEditor::setMaskColor
void setMaskColor(const QColor &newColor)
Definition: ImageMaskEditor.cpp:118
min
T min(T t1, T t2)
Definition: gdiam.h:42
ImageMaskEditor::setPenCircleVisible
void setPenCircleVisible(bool b=true)
Definition: ImageMaskEditor.cpp:359
ImageMaskEditor::penWidth
int penWidth() const
Definition: ImageMaskEditor.cpp:76
ImageMaskEditor::setMaskAlpha
void setMaskAlpha(int newAlpha)
Definition: ImageMaskEditor.cpp:174
ImageMaskEditor::mousePressEvent
void mousePressEvent(QMouseEvent *event) override
Definition: ImageMaskEditor.cpp:213