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 QDoubleValidator *dval = new QDoubleValidator(hbox);
187 m_stretchMinEdit = new QLineEdit(hbox);
188 m_stretchMinEdit->setValidator(dval);
189 m_stretchMinEdit->setToolTip("Minimum");
190 text =
191 "<b>Function:</b> Shows the current minimum pixel value. Pixel values \
192 below minimum are shown as black. Pixel values above the maximum \
193 are shown as white or the highest intensity of red/green/blue \
194 if in color. Pixel values between the minimum and maximum are stretched \
195 linearly between black and white (or color component). \
196 <p><b>Hint:</b> You can manually edit the minimum but it must be \
197 less than the maximum.";
198 m_stretchMinEdit->setWhatsThis(text);
199 m_stretchMinEdit->setMaximumWidth(100);
200 connect(m_stretchMinEdit, SIGNAL(returnPressed()),
201 this, SLOT(changeStretch()));
202
203 m_stretchMaxEdit = new QLineEdit(hbox);
204 m_stretchMaxEdit->setValidator(dval);
205 m_stretchMaxEdit->setToolTip("Maximum");
206 text =
207 "<b>Function:</b> Shows the current maximum pixel value. Pixel values \
208 below minimum are shown as black. Pixel values above the maximum \
209 are shown as white or the highest intensity of red/green/blue \
210 if in color. Pixel values between the minimum and maximum are stretched \
211 linearly between black and white (or color component). \
212 <p><b>Hint:</b> You can manually edit the maximum but it must be \
213 greater than the minimum";
214 m_stretchMaxEdit->setWhatsThis(text);
215 m_stretchMaxEdit->setMaximumWidth(100);
216 connect(m_stretchMaxEdit, SIGNAL(returnPressed()), this, SLOT(changeStretch()));
217
218 // Create the two menus that drop down from the buttons
219 QMenu *copyMenu = new QMenu();
220 QMenu *globalMenu = new QMenu();
221
222 m_copyBands = new QAction(parent);
223 m_copyBands->setText("to All Bands");
224 connect(m_copyBands, SIGNAL(triggered(bool)), this, SLOT(setStretchAcrossBands()));
225
226 QAction *copyAll = new QAction(parent);
227 copyAll->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
228 copyAll->setText("to All Viewports");
229 connect(copyAll, SIGNAL(triggered(bool)), this, SLOT(setStretchAllViewports()));
230
231 copyMenu->addAction(copyAll);
232 copyMenu->addAction(m_copyBands);
233
234 m_copyButton = new QToolButton();
235 m_copyButton->setAutoRaise(true);
236 m_copyButton->setIconSize(QSize(22, 22));
237 m_copyButton->setIcon(QPixmap(toolIconDir() + "/copy_stretch.png"));
238 m_copyButton->setPopupMode(QToolButton::MenuButtonPopup);
239 m_copyButton->setMenu(copyMenu);
240 m_copyButton->setDefaultAction(copyAll);
241 m_copyButton->setToolTip("Copy");
242 text =
243 "<b>Function:</b> Copy the current stretch to all the \
244 active viewports. Or use the drop down menu to copy the current stretch \
245 to all the bands in the active viewport. \
246 <p><b>Hint:</b> Can reset the stretch to an automaticaly computed \
247 stretch by using the 'Reset' stretch button option. </p>";
248 m_copyButton->setWhatsThis(text);
249
250 QAction *currentView = new QAction(parent);
251 currentView->setText("Active Viewport");
252 currentView->setIcon(QPixmap(toolIconDir() + "/global_stretch.png"));
253 globalMenu->addAction(currentView);
254 connect(currentView, SIGNAL(triggered(bool)), this, SLOT(stretchGlobal()));
255
256 QAction *globalAll = new QAction(parent);
257 globalAll->setText("All Viewports");
258 globalMenu->addAction(globalAll);
259 connect(globalAll, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllViewports()));
260
261 QAction *globalBands = new QAction(parent);
262 globalBands->setText("All Bands");
263 globalMenu->addAction(globalBands);
264 connect(globalBands, SIGNAL(triggered(bool)), this, SLOT(stretchGlobalAllBands()));
265
266 m_globalButton = new QToolButton(); //basically acts as a 'reset'
267 m_globalButton->setAutoRaise(true);
268 m_globalButton->setIconSize(QSize(22, 22));
269 m_globalButton->setPopupMode(QToolButton::MenuButtonPopup);
270 m_globalButton->setMenu(globalMenu);
271 m_globalButton->setDefaultAction(currentView);
272 m_globalButton->setToolTip("Reset");
273 text =
274 "<b>Function:</b> Reset the stretch to be automatically computed "
275 "using the statisics from the entire image. Use the drop down menu "
276 "to reset the stretch for all the bands in the active viewport or "
277 "to reset the stretch for all the viewports.";
278 m_globalButton->setWhatsThis(text);
279
280 QPushButton *advancedButton = new QPushButton("Advanced");
281 connect(advancedButton, SIGNAL(clicked()), this, SLOT(showAdvancedDialog()));
282
283 m_flashButton = new QPushButton("Show Global");
284 text =
285 "<b>Function:</b> While this button is pressed down, the visible stretch "
286 "will be the automatically computed stretch using the statisics from the "
287 "entire image. The original stretch is restored once you let up on this "
288 "button.";
289 m_flashButton->setWhatsThis(text);
290 connect(m_flashButton, SIGNAL(pressed()), this, SLOT(stretchChanged()));
291 connect(m_flashButton, SIGNAL(released()), this, SLOT(stretchChanged()));
292
293 // Buttons migrated out of Advanced Stretch Tool
294 QPushButton *saveToCubeButton = new QPushButton("Save");
295 connect(saveToCubeButton, SIGNAL(clicked(bool)), this, SLOT(saveStretchToCube()));
296
297 QPushButton *deleteFromCubeButton = new QPushButton("Delete");
298 connect(deleteFromCubeButton, SIGNAL(clicked(bool)), this, SLOT(deleteFromCube()));
299
300 QPushButton *loadStretchButton = new QPushButton("Restore");
301 connect(loadStretchButton, SIGNAL(clicked(bool)), this, SLOT(loadStretchFromCube()));
302
303 QHBoxLayout *layout = new QHBoxLayout(hbox);
304 layout->setMargin(0);
305 layout->addWidget(m_copyButton);
306 layout->addWidget(m_globalButton);
307 layout->addWidget(m_stretchRegionalButton);
308 layout->addWidget(m_stretchBandComboBox);
309 layout->addWidget(m_stretchMinEdit);
310 layout->addWidget(m_stretchMaxEdit);
311 layout->addWidget(advancedButton);
312 layout->addWidget(m_flashButton);
313
314 // should only display if gray stretch
315 // Save/Restore strech only supported for Grayscale images. Hide buttons if in RGB.
316 layout->addWidget(saveToCubeButton);
317 layout->addWidget(deleteFromCubeButton);
318 layout->addWidget(loadStretchButton);
319
320 layout->addStretch(); // Pushes everything else left in the menu bar
321 hbox->setLayout(layout);
322
323 return hbox;
324 }
325
326
332 if(m_advancedStretch->isVisible()) {
334
335 if(!cvp) return;
336
337 if(cvp->isGray() && !cvp->grayBuffer()->working()) {
339 updateTool();
340 }
341 else {
342 Histogram hist(histFromBuffer(cvp->grayBuffer()));
343
344 if(hist.ValidPixels() > 0) {
346 }
347 }
348 }
349 // Otherwise it is in color mode
350 else if(!cvp->isGray() &&
351 !cvp->redBuffer()->working() &&
352 !cvp->greenBuffer()->working() &&
353 !cvp->blueBuffer()->working()) {
355 updateTool();
356 }
357 else {
358 Histogram redHist(histFromBuffer(cvp->redBuffer()));
359 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
360 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
361
362 if(redHist.ValidPixels() > 0 &&
363 grnHist.ValidPixels() > 0 &&
364 bluHist.ValidPixels() > 0) {
365 m_advancedStretch->updateHistograms(redHist, grnHist, bluHist);
366 }
367 }
368 }
369 }
370 }
371
372
380 {
381 if(m_advancedStretch->isVisible()) {
383
384 if(!cvp->isGray() &&
385 !cvp->redBuffer()->working() &&
386 !cvp->greenBuffer()->working() &&
387 !cvp->blueBuffer()->working()) {
388
389 Histogram redHist(histFromBuffer(cvp->redBuffer()));
390 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
391 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
392 Stretch redStretch(cvp->redStretch());
393 Stretch grnStretch(cvp->greenStretch());
394 Stretch bluStretch(cvp->blueStretch());
395
396 m_advancedStretch->updateForRGBMode(redStretch, redHist,
397 grnStretch, grnHist,
398 bluStretch, bluHist);
399 }
400 }
401 }
402
403
409 Cube* icube = cvp->cube();
410 Pvl* lab = icube->label();
411
412 QStringList namelist;
413
414 // Create a list of existing Stretch names
415 if (cvp->isGray()) {
417 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
418 if (objIter->name() == "Stretch") {
419 PvlKeyword tempKeyword = objIter->findKeyword("Name");
420 int bandNumber = int(objIter->findKeyword("BandNumber"));
421 if (cvp->grayBand() == bandNumber) {
422 QString tempName = tempKeyword[0];
423 namelist.append(tempName);
424 }
425 }
426 }
427 }
428 else {
429 int redBandNumber = cvp->redBand();
430 int greenBandNumber = cvp->greenBand();
431 int blueBandNumber = cvp->blueBand();
432
433 QMap<QString, QList<int>> tempNameMap;
435 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
436 if (objIter->name() == "Stretch") {
437 PvlKeyword tempKeyword = objIter->findKeyword("Name");
438 int bandNumber = int(objIter->findKeyword("BandNumber"));
439 if (bandNumber == redBandNumber || bandNumber == greenBandNumber
440 || bandNumber == blueBandNumber) {
441 QString tempName = tempKeyword[0];
442 if (tempNameMap.contains(tempName)) {
443 tempNameMap[tempName].append(bandNumber);
444 }
445 else
446 {
447 tempNameMap[tempName] = {bandNumber};
448 }
449 }
450 }
451 }
452 QMap<QString, QList<int>>::const_iterator i = tempNameMap.constBegin();
453 while (i != tempNameMap.constEnd()) {
454 if (i.value().contains(redBandNumber) && i.value().contains(greenBandNumber) &&
455 i.value().contains(blueBandNumber) ){
456 namelist.append(i.key());
457 }
458 ++i;
459 }
460 }
461
462 bool ok = false;
463 QString stretchName;
464 // Only display load stretch dialog if there are stretches saved to the cube
465 if (namelist.size() >=1) {
466 stretchName = QInputDialog::getItem((QWidget *)parent(), tr("Load Stretch"),
467 tr("Name of Stretch to Load:"), namelist, 0,
468 false, &ok);
469 }
470 else {
471 QMessageBox::information((QWidget *)parent(), "Information",
472 "There are no saved stretches to restore.");
473 }
474
475 if (ok) {
476 if (cvp->isGray()) {
477 CubeStretch cubeStretch = icube->readCubeStretch(stretchName);
478 if (m_advancedStretch->isVisible()) {
480 }
481 // Get the current cube stretche and copy the new stretch pairs over so that the
482 // special pixel values set in the viewport are maintained.
483 CubeStretch grayOriginal = cvp->grayStretch();
484 grayOriginal.CopyPairs(cubeStretch);
485 cvp->stretchGray(grayOriginal);
486 }
487 else {
488 std::vector<PvlKeyword> keywordValueRed;
489 keywordValueRed.push_back(PvlKeyword("BandNumber", QString::number(cvp->redBand())));
490
491 std::vector<PvlKeyword> keywordValueGreen;
492 keywordValueGreen.push_back(PvlKeyword("BandNumber", QString::number(cvp->greenBand())));
493
494 std::vector<PvlKeyword> keywordValueBlue;
495 keywordValueBlue.push_back(PvlKeyword("BandNumber", QString::number(cvp->blueBand())));
496
497 CubeStretch redStretch = icube->readCubeStretch(stretchName, keywordValueRed);
498 CubeStretch greenStretch = icube->readCubeStretch(stretchName, keywordValueGreen);
499 CubeStretch blueStretch = icube->readCubeStretch(stretchName, keywordValueBlue);
500
501 if (m_advancedStretch->isVisible()) {
502 m_advancedStretch->restoreRgbStretch(redStretch, greenStretch, blueStretch);
503 }
504
505 // Get the current cube stretches and copy the new stretch pairs over so that the
506 // special pixel values set in the viewport are maintained.
507 CubeStretch redOriginal = cvp->redStretch();
508 CubeStretch greenOriginal = cvp->greenStretch();
509 CubeStretch blueOriginal = cvp->blueStretch();
510
511 redOriginal.CopyPairs(redStretch);
512 greenOriginal.CopyPairs(greenStretch);
513 blueOriginal.CopyPairs(blueStretch);
514
515 cvp->stretchRed(redOriginal);
516 cvp->stretchGreen(greenOriginal);
517 cvp->stretchBlue(blueOriginal);
518 }
519 emit stretchChanged();
520 }
521 }
522
523
529 Cube* icube = cvp->cube();
530 Pvl* lab = icube->label();
531
532 // Create a list of existing Stretch names
533 QStringList namelist;
535 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
536 if (objIter->name() == "Stretch") {
537 PvlKeyword tempKeyword = objIter->findKeyword("Name");
538 int bandNumber = int(objIter->findKeyword("BandNumber"));
539 if (cvp->grayBand() == bandNumber) {
540 QString tempName = tempKeyword[0];
541 namelist.append(tempName);
542 }
543 }
544 }
545
546 bool ok = false;
547 QString toDelete;
548 // Only display list of stretches to delete if there are stretches saved to the cube
549 if (namelist.size() >= 1) {
550 toDelete = QInputDialog::getItem((QWidget *)parent(), tr("Delete Stretch"),
551 tr("Name of Stretch to Delete:"), namelist, 0,
552 false, &ok);
553 }
554 else {
555 QMessageBox::information((QWidget *)parent(), "Information",
556 "There are no saved stretches to delete.");
557 }
558
559 if (ok) {
560 if (icube->isReadOnly()) {
561 try {
562 cvp->cube()->reopen("rw");
563 }
564 catch(IException &) {
565 cvp->cube()->reopen("r");
566 QMessageBox::information((QWidget *)parent(), "Error",
567 "Cannot open cube read/write to delete stretch");
568 return;
569 }
570 }
571
572 bool cubeDeleted = icube->deleteBlob(toDelete, "Stretch");
573
574 if (!cubeDeleted) {
575 QMessageBox msgBox;
576 msgBox.setText("Stretch Could Not Be Deleted!");
577 msgBox.setInformativeText("A stretch with name: \"" + toDelete +
578 "\" Could not be found, so there was nothing to delete from the Cube.");
579 msgBox.setStandardButtons(QMessageBox::Ok);
580 msgBox.setIcon(QMessageBox::Critical);
581 msgBox.exec();
582 }
583
584 // Don't leave open rw -- not optimal.
585 cvp->cube()->reopen("r");
586 }
587 }
588
589
595 Cube* icube = cvp->cube();
596 Pvl* lab = icube->label();
597
598 // Create a list of existing Stretch names
599 QStringList namelist;
601 for (objIter=lab->beginObject(); objIter<lab->endObject(); objIter++) {
602 if (objIter->name() == "Stretch") {
603 PvlKeyword tempKeyword = objIter->findKeyword("Name");
604 QString tempName = tempKeyword[0];
605 namelist.append(tempName);
606 }
607 }
608
609 bool ok;
610 QString name;
611
612 //
613 // At this time, it is NOT possible to save an RGB stretch with the same band number
614 // multiple times, if the saved stretch for each is different. If the saved stretch is the same
615 // this is okay.
616 //
617 // For example, r=1, g=1, b=1, with the same stretch for each is okay
618 // r=1, g=1, b=2, where the stretches for band 1 are the same, is okay
619 // r=1, g=1, b=1, where the the stretches for band 1 are different (red stretch !=
620 // green stretch)
621 //
622 if (!cvp->isGray()) {
623 CubeStretch redStretch, greenStretch, blueStretch;
624 if (m_advancedStretch->isVisible()) {
625 redStretch = m_advancedStretch->getRedStretch();
626 greenStretch = m_advancedStretch->getGrnStretch();
627 blueStretch = m_advancedStretch->getBluStretch();
628 }
629 else {
630 redStretch = cvp->redStretch();
631 greenStretch = cvp->greenStretch();
632 blueStretch = cvp->blueStretch();
633 }
634
635 int redBand = cvp->redBand();
636 int greenBand = cvp->greenBand();
637 int blueBand = cvp->blueBand();
638
639 if (((redBand == greenBand) && !(redStretch == greenStretch)) ||
640 ((redBand == blueBand) && !(redBand == blueBand)) ||
641 ((greenBand == blueBand) && !(greenBand == blueBand))) {
642 QMessageBox::information((QWidget *)parent(), "Error", "Sorry, cannot save RGB stretches which include the same band multiple times, but have different stretches for each");
643 return;
644 }
645 }
646
647 // "Get the name for the stretch" dialog
648 QString text = QInputDialog::getText(m_advancedStretch, tr("Save Stretch"),
649 tr("Enter a name to save the stretch as:"), QLineEdit::Normal,
650 "stretch", &ok);
651
652 if (ok) {
653 // Stretch Name Already Exists Dialog!
654 if (namelist.contains(text)) {
655 QMessageBox msgBox;
656 msgBox.setText(tr("Stretch Name Already Exists!"));
657 msgBox.setInformativeText("A stretch pair with name: \"" + text + "\" already exists and "
658 "the existing saved data will be overwritten. Are you sure you "
659 "wish to proceed?");
660 msgBox.setStandardButtons(QMessageBox::Save | QMessageBox::Cancel);
661 msgBox.setIcon(QMessageBox::Warning);
662 msgBox.setDefaultButton(QMessageBox::Cancel);
663 int ret = msgBox.exec();
664
665 switch (ret) {
666 case QMessageBox::Save:
667 break;
668 case QMessageBox::Cancel:
669 // Cancel was clicked, exit this function
670 return;
671 break;
672 default:
673 // should never be reached
674 return;
675 break;
676 }
677 }
678
679 if (icube->isReadOnly()) {
680 // reOpen cube as read/write
681 try {
682 icube->reopen("rw");
683 }
684 catch(IException &) {
685 icube->reopen("r");
686 QMessageBox::information((QWidget *)parent(), "Error", "Cannot open cube read/write to save stretch");
687 return;
688 }
689 }
690
691 // If gray, only one stretch to save
692 if (cvp->isGray()) {
693 CubeStretch stretch;
694 if (m_advancedStretch->isVisible()) {
696 }
697 else {
698 stretch = cvp->grayStretch();
699 }
700
701 // Write single stretch to cube
702 stretch.setName(text);
703 stretch.setBandNumber(cvp->grayBand());
704
705 // Overwrite an existing stretch with the same name if it exists. The user was warned
706 // and decided to overwrite.
707 icube->write(stretch);
708 }
709 else {
710 CubeStretch redStretch, greenStretch, blueStretch;
711 if (m_advancedStretch->isVisible()) {
712 redStretch = m_advancedStretch->getRedStretch();
713 greenStretch = m_advancedStretch->getGrnStretch();
714 blueStretch = m_advancedStretch->getBluStretch();
715 }
716 else {
717 redStretch = cvp->redStretch();
718 greenStretch = cvp->greenStretch();
719 blueStretch = cvp->blueStretch();
720 }
721
722 redStretch.setName(text);
723 redStretch.setBandNumber(cvp->redBand());
724 Blob stretchBlob = redStretch.toBlob();
725 icube->write(stretchBlob, false);
726
727 greenStretch.setName(text);
728 greenStretch.setBandNumber(cvp->greenBand());
729 stretchBlob = greenStretch.toBlob();
730 icube->write(stretchBlob, false);
731
732 blueStretch.setName(text);
733 blueStretch.setBandNumber(cvp->blueBand());
734 stretchBlob = blueStretch.toBlob();
735 icube->write(stretchBlob, false);
736 }
737
738 // Don't leave open rw -- not optimal.
739 cvp->cube()->reopen("r");
740 }
741 }
742
743
750
751
758 if(m_advancedStretch->isVisible()) {
760 //If the viewport is in gray mode
761 if(cvp->isGray() && !cvp->grayBuffer()->working()) {
762 Histogram hist(histFromBuffer(cvp->grayBuffer()));
763 Stretch stretch(cvp->grayStretch());
764 m_advancedStretch->enableGrayMode(stretch, hist);
765 }
766 //Otherwise it is in color mode
767 else if(!cvp->isGray() &&
768 !cvp->redBuffer()->working() &&
769 !cvp->greenBuffer()->working() &&
770 !cvp->blueBuffer()->working()) {
771 Histogram redHist(histFromBuffer(cvp->redBuffer()));
772 Histogram grnHist(histFromBuffer(cvp->greenBuffer()));
773 Histogram bluHist(histFromBuffer(cvp->blueBuffer()));
774 Stretch redStretch(cvp->redStretch());
775 Stretch grnStretch(cvp->greenStretch());
776 Stretch bluStretch(cvp->blueStretch());
777 m_advancedStretch->enableRgbMode(redStretch, redHist,
778 grnStretch, grnHist,
779 bluStretch, bluHist);
780 }
781 else {
783 }
784 }
785 else {
787 }
788 }
789
790
796 CubeViewport *cvp = cubeViewport();
797
798 if(cvp == NULL) {
799 //If the current viewport is NULL and the advanced dialog is visible, hide it
800 if(m_advancedStretch->isVisible()) {
801 m_advancedStretch->hide();
802 }
803 }
804 else {
805 if(!m_advancedStretch->enabled() ||
806 m_advancedStretch->isRgbMode() != !cvp->isGray()) {
807 setCubeViewport(cvp);
808 }
809 }
810
811 if(cvp && cvp->isGray()) {
812 m_copyBands->setEnabled(true);
813 m_stretchBandComboBox->setVisible(false);
814 m_stretchMinEdit->show();
815 m_stretchMaxEdit->show();
816 }
817 else if(cvp) {
818 m_copyBands->setEnabled(true);
819 m_stretchBandComboBox->setVisible(true);
821 }
822 else {
823 m_copyBands->setEnabled(false);
824 m_stretchBandComboBox->setVisible(false);
825 }
826
827 if(m_advancedStretch->isVisible()) {
828 m_stretchMinEdit->setEnabled(false);
829 m_stretchMaxEdit->setEnabled(false);
830 }
831 else {
832 m_stretchMinEdit->setEnabled(true);
833 m_stretchMaxEdit->setEnabled(true);
834 }
835
838 }
839
840
849 // Yeah this is a hack... but it's necessary to make this tool
850 // do anything while its not the active tool.
851 connect(cvp, SIGNAL(screenPixelsChanged()), this, SLOT(updateHistograms()));
852 QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
853
854 if(bandId == (int)Gray) {
855 if(cvp->grayBuffer() && cvp->grayBuffer()->hasEntireCube()) {
856 Stretch newStretch = cvp->grayStretch();
857 newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
858 cvp->stretchGray(newStretch);
859 }
860 else {
861 Stretch newStretch = stretchBand(cvp, (StretchBand)bandId);
862 cvp->stretchGray(newStretch);
863 }
864 }
865 else
866 {
867 if(bandId == (int)Red || bandId == (int)All) {
868 if(cvp->redBuffer() && cvp->redBuffer()->hasEntireCube()) {
869 Stretch newStretch = cvp->redStretch();
870 newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
871 cvp->stretchRed(newStretch);
872 }
873 else {
874 Stretch newStretch = stretchBand(cvp, Red);
875 cvp->stretchRed(newStretch);
876 }
877 }
878 if(bandId == (int)Green || bandId == (int)All) {
879 if(cvp->greenBuffer() && cvp->greenBuffer()->hasEntireCube()) {
880 Stretch newStretch = cvp->greenStretch();
881 newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
882 cvp->stretchGreen(newStretch);
883 }
884 else {
885 Stretch newStretch = stretchBand(cvp, Green);
886 cvp->stretchGreen(newStretch);
887 }
888 }
889 if(bandId == (int)Blue || bandId == (int)All) {
890 if(cvp->blueBuffer() && cvp->blueBuffer()->hasEntireCube()) {
891 Stretch newStretch = cvp->blueStretch();
892 newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
893 cvp->stretchBlue(newStretch);
894 }
895 else {
896 Stretch newStretch = stretchBand(cvp, Blue);
897 cvp->stretchBlue(newStretch);
898 }
899 }
900 }
902 }
903
904
912 if(cvp == NULL) return;
913
914 if(m_flashButton->isDown()) {
917 m_preGlobalStretches[0] = cvp->grayStretch();
918 m_preGlobalStretches[1] = cvp->redStretch();
919 m_preGlobalStretches[2] = cvp->greenStretch();
920 m_preGlobalStretches[3] = cvp->blueStretch();
921 }
922
923 cvp->stretchKnownGlobal();
924 return;
925 }
926 else if(m_preGlobalStretches) {
927 if(cvp->isGray()) {
928 cvp->stretchGray(m_preGlobalStretches[0]);
929 }
930 else {
931 cvp->stretchRed(m_preGlobalStretches[1]);
932 cvp->stretchGreen(m_preGlobalStretches[2]);
933 cvp->stretchBlue(m_preGlobalStretches[3]);
934 }
935
936 delete [] m_preGlobalStretches;
938 }
939
940 double min = 0, max = 0;
941 //If the viewport is in gray mode
942 if(cvp->isGray()) {
943 //Get the min/max from the current stretch
944 Stretch stretch = cvp->grayStretch();
945 min = stretch.Input(0);
946 max = stretch.Input(stretch.Pairs() - 1);
947 }
948
949 //Otherwise it is in color mode
950 else {
951 Stretch rstretch = cvp->redStretch();
952 Stretch gstretch = cvp->greenStretch();
953 Stretch bstretch = cvp->blueStretch();
954
955 //Get the min/max from the current stretch
956 if(m_stretchBand == Red) {
957 min = rstretch.Input(0);
958 max = rstretch.Input(rstretch.Pairs() - 1);
959 }
960 else if(m_stretchBand == Green) {
961 min = gstretch.Input(0);
962 max = gstretch.Input(gstretch.Pairs() - 1);
963 }
964 else if(m_stretchBand == Blue) {
965 min = bstretch.Input(0);
966 max = bstretch.Input(bstretch.Pairs() - 1);
967 }
968 }
969
970 //Set the min/max text fields
971 if(m_stretchBand != All || cvp->isGray()) {
972 QString strMin;
973 strMin.setNum(min);
974 m_stretchMinEdit->setText(strMin);
975
976 QString strMax;
977 strMax.setNum(max);
978 m_stretchMaxEdit->setText(strMax);
979 }
980
981 if(m_advancedStretch->isVisible()) {
982 if(m_stretchBand == All){
984 }
986 }
987 }
988
989
995 CubeViewport *cvp = cubeViewport();
996 if(cvp == NULL) return;
997
999 Stretch grayStretch = cvp->grayStretch();
1000 grayStretch.ClearPairs();
1002 cvp->stretchGray(grayStretch);
1003
1004 // send the stretch to any ChipViewports that want to listen
1005 *m_chipViewportStretch = grayStretch;
1007 }
1008 else {
1009 Stretch redStretch = cvp->redStretch();
1010 redStretch.ClearPairs();
1012 cvp->stretchRed(redStretch);
1013
1014 Stretch grnStretch = cvp->greenStretch();
1015 grnStretch.ClearPairs();
1016 grnStretch.CopyPairs(m_advancedStretch->getGrnStretch());
1017 cvp->stretchGreen(grnStretch);
1018
1019 Stretch bluStretch = cvp->blueStretch();
1020 bluStretch.ClearPairs();
1021 bluStretch.CopyPairs(m_advancedStretch->getBluStretch());
1022 cvp->stretchBlue(bluStretch);
1023 }
1025 }
1026
1027
1036 if(cvp == NULL) return;
1037
1038 // Make sure the user didn't enter bad min/max and if so fix it
1039 double min = m_stretchMinEdit->text().toDouble();
1040 double max = m_stretchMaxEdit->text().toDouble();
1041
1042 if(min >= max || m_stretchMinEdit->text() == "" ||
1043 m_stretchMaxEdit->text() == "") {
1044 updateTool();
1045 return;
1046 }
1047
1048 //The viewport is in gray mode
1049 if(cvp->isGray()) {
1050 Stretch stretch = cvp->grayStretch();
1051 stretch.ClearPairs();
1052 stretch.AddPair(min, 0.0);
1053 stretch.AddPair(max, 255.0);
1054
1055 // send the stretch to any ChipViewports that want to listen
1056 *m_chipViewportStretch = stretch;
1058
1059 cvp->stretchGray(stretch);
1060 }
1061 //Otherwise the viewport is in color mode
1062 else {
1063 Stretch redStretch = cvp->redStretch();
1064 Stretch greenStretch = cvp->greenStretch();
1065 Stretch blueStretch = cvp->blueStretch();
1066
1067 if(m_stretchBand == Red) {
1068 redStretch.ClearPairs();
1069 redStretch.AddPair(min, 0.0);
1070 redStretch.AddPair(max, 255.0);
1071 }
1072 if(m_stretchBand == Green) {
1073 greenStretch.ClearPairs();
1074 greenStretch.AddPair(min, 0.0);
1075 greenStretch.AddPair(max, 255.0);
1076 }
1077 if(m_stretchBand == Blue) {
1078 blueStretch.ClearPairs();
1079 blueStretch.AddPair(min, 0.0);
1080 blueStretch.AddPair(max, 255.0);
1081 }
1082
1083 cvp->stretchRed(redStretch);
1084 cvp->stretchGreen(greenStretch);
1085 cvp->stretchBlue(blueStretch);
1086 }
1087
1089 }
1090
1091
1097 if(m_advancedStretch->isVisible()) return;
1098
1099 if(cubeViewport()) {
1101 m_advancedStretch->show();
1102 }
1103 updateTool();
1104 }
1105
1106
1112 CubeViewport *cvp = cubeViewport();
1113 if(cvp == NULL) return;
1114
1115 stretchGlobal(cvp);
1116 }
1117
1118
1123 CubeViewport *cvp = cubeViewport();
1124 if(cvp == NULL) return;
1125
1126 cvp->forgetStretches();
1127 stretchGlobal(cvp);
1128 }
1129
1130
1136 cvp->stretchKnownGlobal();
1138 }
1139
1140
1146 for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
1147 CubeViewport *cvp = cubeViewportList()->at(i);
1148
1149 stretchGlobal(cvp);
1150 }
1151 }
1152
1153
1159 CubeViewport *cvp = cubeViewport();
1160 if(cvp == NULL) return;
1161
1162 stretchRegional(cvp);
1163 }
1164
1170 try {
1171 QRect rect(0, 0, cvp->viewport()->width(), cvp->viewport()->height());
1172
1173 stretchRect(cvp, rect);
1174 }
1175 catch (IException &e) {
1176 QString message = "Cannot stretch while the cube is still loading";
1177 QMessageBox::warning((QWidget *)parent(), "Warning", message);
1178 return;
1179 }
1180 }
1181
1182
1190 CubeViewport *cvp = cubeViewport();
1191 if(cvp == NULL) return;
1192 if(!rubberBandTool()->isValid()) return;
1193
1194 QRect rubberBandRect = rubberBandTool()->rectangle();
1195 //Return if the width or height is zero
1196 if(rubberBandRect.width() == 0 || rubberBandRect.height() == 0) return;
1197
1198 stretchRect(cvp, rubberBandRect);
1199 }
1200
1201
1209 Stretch newStretch;
1210 if(cvp->isGray()) {
1211 newStretch = cvp->grayStretch();
1212 newStretch.ClearPairs();
1213 newStretch.CopyPairs(stretchBuffer(cvp->grayBuffer(), rect));
1214 cvp->stretchGray(newStretch);
1215
1216 // send the stretch to any ChipViewports that want to listen
1217 *m_chipViewportStretch = newStretch;
1219 }
1220 else {
1222 newStretch = cvp->redStretch();
1223 newStretch.ClearPairs();
1224 newStretch.CopyPairs(stretchBuffer(cvp->redBuffer(), rect));
1225 cvp->stretchRed(newStretch);
1226 }
1228 newStretch = cvp->greenStretch();
1229 newStretch.ClearPairs();
1230 newStretch.CopyPairs(stretchBuffer(cvp->greenBuffer(), rect));
1231 cvp->stretchGreen(newStretch);
1232 }
1234 newStretch = cvp->blueStretch();
1235 newStretch.ClearPairs();
1236 newStretch.CopyPairs(stretchBuffer(cvp->blueBuffer(), rect));
1237 cvp->stretchBlue(newStretch);
1238 }
1239 if(m_stretchBand != Red && m_stretchBand != Blue &&
1242 "Unknown stretch band",
1243 _FILEINFO_);
1244 }
1245 }
1246
1248 }
1249
1250
1258 void StretchTool::mouseButtonRelease(QPoint start, Qt::MouseButton s) {
1259 CubeViewport *cvp = cubeViewport();
1260 if(cvp == NULL) return;
1261
1262 // Call the parent Tool function to reset the Warning as different activity is
1263 // taking place
1264 Tool::mouseButtonRelease(start, s);
1265
1266 if(s == Qt::RightButton) {
1267 stretchGlobal(cvp);
1268
1269 // notify any ChipViewports listening that the CubeViewport was stretched
1270 // back to global
1271 emit stretchChipViewport(NULL, cvp);
1272
1273 // Resets the RubberBandTool on screen.
1275 }
1276 }
1277
1283 rubberBandTool()->enable(RubberBandTool::RectangleMode);
1284 rubberBandTool()->setDrawActiveViewportOnly(true);
1285 }
1286
1287
1294 CubeViewport *cvp = cubeViewport();
1295 if(cvp == NULL) return;
1296
1297 double min = m_stretchMinEdit->text().toDouble();
1298 double max = m_stretchMaxEdit->text().toDouble();
1299
1300 Stretch stretch;
1301 if(cvp->isGray()) {
1302 stretch = cvp->grayStretch();
1303 stretch.ClearPairs();
1304 stretch.AddPair(min, 0.0);
1305 stretch.AddPair(max, 255.0);
1306 }
1307 else if(m_stretchBand == Red) {
1308 stretch = cvp->redStretch();
1309 stretch.ClearPairs();
1310 stretch.AddPair(min, 0.0);
1311 stretch.AddPair(max, 255.0);
1312 cvp->stretchGreen(stretch);
1313 cvp->stretchBlue(stretch);
1314 }
1315 else if(m_stretchBand == Green) {
1316 stretch = cvp->greenStretch();
1317 stretch.ClearPairs();
1318 stretch.AddPair(min, 0.0);
1319 stretch.AddPair(max, 255.0);
1320 cvp->stretchRed(stretch);
1321 cvp->stretchBlue(stretch);
1322 }
1323 else if(m_stretchBand == Blue) {
1324 stretch = cvp->blueStretch();
1325 stretch.ClearPairs();
1326 stretch.AddPair(min, 0.0);
1327 stretch.AddPair(max, 255.0);
1328 cvp->stretchRed(stretch);
1329 cvp->stretchGreen(stretch);
1330 }
1331 else {
1332 return;
1333 }
1334
1335 cvp->setAllBandStretches(stretch);
1336 }
1337
1338
1345 CubeViewport *thisViewport = cubeViewport();
1346
1347 if(thisViewport == NULL) return;
1348
1349 for(int i = 0; i < (int)cubeViewportList()->size(); i++) {
1350 CubeViewport *cvp = cubeViewportList()->at(i);
1351
1352 if(thisViewport->isGray() && cvp->isGray()) {
1353 Stretch newStretch(cvp->grayStretch());
1354 newStretch.CopyPairs(thisViewport->grayStretch());
1355 cvp->stretchGray(newStretch);
1356 }
1357 else if(!thisViewport->isGray() && !cvp->isGray()) {
1358 Stretch newStretchRed(cvp->redStretch());
1359 newStretchRed.CopyPairs(thisViewport->redStretch());
1360 cvp->stretchRed(newStretchRed);
1361
1362 Stretch newStretchGreen(cvp->greenStretch());
1363 newStretchGreen.CopyPairs(thisViewport->greenStretch());
1364 cvp->stretchGreen(newStretchGreen);
1365
1366 Stretch newStretchBlue(cvp->blueStretch());
1367 newStretchBlue.CopyPairs(thisViewport->blueStretch());
1368 cvp->stretchBlue(newStretchBlue);
1369 }
1370 else if(!thisViewport->isGray() && cvp->isGray()) {
1371 // don't copy rgb to gray
1372 }
1373 else if(thisViewport->isGray() && !cvp->isGray()) {
1374 // don't copy gray stretches to rgb
1375 }
1376 }
1377
1379 }
1380
1381
1389 //Get the statistics and histogram from the region
1390 Statistics stats = statsFromBuffer(buffer, rect);
1391 Stretch stretch;
1392 if(stats.ValidPixels() > 1 &&
1393 fabs(stats.Minimum() - stats.Maximum()) > DBL_EPSILON) {
1394 Histogram hist = histFromBuffer(buffer, rect,
1395 stats.BestMinimum(), stats.BestMaximum());
1396
1397 if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1398 stretch.AddPair(hist.Percent(0.5), 0.0);
1399 stretch.AddPair(hist.Percent(99.5), 255.0);
1400 }
1401 }
1402
1403 if(stretch.Pairs() == 0) {
1404 stretch.AddPair(-DBL_MAX, 0.0);
1405 stretch.AddPair(DBL_MAX, 255.0);
1406 }
1407
1408 return stretch;
1409 }
1410
1411
1419
1420 int bandNum = cvp->grayBand();
1421 Stretch stretch = cvp->grayStretch();
1422 if(band == Red) {
1423 bandNum = cvp->redBand();
1424 stretch = cvp->redStretch();
1425 }
1426 else if(band == Green) {
1427 bandNum = cvp->greenBand();
1428 stretch = cvp->greenStretch();
1429 }
1430 else if(band == Blue) {
1431 bandNum = cvp->blueBand();
1432 stretch = cvp->blueStretch();
1433 }
1434
1435 Statistics stats = statsFromCube(cvp->cube(), bandNum);
1436 Histogram hist = histFromCube(cvp->cube(), bandNum,
1437 stats.BestMinimum(), stats.BestMaximum());
1438
1439 stretch.ClearPairs();
1440 if(fabs(hist.Percent(0.5) - hist.Percent(99.5)) > DBL_EPSILON) {
1441 stretch.AddPair(hist.Percent(0.5), 0.0);
1442 stretch.AddPair(hist.Percent(99.5), 255.0);
1443 }
1444 else {
1445 stretch.AddPair(-DBL_MAX, 0.0);
1446 stretch.AddPair(DBL_MAX, 255.0);
1447 }
1448
1449 return stretch;
1450 }
1451
1462 Statistics stats;
1463 Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1464
1465 for(int line = 0; line < cube->lineCount(); line++) {
1466 brick.SetBasePosition(0, line, band);
1467 cube->read(brick);
1468 stats.AddData(brick.DoubleBuffer(), cube->sampleCount());
1469 }
1470
1471 return stats;
1472 }
1473
1474
1485 QRect rect) {
1486 if(buffer->working()) {
1488 "Cannot stretch while the cube is still loading",
1489 _FILEINFO_);
1490 }
1491
1492 QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1493 Statistics stats;
1494
1495 for(int y = dataArea.top();
1496 !dataArea.isNull() && y <= dataArea.bottom();
1497 y++) {
1498 const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1499
1500 for(int x = dataArea.left(); x < dataArea.right(); x++) {
1501 stats.AddData(line[x - buffer->bufferXYRect().left()]);
1502 }
1503 }
1504
1505 return stats;
1506 }
1507
1520 double min, double max) {
1521 Histogram hist(min, max);
1522 Brick brick(cube->sampleCount(), 1, 1, cube->pixelType());
1523
1524 for(int line = 0; line < cube->lineCount(); line++) {
1525 brick.SetBasePosition(0, line, band);
1526 cube->read(brick);
1527 hist.AddData(brick.DoubleBuffer(), cube->sampleCount());
1528 }
1529
1530 return hist;
1531 }
1532
1533
1542 Statistics stats = statsFromBuffer(buffer, buffer->bufferXYRect());
1543 return histFromBuffer(buffer, buffer->bufferXYRect(),
1544 stats.BestMinimum(), stats.BestMaximum());
1545
1546 }
1547
1548
1561 QRect rect, double min, double max) {
1562 QRect dataArea = QRect(buffer->bufferXYRect().intersected(rect));
1563
1564 try {
1565 Histogram hist(min, max);
1566
1567 for(int y = dataArea.top(); !dataArea.isNull() && y <= dataArea.bottom(); y++) {
1568 const std::vector<double> &line = buffer->getLine(y - buffer->bufferXYRect().top());
1569 hist.AddData(&line.front() + (dataArea.left() - buffer->bufferXYRect().left()), dataArea.width());
1570 }
1571
1572 return hist;
1573 }
1574 catch(IException &e) {
1575 // get the min and max DN values of the data area
1576 IString sMin(min);
1577 IString sMax(max);
1578 std::string msg = "Insufficient data Min [" + sMin + "], Max [" + sMax + "]";
1579 msg += " in the stretch area.";
1580
1581 // Emit signal to the parent tool to display Warning object with the warning message
1582 //emit warningSignal(msg, e.Errors());
1583
1584 throw IException(e, IException::Unknown, msg, _FILEINFO_);
1585 }
1586 }
1587
1588
1589
1594
1596 m_stretchBandComboBox->currentIndex()
1597 ).toInt();
1598
1599 if(m_stretchBand == All) {
1600 m_stretchMinEdit->hide();
1601 m_stretchMaxEdit->hide();
1602 }
1603 else {
1604 m_stretchMinEdit->show();
1605 m_stretchMaxEdit->show();
1606 }
1608 }
1609
1610
1725}
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.
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 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.