Isis 3 Programmer Reference
StretchTool.cpp
1#include "StretchTool.h"
2
3#include <sstream>
4
5#include <QAction>
6#include <QComboBox>
7#include <QHBoxLayout>
8#include <QLineEdit>
9#include <QMenuBar>
10#include <QMessageBox>
11#include <QPixmap>
12#include <QPushButton>
13#include <QSizePolicy>
14#include <QStackedWidget>
15#include <QToolBar>
16#include <QToolButton>
17#include <QValidator>
18#include <QInputDialog>
19
20#include "AdvancedStretchDialog.h"
21#include "Brick.h"
22#include "Blob.h"
23#include "CubeViewport.h"
24#include "Histogram.h"
25#include "IException.h"
26#include "IString.h"
27#include "MainWindow.h"
28#include "MdiCubeViewport.h"
29#include "RubberBandTool.h"
30#include "Statistics.h"
31#include "Stretch.h"
32#include "ToolPad.h"
33#include "ViewportBuffer.h"
34#include "ViewportMainWindow.h"
35#include "Workspace.h"
36
37#include "CubeStretch.h"
38
39using namespace std;
40
41namespace Isis {
51 m_advancedStretch = NULL;
52
54
56 connect(m_advancedStretch, SIGNAL(stretchChanged()),
57 this, SLOT(advancedStretchChanged()));
58 connect(m_advancedStretch, SIGNAL(visibilityChanged()),
59 this, SLOT(updateTool()));
60 connect(m_advancedStretch, SIGNAL(saveToCube()),
61 this, SLOT(saveStretchToCube()));
62 connect(m_advancedStretch, SIGNAL(deleteFromCube()),
63 this, SLOT(deleteFromCube()));
64 connect(m_advancedStretch, SIGNAL(loadStretch()),
65 this, SLOT(loadStretchFromCube()));
66
67 QPushButton *hiddenButton = new QPushButton();
68 hiddenButton->setVisible(false);
69 hiddenButton->setDefault(true);
70
71 m_stretchGlobal = new QAction(parent);
72 m_stretchGlobal->setShortcut(Qt::CTRL + Qt::Key_G);
73 m_stretchGlobal->setText("Global Stretch");
74 connect(m_stretchGlobal, SIGNAL(triggered()), this, SLOT(stretchGlobal()));
75
76 m_stretchRegional = new QAction(parent);
77 m_stretchRegional->setShortcut(Qt::CTRL + Qt::Key_R);
78 m_stretchRegional->setText("Regional Stretch");
79 connect(m_stretchRegional, SIGNAL(triggered()), this, SLOT(stretchRegional()));
80
81 // Emit a signal when an exception occurs and connect to the Warning object
82 // to display Warning icon and the message
83 ViewportMainWindow *parentMainWindow = qobject_cast<ViewportMainWindow *>(parent);
84 if (parentMainWindow) {
85 connect(this, SIGNAL(warningSignal(std::string &, const std::string)),
86 parentMainWindow, SLOT(displayWarning(std::string &, const std::string &)));
87 }
88 }
89
90
101
102
112 QAction *action = new QAction(pad);
113 action->setIcon(QPixmap(toolIconDir() + "/stretch_global.png"));
114 action->setToolTip("Stretch (S)");
115 action->setShortcut(Qt::Key_S);
116 QString text =
117 "<b>Function:</b> Change the stretch range of the cube.\
118 <p><b>Shortcut:</b> S</p> ";
119 action->setWhatsThis(text);
120
121 return action;
122 }
123
124
132 menu->addAction(m_stretchGlobal);
133 menu->addAction(m_stretchRegional);
134 }
135
136
145 QWidget *StretchTool::createToolBarWidget(QStackedWidget *parent) {
146 QWidget *hbox = new QWidget(parent);
147
148 QToolButton *butt = new QToolButton(hbox);
149 butt->setAutoRaise(true);
150 butt->setIconSize(QSize(22, 22));
151 butt->setIcon(QPixmap(toolIconDir() + "/regional_stretch-2.png"));
152 butt->setToolTip("Stretch");
153 QString text =
154 "<b>Function:</b> Automatically compute min/max stretch using viewed \
155 pixels in the band(s) of the active viewport. That is, only pixels \
156 that are visible in the viewport are used. \
157 If the viewport is in RGB color all three bands will be stretched. \
158 <p><b>Shortcut:</b> Ctrl+R</p> \
159 <p><b>Mouse:</b> Left click \
160 <p><b>Hint:</b> Left click and drag for a local stretch. Uses only \
161 pixels in the red marquee</p>";
162 butt->setWhatsThis(text);
163 connect(butt, SIGNAL(clicked()), this, SLOT(stretchRegional()));
165
167 m_stretchBandComboBox->setEditable(false);
168 m_stretchBandComboBox->addItem("Red Band", Red);
169 m_stretchBandComboBox->addItem("Green Band", Green);
170 m_stretchBandComboBox->addItem("Blue Band", Blue);
171 m_stretchBandComboBox->addItem("All Bands", All);
172 m_stretchBandComboBox->setToolTip("Select Color");
173 text =
174 "<b>Function:</b> Selecting the color will allow the appropriate \
175 min/max to be seen and/or edited in text fields to the right.";
176
177// The All option implies the same min/max will be applied
178// to all three colors (RGB) if either text field is edited";
179 m_stretchBandComboBox->setWhatsThis(text);
181 m_stretchBandComboBox->setCurrentIndex(
183 connect(m_stretchBandComboBox, SIGNAL(currentIndexChanged(int)),
184 this, SLOT(stretchBandChanged(int)));
185
186 // Create drop-down selection option to set min/max type
188 p_minMaxTypeSelection->setToolTip("Min/Max Type");
189 text =
190 "<b>Function:</b> Select the minimum & maximum value types to \
191 set the stretch to. The four options are: \
192 <p>- Default: Min and max values are set to the \
193 0.5 and 99.5 percentiles, respectively. \
194 <p>- Best: The better of the absolute min/max or the \
195 Chebyshev min/max. The better value is considered the value \
196 closest to the mean. \
197 <p>- Absolute: The absolute min/max value of all valid pixels. \
198 <p>- Chebyshev: The min/max value such that a certain percentage \
199 of data will fall within K standard deviations of the average \
200 (Chebyshev's Theorem). It can be used to obtain a value that \
201 does not include statistical outliers.";
202 p_minMaxTypeSelection->setWhatsThis(text);
203 p_minMaxTypeSelection->addItem("Default", 0);
204 p_minMaxTypeSelection->addItem("Best", 1);
205 p_minMaxTypeSelection->addItem("Absolute", 2);
206 p_minMaxTypeSelection->addItem("Chebyshev", 3);
207
208 connect(p_minMaxTypeSelection, SIGNAL(currentIndexChanged(int)), this, SLOT(changeStretch()));
209
210 QDoubleValidator *dval = new QDoubleValidator(hbox);
211 m_stretchMinEdit = new QLineEdit(hbox);
212 m_stretchMinEdit->setValidator(dval);
213 m_stretchMinEdit->setToolTip("Minimum");
214 text =
215 "<b>Function:</b> Shows the current minimum pixel value. Pixel values \
216 below minimum are shown as black. Pixel values above the maximum \
217 are shown as white or the highest intensity of red/green/blue \
218 if in color. Pixel values between the minimum and maximum are stretched \
219 linearly between black and white (or color component). \
220 <p><b>Hint:</b> You can manually edit the minimum but it must be \
221 less than the maximum.";
222 m_stretchMinEdit->setWhatsThis(text);
223 m_stretchMinEdit->setMaximumWidth(100);
224 connect(m_stretchMinEdit, SIGNAL(returnPressed()),
225 this, SLOT(changeStretch()));
226
227 m_stretchMaxEdit = new QLineEdit(hbox);
228 m_stretchMaxEdit->setValidator(dval);
229 m_stretchMaxEdit->setToolTip("Maximum");
230 text =
231 "<b>Function:</b> Shows the current maximum pixel value. Pixel values \
232 below minimum are shown as black. Pixel values above the maximum \
233 are shown as white or the highest intensity of red/green/blue \
234 if in color. Pixel values between the minimum and maximum are stretched \
235 linearly between black and white (or color component). \
236 <p><b>Hint:</b> You can manually edit the maximum but it must be \
237 greater than the minimum";
238 m_stretchMaxEdit->setWhatsThis(text);
239 m_stretchMaxEdit->setMaximumWidth(100);
240 connect(m_stretchMaxEdit, SIGNAL(returnPressed()), this, SLOT(changeStretch()));
241
242 // Create the two menus that drop down from the buttons
243 QMenu *copyMenu = new QMenu();
244 QMenu *globalMenu = new QMenu();
245
246 m_copyBands = new QAction(parent);
247 m_copyBands->setText("to All Bands");
248 connect(m_copyBands, SIGNAL(triggered(bool)), this, SLOT(setStretchAcrossBands()));
249
250 QAction *copyAll = new QAction(parent);
251 copyAll->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
252 copyAll->setText("to All Viewports");
253 connect(copyAll, SIGNAL(triggered(bool)), this, SLOT(setStretchAllViewports()));
254
255 copyMenu->addAction(copyAll);
256 copyMenu->addAction(m_copyBands);
257
258 m_copyButton = new QToolButton();
259 m_copyButton->setAutoRaise(true);
260 m_copyButton->setIconSize(QSize(22, 22));
261 m_copyButton->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
262 m_copyButton->setPopupMode(QToolButton::MenuButtonPopup);
263 m_copyButton->setMenu(copyMenu);
264 m_copyButton->setDefaultAction(copyAll);
265 m_copyButton->setToolTip("Copy");
266 text =
267 "<b>Function:</b> Copy the current stretch to all the \
268 active viewports. Or use the drop down menu to copy the current stretch \
269 to all the bands in the active viewport. \
270 <p><b>Hint:</b> Can reset the stretch to an automaticaly computed \
271 stretch by using the 'Reset' stretch button option. </p>";
272 m_copyButton->setWhatsThis(text);
273
274 QAction *currentView = new QAction(parent);
275 currentView->setText("Active Viewport");
276 currentView->setIcon(QPixmap(toolIconDir() + "/global_stretch.png"));
277 globalMenu->addAction(currentView);
278 connect(currentView, SIGNAL(triggered(bool)), this, SLOT(stretchGlobal()));
279
280 QAction *globalAll = new QAction(parent);
281 globalAll->setText("All Viewports");
282 globalMenu->addAction(globalAll);
283 connect(globalAll, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllViewports()));
284
285 QAction *globalBands = new QAction(parent);
286 globalBands->setText("All Bands");
287 globalMenu->addAction(globalBands);
288 connect(globalBands, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllBands()));
289
290 m_globalButton = new QToolButton(); //basically acts as a 'reset'
291 m_globalButton->setAutoRaise(true);
292 m_globalButton->setIconSize(QSize(22, 22));
293 m_globalButton->setPopupMode(QToolButton::MenuButtonPopup);
294 m_globalButton->setMenu(globalMenu);
295 m_globalButton->setDefaultAction(currentView);
296 m_globalButton->setToolTip("Reset");
297 text =
298 "<b>Function:</b> Reset the stretch to be automatically computed "
299 "using the statisics from the entire image. Use the drop down menu "
300 "to reset the stretch for all the bands in the active viewport or "
301 "to reset the stretch for all the viewports.";
302 m_globalButton->setWhatsThis(text);
303
304 QPushButton *advancedButton = new QPushButton("Advanced");
305 connect(advancedButton, SIGNAL(clicked()), this, SLOT(showAdvancedDialog()));
306
307 m_flashButton = new QPushButton("Show Global");
308 text =
309 "<b>Function:</b> While this button is pressed down, the visible stretch "
310 "will be the automatically computed stretch using the statisics from the "
311 "entire image. The original stretch is restored once you let up on this "
312 "button.";
313 m_flashButton->setWhatsThis(text);
314 connect(m_flashButton, SIGNAL(pressed()), this, SLOT(stretchChanged()));
315 connect(m_flashButton, SIGNAL(released()), this, SLOT(stretchChanged()));
316
317 // Buttons migrated out of Advanced Stretch Tool
318 QPushButton *saveToCubeButton = new QPushButton("Save");
319 connect(saveToCubeButton, SIGNAL(clicked(bool)), this, SLOT(saveStretchToCube()));
320
321 QPushButton *deleteFromCubeButton = new QPushButton("Delete");
322 connect(deleteFromCubeButton, SIGNAL(clicked(bool)), this, SLOT(deleteFromCube()));
323
324 QPushButton *loadStretchButton = new QPushButton("Restore");
325 connect(loadStretchButton, SIGNAL(clicked(bool)), this, SLOT(loadStretchFromCube()));
326
327 QHBoxLayout *layout = new QHBoxLayout(hbox);
328 layout->setMargin(0);
329 layout->addWidget(m_copyButton);
330 layout->addWidget(m_globalButton);
331 layout->addWidget(m_stretchRegionalButton);
332 layout->addWidget(m_stretchBandComboBox);
333 layout->addWidget(p_minMaxTypeSelection);
334 layout->addWidget(m_stretchMinEdit);
335 layout->addWidget(m_stretchMaxEdit);
336 layout->addWidget(advancedButton);
337 layout->addWidget(m_flashButton);
338
339 // should only display if gray stretch
340 // Save/Restore strech only supported for Grayscale images. Hide buttons if in RGB.
341 layout->addWidget(saveToCubeButton);
342 layout->addWidget(deleteFromCubeButton);
343 layout->addWidget(loadStretchButton);
344
345 layout->addStretch(); // Pushes everything else left in the menu bar
346 hbox->setLayout(layout);
347
348 return hbox;
349 }
350
351
357 if(m_advancedStretch->isVisible()) {
359
360 if(!cvp) return;
361
362 if(cvp->isGray() && !cvp->grayBuffer()->working()) {
364 updateTool();
365 }
366 else {
367 Histogram hist(histFromBuffer(cvp->grayBuffer()));
368
369 if(hist.ValidPixels() > 0) {
371 }
372 }
373 }
374 // Otherwise it is in color mode
375 else if(!cvp->isGray() &&
376 !cvp->redBuffer()->working() &&
377 !cvp->greenBuffer()->working() &&
378 !cvp->blueBuffer()->working()) {
380 updateTool();
381 }
382 else {
383 Histogram redHist(histFromBuffer(cvp->redBuffer()));
384 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
385 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
386
387 if(redHist.ValidPixels() > 0 &&
388 grnHist.ValidPixels() > 0 &&
389 bluHist.ValidPixels() > 0) {
390 m_advancedStretch->updateHistograms(redHist, grnHist, bluHist);
391 }
392 }
393 }
394 }
395 }
396
397
405 {
406 if(m_advancedStretch->isVisible()) {
408
409 if(!cvp->isGray() &&
410 !cvp->redBuffer()->working() &&
411 !cvp->greenBuffer()->working() &&
412 !cvp->blueBuffer()->working()) {
413
414 Histogram redHist(histFromBuffer(cvp->redBuffer()));
415 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
416 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
417 Stretch redStretch(cvp->redStretch());
418 Stretch grnStretch(cvp->greenStretch());
419 Stretch bluStretch(cvp->blueStretch());
420
421 m_advancedStretch->updateForRGBMode(redStretch, redHist,
422 grnStretch, grnHist,
423 bluStretch, bluHist);
424 }
425 }
426 }
427
428
434 Cube* icube = cvp->cube();
435 Pvl* lab = icube->label();
436
437 QStringList namelist;
438
439 // Create a list of existing Stretch names
440 if (cvp->isGray()) {
442 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
443 if (objIter->name() == "Stretch") {
444 PvlKeyword tempKeyword = objIter->findKeyword("Name");
445 int bandNumber = int(objIter->findKeyword("BandNumber"));
446 if (cvp->grayBand() == bandNumber) {
447 QString tempName = tempKeyword[0];
448 namelist.append(tempName);
449 }
450 }
451 }
452 }
453 else {
454 int redBandNumber = cvp->redBand();
455 int greenBandNumber = cvp->greenBand();
456 int blueBandNumber = cvp->blueBand();
457
458 QMap<QString, QList<int>> tempNameMap;
460 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
461 if (objIter->name() == "Stretch") {
462 PvlKeyword tempKeyword = objIter->findKeyword("Name");
463 int bandNumber = int(objIter->findKeyword("BandNumber"));
464 if (bandNumber == redBandNumber || bandNumber == greenBandNumber
465 || bandNumber == blueBandNumber) {
466 QString tempName = tempKeyword[0];
467 if (tempNameMap.contains(tempName)) {
468 tempNameMap[tempName].append(bandNumber);
469 }
470 else
471 {
472 tempNameMap[tempName] = {bandNumber};
473 }
474 }
475 }
476 }
477 QMap<QString, QList<int>>::const_iterator i = tempNameMap.constBegin();
478 while (i != tempNameMap.constEnd()) {
479 if (i.value().contains(redBandNumber) && i.value().contains(greenBandNumber) &&
480 i.value().contains(blueBandNumber) ){
481 namelist.append(i.key());
482 }
483 ++i;
484 }
485 }
486
487 bool ok = false;
488 QString stretchName;
489 // Only display load stretch dialog if there are stretches saved to the cube
490 if (namelist.size() >=1) {
491 stretchName = QInputDialog::getItem((QWidget *)parent(), tr("Load Stretch"),
492 tr("Name of Stretch to Load:"), namelist, 0,
493 false, &ok);
494 }
495 else {
496 QMessageBox::information((QWidget *)parent(), "Information",
497 "There are no saved stretches to restore.");
498 }
499
500 if (ok) {
501 if (cvp->isGray()) {
502 CubeStretch cubeStretch = icube->readCubeStretch(stretchName);
503 if (m_advancedStretch->isVisible()) {
505 }
506 // Get the current cube stretche and copy the new stretch pairs over so that the
507 // special pixel values set in the viewport are maintained.
508 CubeStretch grayOriginal = cvp->grayStretch();
509 grayOriginal.CopyPairs(cubeStretch);
510 cvp->stretchGray(grayOriginal);
511 }
512 else {
513 std::vector<PvlKeyword> keywordValueRed;
514 keywordValueRed.push_back(PvlKeyword("BandNumber", QString::number(cvp->redBand())));
515
516 std::vector<PvlKeyword> keywordValueGreen;
517 keywordValueGreen.push_back(PvlKeyword("BandNumber", QString::number(cvp->greenBand())));
518
519 std::vector<PvlKeyword> keywordValueBlue;
520 keywordValueBlue.push_back(PvlKeyword("BandNumber", QString::number(cvp->blueBand())));
521
522 CubeStretch redStretch = icube->readCubeStretch(stretchName, keywordValueRed);
523 CubeStretch greenStretch = icube->readCubeStretch(stretchName, keywordValueGreen);
524 CubeStretch blueStretch = icube->readCubeStretch(stretchName, keywordValueBlue);
525
526 if (m_advancedStretch->isVisible()) {
527 m_advancedStretch->restoreRgbStretch(redStretch, greenStretch, blueStretch);
528 }
529
530 // Get the current cube stretches and copy the new stretch pairs over so that the
531 // special pixel values set in the viewport are maintained.
532 CubeStretch redOriginal = cvp->redStretch();
533 CubeStretch greenOriginal = cvp->greenStretch();
534 CubeStretch blueOriginal = cvp->blueStretch();
535
536 redOriginal.CopyPairs(redStretch);
537 greenOriginal.CopyPairs(greenStretch);
538 blueOriginal.CopyPairs(blueStretch);
539
540 cvp->stretchRed(redOriginal);
541 cvp->stretchGreen(greenOriginal);
542 cvp->stretchBlue(blueOriginal);
543 }
544 emit stretchChanged();
545 }
546 }
547
548
554 Cube* icube = cvp->cube();
555 Pvl* lab = icube->label();
556
557 // Create a list of existing Stretch names
558 QStringList namelist;
560 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
561 if (objIter->name() == "Stretch") {
562 PvlKeyword tempKeyword = objIter->findKeyword("Name");
563 int bandNumber = int(objIter->findKeyword("BandNumber"));
564 if (cvp->grayBand() == bandNumber) {
565 QString tempName = tempKeyword[0];
566 namelist.append(tempName);
567 }
568 }
569 }
570
571 bool ok = false;
572 QString toDelete;
573 // Only display list of stretches to delete if there are stretches saved to the cube
574 if (namelist.size() >= 1) {
575 toDelete = QInputDialog::getItem((QWidget *)parent(), tr("Delete Stretch"),
576 tr("Name of Stretch to Delete:"), namelist, 0,
577 false, &ok);
578 }
579 else {
580 QMessageBox::information((QWidget *)parent(), "Information",
581 "There are no saved stretches to delete.");
582 }
583
584 if (ok) {
585 if (icube->isReadOnly()) {
586 try {
587 cvp->cube()->reopen("rw");
588 }
589 catch(IException &) {
590 cvp->cube()->reopen("r");
591 QMessageBox::information((QWidget *)parent(), "Error",
592 "Cannot open cube read/write to delete stretch");
593 return;
594 }
595 }
596
597 bool cubeDeleted = icube->deleteBlob(toDelete, "Stretch");
598
599 if (!cubeDeleted) {
600 QMessageBox msgBox;
601 msgBox.setText("Stretch Could Not Be Deleted!");
602 msgBox.setInformativeText("A stretch with name: \"" + toDelete +
603 "\" Could not be found, so there was nothing to delete from the Cube.");
604 msgBox.setStandardButtons(QMessageBox::Ok);
605 msgBox.setIcon(QMessageBox::Critical);
606 msgBox.exec();
607 }
608
609 // Don't leave open rw -- not optimal.
610 cvp->cube()->reopen("r");
611 }
612 }
613
614
620 Cube* icube = cvp->cube();
621 Pvl* lab = icube->label();
622
623 // Create a list of existing Stretch names
624 QStringList namelist;
626 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
627 if (objIter->name() == "Stretch") {
628 PvlKeyword tempKeyword = objIter->findKeyword("Name");
629 QString tempName = tempKeyword[0];
630 namelist.append(tempName);
631 }
632 }
633
634 bool ok;
635 QString name;
636
637 //
638 // At this time, it is NOT possible to save an RGB stretch with the same band number
639 // multiple times, if the saved stretch for each is different. If the saved stretch is the same
640 // this is okay.
641 //
642 // For example, r=1, g=1, b=1, with the same stretch for each is okay
643 // r=1, g=1, b=2, where the stretches for band 1 are the same, is okay
644 // r=1, g=1, b=1, where the the stretches for band 1 are different (red stretch !=
645 // green stretch)
646 //
647 if (!cvp->isGray()) {
648 CubeStretch redStretch, greenStretch, blueStretch;
649 if (m_advancedStretch->isVisible()) {
650 redStretch = m_advancedStretch->getRedStretch();
651 greenStretch = m_advancedStretch->getGrnStretch();
652 blueStretch = m_advancedStretch->getBluStretch();
653 }
654 else {
655 redStretch = cvp->redStretch();
656 greenStretch = cvp->greenStretch();
657 blueStretch = cvp->blueStretch();
658 }
659
660 int redBand = cvp->redBand();
661 int greenBand = cvp->greenBand();
662 int blueBand = cvp->blueBand();
663
664 if (((redBand == greenBand) && !(redStretch == greenStretch)) ||
665 ((redBand == blueBand) && !(redBand == blueBand)) ||
666 ((greenBand == blueBand) && !(greenBand == blueBand))) {
667 QMessageBox::information((QWidget *)parent(), "Error", "Sorry, cannot save RGB stretches which include the same band multiple times, but have different stretches for each");
668 return;
669 }
670 }
671
672 // "Get the name for the stretch" dialog
673 QString text = QInputDialog::getText(m_advancedStretch, tr("Save Stretch"),
674 tr("Enter a name to save the stretch as:"), QLineEdit::Normal,
675 "stretch", &ok);
676
677 if (ok) {
678 // Stretch Name Already Exists Dialog!
679 if (namelist.contains(text)) {
680 QMessageBox msgBox;
681 msgBox.setText(tr("Stretch Name Already Exists!"));
682 msgBox.setInformativeText("A stretch pair with name: \"" + text + "\" already exists and "
683 "the existing saved data will be overwritten. Are you sure you "
684 "wish to proceed?");
685 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
686 msgBox.setIcon(QMessageBox::Warning);
687 msgBox.setDefaultButton(QMessageBox::Cancel);
688 int ret = msgBox.exec();
689
690 switch (ret) {
691 case QMessageBox::Save:
692 break;
693 case QMessageBox::Cancel:
694 // Cancel was clicked, exit this function
695 return;
696 break;
697 default:
698 // should never be reached
699 return;
700 break;
701 }
702 }
703
704 if (icube->isReadOnly()) {
705 // reOpen cube as read/write
706 try {
707 icube->reopen("rw");
708 }
709 catch(IException &) {
710 icube->reopen("r");
711 QMessageBox::information((QWidget *)parent(), "Error", "Cannot open cube read/write to save stretch");
712 return;
713 }
714 }
715
716 // If gray, only one stretch to save
717 if (cvp->isGray()) {
718 CubeStretch stretch;
719 if (m_advancedStretch->isVisible()) {
721 }
722 else {
723 stretch = cvp->grayStretch();
724 }
725
726 // Write single stretch to cube
727 stretch.setName(text);
728 stretch.setBandNumber(cvp->grayBand());
729
730 // Overwrite an existing stretch with the same name if it exists. The user was warned
731 // and decided to overwrite.
732 icube->write(stretch);
733 }
734 else {
735 CubeStretch redStretch, greenStretch, blueStretch;
736 if (m_advancedStretch->isVisible()) {
737 redStretch = m_advancedStretch->getRedStretch();
738 greenStretch = m_advancedStretch->getGrnStretch();
739 blueStretch = m_advancedStretch->getBluStretch();
740 }
741 else {
742 redStretch = cvp->redStretch();
743 greenStretch = cvp->greenStretch();
744 blueStretch = cvp->blueStretch();
745 }
746
747 redStretch.setName(text);
748 redStretch.setBandNumber(cvp->redBand());
749 Blob stretchBlob = redStretch.toBlob();
750 icube->write(stretchBlob, false);
751
752 greenStretch.setName(text);
753 greenStretch.setBandNumber(cvp->greenBand());
754 stretchBlob = greenStretch.toBlob();
755 icube->write(stretchBlob, false);
756
757 blueStretch.setName(text);
758 blueStretch.setBandNumber(cvp->blueBand());
759 stretchBlob = blueStretch.toBlob();
760 icube->write(stretchBlob, false);
761 }
762
763 // Don't leave open rw -- not optimal.
764 cvp->cube()->reopen("r");
765 }
766 }
767
768
775
776
783 if(m_advancedStretch->isVisible()) {
785 //If the viewport is in gray mode
786 if(cvp->isGray() && !cvp->grayBuffer()->working()) {
787 Histogram hist(histFromBuffer(cvp->grayBuffer()));
788 Stretch stretch(cvp->grayStretch());
789 m_advancedStretch->enableGrayMode(stretch, hist);
790 }
791 //Otherwise it is in color mode
792 else if(!cvp->isGray() &&
793 !cvp->redBuffer()->working() &&
794 !cvp->greenBuffer()->working() &&
795 !cvp->blueBuffer()->working()) {
796 Histogram redHist(histFromBuffer(cvp->redBuffer()));
797 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
798 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
799 Stretch redStretch(cvp->redStretch());
800 Stretch grnStretch(cvp->greenStretch());
801 Stretch bluStretch(cvp->blueStretch());
802 m_advancedStretch->enableRgbMode(redStretch, redHist,
803 grnStretch, grnHist,
804 bluStretch, bluHist);
805 }
806 else {
808 }
809 }
810 else {
812 }
813 }
814
815
821 CubeViewport *cvp = cubeViewport();
822
823 if(cvp == NULL) {
824 //If the current viewport is NULL and the advanced dialog is visible, hide it
825 if(m_advancedStretch->isVisible()) {
826 m_advancedStretch->hide();
827 }
828 }
829 else {
830 if(!m_advancedStretch->enabled() ||
831 m_advancedStretch->isRgbMode() != !cvp->isGray()) {
832 setCubeViewport(cvp);
833 }
834 }
835
836 if(cvp && cvp->isGray()) {
837 m_copyBands->setEnabled(true);
838 m_stretchBandComboBox->setVisible(false);
839 m_stretchMinEdit->show();
840 m_stretchMaxEdit->show();
841 }
842 else if(cvp) {
843 m_copyBands->setEnabled(true);
844 m_stretchBandComboBox->setVisible(true);
846 }
847 else {
848 m_copyBands->setEnabled(false);
849 m_stretchBandComboBox->setVisible(false);
850 }
851
852 if(m_advancedStretch->isVisible()) {
853 m_stretchMinEdit->setEnabled(false);
854 m_stretchMaxEdit->setEnabled(false);
855 }
856 else {
857 m_stretchMinEdit->setEnabled(true);
858 m_stretchMaxEdit->setEnabled(true);
859 }
860
863 }
864
865
874 // Yeah this is a hack... but it's necessary to make this tool
875 // do anything while its not the active tool.
876 connect(cvp, SIGNAL(screenPixelsChanged()), this, SLOT(updateHistograms()));
877 QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
878
879 if(bandId == (int)Gray) {
880 if(cvp->grayBuffer() && cvp->grayBuffer()->hasEntireCube()) {
881 Stretch newStretch = cvp->grayStretch();
882 newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
883 cvp->stretchGray(newStretch);
884 }
885 else {
886 Stretch newStretch = stretchBand(cvp, (StretchBand)bandId);
887 cvp->stretchGray(newStretch);
888 }
889 }
890 else
891 {
892 if(bandId == (int)Red || bandId == (int)All) {
893 if(cvp->redBuffer() && cvp->redBuffer()->hasEntireCube()) {
894 Stretch newStretch = cvp->redStretch();
895 newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
896 cvp->stretchRed(newStretch);
897 }
898 else {
899 Stretch newStretch = stretchBand(cvp, Red);
900 cvp->stretchRed(newStretch);
901 }
902 }
903 if(bandId == (int)Green || bandId == (int)All) {
904 if(cvp->greenBuffer() && cvp->greenBuffer()->hasEntireCube()) {
905 Stretch newStretch = cvp->greenStretch();
906 newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
907 cvp->stretchGreen(newStretch);
908 }
909 else {
910 Stretch newStretch = stretchBand(cvp, Green);
911 cvp->stretchGreen(newStretch);
912 }
913 }
914 if(bandId == (int)Blue || bandId == (int)All) {
915 if(cvp->blueBuffer() && cvp->blueBuffer()->hasEntireCube()) {
916 Stretch newStretch = cvp->blueStretch();
917 newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
918 cvp->stretchBlue(newStretch);
919 }
920 else {
921 Stretch newStretch = stretchBand(cvp, Blue);
922 cvp->stretchBlue(newStretch);
923 }
924 }
925 }
927 }
928
929
937 if(cvp == NULL) return;
938
939 if(m_flashButton->isDown()) {
942 m_preGlobalStretches[0] = cvp->grayStretch();
943 m_preGlobalStretches[1] = cvp->redStretch();
944 m_preGlobalStretches[2] = cvp->greenStretch();
945 m_preGlobalStretches[3] = cvp->blueStretch();
946 }
947
948 cvp->stretchKnownGlobal();
949 return;
950 }
951 else if(m_preGlobalStretches) {
952 if(cvp->isGray()) {
953 cvp->stretchGray(m_preGlobalStretches[0]);
954 }
955 else {
956 cvp->stretchRed(m_preGlobalStretches[1]);
957 cvp->stretchGreen(m_preGlobalStretches[2]);
958 cvp->stretchBlue(m_preGlobalStretches[3]);
959 }
960
961 delete [] m_preGlobalStretches;
963 }
964
965 double min = 0, max = 0;
966 //If the viewport is in gray mode
967 if(cvp->isGray()) {
968 //Get the min/max from the current stretch
969 Stretch stretch = cvp->grayStretch();
970 min = stretch.Input(0);
971 max = stretch.Input(stretch.Pairs() - 1);
972 }
973
974 //Otherwise it is in color mode
975 else {
976 Stretch rstretch = cvp->redStretch();
977 Stretch gstretch = cvp->greenStretch();
978 Stretch bstretch = cvp->blueStretch();
979
980 //Get the min/max from the current stretch
981 if(m_stretchBand == Red) {
982 min = rstretch.Input(0);
983 max = rstretch.Input(rstretch.Pairs() - 1);
984 }
985 else if(m_stretchBand == Green) {
986 min = gstretch.Input(0);
987 max = gstretch.Input(gstretch.Pairs() - 1);
988 }
989 else if(m_stretchBand == Blue) {
990 min = bstretch.Input(0);
991 max = bstretch.Input(bstretch.Pairs() - 1);
992 }
993 }
994
995 //Set the min/max text fields
996 if(m_stretchBand != All || cvp->isGray()) {
997 QString strMin;
998 strMin.setNum(min);
999 m_stretchMinEdit->setText(strMin);
1000
1001 QString strMax;
1002 strMax.setNum(max);
1003 m_stretchMaxEdit->setText(strMax);
1004 }
1005
1006 if(m_advancedStretch->isVisible()) {
1007 if(m_stretchBand == All){
1009 }
1011 }
1012 }
1013
1014
1020 CubeViewport *cvp = cubeViewport();
1021 if(cvp == NULL) return;
1022
1024 Stretch grayStretch = cvp->grayStretch();
1025 grayStretch.ClearPairs();
1027 cvp->stretchGray(grayStretch);
1028
1029 // send the stretch to any ChipViewports that want to listen
1030 *m_chipViewportStretch = grayStretch;
1032 }
1033 else {
1034 Stretch redStretch = cvp->redStretch();
1035 redStretch.ClearPairs();
1037 cvp->stretchRed(redStretch);
1038
1039 Stretch grnStretch = cvp->greenStretch();
1040 grnStretch.ClearPairs();
1041 grnStretch.CopyPairs(m_advancedStretch->getGrnStretch());
1042 cvp->stretchGreen(grnStretch);
1043
1044 Stretch bluStretch = cvp->blueStretch();
1045 bluStretch.ClearPairs();
1046 bluStretch.CopyPairs(m_advancedStretch->getBluStretch());
1047 cvp->stretchBlue(bluStretch);
1048 }
1050 }
1051
1052
1061 if(cvp == NULL) return;
1062
1063 // Set the min/max based on selected type
1064 stretchMinMaxType(cvp);
1065
1066 // Make sure the user didn't enter bad min/max and if so fix it
1067 double min = m_stretchMinEdit->text().toDouble();
1068 double max = m_stretchMaxEdit->text().toDouble();
1069
1070 if(min >= max || m_stretchMinEdit->text() == "" ||
1071 m_stretchMaxEdit->text() == "") {
1072 updateTool();
1073 return;
1074 }
1075
1076 //The viewport is in gray mode
1077 if(cvp->isGray()) {
1078 Stretch stretch = cvp->grayStretch();
1079 stretch.ClearPairs();
1080 stretch.AddPair(min, 0.0);
1081 stretch.AddPair(max, 255.0);
1082
1083 // send the stretch to any ChipViewports that want to listen
1084 *m_chipViewportStretch = stretch;
1086
1087 cvp->stretchGray(stretch);
1088 }
1089 //Otherwise the viewport is in color mode
1090 else {
1091 Stretch redStretch = cvp->redStretch();
1092 Stretch greenStretch = cvp->greenStretch();
1093 Stretch blueStretch = cvp->blueStretch();
1094
1095 if(m_stretchBand == Red) {
1096 redStretch.ClearPairs();
1097 redStretch.AddPair(min, 0.0);
1098 redStretch.AddPair(max, 255.0);
1099 }
1100 if(m_stretchBand == Green) {
1101 greenStretch.ClearPairs();
1102 greenStretch.AddPair(min, 0.0);
1103 greenStretch.AddPair(max, 255.0);
1104 }
1105 if(m_stretchBand == Blue) {
1106 blueStretch.ClearPairs();
1107 blueStretch.AddPair(min, 0.0);
1108 blueStretch.AddPair(max, 255.0);
1109 }
1110
1111 cvp->stretchRed(redStretch);
1112 cvp->stretchGreen(greenStretch);
1113 cvp->stretchBlue(blueStretch);
1114 }
1115
1117 }
1118
1124 // Get current band
1125 int bandId = m_stretchBandComboBox->currentIndex();
1126 int bandNum = cvp->grayBand();
1127 if(bandId == (int)Red) {
1128 bandNum = cvp->redBand();
1129 }
1130 else if(bandId == (int)Green) {
1131 bandNum = cvp->greenBand();
1132 }
1133 else if(bandId == (int)Blue) {
1134 bandNum = cvp->blueBand();
1135 }
1136
1137 // Get current band statistics
1138 Statistics stats = statsFromCube(cvp->cube(), bandNum);
1139 Histogram hist = histFromCube(cvp->cube(), bandNum, stats.BestMinimum(), stats.BestMaximum());
1140
1141 // Set min/max given ComboBox selection
1142 int minMaxIndex = p_minMaxTypeSelection->currentIndex();
1143 double selectedMin = 0;
1144 double selectedMax = 0;
1145
1146 if (minMaxIndex == 0) {
1147 selectedMin = hist.Percent(0.5);
1148 selectedMax = hist.Percent(99.5);
1149 } else if (minMaxIndex == 1) {
1150 // Best
1151 selectedMin = stats.BestMinimum();
1152 selectedMax = stats.BestMaximum();
1153 } else if (minMaxIndex == 2) {
1154 // Absolute
1155 selectedMin = stats.Minimum();
1156 selectedMax = stats.Maximum();
1157 } else if (minMaxIndex == 3) {
1158 // Chebyshev
1159 selectedMin = stats.ChebyshevMinimum();
1160 selectedMax = stats.ChebyshevMaximum();
1161 }
1162
1163 QString qMin = QString::number(selectedMin);
1164 QString qMax = QString::number(selectedMax);
1165
1166 // Set the min/max text
1167 m_stretchMinEdit->setText(qMin);
1168 m_stretchMaxEdit->setText(qMax);
1169 }
1170
1171
1177 if(m_advancedStretch->isVisible()) return;
1178
1179 if(cubeViewport()) {
1181 m_advancedStretch->show();
1182 }
1183 updateTool();
1184 }
1185
1186
1192 CubeViewport *cvp = cubeViewport();
1193 if(cvp == NULL) return;
1194
1195 stretchGlobal(cvp);
1196 }
1197
1198
1203 CubeViewport *cvp = cubeViewport();
1204 if(cvp == NULL) return;
1205
1206 cvp->forgetStretches();
1207 stretchGlobal(cvp);
1208 }
1209
1210
1216 cvp->stretchKnownGlobal();
1218 }
1219
1220
1226 for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
1227 CubeViewport *cvp = cubeViewportList()->at(i);
1228
1229 stretchGlobal(cvp);
1230 }
1231 }
1232
1233
1239 CubeViewport *cvp = cubeViewport();
1240 if(cvp == NULL) return;
1241
1242 stretchRegional(cvp);
1243 }
1244
1250 try {
1251 QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
1252
1253 stretchRect(cvp, rect);
1254 }
1255 catch (IException &e) {
1256 QString message = "Cannot stretch while the cube is still loading";
1257 QMessageBox::warning((QWidget *)parent(), "Warning", message);
1258 return;
1259 }
1260 }
1261
1262
1270 CubeViewport *cvp = cubeViewport();
1271 if(cvp == NULL) return;
1272 if(!rubberBandTool()->isValid()) return;
1273
1274 QRect rubberBandRect = rubberBandTool()->rectangle();
1275 //Return if the width or height is zero
1276 if(rubberBandRect.width() == 0 || rubberBandRect.height() == 0) return;
1277
1278 stretchRect(cvp, rubberBandRect);
1279 }
1280
1281
1289 Stretch newStretch;
1290 if(cvp->isGray()) {
1291 newStretch = cvp->grayStretch();
1292 newStretch.ClearPairs();
1293 newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
1294 cvp->stretchGray(newStretch);
1295
1296 // send the stretch to any ChipViewports that want to listen
1297 *m_chipViewportStretch = newStretch;
1299 }
1300 else {
1302 newStretch = cvp->redStretch();
1303 newStretch.ClearPairs();
1304 newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
1305 cvp->stretchRed(newStretch);
1306 }
1308 newStretch = cvp->greenStretch();
1309 newStretch.ClearPairs();
1310 newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
1311 cvp->stretchGreen(newStretch);
1312 }
1314 newStretch = cvp->blueStretch();
1315 newStretch.ClearPairs();
1316 newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
1317 cvp->stretchBlue(newStretch);
1318 }
1319 if(m_stretchBand != Red && m_stretchBand != Blue &&
1322 "Unknown stretch band",
1323 _FILEINFO_);
1324 }
1325 }
1326
1328 }
1329
1330
1338 void StretchTool::mouseButtonRelease(QPoint start, Qt::MouseButton s) {
1339 CubeViewport *cvp = cubeViewport();
1340 if(cvp == NULL) return;
1341
1342 // Call the parent Tool function to reset the Warning as different activity is
1343 // taking place
1344 Tool::mouseButtonRelease(start, s);
1345
1346 if(s == Qt::RightButton) {
1347 stretchGlobal(cvp);
1348
1349 // notify any ChipViewports listening that the CubeViewport was stretched
1350 // back to global
1351 emit stretchChipViewport(NULL, cvp);
1352
1353 // Resets the RubberBandTool on screen.
1355 }
1356 }
1357
1363 rubberBandTool()->enable(RubberBandTool::RectangleMode);
1364 rubberBandTool()->setDrawActiveViewportOnly(true);
1365 }
1366
1367
1374 CubeViewport *cvp = cubeViewport();
1375 if(cvp == NULL) return;
1376
1377 double min = m_stretchMinEdit->text().toDouble();
1378 double max = m_stretchMaxEdit->text().toDouble();
1379
1380 Stretch stretch;
1381 if(cvp->isGray()) {
1382 stretch = cvp->grayStretch();
1383 stretch.ClearPairs();
1384 stretch.AddPair(min, 0.0);
1385 stretch.AddPair(max, 255.0);
1386 }
1387 else if(m_stretchBand == Red) {
1388 stretch = cvp->redStretch();
1389 stretch.ClearPairs();
1390 stretch.AddPair(min, 0.0);
1391 stretch.AddPair(max, 255.0);
1392 cvp->stretchGreen(stretch);
1393 cvp->stretchBlue(stretch);
1394 }
1395 else if(m_stretchBand == Green) {
1396 stretch = cvp->greenStretch();
1397 stretch.ClearPairs();
1398 stretch.AddPair(min, 0.0);
1399 stretch.AddPair(max, 255.0);
1400 cvp->stretchRed(stretch);
1401 cvp->stretchBlue(stretch);
1402 }
1403 else if(m_stretchBand == Blue) {
1404 stretch = cvp->blueStretch();
1405 stretch.ClearPairs();
1406 stretch.AddPair(min, 0.0);
1407 stretch.AddPair(max, 255.0);
1408 cvp->stretchRed(stretch);
1409 cvp->stretchGreen(stretch);
1410 }
1411 else {
1412 return;
1413 }
1414
1415 cvp->setAllBandStretches(stretch);
1416 }
1417
1418
1425 CubeViewport *thisViewport = cubeViewport();
1426
1427 if(thisViewport == NULL) return;
1428
1429 for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
1430 CubeViewport *cvp = cubeViewportList()->at(i);
1431
1432 if(thisViewport->isGray() && cvp->isGray()) {
1433 Stretch newStretch(cvp->grayStretch());
1434 newStretch.CopyPairs(thisViewport->grayStretch());
1435 cvp->stretchGray(newStretch);
1436 }
1437 else if(!thisViewport->isGray() && !cvp->isGray()) {
1438 Stretch newStretchRed(cvp->redStretch());
1439 newStretchRed.CopyPairs(thisViewport->redStretch());
1440 cvp->stretchRed(newStretchRed);
1441
1442 Stretch newStretchGreen(cvp->greenStretch());
1443 newStretchGreen.CopyPairs(thisViewport->greenStretch());
1444 cvp->stretchGreen(newStretchGreen);
1445
1446 Stretch newStretchBlue(cvp->blueStretch());
1447 newStretchBlue.CopyPairs(thisViewport->blueStretch());
1448 cvp->stretchBlue(newStretchBlue);
1449 }
1450 else if(!thisViewport->isGray() && cvp->isGray()) {
1451 // don't copy rgb to gray
1452 }
1453 else if(thisViewport->isGray() && !cvp->isGray()) {
1454 // don't copy gray stretches to rgb
1455 }
1456 }
1457
1459 }
1460
1461
1469 //Get the statistics and histogram from the region
1470 Statistics stats = statsFromBuffer(buffer, rect);
1471 Stretch stretch;
1472 if(stats.ValidPixels() > 1 &&
1473 fabs(stats.Minimum() - stats.Maximum()) > DBL_EPSILON) {
1474 Histogram hist = histFromBuffer(buffer, rect,
1475 stats.BestMinimum(), stats.BestMaximum());
1476
1477 if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1478 stretch.AddPair(hist.Percent(0.5), 0.0);
1479 stretch.AddPair(hist.Percent(99.5), 255.0);
1480 }
1481 }
1482
1483 if(stretch.Pairs() == 0) {
1484 stretch.AddPair(-DBL_MAX, 0.0);
1485 stretch.AddPair(DBL_MAX, 255.0);
1486 }
1487
1488 return stretch;
1489 }
1490
1491
1499
1500 int bandNum = cvp->grayBand();
1501 Stretch stretch = cvp->grayStretch();
1502 if(band == Red) {
1503 bandNum = cvp->redBand();
1504 stretch = cvp->redStretch();
1505 }
1506 else if(band == Green) {
1507 bandNum = cvp->greenBand();
1508 stretch = cvp->greenStretch();
1509 }
1510 else if(band == Blue) {
1511 bandNum = cvp->blueBand();
1512 stretch = cvp->blueStretch();
1513 }
1514
1515 Statistics stats = statsFromCube(cvp->cube(), bandNum);
1516 Histogram hist = histFromCube(cvp->cube(), bandNum,
1517 stats.BestMinimum(), stats.BestMaximum());
1518
1519 stretch.ClearPairs();
1520 if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1521 stretch.AddPair(hist.Percent(0.5), 0.0);
1522 stretch.AddPair(hist.Percent(99.5), 255.0);
1523 }
1524 else {
1525 stretch.AddPair(-DBL_MAX, 0.0);
1526 stretch.AddPair(DBL_MAX, 255.0);
1527 }
1528
1529 return stretch;
1530 }
1531
1542 Statistics stats;
1543 Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1544
1545 for(int line = 0; line < cube->lineCount(); line++) {
1546 brick.SetBasePosition(0, line, band);
1547 cube->read(brick);
1548 stats.AddData(brick.DoubleBuffer(), cube->sampleCount());
1549 }
1550
1551 return stats;
1552 }
1553
1554
1565 QRect rect) {
1566 if(buffer->working()) {
1568 "Cannot stretch while the cube is still loading",
1569 _FILEINFO_);
1570 }
1571
1572 QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1573 Statistics stats;
1574
1575 for(int y = dataArea.top();
1576 !dataArea.isNull() && y <= dataArea.bottom();
1577 y++) {
1578 const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1579
1580 for(int x = dataArea.left(); x < dataArea.right(); x++) {
1581 stats.AddData(line[x - buffer->bufferXYRect().left()]);
1582 }
1583 }
1584
1585 return stats;
1586 }
1587
1600 double min, double max) {
1601 Histogram hist(min, max);
1602 Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1603
1604 for(int line = 0; line < cube->lineCount(); line++) {
1605 brick.SetBasePosition(0, line, band);
1606 cube->read(brick);
1607 hist.AddData(brick.DoubleBuffer(), cube->sampleCount());
1608 }
1609
1610 return hist;
1611 }
1612
1613
1622 Statistics stats = statsFromBuffer(buffer, buffer->bufferXYRect());
1623 return histFromBuffer(buffer, buffer->bufferXYRect(),
1624 stats.BestMinimum(), stats.BestMaximum());
1625
1626 }
1627
1628
1641 QRect rect, double min, double max) {
1642 QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1643
1644 try {
1645 Histogram hist(min, max);
1646
1647 for(int y = dataArea.top(); !dataArea.isNull() && y <= dataArea.bottom(); y++) {
1648 const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1649 hist.AddData(&line.front() + (dataArea.left() - buffer->bufferXYRect().left()), dataArea.width());
1650 }
1651
1652 return hist;
1653 }
1654 catch(IException &e) {
1655 // get the min and max DN values of the data area
1656 IString sMin(min);
1657 IString sMax(max);
1658 std::string msg = "Insufficient data Min [" + sMin + "], Max [" + sMax + "]";
1659 msg += " in the stretch area.";
1660
1661 // Emit signal to the parent tool to display Warning object with the warning message
1662 //emit warningSignal(msg, e.Errors());
1663
1664 throw IException(e, IException::Unknown, msg, _FILEINFO_);
1665 }
1666 }
1667
1668
1669
1674
1676 m_stretchBandComboBox->currentIndex()
1677 ).toInt();
1678
1679 if(m_stretchBand == All) {
1680 m_stretchMinEdit->hide();
1681 m_stretchMaxEdit->hide();
1682 }
1683 else {
1684 m_stretchMinEdit->show();
1685 m_stretchMaxEdit->show();
1686 }
1688 }
1689
1690
1805}
CubeStretch getBluStretch()
This returns the advanced stretch's stretch for blue.
void updateHistograms(const Histogram &redHist, const Histogram &grnHist, const Histogram &bluHist)
This calls setHistogram on all of the advanced stretches.
void enable(bool enable)
Sets the enabled state to enable.
void restoreGrayStretch(CubeStretch stretch)
Restores a saved grayscale stretch from the cube.
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.
void updateHistogram(const Histogram &grayHist)
This calls setHistogram on the gray advanced stretches.
void enableRgbMode(Stretch &redStretch, Histogram &redHist, Stretch &grnStretch, Histogram &grnHist, Stretch &bluStretch, Histogram &bluHist)
This displays RGB advanced stretches.
CubeStretch getGrnStretch()
This returns the advanced stretch's stretch for green.
CubeStretch getGrayStretch()
This returns the advanced stretch's stretch for gray.
CubeStretch getRedStretch()
This returns the advanced stretch's stretch for red.
bool isRgbMode() const
Returns true if the dialog is displaying the RGB advanced stretches.
bool enabled()
Returns true if the advanced stretch is enabled.
void restoreRgbStretch(CubeStretch red, CubeStretch green, CubeStretch blue)
Restores a saved RGB stretch from the cube.
void updateStretch(CubeViewport *)
This calls setStretch on all applicable advanced stretches.
void enableGrayMode(Stretch &grayStretch, Histogram &grayHist)
This displays a gray advanced stretch.
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
int sampleCount() const
Definition Cube.cpp:1813
PixelType pixelType() const
Definition Cube.cpp:1764
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition Cube.cpp:813
Stores stretch information for a cube.
Definition CubeStretch.h:27
void setBandNumber(int bandNumber)
Set the band number for the stretch.
void setName(QString name)
Set the Stretch name.
Isis::Blob toBlob() const
Serialize the CubeStretch to a Blob.
Widget to display Isis cubes for qt apps.
Container of a cube histogram.
Definition Histogram.h:74
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Adds specific functionality to C++ strings.
Definition IString.h:165
Cube display widget for certain Isis MDI applications.
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
QList< PvlObject >::iterator PvlObjectIterator
The counter for objects.
Definition PvlObject.h:229
QRect rectangle()
This method returns a rectangle from the vertices set by the RubberBandTool.
void setDrawActiveViewportOnly(bool activeOnly=false)
This called to set whether rubber band is drawn on active viewport only rather than all linked viewpo...
void enable(RubberBandMode mode, bool showIndicatorColors=false)
This is called when changing modes or turning on.
This class is used to accumulate statistics on double arrays.
Definition Statistics.h:94
Pixel value mapper.
Definition Stretch.h:58
void CopyPairs(const Stretch &other)
Copies the stretch pairs from another Stretch object, but maintains special pixel values.
Definition Stretch.cpp:392
void AddPair(const double input, const double output)
Adds a stretch pair to the list of pairs.
Definition Stretch.cpp:48
double Input(const int index) const
Returns the value of the input side of the stretch pair at the specified index.
Definition Stretch.cpp:287
void ClearPairs()
Clears the stretch pairs.
Definition Stretch.h:170
int Pairs() const
Returns the number of stretch pairs.
Definition Stretch.h:162
void showAdvancedDialog()
This methods shows and updates the advanced dialog.
QAction * m_stretchGlobal
Global stretch action.
QComboBox * m_stretchBandComboBox
Stretch combo box.
QAction * m_stretchRegional
Regional stretch action.
void updateAdvStretchDialogforAll(void)
Update the streches and corresponding histograms for all the colors Red, Green and Blue for Stretch A...
void stretchRect(CubeViewport *cvp, QRect rect)
stretch the specified CubeViewport with the given rect
static Statistics statsFromBuffer(ViewportBuffer *buffer, QRect rect)
This method will calculate and return the statistics for a given region and viewport buffer.
void stretchGlobal()
Does a global stretch for the active viewport.
QAction * m_copyBands
Copy band stretch action.
void setStretchAcrossBands()
Sets the stretch for all the bands in the active viewport to the current stretch.
void stretchRegional()
Does a regional stretch for the active viewport.
QToolButton * m_copyButton
Copy Button.
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.
void screenPixelsChanged()
This is called when the visible area changes.
Stretch * m_preGlobalStretches
Stretches before global button pressed.
StretchBand m_stretchBand
Current stretch band.
QLineEdit * m_stretchMaxEdit
Max. line edit.
StretchBand
Enum to store the bands.
Definition StretchTool.h:96
@ Gray
Gray Band.
Definition StretchTool.h:97
@ Green
Green Band.
Definition StretchTool.h:99
@ Blue
Blue Band.
@ All
All Bands.
void rubberBandComplete()
This method is called when the RubberBandTool is complete.
QLineEdit * m_stretchMinEdit
Min. line edit.
static Statistics statsFromCube(Cube *cube, int band)
This method will calculate and return the statistics for a given cube and band.
void stretchRequested(MdiCubeViewport *cvp, int bandId)
The cube viewport requested a stretch at this time, give it to the viewport.
~StretchTool()
Destructor.
static Histogram histFromBuffer(ViewportBuffer *buffer)
Given a viewport buffer, this calculates a histogram.
QAction * toolPadAction(ToolPad *pad)
Adds the stretch action to the toolpad.
StretchTool(QWidget *parent)
StretchTool constructor.
void updateHistograms()
This updates the visible histograms in the advanced stretch, if present.
QComboBox * p_minMaxTypeSelection
Min/Max type combo box.
void deleteFromCube()
Deletes a saved stretch from the cube.
void addTo(QMenu *menu)
Adds the stretch action to the given menu.
void setCubeViewport(CubeViewport *)
This updates the advanced stretch to use the given viewport.
void enableRubberBandTool()
This method enables the RubberBandTool.
QToolButton * m_globalButton
Global Button.
void stretchChanged()
This method is called when the stretch has changed and sets the min/max text fields to the correct va...
void changeStretch()
This method is called when the stretch has changed and sets the min/max text fields to the correct va...
void stretchGlobalAllViewports()
Does a global stretch for all the viewports.
Stretch * m_chipViewportStretch
ChipViewport's stretch.
void mouseButtonRelease(QPoint p, Qt::MouseButton s)
This method will call a global stretch if the right mouse button is released.
static Stretch stretchBuffer(ViewportBuffer *buffer, QRect rect)
This method computes the stretch over a region using the viewport buffer.
void setStretchAllViewports()
Sets the stretch for all the viewports to the current stretch in the active viewport.
AdvancedStretchDialog * m_advancedStretch
The advanced dialog.
void saveStretchToCube()
Saves a strech to the cube.
QWidget * createToolBarWidget(QStackedWidget *parent)
Creates the widget to add to the tool bar.
void stretchGlobalAllBands()
This resets the stretch across all bands.
void advancedStretchChanged()
This is called when one of the advanced stretches changed.
void updateTool()
Updates the stretch tool.
void stretchMinMaxType(CubeViewport *cvp)
Sets stretch for current band in active viewport given the min/max type selection.
void stretchChipViewport(Stretch *, CubeViewport *)
when a viewport is stretched, send the stretch and the viewport associated with it to any ChipViewpor...
void loadStretchFromCube()
Restores a saved stretch from the cube.
static Stretch stretchBand(CubeViewport *cvp, StretchBand band)
This method computes the stretch over the entire cube.
QPushButton * m_flashButton
Button to press for global stretch.
QToolButton * m_stretchRegionalButton
Regional Stretch Button.
void stretchBandChanged(int)
The selected band for stretching changed.
void warningSignal(std::string &pStr, const std::string pExStr)
Shows a warning.
Base class for the Qisis tools.
Definition Tool.h:67
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
MdiCubeViewport * cubeViewport() const
Return the current cubeviewport.
Definition Tool.h:197
QString toolIconDir() const
returns the path to the icon directory.
Definition Tool.h:113
Reads and stores visible DN values.
const std::vector< double > & getLine(int line)
Retrieves a line from the buffer.
QRect bufferXYRect()
Returns a rect, in screen pixels, of the area this buffer covers.
bool working()
This tests if queued actions exist in the viewport buffer.
This was called the Qisis MainWindow.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
int toInt(const QString &string)
Global function to convert from a string to an integer.
Definition IString.cpp:93
Namespace for the standard library.