Isis 3 Programmer Reference
StretchTool.cpp
1 #include "StretchTool.h"
2 
3 #include <QAction>
4 #include <QComboBox>
5 #include <QHBoxLayout>
6 #include <QLineEdit>
7 #include <QMenuBar>
8 #include <QMessageBox>
9 #include <QPixmap>
10 #include <QPushButton>
11 #include <QSizePolicy>
12 #include <QStackedWidget>
13 #include <QToolBar>
14 #include <QToolButton>
15 #include <QValidator>
16 
17 #include "AdvancedStretchDialog.h"
18 #include "Brick.h"
19 #include "CubeViewport.h"
20 #include "Histogram.h"
21 #include "IException.h"
22 #include "IString.h"
23 #include "MainWindow.h"
24 #include "MdiCubeViewport.h"
25 #include "RubberBandTool.h"
26 #include "Statistics.h"
27 #include "Stretch.h"
28 #include "ToolPad.h"
29 #include "ViewportBuffer.h"
30 #include "ViewportMainWindow.h"
31 #include "Workspace.h"
32 
33 using namespace std;
34 
35 namespace Isis {
42  StretchTool::StretchTool(QWidget *parent) : Tool::Tool(parent) {
43  m_chipViewportStretch = NULL;
44  m_preGlobalStretches = NULL;
45  m_advancedStretch = NULL;
46 
48 
50  connect(m_advancedStretch, SIGNAL(stretchChanged()),
51  this, SLOT(advancedStretchChanged()));
52  connect(m_advancedStretch, SIGNAL(visibilityChanged()),
53  this, SLOT(updateTool()));
54 
55  QPushButton *hiddenButton = new QPushButton();
56  hiddenButton->setVisible(false);
57  hiddenButton->setDefault(true);
58 
59  m_stretchGlobal = new QAction(parent);
60  m_stretchGlobal->setShortcut(Qt::CTRL + Qt::Key_G);
61  m_stretchGlobal->setText("Global Stretch");
62  connect(m_stretchGlobal, SIGNAL(triggered()), this, SLOT(stretchGlobal()));
63 
64  m_stretchRegional = new QAction(parent);
65  m_stretchRegional->setShortcut(Qt::CTRL + Qt::Key_R);
66  m_stretchRegional->setText("Regional Stretch");
67  connect(m_stretchRegional, SIGNAL(triggered()), this, SLOT(stretchRegional()));
68 
69  // Emit a signal when an exception occurs and connect to the Warning object
70  // to display Warning icon and the message
71  ViewportMainWindow *parentMainWindow = qobject_cast<ViewportMainWindow *>(parent);
72  if (parentMainWindow) {
73  connect(this, SIGNAL(warningSignal(std::string &, const std::string)),
74  parentMainWindow, SLOT(displayWarning(std::string &, const std::string &)));
75  }
76  }
77 
78 
83  delete [] m_preGlobalStretches;
84  m_preGlobalStretches = NULL;
85 
86  delete m_chipViewportStretch;
87  m_chipViewportStretch = NULL;
88  }
89 
90 
100  QAction *action = new QAction(pad);
101  action->setIcon(QPixmap(toolIconDir() + "/stretch_global.png"));
102  action->setToolTip("Stretch (S)");
103  action->setShortcut(Qt::Key_S);
104  QString text =
105  "<b>Function:</b> Change the stretch range of the cube.\
106  <p><b>Shortcut:</b> S</p> ";
107  action->setWhatsThis(text);
108 
109  return action;
110  }
111 
112 
119  void StretchTool::addTo(QMenu *menu) {
120  menu->addAction(m_stretchGlobal);
121  menu->addAction(m_stretchRegional);
122  }
123 
124 
133  QWidget *StretchTool::createToolBarWidget(QStackedWidget *parent) {
134  QWidget *hbox = new QWidget(parent);
135 
136  QToolButton *butt = new QToolButton(hbox);
137  butt->setAutoRaise(true);
138  butt->setIconSize(QSize(22, 22));
139  butt->setIcon(QPixmap(toolIconDir() + "/regional_stretch-2.png"));
140  butt->setToolTip("Stretch");
141  QString text =
142  "<b>Function:</b> Automatically compute min/max stretch using viewed \
143  pixels in the band(s) of the active viewport. That is, only pixels \
144  that are visible in the viewport are used. \
145  If the viewport is in RGB color all three bands will be stretched. \
146  <p><b>Shortcut:</b> Ctrl+R</p> \
147  <p><b>Mouse:</b> Left click \
148  <p><b>Hint:</b> Left click and drag for a local stretch. Uses only \
149  pixels in the red marquee</p>";
150  butt->setWhatsThis(text);
151  connect(butt, SIGNAL(clicked()), this, SLOT(stretchRegional()));
153 
154  m_stretchBandComboBox = new QComboBox(hbox);
155  m_stretchBandComboBox->setEditable(false);
156  m_stretchBandComboBox->addItem("Red Band", Red);
157  m_stretchBandComboBox->addItem("Green Band", Green);
158  m_stretchBandComboBox->addItem("Blue Band", Blue);
159  m_stretchBandComboBox->addItem("All Bands", All);
160  m_stretchBandComboBox->setToolTip("Select Color");
161  text =
162  "<b>Function:</b> Selecting the color will allow the appropriate \
163  min/max to be seen and/or edited in text fields to the right.";
164 
165 // The All option implies the same min/max will be applied
166 // to all three colors (RGB) if either text field is edited";
167  m_stretchBandComboBox->setWhatsThis(text);
168  m_stretchBand = All;
169  m_stretchBandComboBox->setCurrentIndex(
171  connect(m_stretchBandComboBox, SIGNAL(currentIndexChanged(int)),
172  this, SLOT(stretchBandChanged(int)));
173 
174  QDoubleValidator *dval = new QDoubleValidator(hbox);
175  m_stretchMinEdit = new QLineEdit(hbox);
176  m_stretchMinEdit->setValidator(dval);
177  m_stretchMinEdit->setToolTip("Minimum");
178  text =
179  "<b>Function:</b> Shows the current minimum pixel value. Pixel values \
180  below minimum are shown as black. Pixel values above the maximum \
181  are shown as white or the highest intensity of red/green/blue \
182  if in color. Pixel values between the minimum and maximum are stretched \
183  linearly between black and white (or color component). \
184  <p><b>Hint:</b> You can manually edit the minimum but it must be \
185  less than the maximum.";
186  m_stretchMinEdit->setWhatsThis(text);
187  m_stretchMinEdit->setMaximumWidth(100);
188  connect(m_stretchMinEdit, SIGNAL(returnPressed()),
189  this, SLOT(changeStretch()));
190 
191  m_stretchMaxEdit = new QLineEdit(hbox);
192  m_stretchMaxEdit->setValidator(dval);
193  m_stretchMaxEdit->setToolTip("Maximum");
194  text =
195  "<b>Function:</b> Shows the current maximum pixel value. Pixel values \
196  below minimum are shown as black. Pixel values above the maximum \
197  are shown as white or the highest intensity of red/green/blue \
198  if in color. Pixel values between the minimum and maximum are stretched \
199  linearly between black and white (or color component). \
200  <p><b>Hint:</b> You can manually edit the maximum but it must be \
201  greater than the minimum";
202  m_stretchMaxEdit->setWhatsThis(text);
203  m_stretchMaxEdit->setMaximumWidth(100);
204  connect(m_stretchMaxEdit, SIGNAL(returnPressed()), this, SLOT(changeStretch()));
205 
206  // Create the two menus that drop down from the buttons
207  QMenu *copyMenu = new QMenu();
208  QMenu *globalMenu = new QMenu();
209 
210  m_copyBands = new QAction(parent);
211  m_copyBands->setText("to All Bands");
212  connect(m_copyBands, SIGNAL(triggered(bool)), this, SLOT(setStretchAcrossBands()));
213 
214  QAction *copyAll = new QAction(parent);
215  copyAll->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
216  copyAll->setText("to All Viewports");
217  connect(copyAll, SIGNAL(triggered(bool)), this, SLOT(setStretchAllViewports()));
218 
219  copyMenu->addAction(copyAll);
220  copyMenu->addAction(m_copyBands);
221 
222  m_copyButton = new QToolButton();
223  m_copyButton->setAutoRaise(true);
224  m_copyButton->setIconSize(QSize(22, 22));
225  m_copyButton->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
226  m_copyButton->setPopupMode(QToolButton::MenuButtonPopup);
227  m_copyButton->setMenu(copyMenu);
228  m_copyButton->setDefaultAction(copyAll);
229  m_copyButton->setToolTip("Copy");
230  text =
231  "<b>Function:</b> Copy the current stretch to all the \
232  active viewports. Or use the drop down menu to copy the current stretch \
233  to all the bands in the active viewport. \
234  <p><b>Hint:</b> Can reset the stretch to an automaticaly computed \
235  stretch by using the 'Reset' stretch button option. </p>";
236  m_copyButton->setWhatsThis(text);
237 
238  QAction *currentView = new QAction(parent);
239  currentView->setText("Active Viewport");
240  currentView->setIcon(QPixmap(toolIconDir() + "/global_stretch.png"));
241  globalMenu->addAction(currentView);
242  connect(currentView, SIGNAL(triggered(bool)), this, SLOT(stretchGlobal()));
243 
244  QAction *globalAll = new QAction(parent);
245  globalAll->setText("All Viewports");
246  globalMenu->addAction(globalAll);
247  connect(globalAll, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllViewports()));
248 
249  QAction *globalBands = new QAction(parent);
250  globalBands->setText("All Bands");
251  globalMenu->addAction(globalBands);
252  connect(globalBands, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllBands()));
253 
254  m_globalButton = new QToolButton(); //basically acts as a 'reset'
255  m_globalButton->setAutoRaise(true);
256  m_globalButton->setIconSize(QSize(22, 22));
257  m_globalButton->setPopupMode(QToolButton::MenuButtonPopup);
258  m_globalButton->setMenu(globalMenu);
259  m_globalButton->setDefaultAction(currentView);
260  m_globalButton->setToolTip("Reset");
261  text =
262  "<b>Function:</b> Reset the stretch to be automatically computed "
263  "using the statisics from the entire image. Use the drop down menu "
264  "to reset the stretch for all the bands in the active viewport or "
265  "to reset the stretch for all the viewports.";
266  m_globalButton->setWhatsThis(text);
267 
268  QPushButton *advancedButton = new QPushButton("Advanced");
269  connect(advancedButton, SIGNAL(clicked()), this, SLOT(showAdvancedDialog()));
270 
271  m_flashButton = new QPushButton("Show Global");
272  text =
273  "<b>Function:</b> While this button is pressed down, the visible stretch "
274  "will be the automatically computed stretch using the statisics from the "
275  "entire image. The original stretch is restored once you let up on this "
276  "button.";
277  m_flashButton->setWhatsThis(text);
278  connect(m_flashButton, SIGNAL(pressed()), this, SLOT(stretchChanged()));
279  connect(m_flashButton, SIGNAL(released()), this, SLOT(stretchChanged()));
280 
281  QHBoxLayout *layout = new QHBoxLayout(hbox);
282  layout->setMargin(0);
283  layout->addWidget(m_copyButton);
284  layout->addWidget(m_globalButton);
285  layout->addWidget(m_stretchRegionalButton);
286  layout->addWidget(m_stretchBandComboBox);
287  layout->addWidget(m_stretchMinEdit);
288  layout->addWidget(m_stretchMaxEdit);
289  layout->addWidget(advancedButton);
290  layout->addWidget(m_flashButton);
291  layout->addStretch(); // Pushes everything else left in the menu bar
292  hbox->setLayout(layout);
293 
294  return hbox;
295  }
296 
297 
303  if(m_advancedStretch->isVisible()) {
304  MdiCubeViewport *cvp = cubeViewport();
305 
306  if(!cvp) return;
307 
308  if(cvp->isGray() && !cvp->grayBuffer()->working()) {
310  updateTool();
311  }
312  else {
313  Histogram hist(histFromBuffer(cvp->grayBuffer()));
314 
315  if(hist.ValidPixels() > 0) {
317  }
318  }
319  }
320  //Otherwise it is in color mode
321  else if(!cvp->isGray() &&
322  !cvp->redBuffer()->working() &&
323  !cvp->greenBuffer()->working() &&
324  !cvp->blueBuffer()->working()) {
325  if(!m_advancedStretch->isRgbMode()) {
326  updateTool();
327  }
328  else {
329  Histogram redHist(histFromBuffer(cvp->redBuffer()));
330  Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
331  Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
332 
333  if(redHist.ValidPixels() > 0 &&
334  grnHist.ValidPixels() > 0 &&
335  bluHist.ValidPixels() > 0) {
336  m_advancedStretch->updateHistograms(redHist, grnHist, bluHist);
337  }
338  }
339  }
340  }
341  }
342 
350  {
351  if(m_advancedStretch->isVisible()) {
352  MdiCubeViewport *cvp = cubeViewport();
353 
354  if(!cvp->isGray() &&
355  !cvp->redBuffer()->working() &&
356  !cvp->greenBuffer()->working() &&
357  !cvp->blueBuffer()->working()) {
358 
359  Histogram redHist(histFromBuffer(cvp->redBuffer()));
360  Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
361  Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
362  Stretch redStretch(cvp->redStretch());
363  Stretch grnStretch(cvp->greenStretch());
364  Stretch bluStretch(cvp->blueStretch());
365 
366  m_advancedStretch->updateForRGBMode(redStretch, redHist,
367  grnStretch, grnHist,
368  bluStretch, bluHist);
369  }
370  }
371  }
372 
378  }
379 
380 
387  if(m_advancedStretch->isVisible()) {
388  m_advancedStretch->enable(true);
389  //If the viewport is in gray mode
390  if(cvp->isGray() && !cvp->grayBuffer()->working()) {
391  Histogram hist(histFromBuffer(cvp->grayBuffer()));
392  Stretch stretch(cvp->grayStretch());
393  m_advancedStretch->enableGrayMode(stretch, hist);
394  }
395  //Otherwise it is in color mode
396  else if(!cvp->isGray() &&
397  !cvp->redBuffer()->working() &&
398  !cvp->greenBuffer()->working() &&
399  !cvp->blueBuffer()->working()) {
400  Histogram redHist(histFromBuffer(cvp->redBuffer()));
401  Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
402  Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
403  Stretch redStretch(cvp->redStretch());
404  Stretch grnStretch(cvp->greenStretch());
405  Stretch bluStretch(cvp->blueStretch());
406  m_advancedStretch->enableRgbMode(redStretch, redHist,
407  grnStretch, grnHist,
408  bluStretch, bluHist);
409  }
410  else {
411  m_advancedStretch->enable(false);
412  }
413  }
414  else {
415  m_advancedStretch->enable(false);
416  }
417  }
418 
419 
425  CubeViewport *cvp = cubeViewport();
426 
427  if(cvp == NULL) {
428  //If the current viewport is NULL and the advanced dialog is visible, hide it
429  if(m_advancedStretch->isVisible()) {
430  m_advancedStretch->hide();
431  }
432  }
433  else {
434  if(!m_advancedStretch->enabled() ||
435  m_advancedStretch->isRgbMode() != !cvp->isGray()) {
436  setCubeViewport(cvp);
437  }
438  }
439 
440  if(cvp && cvp->isGray()) {
441  m_copyBands->setEnabled(true);
442  m_stretchBandComboBox->setVisible(false);
443  m_stretchMinEdit->show();
444  m_stretchMaxEdit->show();
445  }
446  else if(cvp) {
447  m_copyBands->setEnabled(true);
448  m_stretchBandComboBox->setVisible(true);
450  }
451  else {
452  m_copyBands->setEnabled(false);
453  m_stretchBandComboBox->setVisible(false);
454  }
455 
456  if(m_advancedStretch->isVisible()) {
457  m_stretchMinEdit->setEnabled(false);
458  m_stretchMaxEdit->setEnabled(false);
459  }
460  else {
461  m_stretchMinEdit->setEnabled(true);
462  m_stretchMaxEdit->setEnabled(true);
463  }
464 
465  stretchChanged();
467  }
468 
469 
478  // Yeah this is a hack... but it's necessary to make this tool
479  // do anything while its not the active tool.
480  connect(cvp, SIGNAL(screenPixelsChanged()), this, SLOT(updateHistograms()));
481  QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
482 
483  if(bandId == (int)Gray) {
484  if(cvp->grayBuffer() && cvp->grayBuffer()->hasEntireCube()) {
485  Stretch newStretch = cvp->grayStretch();
486  newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
487  cvp->stretchGray(newStretch);
488  }
489  else {
490  Stretch newStretch = stretchBand(cvp, (StretchBand)bandId);
491  cvp->stretchGray(newStretch);
492  }
493  }
494  else
495  {
496  if(bandId == (int)Red || bandId == (int)All) {
497  if(cvp->redBuffer() && cvp->redBuffer()->hasEntireCube()) {
498  Stretch newStretch = cvp->redStretch();
499  newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
500  cvp->stretchRed(newStretch);
501  }
502  else {
503  Stretch newStretch = stretchBand(cvp, Red);
504  cvp->stretchRed(newStretch);
505  }
506  }
507  if(bandId == (int)Green || bandId == (int)All) {
508  if(cvp->greenBuffer() && cvp->greenBuffer()->hasEntireCube()) {
509  Stretch newStretch = cvp->greenStretch();
510  newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
511  cvp->stretchGreen(newStretch);
512  }
513  else {
514  Stretch newStretch = stretchBand(cvp, Green);
515  cvp->stretchGreen(newStretch);
516  }
517  }
518  if(bandId == (int)Blue || bandId == (int)All) {
519  if(cvp->blueBuffer() && cvp->blueBuffer()->hasEntireCube()) {
520  Stretch newStretch = cvp->blueStretch();
521  newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
522  cvp->stretchBlue(newStretch);
523  }
524  else {
525  Stretch newStretch = stretchBand(cvp, Blue);
526  cvp->stretchBlue(newStretch);
527  }
528  }
529  }
530  stretchChanged();
531  }
532 
533 
540  MdiCubeViewport *cvp = cubeViewport();
541  if(cvp == NULL) return;
542 
543  if(m_flashButton->isDown()) {
544  if(!m_preGlobalStretches) {
545  m_preGlobalStretches = new Stretch[4];
546  m_preGlobalStretches[0] = cvp->grayStretch();
547  m_preGlobalStretches[1] = cvp->redStretch();
549  m_preGlobalStretches[3] = cvp->blueStretch();
550  }
551 
552  cvp->stretchKnownGlobal();
553  return;
554  }
555  else if(m_preGlobalStretches) {
556  if(cvp->isGray()) {
558  }
559  else {
563  }
564 
565  delete [] m_preGlobalStretches;
566  m_preGlobalStretches = NULL;
567  }
568 
569  double min = 0, max = 0;
570  //If the viewport is in gray mode
571  if(cvp->isGray()) {
572  //Get the min/max from the current stretch
573  Stretch stretch = cvp->grayStretch();
574  min = stretch.Input(0);
575  max = stretch.Input(stretch.Pairs() - 1);
576  }
577 
578  //Otherwise it is in color mode
579  else {
580  Stretch rstretch = cvp->redStretch();
581  Stretch gstretch = cvp->greenStretch();
582  Stretch bstretch = cvp->blueStretch();
583 
584  //Get the min/max from the current stretch
585  if(m_stretchBand == Red) {
586  min = rstretch.Input(0);
587  max = rstretch.Input(rstretch.Pairs() - 1);
588  }
589  else if(m_stretchBand == Green) {
590  min = gstretch.Input(0);
591  max = gstretch.Input(gstretch.Pairs() - 1);
592  }
593  else if(m_stretchBand == Blue) {
594  min = bstretch.Input(0);
595  max = bstretch.Input(bstretch.Pairs() - 1);
596  }
597  }
598 
599  //Set the min/max text fields
600  if(m_stretchBand != All || cvp->isGray()) {
601  QString strMin;
602  strMin.setNum(min);
603  m_stretchMinEdit->setText(strMin);
604 
605  QString strMax;
606  strMax.setNum(max);
607  m_stretchMaxEdit->setText(strMax);
608  }
609 
610  if(m_advancedStretch->isVisible()) {
611  if(m_stretchBand == All){
613  }
615  }
616  }
617 
618 
624  CubeViewport *cvp = cubeViewport();
625  if(cvp == NULL) return;
626 
627  if(!m_advancedStretch->isRgbMode()) {
628  Stretch grayStretch = cvp->grayStretch();
629  grayStretch.ClearPairs();
631  cvp->stretchGray(grayStretch);
632 
633  // send the stretch to any ChipViewports that want to listen
634  *m_chipViewportStretch = grayStretch;
636  }
637  else {
638  Stretch redStretch = cvp->redStretch();
639  redStretch.ClearPairs();
641  cvp->stretchRed(redStretch);
642 
643  Stretch grnStretch = cvp->greenStretch();
644  grnStretch.ClearPairs();
646  cvp->stretchGreen(grnStretch);
647 
648  Stretch bluStretch = cvp->blueStretch();
649  bluStretch.ClearPairs();
651  cvp->stretchBlue(bluStretch);
652  }
653  stretchChanged();
654  }
655 
656 
664  MdiCubeViewport *cvp = cubeViewport();
665  if(cvp == NULL) return;
666 
667  // Make sure the user didn't enter bad min/max and if so fix it
668  double min = m_stretchMinEdit->text().toDouble();
669  double max = m_stretchMaxEdit->text().toDouble();
670 
671  if(min >= max || m_stretchMinEdit->text() == "" ||
672  m_stretchMaxEdit->text() == "") {
673  updateTool();
674  return;
675  }
676 
677  //The viewport is in gray mode
678  if(cvp->isGray()) {
679  Stretch stretch = cvp->grayStretch();
680  stretch.ClearPairs();
681  stretch.AddPair(min, 0.0);
682  stretch.AddPair(max, 255.0);
683 
684  // send the stretch to any ChipViewports that want to listen
685  *m_chipViewportStretch = stretch;
687 
688  cvp->stretchGray(stretch);
689  }
690  //Otherwise the viewport is in color mode
691  else {
692  Stretch redStretch = cvp->redStretch();
693  Stretch greenStretch = cvp->greenStretch();
694  Stretch blueStretch = cvp->blueStretch();
695 
696  if(m_stretchBand == Red) {
697  redStretch.ClearPairs();
698  redStretch.AddPair(min, 0.0);
699  redStretch.AddPair(max, 255.0);
700  }
701  if(m_stretchBand == Green) {
702  greenStretch.ClearPairs();
703  greenStretch.AddPair(min, 0.0);
704  greenStretch.AddPair(max, 255.0);
705  }
706  if(m_stretchBand == Blue) {
707  blueStretch.ClearPairs();
708  blueStretch.AddPair(min, 0.0);
709  blueStretch.AddPair(max, 255.0);
710  }
711 
712  cvp->stretchRed(redStretch);
713  cvp->stretchGreen(greenStretch);
714  cvp->stretchBlue(blueStretch);
715  }
716 
717  stretchChanged();
718  }
719 
720 
726  if(m_advancedStretch->isVisible()) return;
727 
728  if(cubeViewport()) {
730  m_advancedStretch->show();
731  }
732 
733  updateTool();
734  }
735 
736 
742  CubeViewport *cvp = cubeViewport();
743  if(cvp == NULL) return;
744 
745  stretchGlobal(cvp);
746  }
747 
748 
753  CubeViewport *cvp = cubeViewport();
754  if(cvp == NULL) return;
755 
756  cvp->forgetStretches();
757  stretchGlobal(cvp);
758  }
759 
760 
766  cvp->stretchKnownGlobal();
767  stretchChanged();
768  }
769 
770 
776  for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
777  CubeViewport *cvp = cubeViewportList()->at(i);
778 
779  stretchGlobal(cvp);
780  }
781  }
782 
783 
789  CubeViewport *cvp = cubeViewport();
790  if(cvp == NULL) return;
791 
792  stretchRegional(cvp);
793  }
794 
800  try {
801  QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
802 
803  stretchRect(cvp, rect);
804  }
805  catch (IException &e) {
806  QString message = "Cannot stretch while the cube is still loading";
807  QMessageBox::warning((QWidget *)parent(), "Warning", message);
808  return;
809  }
810  }
811 
812 
820  CubeViewport *cvp = cubeViewport();
821  if(cvp == NULL) return;
822  if(!rubberBandTool()->isValid()) return;
823 
824  QRect rubberBandRect = rubberBandTool()->rectangle();
825  //Return if the width or height is zero
826  if(rubberBandRect.width() == 0 || rubberBandRect.height() == 0) return;
827 
828  stretchRect(cvp, rubberBandRect);
829  }
830 
831 
838  void StretchTool::stretchRect(CubeViewport *cvp, QRect rect) {
839  Stretch newStretch;
840  if(cvp->isGray()) {
841  newStretch = cvp->grayStretch();
842  newStretch.ClearPairs();
843  newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
844  cvp->stretchGray(newStretch);
845 
846  // send the stretch to any ChipViewports that want to listen
847  *m_chipViewportStretch = newStretch;
849  }
850  else {
851  if (m_stretchBand==Red || m_stretchBand==All) {
852  newStretch = cvp->redStretch();
853  newStretch.ClearPairs();
854  newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
855  cvp->stretchRed(newStretch);
856  }
858  newStretch = cvp->greenStretch();
859  newStretch.ClearPairs();
860  newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
861  cvp->stretchGreen(newStretch);
862  }
864  newStretch = cvp->blueStretch();
865  newStretch.ClearPairs();
866  newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
867  cvp->stretchBlue(newStretch);
868  }
869  if(m_stretchBand != Red && m_stretchBand != Blue &&
872  "Unknown stretch band",
873  _FILEINFO_);
874  }
875  }
876 
877  stretchChanged();
878  }
879 
880 
888  void StretchTool::mouseButtonRelease(QPoint start, Qt::MouseButton s) {
889  CubeViewport *cvp = cubeViewport();
890  if(cvp == NULL) return;
891 
892  // Call the parent Tool function to reset the Warning as different activity is
893  // taking place
894  Tool::mouseButtonRelease(start, s);
895 
896  if(s == Qt::RightButton) {
897  stretchGlobal(cvp);
898 
899  // notify any ChipViewports listening that the CubeViewport was stretched
900  // back to global
901  emit stretchChipViewport(NULL, cvp);
902 
903  // Resets the RubberBandTool on screen.
905  }
906  }
907 
913  rubberBandTool()->enable(RubberBandTool::RectangleMode);
914  rubberBandTool()->setDrawActiveViewportOnly(true);
915  }
916 
917 
924  CubeViewport *cvp = cubeViewport();
925  if(cvp == NULL) return;
926 
927  double min = m_stretchMinEdit->text().toDouble();
928  double max = m_stretchMaxEdit->text().toDouble();
929 
930  Stretch stretch;
931  if(cvp->isGray()) {
932  stretch = cvp->grayStretch();
933  stretch.ClearPairs();
934  stretch.AddPair(min, 0.0);
935  stretch.AddPair(max, 255.0);
936  }
937  else if(m_stretchBand == Red) {
938  stretch = cvp->redStretch();
939  stretch.ClearPairs();
940  stretch.AddPair(min, 0.0);
941  stretch.AddPair(max, 255.0);
942  cvp->stretchGreen(stretch);
943  cvp->stretchBlue(stretch);
944  }
945  else if(m_stretchBand == Green) {
946  stretch = cvp->greenStretch();
947  stretch.ClearPairs();
948  stretch.AddPair(min, 0.0);
949  stretch.AddPair(max, 255.0);
950  cvp->stretchRed(stretch);
951  cvp->stretchBlue(stretch);
952  }
953  else if(m_stretchBand == Blue) {
954  stretch = cvp->blueStretch();
955  stretch.ClearPairs();
956  stretch.AddPair(min, 0.0);
957  stretch.AddPair(max, 255.0);
958  cvp->stretchRed(stretch);
959  cvp->stretchGreen(stretch);
960  }
961  else {
962  return;
963  }
964 
965  cvp->setAllBandStretches(stretch);
966  }
967 
968 
975  CubeViewport *thisViewport = cubeViewport();
976 
977  if(thisViewport == NULL) return;
978 
979  for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
980  CubeViewport *cvp = cubeViewportList()->at(i);
981 
982  if(thisViewport->isGray() && cvp->isGray()) {
983  Stretch newStretch(cvp->grayStretch());
984  newStretch.CopyPairs(thisViewport->grayStretch());
985  cvp->stretchGray(newStretch);
986  }
987  else if(!thisViewport->isGray() && !cvp->isGray()) {
988  Stretch newStretchRed(cvp->redStretch());
989  newStretchRed.CopyPairs(thisViewport->redStretch());
990  cvp->stretchRed(newStretchRed);
991 
992  Stretch newStretchGreen(cvp->greenStretch());
993  newStretchGreen.CopyPairs(thisViewport->greenStretch());
994  cvp->stretchGreen(newStretchGreen);
995 
996  Stretch newStretchBlue(cvp->blueStretch());
997  newStretchBlue.CopyPairs(thisViewport->blueStretch());
998  cvp->stretchBlue(newStretchBlue);
999  }
1000  else if(!thisViewport->isGray() && cvp->isGray()) {
1001  // don't copy rgb to gray
1002  }
1003  else if(thisViewport->isGray() && !cvp->isGray()) {
1004  // don't copy gray stretches to rgb
1005  }
1006  }
1007 
1008  stretchChanged();
1009  }
1010 
1011 
1019  //Get the statistics and histogram from the region
1020  Statistics stats = statsFromBuffer(buffer, rect);
1021  Stretch stretch;
1022  if(stats.ValidPixels() > 1 &&
1023  fabs(stats.Minimum() - stats.Maximum()) > DBL_EPSILON) {
1024  Histogram hist = histFromBuffer(buffer, rect,
1025  stats.BestMinimum(), stats.BestMaximum());
1026 
1027  if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1028  stretch.AddPair(hist.Percent(0.5), 0.0);
1029  stretch.AddPair(hist.Percent(99.5), 255.0);
1030  }
1031  }
1032 
1033  if(stretch.Pairs() == 0) {
1034  stretch.AddPair(-DBL_MAX, 0.0);
1035  stretch.AddPair(DBL_MAX, 255.0);
1036  }
1037 
1038  return stretch;
1039  }
1040 
1041 
1049 
1050  int bandNum = cvp->grayBand();
1051  Stretch stretch = cvp->grayStretch();
1052  if(band == Red) {
1053  bandNum = cvp->redBand();
1054  stretch = cvp->redStretch();
1055  }
1056  else if(band == Green) {
1057  bandNum = cvp->greenBand();
1058  stretch = cvp->greenStretch();
1059  }
1060  else if(band == Blue) {
1061  bandNum = cvp->blueBand();
1062  stretch = cvp->blueStretch();
1063  }
1064 
1065  Statistics stats = statsFromCube(cvp->cube(), bandNum);
1066  Histogram hist = histFromCube(cvp->cube(), bandNum,
1067  stats.BestMinimum(), stats.BestMaximum());
1068 
1069  stretch.ClearPairs();
1070  if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1071  stretch.AddPair(hist.Percent(0.5), 0.0);
1072  stretch.AddPair(hist.Percent(99.5), 255.0);
1073  }
1074  else {
1075  stretch.AddPair(-DBL_MAX, 0.0);
1076  stretch.AddPair(DBL_MAX, 255.0);
1077  }
1078 
1079  return stretch;
1080  }
1081 
1092  Statistics stats;
1093  Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1094 
1095  for(int line = 0; line < cube->lineCount(); line++) {
1096  brick.SetBasePosition(0, line, band);
1097  cube->read(brick);
1098  stats.AddData(brick.DoubleBuffer(), cube->sampleCount());
1099  }
1100 
1101  return stats;
1102  }
1103 
1104 
1115  QRect rect) {
1116  if(buffer->working()) {
1118  "Cannot stretch while the cube is still loading",
1119  _FILEINFO_);
1120  }
1121 
1122  QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1123  Statistics stats;
1124 
1125  for(int y = dataArea.top();
1126  !dataArea.isNull() && y <= dataArea.bottom();
1127  y++) {
1128  const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1129 
1130  for(int x = dataArea.left(); x < dataArea.right(); x++) {
1131  stats.AddData(line[x - buffer->bufferXYRect().left()]);
1132  }
1133  }
1134 
1135  return stats;
1136  }
1137 
1150  double min, double max) {
1151  Histogram hist(min, max);
1152  Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1153 
1154  for(int line = 0; line < cube->lineCount(); line++) {
1155  brick.SetBasePosition(0, line, band);
1156  cube->read(brick);
1157  hist.AddData(brick.DoubleBuffer(), cube->sampleCount());
1158  }
1159 
1160  return hist;
1161  }
1162 
1163 
1172  Statistics stats = statsFromBuffer(buffer, buffer->bufferXYRect());
1173  return histFromBuffer(buffer, buffer->bufferXYRect(),
1174  stats.BestMinimum(), stats.BestMaximum());
1175 
1176  }
1177 
1178 
1191  QRect rect, double min, double max) {
1192  QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1193 
1194  try {
1195  Histogram hist(min, max);
1196 
1197  for(int y = dataArea.top(); !dataArea.isNull() && y <= dataArea.bottom(); y++) {
1198  const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1199  hist.AddData(&line.front() + (dataArea.left() - buffer->bufferXYRect().left()), dataArea.width());
1200  }
1201 
1202  return hist;
1203  }
1204  catch(IException &e) {
1205  // get the min and max DN values of the data area
1206  IString sMin(min);
1207  IString sMax(max);
1208  std::string msg = "Insufficient data Min [" + sMin + "], Max [" + sMax + "]";
1209  msg += " in the stretch area.";
1210 
1211  // Emit signal to the parent tool to display Warning object with the warning message
1212  //emit warningSignal(msg, e.Errors());
1213 
1214  throw IException(e, IException::Unknown, msg, _FILEINFO_);
1215  }
1216  }
1217 
1218 
1219 
1224 
1226  m_stretchBandComboBox->currentIndex()
1227  ).toInt();
1228 
1229  if(m_stretchBand == All) {
1230  m_stretchMinEdit->hide();
1231  m_stretchMaxEdit->hide();
1232  }
1233  else {
1234  m_stretchMinEdit->show();
1235  m_stretchMaxEdit->show();
1236  }
1237  stretchChanged();
1238  }
1239 
1240 
1355 }
void setAllBandStretches(Stretch stretch)
Sets a stretch for all bands.
Cube display widget for certain Isis MDI applications.
Stretch * m_preGlobalStretches
Stretches before global button pressed.
Definition: StretchTool.h:213
void setCubeViewport(CubeViewport *)
This updates the advanced stretch to use the given viewport.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the histogram counters.
Definition: Histogram.cpp:453
Stretch redStretch() const
Return the red band stretch.
void stretchGlobal()
Does a global stretch for the active viewport.
ViewportBuffer * grayBuffer()
Returns the gray viewport buffer (Will be NULL if in RGB mode.)
Definition: CubeViewport.h:421
QString toolIconDir() const
returns the path to the icon directory.
Definition: Tool.h:127
Reads and stores visible DN values.
static Stretch stretchBuffer(ViewportBuffer *buffer, QRect rect)
This method computes the stretch over a region using the viewport buffer.
Cube * cube() const
Definition: CubeViewport.h:348
QWidget * createToolBarWidget(QStackedWidget *parent)
Creates the widget to add to the tool bar.
void stretchChipViewport(Stretch *, CubeViewport *)
when a viewport is stretched, send the stretch and the viewport associated with it to any ChipViewpor...
void updateHistograms()
This updates the visible histograms in the advanced stretch, if present.
ViewportBuffer * redBuffer()
Returns the red viewport buffer (Will be NULL if in Gray mode.)
Definition: CubeViewport.h:431
int greenBand() const
Definition: CubeViewport.h:214
void stretchBlue(const QString &string)
Apply stretch pairs to blue bands.
Stretch greenStretch() const
Return the green band stretch.
double Input(const int index) const
Returns the value of the input side of the stretch pair at the specified index.
Definition: Stretch.cpp:302
double Minimum() const
Returns the absolute minimum double found in all data passed through the AddData method.
Definition: Statistics.cpp:395
bool isGray() const
Definition: CubeViewport.h:199
void stretchGlobalAllBands()
This resets the stretch across all bands.
void forgetStretches()
Resets all remembered stretches.
~StretchTool()
Destructor.
Definition: StretchTool.cpp:82
void stretchRed(const QString &string)
Apply stretch pairs to red bands.
QAction * m_stretchRegional
Regional stretch action.
Definition: StretchTool.h:201
Stretch getGrayStretch()
This returns the advanced stretch&#39;s stretch for gray.
virtual void mouseButtonRelease(QPoint p, Qt::MouseButton s)
Resets the Warning to Nowarning when a different activity occurs on the application.
Definition: Tool.cpp:380
CubeViewportList * cubeViewportList() const
Return the list of cubeviewports.
Definition: Tool.cpp:390
QComboBox * m_stretchBandComboBox
Stretch combo box.
Definition: StretchTool.h:205
void screenPixelsChanged()
This is called when the visible area changes.
int sampleCount() const
Definition: Cube.cpp:1452
double BestMaximum(const double percent=99.5) const
This method returns the better of the absolute maximum or the Chebyshev maximum.
Definition: Statistics.cpp:634
QRect rectangle()
This method returns a rectangle from the vertices set by the RubberBandTool.
const std::vector< double > & getLine(int line)
Retrieves a line from the buffer.
static Statistics statsFromBuffer(ViewportBuffer *buffer, QRect rect)
This method will calculate and return the statistics for a given region and viewport buffer...
static Stretch stretchBand(CubeViewport *cvp, StretchBand band)
This method computes the stretch over the entire cube.
Buffer for containing a three dimensional section of an image.
Definition: Brick.h:61
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition: IString.cpp:108
Namespace for the standard library.
int blueBand() const
Definition: CubeViewport.h:219
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Definition: Brick.h:136
void warningSignal(std::string &pStr, const std::string pExStr)
Shows a warning.
void stretchRect(CubeViewport *cvp, QRect rect)
stretch the specified CubeViewport with the given rect
Stretch getRedStretch()
This returns the advanced stretch&#39;s stretch for red.
void setDrawActiveViewportOnly(bool activeOnly=false)
This called to set whether rubber band is drawn on active viewport only rather than all linked viewpo...
QAction * m_stretchGlobal
Global stretch action.
Definition: StretchTool.h:200
Widget to display Isis cubes for qt apps.
Definition: CubeViewport.h:132
BigInt ValidPixels() const
Returns the total number of valid pixels processed.
Definition: Statistics.cpp:446
void showAdvancedDialog()
This methods shows and updates the advanced dialog.
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
void setStretchAcrossBands()
Sets the stretch for all the bands in the active viewport to the current stretch. ...
QPushButton * m_flashButton
Button to press for global stretch.
Definition: StretchTool.h:198
QRect bufferXYRect()
Returns a rect, in screen pixels, of the area this buffer covers.
int Pairs() const
Returns the number of stretch pairs.
Definition: Stretch.h:176
static Histogram histFromBuffer(ViewportBuffer *buffer)
Given a viewport buffer, this calculates a histogram.
Stretch grayStretch() const
Return the gray band stretch.
Stretch * m_chipViewportStretch
ChipViewport&#39;s stretch.
Definition: StretchTool.h:215
Advanced Stretch Dialog.
This was called the Qisis MainWindow.
bool isRgbMode() const
Returns true if the dialog is displaying the RGB advanced stretches.
double Maximum() const
Returns the absolute maximum double found in all data passed through the AddData method.
Definition: Statistics.cpp:416
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:107
void AddPair(const double input, const double output)
Adds a stretch pair to the list of pairs.
Definition: Stretch.cpp:63
double BestMinimum(const double percent=99.5) const
This method returns the better of the absolute minimum or the Chebyshev minimum.
Definition: Statistics.cpp:611
StretchBand m_stretchBand
Current stretch band.
Definition: StretchTool.h:210
void changeStretch()
This method is called when the stretch has changed and sets the min/max text fields to the correct va...
void advancedStretchChanged()
This is called when one of the advanced stretches changed.
void stretchKnownGlobal()
List<Tool *> p This stretches to the global stretch.
void CopyPairs(const Stretch &other)
Copies the stretch pairs from another Stretch object, but maintains special pixel values...
Definition: Stretch.cpp:407
bool enabled()
Returns true if the advanced stretch is enabled.
QToolButton * m_stretchRegionalButton
Regional Stretch Button.
Definition: StretchTool.h:197
AdvancedStretchDialog * m_advancedStretch
The advanced dialog.
Definition: StretchTool.h:193
Container of a cube histogram.
Definition: Histogram.h:86
void enableRubberBandTool()
This method enables the RubberBandTool.
void updateAdvStretchDialogforAll(void)
Update the streches and corresponding histograms for all the colors Red, Green and Blue for Stretch A...
static Histogram histFromCube(Cube *cube, int band, double min, double max)
This method will calculate and return the histogram for a given cube and band.
Pixel value mapper.
Definition: Stretch.h:72
int grayBand() const
Definition: CubeViewport.h:204
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
void enableRgbMode(Stretch &redStretch, Histogram &redHist, Stretch &grnStretch, Histogram &grnHist, Stretch &bluStretch, Histogram &bluHist)
This displays RGB advanced stretches.
void rubberBandComplete()
This method is called when the RubberBandTool is complete.
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
void enableGrayMode(Stretch &grayStretch, Histogram &grayHist)
This displays a gray advanced stretch.
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
double Percent(const double percent) const
Computes and returns the value at X percent of the histogram.
Definition: Histogram.cpp:572
Stretch getBluStretch()
This returns the advanced stretch&#39;s stretch for blue.
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
QToolButton * m_copyButton
Copy Button.
Definition: StretchTool.h:195
void stretchRequested(MdiCubeViewport *cvp, int bandId)
The cube viewport requested a stretch at this time, give it to the viewport.
QToolButton * m_globalButton
Global Button.
Definition: StretchTool.h:196
bool working()
This tests if queued actions exist in the viewport buffer.
PixelType pixelType() const
Definition: Cube.cpp:1403
void stretchRegional()
Does a regional stretch for the active viewport.
StretchBand
Enum to store the bands.
Definition: StretchTool.h:110
ViewportBuffer * blueBuffer()
Returns the blue viewport buffer (Will be NULL if in Gray mode.)
Definition: CubeViewport.h:451
void addTo(QMenu *menu)
Adds the stretch action to the given menu.
void ClearPairs()
Clears the stretch pairs.
Definition: Stretch.h:184
int lineCount() const
Definition: Cube.cpp:1379
QLineEdit * m_stretchMinEdit
Min. line edit.
Definition: StretchTool.h:207
Stretch getGrnStretch()
This returns the advanced stretch&#39;s stretch for green.
void stretchGreen(const QString &string)
Apply stretch pairs to green bands.
Isis exception class.
Definition: IException.h:107
Adds specific functionality to C++ strings.
Definition: IString.h:181
QAction * toolPadAction(ToolPad *pad)
Adds the stretch action to the toolpad.
Definition: StretchTool.cpp:99
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
Base class for the Qisis tools.
Definition: Tool.h:81
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition: Tool.h:211
QLineEdit * m_stretchMaxEdit
Max. line edit.
Definition: StretchTool.h:208
void updateHistogram(const Histogram &grayHist)
This calls setHistogram on the gray advanced stretche.
void updateHistograms(const Histogram &redHist, const Histogram &grnHist, const Histogram &bluHist)
This calls setHistogram on all of the advanced stretches.
static Statistics statsFromCube(Cube *cube, int band)
This method will calculate and return the statistics for a given cube and band.
void updateTool()
Updates the stretch tool.
int redBand() const
Definition: CubeViewport.h:209
void stretchGlobalAllViewports()
Does a global stretch for all the viewports.
bool hasEntireCube()
Method to see if the entire cube is in the buffer.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:154
void stretchGray(const QString &string)
Apply stretch pairs to gray band.
void mouseButtonRelease(QPoint p, Qt::MouseButton s)
This method will call a global stretch if the right mouse button is released.
ViewportBuffer * greenBuffer()
Returns the green viewport buffer (Will be NULL if in Gray mode.)
Definition: CubeViewport.h:441
void updateForRGBMode(Stretch &redStretch, Histogram &redHist, Stretch &grnStretch, Histogram &grnHist, Stretch &bluStretch, Histogram &bluHist)
Update the stretch and histogram for all the bands for All BandId option.
Stretch blueStretch() const
Return the blue band stretch.
void updateStretch(CubeViewport *)
This calls setStretch on all applicable advanced stretches.
QAction * m_copyBands
Copy band stretch action.
Definition: StretchTool.h:203
void setStretchAllViewports()
Sets the stretch for all the viewports to the current stretch in the active viewport.
void stretchBandChanged(int)
The selected band for stretching changed.
void stretchChanged()
This method is called when the stretch has changed and sets the min/max text fields to the correct va...
IO Handler for Isis Cubes.
Definition: Cube.h:170
void enable(bool enable)
Sets the enabled state to enable.
void enable(RubberBandMode mode, bool showIndicatorColors=false)
This is called when changing modes or turning on.