SMIL  0.9.1
DQtImageViewer.hxx
1 /*
2  * Copyright (c) 2011-2016, Matthieu FAESSEL and ARMINES
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  *
8  * * Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * * Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * * Neither the name of Matthieu FAESSEL, or ARMINES nor the
14  * names of its contributors may be used to endorse or promote products
15  * derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS AND CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 
30 #ifndef _D_QT_IMAGE_VIEWER_HXX
31 #define _D_QT_IMAGE_VIEWER_HXX
32 
33 #include <QApplication>
34 #include <QGraphicsSceneEvent>
35 #include <QList>
36 #include <QUrl>
37 #include <QMimeData>
38 
39 #ifdef USE_QWT
40 #include "PureQt/PlotWidget.h"
41 #endif // USE_QWT
42 
43 #include "Core/include/private/DImage.hpp"
44 #include "Base/include/private/DImageHistogram.hpp"
45 #include "Base/include/DImageDraw.h"
46 #include "IO/include/private/DImageIO.hpp"
47 #include "Core/include/DColor.h"
48 
49 namespace smil
50 {
51  template <class T>
52  QtImageViewer<T>::QtImageViewer()
53  : BASE_QT_VIEWER(NULL)
54  {
55  #ifdef USE_QWT
56  histoPlot = NULL;
57  profilePlot = NULL;
58  #endif // USE_QWT
59  }
60 
61  template <class T>
62  QtImageViewer<T>::QtImageViewer(Image<T> &im)
63  : ImageViewer<T>(im),
64  BASE_QT_VIEWER(NULL)
65  {
66  #ifdef USE_QWT
67  histoPlot = NULL;
68  profilePlot = NULL;
69  #endif // USE_QWT
70  setImage(im);
71  }
72 
73  template <class T>
74  QtImageViewer<T>::~QtImageViewer()
75  {
76  close();
77 
78  #ifdef USE_QWT
79  if (histoPlot)
80  delete histoPlot;
81  if (profilePlot)
82  delete profilePlot;
83  #endif // USE_QWT
84  }
85 
86 
87  template <class T>
88  void QtImageViewer<T>::setImage(Image<T> &im)
89  {
90  ImageViewer<T>::setImage(im);
91  BASE_QT_VIEWER::setImageSize(im.getWidth(), im.getHeight(), im.getDepth());
92  if (im.getName()!=string(""))
93  setName(this->image->getName());
94  if (!qOverlayImage.isEmpty())
95  deleteOverlayImage();
96  }
97 
98  template <class T>
99  void QtImageViewer<T>::show()
100  {
101  if (!BASE_QT_VIEWER::isVisible())
102  {
103  drawImage();
104  BASE_QT_VIEWER::dataChanged();
105  }
106  BASE_QT_VIEWER::showNormal();
107  BASE_QT_VIEWER::raise();
108  BASE_QT_VIEWER::activateWindow();
109  }
110 
111  template <class T>
112  void QtImageViewer<T>::showLabel()
113  {
114  this->setLabelImage(true);
115  if (!BASE_QT_VIEWER::isVisible())
116  {
117  drawImage();
118  BASE_QT_VIEWER::dataChanged();
119  }
120  BASE_QT_VIEWER::showNormal();
121  BASE_QT_VIEWER::raise();
122  BASE_QT_VIEWER::activateWindow();
123  update();
124  }
125 
126  template <class T>
127  void QtImageViewer<T>::hide()
128  {
129  BASE_QT_VIEWER::hide();
130  }
131 
132  template <class T>
133  bool QtImageViewer<T>::isVisible()
134  {
135  return BASE_QT_VIEWER::isVisible();
136  }
137 
138  template <class T>
139  void QtImageViewer<T>::setName(const char *_name)
140  {
141  parentClass::setName(_name);
142  QString buf = _name + QString(" (") + QString(parentClass::image->getTypeAsString()) + QString(")");
143  BASE_QT_VIEWER::setName(buf);
144  }
145 
146  template <class T>
147  void QtImageViewer<T>::setLabelImage(bool val)
148  {
149  if (parentClass::labelImage==val)
150  return;
151 
152  BASE_QT_VIEWER::setLabelImage(val);
153  parentClass::labelImage = val;
154 
155  update();
156  }
157 
158  template <class T>
159  void QtImageViewer<T>::update()
160  {
161  if (!this->image)
162  return;
163 
164  drawImage();
165  BASE_QT_VIEWER::dataChanged();
166 
167  BASE_QT_VIEWER::update();
168 
169  #ifdef USE_QWT
170  if (histoPlot && histoPlot->isVisible())
171  displayHistogram(true);
172  if (profilePlot && profilePlot->isVisible())
173  displayProfile(true);
174  #endif // USE_QWT
175 // qApp->processEvents();
176  }
177 
178 
179  template <class T>
180  void QtImageViewer<T>::saveSnapshot(const char *fileName)
181  {
182  BASE_QT_VIEWER::saveAs(fileName);
183  }
184 
185  template <class T>
186  void QtImageViewer<T>::drawImage()
187  {
188  typename Image<T>::sliceType lines = this->image->getSlices()[slider->value()];
189 
190  size_t w = this->image->getWidth();
191  size_t h = this->image->getHeight();
192 
193  UINT8 *destLine;
194  double coeff;
195  double floor = ImDtTypes<T>::min();
196 
197 
198  if (parentClass::labelImage)
199  coeff = 1.0;
200  else
201  {
202  if (autoRange)
203  {
204  vector<T> rangeV = rangeVal(*this->image);
205  floor = rangeV[0];
206  coeff = 255. / double(rangeV[1]-rangeV[0]);
207  }
208  else
209  coeff = 255. / ( double(ImDtTypes<T>::max()) - double(ImDtTypes<T>::min()) );
210  }
211 
212  for (size_t j=0;j<h;j++,lines++)
213  {
214  typename Image<T>::lineType pixels = *lines;
215 
216  destLine = this->qImage->scanLine(j);
217  for (size_t i=0;i<w;i++)
218  // pixels[i] = 0;
219  destLine[i] = (UINT8)(coeff * (double(pixels[i]) - floor));
220  }
221  }
222 
223 
224  // Specialization for UINT8 type (faster)
225  template <>
226  void QtImageViewer<UINT8>::drawImage();
227 
228 
229  #ifdef SMIL_WRAP_Bit
230  // template <>
231  // void QtImageViewer<Bit>::drawImage();
232  #endif // SMIL_WRAP_Bit
233 
234 
235  template <class T>
236  void QtImageViewer<T>::drawOverlay(const Image<T> &im)
237  {
238  if (qOverlayImage.isEmpty())
239  createOverlayImage();
240 
241  typename Image<T>::lineType pixels;
242 
243  for (size_t i=0;i<im.getDepth();i++)
244  qOverlayImage[i]->fill(0);
245 
246  QRgb *destLine;
247 
248  for (size_t k=0;k<im.getDepth();k++)
249  {
250  typename Image<T>::sliceType lines = im.getSlices()[k];
251  for (size_t j=0;j<im.getHeight();j++)
252  {
253  destLine = (QRgb*)(this->qOverlayImage[k]->scanLine(j));
254  pixels = *lines++;
255  for (size_t i=0;i<im.getWidth();i++)
256  {
257  if (pixels[i]!=T(0))
258  destLine[i] = overlayColorTable[(UINT8)pixels[i]];
259  }
260  }
261  }
262 
263  BASE_QT_VIEWER::overlayDataChanged();
264  BASE_QT_VIEWER::update();
265  }
266 
267  template <class T>
268  RES_T QtImageViewer<T>::getOverlay(Image<T> &img)
269  {
270  if (qOverlayImage.isEmpty())
271  createOverlayImage();
272 
273  img.setSize(qOverlayImage[0]->width(), qOverlayImage[0]->height(), qOverlayImage.size());
274 
275  QRgb *srcLine;
276  int value;
277  typename Image<T>::lineType pixels;
278 
279  for (size_t k=0;k<imDepth;k++)
280  {
281  typename Image<T>::sliceType lines = img.getSlices()[k];
282  for (size_t j=0;j<imHeight;j++)
283  {
284  srcLine = (QRgb*)(this->qOverlayImage[k]->scanLine(j));
285  pixels = *lines++;
286  for (size_t i=0;i<imWidth;i++)
287  {
288  value = overlayColorTable.indexOf(srcLine[i]);
289  pixels[i] = value>=0 ? T(value) : T(0);
290  }
291  }
292  }
293  img.modified();
294  return RES_OK;
295  }
296 
297  template <class T>
298  void QtImageViewer<T>::overlayDataChanged(bool triggerEvents)
299  {
300  BASE_QT_VIEWER::overlayDataChanged();
301  if (!triggerEvents)
302  return;
303  Event event(this);
304  ImageViewer<T>::onOverlayModified.trigger(&event);
305  }
306 
307  template <class T>
308  void QtImageViewer<T>::setLookup(const map<UINT8,RGB> &lut)
309  {
310  baseColorTable.clear();
311  map<UINT8,RGB>::const_iterator it;
312  for (int i=0;i<256;i++)
313  {
314  it = lut.find(UINT8(i));
315  if (it!=lut.end())
316  baseColorTable.append(qRgb((*it).second[0], (*it).second[1], (*it).second[2]));
317  else
318  baseColorTable.append(qRgb(0, 0, 0));
319  }
320  qImage->setColorTable(baseColorTable);
321  showNormal();
322  update();
323  }
324 
325  template <class T>
327  {
328  baseColorTable.clear();
329  for (int i=0;i<256;i++)
330  baseColorTable.append(qRgb(i, i, i));
331  qImage->setColorTable(baseColorTable);
332  showNormal();
333  update();
334  }
335 
336  template <class T>
337  void QtImageViewer<T>::displayPixelValue(size_t x, size_t y, size_t z)
338  {
339  T pixVal;
340 
341  pixVal = this->image->getPixel(x, y, z);
342  QString txt = "(" + QString::number(x) + ", " + QString::number(y);
343  if (this->image->getDepth()>1)
344  txt = txt + ", " + QString::number(z);
345  txt = txt + ") " + QString::number(pixVal);
346  if (!qOverlayImage.isEmpty())
347  {
348  int index = overlayColorTable.indexOf(qOverlayImage[z]->pixel(x,y));
349  if (index>=0)
350  txt = txt + "\n+ " + QString::number(index);
351  }
352  valueLabel->setText(txt);
353  valueLabel->adjustSize();
354  }
355 
356 
357  template <class T>
358  void QtImageViewer<T>::displayMagnifyView(size_t x, size_t y, size_t z)
359  {
360  magnView->displayAt(x, y);
361  // return;
362 
363  int gridSize = magnView->getGridSize();
364  int halfGrid = (gridSize-1)/2;
365 
366  int yi = y-halfGrid;
367 
368  int imW = qImage->width();
369  int imH = qImage->height();
370 
371  typename ImDtTypes<T>::sliceType pSlice = parentClass::image->getSlices()[z];
372  typename ImDtTypes<T>::lineType pLine = pSlice[0]; // dummy initialization
373  T pVal;
374 
375  QGraphicsTextItem *textItem;
376  QList<QGraphicsTextItem*>::Iterator txtIt = magnView->getTextItemList()->begin();
377 
378  QColor lightCol = QColor::fromRgb(255,255,255);
379  QColor darkCol = QColor::fromRgb(0,0,0);
380  T lightThresh = T(double(ImDtTypes<T>::max()-ImDtTypes<T>::min()) * 0.55);
381 
382  bool inYRange;
383 
384  for (int j=0;j<gridSize;j++,yi++)
385  {
386  if (yi>=0 && yi<imH)
387  {
388  inYRange = true;
389  pLine = pSlice[yi];
390  }
391  else inYRange = false;
392 
393  for (int i=0,xi=x-gridSize/2; i<gridSize; i++,xi++)
394  {
395  textItem = *txtIt++;
396  if (inYRange && xi>=0 && xi<imW)
397  {
398  pVal = pLine[xi];
399  if (pVal<lightThresh)
400  textItem->setDefaultTextColor(lightCol);
401  else
402  textItem->setDefaultTextColor(darkCol);
403  textItem->setPlainText(ImDtTypes<T>::toString(pVal).c_str());
404  }
405  else textItem->setPlainText("");
406 
407  }
408  }
409  }
410 
411  template <class T>
412  void QtImageViewer<T>::dropEvent(QDropEvent *de)
413  {
414  QList<QUrl> urls = de->mimeData()->urls();
415  int objNbr = urls.size();
416 
417  if (objNbr==1)
418 #ifdef Q_OS_WIN32
419  read(urls[0].toString().remove("file:///").toStdString().c_str(), *this->image);
420 #else // Q_OS_WIN32
421  read(urls[0].toString().remove("file:/").toStdString().c_str(), *this->image);
422 #endif // Q_OS_WIN32
423  else
424  {
425  vector<string> files;
426  for (QList<QUrl>::iterator it=urls.begin();it!=urls.end();it++)
427 #ifdef Q_OS_WIN32
428  files.push_back((*it).toString().remove("file:///").toStdString());
429 #else // Q_OS_WIN32
430  files.push_back((*it).toString().remove("file:/").toStdString());
431 #endif // Q_OS_WIN32
432  read(files, *this->image);
433  }
434  }
435 
436 #ifdef USE_QWT
437  template <class T>
438  void QtImageViewer<T>::displayHistogram(bool update)
439  {
440  if (!update && histoPlot && histoPlot->isVisible())
441  {
442  histoPlot->raise();
443  histoPlot->activateWindow();
444  return;
445  }
446 
447  if (!histoPlot)
448  {
449  histoPlot = new PlotWidget();
450  histoPlot->setWindowTitle(QString(this->image->getName()) + " histogram");
451 
452  QwtPlotCurve *defaultCurve = histoPlot->getCurrentCurve();
453  defaultCurve->setStyle( QwtPlotCurve::Steps );
454  defaultCurve->setBrush( Qt::blue );
455  }
456 
457 
458  map<T, UINT> hist = histogram(*(this->image));
459 
460  histoPlot->setAxisScale(QwtPlot::xBottom, hist.begin()->first, hist.rbegin()->first);
461 
462  QwtPlotCurve *curve = histoPlot->getCurrentCurve();
463 
464 #if QWT_VERSION < 0x060000
465  int ptsNbr = hist.size();
466  double *xVals = new double[ptsNbr];
467  double *yVals = new double[ptsNbr];
468 
469  int i=0;
470  for(typename map<T,UINT>::iterator it=hist.begin();it!=hist.end();it++,i++)
471  {
472  xVals[i] = it->first;
473  yVals[i] = it->second;
474  }
475  curve->setData(xVals, yVals, ptsNbr);
476 
477  histoPlot->replot();
478  histoPlot->show();
479 
480  delete[] xVals;
481  delete[] yVals;
482 #else // QWT_VERSION < 0x060000
483  QVector<QPointF> samples;
484  for(typename map<T,UINT>::iterator it=hist.begin();it!=hist.end();it++)
485  samples.push_back(QPointF(it->first, it->second));
486 
487  QwtPointSeriesData *myData = new QwtPointSeriesData();
488  myData->setSamples(samples);
489  curve->setData(myData);
490 
491  histoPlot->replot();
492  histoPlot->show();
493 #endif // QWT_VERSION < 0x060000
494 
495  }
496 
497  template <class T>
498  void QtImageViewer<T>::displayProfile(bool update)
499  {
500  if (update && (!profilePlot || !profilePlot->isVisible()))
501  return;
502 
503  if (!update && profilePlot && profilePlot->isVisible())
504  {
505  profilePlot->raise();
506  profilePlot->activateWindow();
507  return;
508  }
509 
510  if (!profilePlot)
511  {
512  profilePlot = new PlotWidget();
513  profilePlot->setWindowTitle(QString(this->image->getName()) + " profile");
514  }
515 // profilePlot->detachItems();
516 
517  QwtPlotCurve *curve = profilePlot->getCurrentCurve();
518 
519  QLineF lnF(this->line->line());
520 
521  vector<IntPoint> bPoints = bresenhamPoints(lnF.x1(), lnF.y1(), lnF.x2(), lnF.y2());
522 
523  T value;
524  typename Image<T>::sliceType lines = this->image->getSlices()[slider->value()];
525  int i = 0;
526 
527 
528 #if QWT_VERSION < 0x060000
529  int ptsNbr = bPoints.size();
530  double *xVals = new double[ptsNbr];
531  double *yVals = new double[ptsNbr];
532 
533  for(vector<IntPoint>::iterator it=bPoints.begin();it!=bPoints.end();it++,i++)
534  {
535  value = lines[(*it).y][(*it).x];
536  xVals[i] = i;
537  yVals[i] = value;
538  }
539  curve->setData(xVals, yVals, ptsNbr);
540 
541  profilePlot->replot();
542  profilePlot->show();
543 
544  delete[] xVals;
545  delete[] yVals;
546 
547 #else // QWT_VERSION < 0x060000
548  QVector<QPointF> samples;
549  for(vector<IntPoint>::iterator it=bPoints.begin();it!=bPoints.end();it++,i++)
550  {
551  value = lines[(*it).y][(*it).x];
552  samples.push_back(QPointF(i, value));
553  }
554 
555  QwtPointSeriesData *myData = new QwtPointSeriesData();
556  myData->setSamples(samples);
557  curve->setData(myData);
558 
559  profilePlot->replot();
560  profilePlot->show();
561 #endif // QWT_VERSION < 0x060000
562 
563 
564  }
565 #endif // USE_QWT
566 
567 } // namespace smil
568 
569 #endif // _D_QT_IMAGE_VIEWER_HXX
Qt image viewer.
Definition: DQtImageViewer.hpp:71
Definition: DColorConvert.h:38
virtual void setLookup(const map< UINT8, RGB > &lut)
Set the color table as a 8bits RGB map (keys between 0 and 255)
Definition: DQtImageViewer.hxx:308
RES_T fill(Image< T > &imOut, const T &value)
Fill an image with a given value.
Definition: DImageArith.hpp:62
RES_T close(const Image< T > &imIn, Image< T > &imOut, const StrElt &se=DEFAULT_SE)
Morphological grayscale closing.
Definition: DMorphoBase.hpp:127
vector< T > rangeVal(const Image< T > &imIn, bool onlyNonZero=false)
Min and Max values of an image.
Definition: DMeasures.hpp:313
Definition: PlotWidget.h:42
virtual void show(const char *_name=NULL, bool labelImage=false)
Show the default viewer associated with the image.
Definition: DImage.hxx:274
Definition: DTypes.hpp:78
RES_T read(const char *filename, Image< T > &image)
Read image file.
Definition: DImageIO.hxx:112