1 
2 
3 #include "cleanupswatch.h"
4 #include "trop.h"
5 #include "toonzqt/gutil.h"
6 #include <QHBoxLayout>
7 #include <QBrush>
8 #include <QPainter>
9 #include <QMouseEvent>
10 #include <QIcon>
11 #include <QPushButton>
12 #include <QActionGroup>
13 #include <QToolBar>
14 #include "toonz/tcleanupper.h"
15 #include "toonzqt/dvdialog.h"
CleanupSwatch(QWidget * parent,int lx,int ly)16 CleanupSwatch::CleanupSwatch(QWidget *parent, int lx, int ly)
17     : QWidget(parent)
18     , m_lx(lx)
19     , m_ly(ly)
20     , m_enabled(false)
21     , m_viewAff()
22 //, m_lastRasCleanupped()
23 {
24   setStyleSheet("background: transparent");
25   QHBoxLayout *layout = new QHBoxLayout(this);
26   layout->setMargin(0);
27   layout->setSpacing(0);
28 
29   m_leftSwatch = new CleanupSwatchArea(this, true);
30 
31   layout->addWidget(m_leftSwatch);
32 
33   DVGui::Separator *sep = new DVGui::Separator();
34   sep->setFixedWidth(1);
35   sep->setOrientation(false);
36   layout->addWidget(sep);
37 
38   m_rightSwatch = new CleanupSwatchArea(this, false);
39   layout->addWidget(m_rightSwatch);
40 
41   setLayout(layout);
42 }
43 
44 //---------------------------------------------------------------------
45 
enable(bool state)46 void CleanupSwatch::enable(bool state) {
47   m_enabled = state;
48   if (!m_enabled) {
49     m_resampledRaster = TRasterP();
50     // m_lastRasCleanupped = TRasterP();
51     m_origRaster  = TRasterP();
52     m_viewAff     = TAffine();
53     m_resampleAff = TAffine();
54     m_leftSwatch->updateRaster();
55     m_rightSwatch->updateRaster();
56   }
57 }
58 
59 //------------------------------------------------------------------------------
60 /*
61 void CleanupSwatch::hideEvent(QHideEvent* e)
62 {
63 m_enabledAct->setChecked(false);
64 }*/
65 
66 //----------------------------------------------------------------
67 
CleanupSwatchArea(CleanupSwatch * parent,bool isLeft)68 CleanupSwatch::CleanupSwatchArea::CleanupSwatchArea(CleanupSwatch *parent,
69                                                     bool isLeft)
70     : QWidget(parent), m_isLeft(isLeft), m_sw(parent) {
71   setMinimumHeight(150);
72 
73   // The following helps in re-establishing focus for wheel events
74   setFocusPolicy(Qt::WheelFocus);
75   setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
76 }
77 
78 //----------------------------------------------------------------
79 
mousePressEvent(QMouseEvent * event)80 void CleanupSwatch::CleanupSwatchArea::mousePressEvent(QMouseEvent *event) {
81   if (!m_sw->m_resampledRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return;
82   // if (m_sw->m_lastRasCleanupped)
83   //   TRop::addBackground(m_sw->m_lastRasCleanupped, TPixel::White);
84   m_pos = event->pos();
85 
86   if (event->button() != Qt::MidButton || !m_sw->m_resampledRaster) {
87     event->ignore();
88     return;
89     m_panning = false;
90   } else
91     m_panning = true;
92 }
93 
94 //-----------------------------------------------------------------------------
95 namespace {
96 #define ZOOMLEVELS 33
97 #define NOZOOMINDEX 20
98 double ZoomFactors[ZOOMLEVELS] = {
99     0.001, 0.002,  0.003,  0.004, 0.005, 0.007, 0.01,  0.015, 0.02,  0.03, 0.04,
100     0.05,  0.0625, 0.0833, 0.125, 0.167, 0.25,  0.333, 0.5,   0.667, 1,    2,
101     3,     4,      5,      6,     7,     8,     12,    16,    24,    32,   40};
102 
getQuantizedZoomFactor(double zf,bool forward)103 double getQuantizedZoomFactor(double zf, bool forward) {
104   if (forward && (zf > ZoomFactors[ZOOMLEVELS - 1] ||
105                   areAlmostEqual(zf, ZoomFactors[ZOOMLEVELS - 1], 1e-5)))
106     return zf;
107   else if (!forward &&
108            (zf < ZoomFactors[0] || areAlmostEqual(zf, ZoomFactors[0], 1e-5)))
109     return zf;
110 
111   assert((!forward && zf > ZoomFactors[0]) ||
112          (forward && zf < ZoomFactors[ZOOMLEVELS - 1]));
113   int i = 0;
114   for (i = 0; i <= ZOOMLEVELS - 1; i++)
115     if (areAlmostEqual(zf, ZoomFactors[i], 1e-5)) zf = ZoomFactors[i];
116 
117   if (forward && zf < ZoomFactors[0])
118     return ZoomFactors[0];
119   else if (!forward && zf > ZoomFactors[ZOOMLEVELS - 1])
120     return ZoomFactors[ZOOMLEVELS - 1];
121 
122   for (i = 0; i < ZOOMLEVELS - 1; i++)
123     if (ZoomFactors[i + 1] - zf >= 0 && zf - ZoomFactors[i] >= 0) {
124       if (forward && ZoomFactors[i + 1] == zf)
125         return ZoomFactors[i + 2];
126       else if (!forward && ZoomFactors[i] == zf)
127         return ZoomFactors[i - 1];
128       else
129         return forward ? ZoomFactors[i + 1] : ZoomFactors[i];
130     }
131   return ZoomFactors[NOZOOMINDEX];
132 }
133 
134 }  // namespace
135 //-----------------------------------------------------------------------------
136 
keyPressEvent(QKeyEvent * event)137 void CleanupSwatch::CleanupSwatchArea::keyPressEvent(QKeyEvent *event) {
138   if (!m_sw->m_resampledRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return;
139   int key = event->key();
140   if (key != '+' && key != '-' && key != '0') return;
141 
142   if (key == '0')
143     m_sw->m_viewAff = TAffine();
144   else {
145     bool forward = (key == '+');
146 
147     double currZoomScale = sqrt(m_sw->m_viewAff.det());
148     double factor        = getQuantizedZoomFactor(currZoomScale, forward);
149 
150     double minZoom =
151         std::min((double)m_sw->m_lx / m_sw->m_resampledRaster->getLx(),
152                  (double)m_sw->m_ly / m_sw->m_resampledRaster->getLy());
153     if ((!forward && factor < minZoom) || (forward && factor > 40.0)) return;
154 
155     TPointD delta(0.5 * width(), 0.5 * height());
156     m_sw->m_viewAff = (TTranslation(delta) * TScale(factor / currZoomScale) *
157                        TTranslation(-delta)) *
158                       m_sw->m_viewAff;
159   }
160   m_sw->m_leftSwatch->updateRaster();
161   m_sw->m_rightSwatch->updateRaster();
162 }
163 
164 //-----------------------------------------------------------------------------
mouseReleaseEvent(QMouseEvent * event)165 void CleanupSwatch::CleanupSwatchArea::mouseReleaseEvent(QMouseEvent *event) {
166   m_sw->m_rightSwatch->updateRaster();
167   m_panning = false;
168 }
169 
170 //----------------------------------------------------------------
mouseMoveEvent(QMouseEvent * event)171 void CleanupSwatch::CleanupSwatchArea::mouseMoveEvent(QMouseEvent *event) {
172   if (!m_panning) return;
173 
174   TPoint curPos = TPoint(event->pos().x(), event->pos().y());
175 
176   QPoint delta = event->pos() - m_pos;
177   if (delta == QPoint()) return;
178   TAffine oldAff  = m_sw->m_viewAff;
179   m_sw->m_viewAff = TTranslation(delta.x(), -delta.y()) * m_sw->m_viewAff;
180 
181   m_sw->m_leftSwatch->updateRaster();
182   m_sw->m_rightSwatch->updateRaster(true);
183 
184   m_pos = event->pos();
185 }
186 
187 //---------------------------------------------------------------
188 
wheelEvent(QWheelEvent * event)189 void CleanupSwatch::CleanupSwatchArea::wheelEvent(QWheelEvent *event) {
190   if (!m_sw->m_resampledRaster || m_sw->m_lx == 0 || m_sw->m_ly == 0) return;
191 
192   int step      = event->delta() > 0 ? 120 : -120;
193   double factor = exp(0.001 * step);
194   if (factor == 1.0) return;
195   double scale = m_sw->m_viewAff.det();
196   double minZoom =
197       std::min((double)m_sw->m_lx / m_sw->m_resampledRaster->getLx(),
198                (double)m_sw->m_ly / m_sw->m_resampledRaster->getLy());
199   if ((factor < 1 && sqrt(scale) < minZoom) || (factor > 1 && scale > 1200.0))
200     return;
201 
202   TPointD delta(event->pos().x(), height() - event->pos().y());
203   m_sw->m_viewAff =
204       (TTranslation(delta) * TScale(factor) * TTranslation(-delta)) *
205       m_sw->m_viewAff;
206 
207   m_sw->m_leftSwatch->updateRaster();
208   m_sw->m_rightSwatch->updateRaster();
209 }
210 
211 //-------------------------------------------------------------------------------
212 
resizeEvent(QResizeEvent * event)213 void CleanupSwatch::resizeEvent(QResizeEvent *event) {
214   QSize s = m_leftSwatch->size();
215   m_lx    = s.width();
216   m_ly    = s.height();
217 
218   // m_rightSwatch->resize(m_lx, m_ly);
219   m_leftSwatch->setMinimumHeight(0);
220   m_rightSwatch->setMinimumHeight(0);
221   m_leftSwatch->updateRaster();
222   m_rightSwatch->updateRaster();
223   // m_rightSwatch->updateRaster();
224   QWidget::resizeEvent(event);
225   // update();
226 }
227 
228 /*
229 void CleanupSwatch::enableRightSwatch(bool state)
230 {
231 setVisible(state);
232 update();
233 }*/
234 
235 //---------------------------------------------------
236 
updateCleanupped(bool dragging)237 void CleanupSwatch::CleanupSwatchArea::updateCleanupped(bool dragging) {
238   TAffine aff = getFinalAff();
239 
240   TRect rectToCompute = convert(aff.inv() * convert(m_r->getBounds()));
241   rectToCompute       = rectToCompute.enlarge(
242       TCleanupper::instance()->getParameters()->m_despeckling);
243 
244   TRect outRect = m_sw->m_resampledRaster->getBounds() * rectToCompute;
245   if (outRect.isEmpty()) return;
246 
247   TRasterP rasCleanupped = TCleanupper::instance()->processColors(
248       m_sw->m_resampledRaster->extract(outRect));
249   TPointD cleanuppedPos = convert(outRect.getP00());
250 
251   TRop::quickPut(m_r, rasCleanupped, aff * TTranslation(cleanuppedPos));
252 }
253 
254 //---------------------------------------------------------------------------------
255 #ifdef LEVO
256 
257 void CleanupSwatch::CleanupSwatchArea::updateCleanupped Versione ricalcolo Al
258     Release Del
mouse(bool dragging)259     mouse(bool dragging) {
260   TAffine aff = getFinalAff();
261 
262   TRect rectToCompute = convert(aff.inv() * convert(m_r->getBounds()));
263   rectToCompute       = rectToCompute.enlarge(
264       TCleanupper::instance()->getParameters()->m_despeckling);
265 
266   TRect outRect = m_sw->m_resampledRaster->getBounds() * rectToCompute;
267   if (outRect.isEmpty()) return;
268 
269   if (dragging && m_sw->m_lastRasCleanupped)
270     m_r->fill(TPixel(200, 200, 200));
271   else {
272     m_sw->m_lastRasCleanupped = TCleanupper::instance()->processColors(
273         m_sw->m_resampledRaster->extract(outRect));
274     m_sw->m_lastCleanuppedPos = convert(outRect.getP00());
275   }
276   TRop::quickPut(m_r, m_sw->m_lastRasCleanupped,
277                  aff * TTranslation(m_sw->m_lastCleanuppedPos));
278 }
279 #endif
280 
281 //---------------------------------------------------------------------------------
282 
getFinalAff()283 TAffine CleanupSwatch::CleanupSwatchArea::getFinalAff() {
284   return m_sw->m_viewAff *
285          TAffine().place(m_sw->m_resampledRaster->getCenterD(),
286                          m_r->getCenterD());
287 }
288 
289 //------------------------------------------------------------------------------
updateRaster(bool dragging)290 void CleanupSwatch::CleanupSwatchArea::updateRaster(bool dragging) {
291   if (isHidden() || m_sw->m_lx == 0 || m_sw->m_ly == 0) return;
292 
293   if (!m_r || m_r->getLx() != m_sw->m_lx || m_r->getLy() != m_sw->m_ly)
294     m_r = TRaster32P(m_sw->m_lx, m_sw->m_ly);
295 
296   if (!m_sw->m_resampledRaster)
297     m_r->fill(TPixel(200, 200, 200));
298   else {
299     m_r->fill(TPixel::White);
300     if (m_isLeft)
301       TRop::quickPut(m_r, m_sw->m_origRaster,
302                      getFinalAff() * m_sw->m_resampleAff);
303     else
304       updateCleanupped(dragging);
305   }
306   if (dragging)
307     repaint();
308   else
309     update();
310 }
311 
312 //----------------------------------------------------------------------------------
313 
paintEvent(QPaintEvent * event)314 void CleanupSwatch::CleanupSwatchArea::paintEvent(QPaintEvent *event) {
315   QPainter p(this);
316   if (!m_r)
317     p.fillRect(rect(), QBrush(QColor(200, 200, 200)));
318   else
319     p.drawImage(rect(), rasterToQImage(m_r));
320 }
321 
322 //-----------------------------------------------------------------
323 
isEnabled()324 bool CleanupSwatch::isEnabled() { return isVisible() && m_enabled; }
325 
326 //------------------------------------------------------------
setRaster(TRasterP rasLeft,const TAffine & aff,TRasterP ras)327 void CleanupSwatch::setRaster(TRasterP rasLeft, const TAffine &aff,
328                               TRasterP ras) {
329   if (!isVisible()) {
330     m_resampledRaster = TRasterP();
331     m_origRaster      = TRasterP();
332     // m_lastRasCleanupped = TRasterP();
333     return;
334   }
335 
336   m_resampledRaster = ras;
337   m_origRaster      = rasLeft;
338   m_resampleAff     = aff;
339 
340   m_leftSwatch->updateRaster();
341   m_rightSwatch->updateRaster();
342 }
343 
344 //--------------------------------------------------------------------
345 
updateCleanupped()346 void CleanupSwatch::updateCleanupped() { m_rightSwatch->updateRaster(); }
347