Isis 3 Programmer Reference
CubeViewport.cpp
1
7/* SPDX-License-Identifier: CC0-1.0 */
8
9#include "CubeViewport.h"
10
11#include <iomanip>
12#include <iostream>
13#include <QApplication>
14#include <QClipboard>
15#include <QCloseEvent>
16#include <QCursor>
17#include <QDebug>
18#include <QIcon>
19#include <QPen>
20#include <QPainter>
21#include <QFileInfo>
22#include <QMessageBox>
23#include <QMouseEvent>
24#include <QRgb>
25#include <QScrollBar>
26#include <QString>
27#include <QTimer>
28
29#include "Brick.h"
30#include "Camera.h"
31#include "CubeDataThread.h"
32#include "IException.h"
33#include "IString.h"
34#include "FileName.h"
35#include "Histogram.h"
36#include "Pvl.h"
37#include "PvlGroup.h"
38#include "PvlKeyword.h"
39#include "PvlObject.h"
40#include "Stretch.h"
41#include "CubeStretch.h"
42#include "StretchTool.h"
43#include "Tool.h"
44#include "UniversalGroundMap.h"
45#include "ViewportBuffer.h"
46
47
48using namespace std;
49
50
51namespace Isis {
60 QWidget *parent) : QAbstractScrollArea(parent) {
61 // Is the cube usable?
62 if(cube == NULL) {
64 "Can not view NULL cube pointer",
65 _FILEINFO_);
66 }
67 else if(!cube->isOpen()) {
69 "Can not view unopened cube",
70 _FILEINFO_);
71 }
72
73 p_cube = cube;
74 p_cubeData = NULL;
75
76 if (cubeData)
77 {
78 p_cubeData = cubeData;
79 p_thisOwnsCubeData = false;
81 }
82 else
83 {
85 p_thisOwnsCubeData = true;
87 }
88
89 if(p_cube->hasGroup("Tracking")) {
91 }
92 else {
93 p_trackingCube = NULL;
94 }
95
96
97 connect(p_cubeData, SIGNAL(BrickChanged(int, const Isis::Brick *)),
98 this, SLOT(cubeDataChanged(int, const Isis::Brick *)));
99 connect(this, SIGNAL(doneWithData(int, const Isis::Brick *)),
100 p_cubeData, SLOT(DoneWithData(int, const Isis::Brick *)));
101
103
104 void doneWithData(int, const Brick *);
105
106 // Set up the scroll area
107 setAttribute(Qt::WA_DeleteOnClose);
108 setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
109 setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
110 viewport()->setObjectName("viewport");
111 viewport()->setCursor(QCursor(Qt::CrossCursor));
112 viewport()->installEventFilter(this);
113 viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
114
115 setAttribute(Qt::WA_NoSystemBackground);
116 setFrameShadow(QFrame::Plain);
117 setFrameShape(QFrame::NoFrame);
118 setAutoFillBackground(false);
119
120// viewport()->setAttribute(Qt::WA_NoSystemBackground);
121// viewport()->setAttribute(Qt::WA_PaintOnScreen,false);
122
123 p_saveEnabled = false;
124 // Save off info about the cube
125 p_scale = -1.0;
126 p_color = false;
127
128
129 setCaption();
130
131 p_redBrick = new Brick(4, 1, 1, cube->pixelType());
132 p_grnBrick = new Brick(4, 1, 1, cube->pixelType());
133 p_bluBrick = new Brick(4, 1, 1, cube->pixelType());
134 p_gryBrick = new Brick(4, 1, 1, cube->pixelType());
135 p_pntBrick = new Brick(4, 1, 1, cube->pixelType());
136
137 p_paintPixmap = false;
138 p_image = NULL;
139 p_cubeShown = true;
140 p_updatingBuffers = false;
141
142 //updateScrollBars(1,1);
143
144 p_groundMap = NULL;
145 p_projection = NULL;
146 p_camera = NULL;
147
148 // Setup a universal ground map
149 try {
151 }
152 catch(IException &) {
153 }
154
155 if(p_groundMap != NULL) {
156 // Setup the camera or the projection
157 if(p_groundMap->Camera() != NULL) {
159 if(p_camera->HasProjection()) {
160 try {
162 }
163 catch(IException &) {
164 }
165 }
166 }
167 else {
169 }
170 }
171
172
173 // Setup context sensitive help
174 QString cubeFileName = p_cube->fileName();
175 p_whatsThisText = QString("<b>Function: </b>Viewport to ") + cubeFileName;
176
178 "<p><b>Cube Dimensions:</b> \
179 <blockQuote>Samples = " +
180 QString::number(cube->sampleCount()) + "<br>" +
181 "Lines = " +
182 QString::number(cube->lineCount()) + "<br>" +
183 "Bands = " +
184 QString::number(cube->bandCount()) + "</blockquote></p>";
185
186 /*setting up the qlist of CubeBandsStretch objs.
187 for( int b = 0; b < p_cube->bandCount(); b++) {
188 CubeBandsStretch *stretch = new CubeBandsStretch();
189 p_bandsStretchList.push_back(stretch);
190 }*/
191
193 p_grayBuffer->enable(false);
195
196 p_redBuffer = NULL;
197 p_greenBuffer = NULL;
198 p_blueBuffer = NULL;
199 p_pixmapPaintRects = NULL;
200
201 p_pixmapPaintRects = new QList<QRect *>();
202 p_progressTimer = new QTimer();
203 p_progressTimer->setInterval(250);
204
205 p_knownStretches = new QVector< Stretch * >();
206 p_globalStretches = new QVector< Stretch * >();
207
208 while(p_cube->bandCount() > p_knownStretches->size()) {
209 p_knownStretches->push_back(NULL);
210 p_globalStretches->push_back(NULL);
211 }
212
213 connect(p_progressTimer, SIGNAL(timeout()), this, SLOT(onProgressTimer()));
214
215 p_bgColor = Qt::black;
216
217 p_comboCount = 0;
218 p_comboIndex = 0;
219
220 p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
221 }
222
223
232 void CubeViewport::showEvent(QShowEvent *event) {
233 if(p_scale == -1) {
234 // This doesn't equal fitScale() ... causes misalignment in qview initial
235 // view versus zoomFit
236 //double sampScale = (double) sizeHint().width() / (double) cubeSamples();
237 //double lineScale = (double) sizeHint().height() / (double) cubeLines();
238 //double scale = sampScale < lineScale ? sampScale : lineScale;
239
240 setScale(fitScale(), cubeSamples() / 2.0 + 0.5, cubeLines() / 2.0 + 0.5);
241 }
242
244 p_grayBuffer->enable(true);
245
246 // gives a proper initial stretch (entire cube)
248 }
249
250 QAbstractScrollArea::show();
251
252 p_paintPixmap = true;
253
254 paintPixmap();
255 }
256
257
263 double progress = 0.0;
264 bool completed = false;
265
266 if(p_grayBuffer) {
267 progress += p_grayBuffer->currentProgress();
268 completed = !p_grayBuffer->working();
269 }
270
271 if(p_redBuffer) {
272 progress += p_redBuffer->currentProgress() / 3.0;
273 completed = !p_redBuffer->working();
274 }
275
276 if(p_greenBuffer) {
277 progress += p_greenBuffer->currentProgress() / 3.0;
278 completed = completed && !p_greenBuffer->working();
279 }
280
281 if(p_blueBuffer) {
282 progress += p_blueBuffer->currentProgress() / 3.0;
283 completed = completed && !p_blueBuffer->working();
284 }
285
286 int realProgress = (int)(progress * 100.0);
287
288 if(completed) {
289 realProgress = 100;
290 p_progressTimer->stop();
291 emit progressComplete();
292 emit screenPixelsChanged();
293 }
294 else if(realProgress == 100) {
295 realProgress = 99;
296 }
297
298 emit progressChanged(realProgress);
299 }
300
301
307 if(p_redBrick) {
308 delete p_redBrick;
309 p_redBrick = NULL;
310 }
311
312 if(p_grnBrick) {
313 delete p_grnBrick;
314 p_grnBrick = NULL;
315 }
316
317 if(p_bluBrick) {
318 delete p_bluBrick;
319 p_bluBrick = NULL;
320 }
321
322 if(p_gryBrick) {
323 delete p_gryBrick;
324 p_gryBrick = NULL;
325 }
326
327 if(p_pntBrick) {
328 delete p_pntBrick;
329 p_pntBrick = NULL;
330 }
331
332 if(p_groundMap) {
333 delete p_groundMap;
334 p_groundMap = NULL;
335 }
336
337 if(p_grayBuffer) {
338 delete p_grayBuffer;
339 p_grayBuffer = NULL;
340 }
341
342 if(p_redBuffer) {
343 delete p_redBuffer;
344 p_redBuffer = NULL;
345 }
346
347 if(p_greenBuffer) {
348 delete p_greenBuffer;
349 p_greenBuffer = NULL;
350 }
351
352 if(p_blueBuffer) {
353 delete p_blueBuffer;
354 p_blueBuffer = NULL;
355 }
356
357 // p_cubeData MUST be deleted AFTER all viewport buffers!!!
358 if(p_cubeData) {
360
362 delete p_cubeData;
363
364 p_cubeData = NULL;
365 }
366
367 p_cube = NULL;
368
369 delete p_trackingCube;
370 p_trackingCube = NULL;
371
372 if(p_progressTimer) {
373 delete p_progressTimer;
374 p_progressTimer = NULL;
375 }
376
377 if(p_image) {
378 delete p_image;
379 p_image = NULL;
380 }
381
383 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
384 delete(*p_pixmapPaintRects)[rect];
385 }
386
387 delete p_pixmapPaintRects;
388 p_pixmapPaintRects = NULL;
389 }
390
391 if(p_knownStretches) {
392 for(int stretch = 0; stretch < p_knownStretches->size(); stretch ++) {
393 if((*p_knownStretches)[stretch] != NULL) {
394 delete(*p_knownStretches)[stretch];
395 (*p_knownStretches)[stretch] = NULL;
396 }
397 }
398
399 p_knownStretches->clear();
400
401 delete p_knownStretches;
402 p_knownStretches = NULL;
403 }
404
406 for(int stretch = 0; stretch < p_globalStretches->size(); stretch ++) {
407 if((*p_globalStretches)[stretch] != NULL) {
408 delete(*p_globalStretches)[stretch];
409 (*p_globalStretches)[stretch] = NULL;
410 }
411 }
412
413 p_globalStretches->clear();
414
415 delete p_globalStretches;
416 p_globalStretches = NULL;
417 }
418 }
419
426 p_cube = cube;
427 setCaption();
428 }
429
430
433 return p_cube->sampleCount();
434 }
435
436
439 return p_cube->lineCount();
440 }
441
442
445 return p_cube->bandCount();
446 }
447
448
456 void CubeViewport::cubeDataChanged(int cubeId, const Brick *data) {
457 if(cubeId == p_cubeId) {
458 double ss, sl, es, el;
459 ss = data->Sample();
460 sl = data->Line();
461 es = data->Sample() + data->SampleDimension();
462 el = data->Line() + data->LineDimension();
463 if(ss < 0.5){
464 ss = 0.5;
465 }
466 if(sl < 0.5){
467 sl = 0.5;
468 }
469 if(es > cube()->sampleCount() + 0.5){
470 es = cube()->sampleCount() + 0.5;
471 }
472 if(el > cube()->lineCount() + 0.5){
473 el = cube()->lineCount() + 0.5;
474 }
475
476 int sx, sy, ex, ey;
477
478 cubeToViewport(ss, sl, sx, sy);
479 cubeToViewport(es, el, ex, ey);
480 if(sx < 0){
481 sx = 0;
482 }
483 if(sy < 0){
484 sy = 0;
485 }
486 if(ex > viewport()->width()){
487 ex = viewport()->width();
488 }
489 if(ey > viewport()->height()){
490 ey = viewport()->height();
491 }
492 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
493
494 p_updatingBuffers = true;
495 if(p_grayBuffer){
496 p_grayBuffer->fillBuffer(vpRect, data);
497 }
498 if(p_redBuffer){
499 p_redBuffer->fillBuffer(vpRect, data);
500 }
501 if(p_greenBuffer){
502 p_greenBuffer->fillBuffer(vpRect, data);
503 }
504 if(p_blueBuffer){
505 p_blueBuffer->fillBuffer(vpRect, data);
506 }
507 p_updatingBuffers = false;
508
510 }
511
512 emit doneWithData(cubeId, data);
513 }
514
515
525 bool canClose = true;
526 if(p_saveEnabled) {
527 // Enter == button 0, Escape == button 2
528 switch(QMessageBox::information(this, tr("Confirm Save"),
529 tr("The cube [<font color='red'>%1</font>] contains unsaved changes. "
530 "Do you want to save the changes before exiting?").arg(cube()->fileName()),
531 QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) {
532 //Save changes and close viewport
533 case QMessageBox::Save:
534 emit saveChanges(this);
535 break;
536
537 //Discard changes and close viewport
538 case QMessageBox::Discard:
539 emit discardChanges(this);
540 break;
541
542 //Cancel, don't close viewport
543 case QMessageBox::Cancel:
544 default:
545 canClose = false;
546 break;
547 }
548 }
549
550// if (canClose) emit viewportClosed(this);
551 return canClose;
552 }
553
560 void CubeViewport::cubeChanged(bool changed) {
561 p_saveEnabled = changed;
562 }
563
571 QSize s(512, 512);
572 return s;
573 }
574
575
587 void CubeViewport::setScale(double scale) {
588 // Sanitize the scale value
589 if (scale == p_scale){
590 return;
591 }
592
593 if (viewport()->width() && viewport()->height()) {
594 // don't let zoom scale be larger than the viewport size
595 double maxScale = max(viewport()->width(),viewport()->height());
596 if (scale > maxScale) {
597 scale = maxScale;
598 }
599 // don't let zoom scale be smaller than one pixel high/wide showing
600 double minScale = 1.0 / (min(cubeSamples(),cubeLines()));
601 if (scale < minScale) {
602 scale = minScale;
603 }
604 }
605
606 // Resize the scrollbars to reflect the new scale
607 double samp, line;
608 contentsToCube(horizontalScrollBar()->value(), verticalScrollBar()->value(),
609 samp, line);
610 p_scale = scale;
611 updateScrollBars(1, 1); // Setting to 1,1 make sure we don't have bad values
612
613 // Now update the scroll bar value to the old line/sample
614 int x, y;
615 cubeToContents(samp, line, x, y);
616 updateScrollBars(x, y);
617
618 p_updatingBuffers = true;
619 if (p_grayBuffer){
621 }
622 if (p_redBuffer){
624 }
625 if (p_greenBuffer){
627 }
628 if (p_blueBuffer){
630 }
631 p_updatingBuffers = false;
632
634
635 // Notify other tools about the scale change
636 emit scaleChanged();
637
638 // Update the display
639 setCaption();
640 paintPixmap(); // Will get rid of old data in the display
641
642 viewport()->repaint();
643 emit screenPixelsChanged();
644 }
645
654 void CubeViewport::setScale(double scale, int x, int y) {
655 double samp, line;
656 viewportToCube(x, y, samp, line);
657 setScale(scale, samp, line);
658 }
659
660
670 void CubeViewport::setScale(double scale, double sample, double line) {
671 viewport()->setUpdatesEnabled(false);
672
673 bool wasEnabled = false;
674
675 if ((p_grayBuffer && p_grayBuffer->enabled()) ||
677 wasEnabled = true;
678 }
679
680 if (p_grayBuffer){
681 p_grayBuffer->enable(false);
682 }
683 if (p_redBuffer){
684 p_redBuffer->enable(false);
685 }
686 if (p_greenBuffer){
687 p_greenBuffer->enable(false);
688 }
689 if (p_blueBuffer){
690 p_blueBuffer->enable(false);
691 }
692 if (p_paintPixmap) {
693 p_paintPixmap = false;
695 p_paintPixmap = true;
696 }
697 else {
699 }
700 center(sample, line);
701
702 if (p_grayBuffer){
703 p_grayBuffer->enable(wasEnabled);
704 }
705 if (p_redBuffer){
706 p_redBuffer->enable(wasEnabled);
707 }
708 if (p_greenBuffer){
709 p_greenBuffer->enable(wasEnabled);
710 }
711 if (p_blueBuffer){
712 p_blueBuffer->enable(wasEnabled);
713 }
714
715 paintPixmap();
716 viewport()->setUpdatesEnabled(true);
717 viewport()->update();
718 emit screenPixelsChanged();
719 }
720
721
729 void CubeViewport::center(int x, int y) {
730 double sample, line;
731 viewportToCube(x, y, sample, line);
732 center(sample, line);
733 }
734
735
742 void CubeViewport::center(double sample, double line) {
743 int x, y;
744 cubeToContents(sample, line, x, y);
745
746 int panX = horizontalScrollBar()->value() - x;
747 int panY = verticalScrollBar()->value() - y;
748
749 updateScrollBars(x, y);
750
751 p_updatingBuffers = true;
752 if(p_grayBuffer){
753 p_grayBuffer->pan(panX, panY);
754 }
755 if(p_redBuffer){
756 p_redBuffer->pan(panX, panY);
757 }
758 if(p_greenBuffer){
759 p_greenBuffer->pan(panX, panY);
760 }
761 if(p_blueBuffer){
762 p_blueBuffer->pan(panX, panY);
763 }
764 p_updatingBuffers = false;
765
767
768 shiftPixmap(panX, panY);
769
770 emit screenPixelsChanged();
771 }
772
773
779 for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
781 }
782
783 p_pixmapPaintRects->clear();
784 }
785
786
798 double &sample, double &line) const {
799 sample = x / p_scale;
800 line = y / p_scale;
801 }
802
803
815 double &sample, double &line) const {
816 x += horizontalScrollBar()->value();
817 x -= viewport()->width() / 2;
818 y += verticalScrollBar()->value();
819 y -= viewport()->height() / 2;
820 contentsToCube(x, y, sample, line);
821 }
822
823
834 void CubeViewport::cubeToContents(double sample, double line,
835 int &x, int &y) const {
836 x = (int)(sample * p_scale + 0.5);
837 y = (int)(line * p_scale + 0.5);
838 }
839
840
851 void CubeViewport::cubeToViewport(double sample, double line,
852 int &x, int &y) const {
853 cubeToContents(sample, line, x, y);
854 x -= horizontalScrollBar()->value();
855 x += viewport()->width() / 2;
856 y -= verticalScrollBar()->value();
857 y += viewport()->height() / 2;
858 }
859
860
868 void CubeViewport::scrollBy(int dx, int dy) {
869 // Make sure we don't generate bad values outside of the scroll range
870 int x = horizontalScrollBar()->value() + dx;
871 if(x <= 1) {
872 dx = 1 - horizontalScrollBar()->value();
873 }
874 else if(x >= horizontalScrollBar()->maximum()) {
875 dx = horizontalScrollBar()->maximum() - horizontalScrollBar()->value();
876 }
877
878 // Make sure we don't generate bad values outside of the scroll range
879 int y = verticalScrollBar()->value() + dy;
880 if(y <= 1) {
881 dy = 1 - verticalScrollBar()->value();
882 }
883 else if(y >= verticalScrollBar()->maximum()) {
884 dy = verticalScrollBar()->maximum() - verticalScrollBar()->value();
885 }
886
887 // Do we do anything?
888 if((dx == 0) && (dy == 0)){
889 return;
890 }
891
892 // We do so update the scroll bars
893 updateScrollBars(horizontalScrollBar()->value() + dx,
894 verticalScrollBar()->value() + dy);
895
896 // Scroll the the pixmap
897 scrollContentsBy(-dx, -dy);
898 }
899
900
908 void CubeViewport::scrollContentsBy(int dx, int dy) {
909
910 // We shouldn't do anything if scrollbars are being updated
911 if(viewport()->signalsBlocked()) {
912 return;
913 }
914
915 // Tell the buffers to update appropriate for the pan and upon completion
916 // they will call bufferUpdated. We don't want bufferUpdated to happen
917 // until afterwards. If only shrinking and no new data then the viewport
918 // buffers will complete immediately. When all buffers don't have their
919 // appropriate actions queued bufferUpdated can't succeed.
920
921 // Also block paints because we'll repaint it all when we're done
922 // telling each buffer about the pan.
923 bool panQueued = false;
924 QRect bufferXYRect;
925
926 p_updatingBuffers = true;
927
928 if(p_grayBuffer) {
929 p_grayBuffer->pan(dx, dy);
930 panQueued |= p_grayBuffer->working();
931 bufferXYRect = p_grayBuffer->bufferXYRect();
932 }
933
934 if(p_redBuffer) {
935 p_redBuffer->pan(dx, dy);
936 panQueued |= p_redBuffer->working();
937 bufferXYRect = p_redBuffer->bufferXYRect();
938 }
939
940 if(p_greenBuffer) {
941 p_greenBuffer->pan(dx, dy);
942 panQueued |= p_greenBuffer->working();
943 }
944
945 if(p_blueBuffer) {
946 p_blueBuffer->pan(dx, dy);
947 panQueued |= p_blueBuffer->working();
948 }
949
950 p_updatingBuffers = false;
951
952 // shift the pixmap by x,y if the viewport buffer didn't do it immediately
953 if(panQueued) {
954 shiftPixmap(dx, dy);
955 }
956 else {
957 // Need to do this to clear area outside of cube
958 p_pixmapPaintRects->clear();
959 paintPixmap();
960 }
961
962 viewport()->update();
963 emit screenPixelsChanged();
964 }
965
966
972 if(!p_progressTimer->isActive()) {
973 p_progressTimer->start();
974
975 emit progressChanged(0);
976 }
977 }
978
979
985 QString cubeFileName = p_cube->fileName();
986 QString str = QFileInfo(cubeFileName).fileName();
987 str += QString(" @ ");
988 str += QString::number(p_scale * 100.0);
989 str += QString("% ");
990
991 if(p_color) {
992 str += QString("(RGB = ");
993 str += QString::number(p_red.band);
994 str += QString(",");
995 str += QString::number(p_green.band);
996 str += QString(",");
997 str += QString::number(p_blue.band);
998 str += QString(")");
999 }
1000 else {
1001 str += QString("(Gray = ");
1002 str += QString::number(p_gray.band);
1003 str += QString(")");
1004 }
1005
1006 //If changes have been made make sure to add '*' to the end
1007 if(p_saveEnabled) {
1008 str += "*";
1009 }
1010
1011 parentWidget()->setWindowTitle(str);
1012 emit windowTitleChanged();
1013 }
1014
1015
1022 void CubeViewport::resizeEvent(QResizeEvent *e) {
1023 p_paintPixmap = false;
1024
1025 // Tell the buffers to update their coefficients to reinitialize
1026 // and have their immediate paint events happen afterwards. Should not
1027 // happen, but if buffers have actions complete immediately and call
1028 // bufferUpdated. We don't want to have bufferUpdated ever when all
1029 // buffers don't have their appropriate actions queued. It can't succeed.
1030 p_updatingBuffers = true;
1031 if(p_grayBuffer){
1033 }
1034 if(p_redBuffer){
1036 }
1037 if(p_greenBuffer){
1039 }
1040 if(p_blueBuffer){
1042 }
1043 p_updatingBuffers = false;
1044
1046
1047 // Change the size of the image and pixmap
1048 if(p_image) {
1049 delete p_image;
1050 p_image = NULL;
1051 }
1052
1053 p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
1054 p_pixmap = QPixmap(viewport()->size());
1055
1056 p_paintPixmap = true;
1057
1058 // Fixup the scroll bars
1059 updateScrollBars(horizontalScrollBar()->value(),
1060 verticalScrollBar()->value());
1061
1063 "<p><b>Viewport Dimensions:</b> \
1064 <blockQuote>Samples = " +
1065 QString::number(viewport()->width()) + "<br>" +
1066 "Lines = " +
1067 QString::number(viewport()->height()) + "</blockquote></p>";
1068
1069 // Repaint the pixmap
1070 paintPixmap();
1071
1072 // Repaint the internal viewport and scroll bars
1073 viewport()->update();
1074 emit screenPixelsChanged();
1075 }
1076
1077
1088 void CubeViewport::paintEvent(QPaintEvent *e) {
1089 if(!p_cubeShown || !viewport()->isVisible()){
1090 return;
1091 }
1092 }
1093
1094
1104 paintPixmap(rect);
1105
1106 // Don't repaint from buffer updates if any buffers are working...
1107 // This set of statements fixes a flash of black when in RGB mode
1108 // and a pan (or other operation?) completes. What would happen is
1109 // the first would reset to black then other buffers still working so
1110 // not restored to DN values.
1112 return;
1113 }
1115 return;
1116 }
1118 return;
1119 }
1121 return;
1122 }
1123
1124 viewport()->repaint(rect);
1125 }
1126
1129 QRect rect(0, 0, p_image->width(), p_image->height());
1130 paintPixmap(rect);
1131 }
1132
1133
1140 void CubeViewport::paintPixmap(QRect rect) {
1141 if(!p_paintPixmap) {
1142 return;
1143 }
1144
1145 if(p_updatingBuffers) {
1146 p_pixmapPaintRects->push_back(new QRect(rect));
1147 return;
1148 }
1149
1150 if(p_pixmap.isNull()){
1151 return;
1152 }
1153
1154 QPainter p(&p_pixmap);
1155
1156 p.fillRect(rect, QBrush(p_bgColor));
1157
1158 QRect dataArea;
1159
1161 if(p_grayBuffer->working()){
1162 return;
1163 }
1164
1165 dataArea = QRect(p_grayBuffer->bufferXYRect().intersected(rect));
1166
1167 for(int y = dataArea.top();
1168 !dataArea.isNull() && y <= dataArea.bottom();
1169 y++) {
1170 const vector< double > & line =
1172
1173 if(line.size() == 0) {
1174 break;
1175 }
1176
1177 if(y >= p_image->height()) {
1178 throw IException(IException::Programmer, "y too big", _FILEINFO_);
1179 }
1180
1181 QRgb *rgb = (QRgb *) p_image->scanLine(y);
1182
1186
1187 for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1188 int bufferLeft = p_grayBuffer->bufferXYRect().left();
1189 int bufferX = x - bufferLeft;
1190
1191 if(bufferX >= (int)line.size()){
1192 break;
1193 }
1194
1195 if(bufferX < 0) {
1196 throw IException(IException::Programmer, "bufferX < 0", _FILEINFO_);
1197 }
1198
1199 if(x >= p_image->width()) {
1200 throw IException(IException::Programmer, "x too big", _FILEINFO_);
1201 }
1202
1203 double bufferVal = line.at(bufferX);
1204
1205 // This is still RGB; the pairs are identical but the boundary
1206 // conditions are different. Display saturations cause this.
1207 int redPix = (int)(redStretch.Map(bufferVal) + 0.5);
1208 int greenPix = (int)(greenStretch.Map(bufferVal) + 0.5);
1209 int bluePix = (int)(blueStretch.Map(bufferVal) + 0.5);
1210 rgb[x] = qRgb(redPix, greenPix, bluePix);
1211 }
1212 }
1213 }
1214 else {
1215 if(p_redBuffer && p_redBuffer->enabled()) {
1217 p_blueBuffer->working()) {
1218 return;
1219 }
1220
1221
1222 if((p_greenBuffer->bufferXYRect().top() !=
1223 p_redBuffer->bufferXYRect().top()) ||
1224 (p_greenBuffer->bufferXYRect().top() !=
1225 p_blueBuffer->bufferXYRect().top())) {
1227 "Buffer rects mismatched",
1228 _FILEINFO_);
1229 }
1230
1231 if((p_greenBuffer->bufferXYRect().left() !=
1232 p_redBuffer->bufferXYRect().left()) ||
1233 (p_greenBuffer->bufferXYRect().left() !=
1234 p_blueBuffer->bufferXYRect().left())) {
1236 "Buffer rects mismatched",
1237 _FILEINFO_);
1238 }
1239
1240 dataArea = QRect(p_redBuffer->bufferXYRect().intersected(rect));
1241
1242 for(int y = dataArea.top();
1243 !dataArea.isNull() && y <= dataArea.bottom();
1244 y++) {
1245 int bufferLine = y - p_redBuffer->bufferXYRect().top();
1246
1247 const vector<double> &redLine = p_redBuffer->getLine(bufferLine);
1248 const vector<double> &greenLine = p_greenBuffer->getLine(bufferLine);
1249 const vector<double> &blueLine = p_blueBuffer->getLine(bufferLine);
1250
1251 if((int)redLine.size() < dataArea.width() ||
1252 (int)greenLine.size() < dataArea.width() ||
1253 (int)blueLine.size() < dataArea.width()) {
1255 "Empty buffer line",
1256 _FILEINFO_);
1257 }
1258
1259 QRgb *rgb = (QRgb *) p_image->scanLine(y);
1260
1264
1265 for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1266 int redPix = (int)(redStretch.Map(redLine[ x - p_redBuffer->bufferXYRect().left()]) + 0.5);
1267 int greenPix = (int)(greenStretch.Map(greenLine[ x - p_greenBuffer->bufferXYRect().left()]) + 0.5);
1268 int bluePix = (int)(blueStretch.Map(blueLine[ x - p_blueBuffer->bufferXYRect().left()]) + 0.5);
1269
1270 rgb[x] = qRgb(redPix, greenPix, bluePix);
1271 }
1272 }
1273 }
1274 }
1275
1276 if(!dataArea.isNull()){
1277 p.drawImage(dataArea.topLeft(), *p_image, dataArea);
1278 }
1279
1280 // Change whats this info
1282 }
1283
1284
1291 void CubeViewport::shiftPixmap(int dx, int dy) {
1292 if(!p_paintPixmap || !p_pixmap){
1293 return;
1294 }
1295
1296 // Prep to scroll the pixmap
1297 int drawStartX = dx;
1298 int pixmapStartX = 0;
1299 if(drawStartX < 0) {
1300 drawStartX = 0;
1301 pixmapStartX = -dx;
1302 }
1303
1304 int drawStartY = dy;
1305 int pixmapStartY = 0;
1306 if(dy < 0) {
1307 drawStartY = 0;
1308 pixmapStartY = -dy;
1309 }
1310
1311 // Ok we can shift the pixmap and filling
1312 int pixmapDrawWidth = p_pixmap.width() - pixmapStartX + 1;
1313 int pixmapDrawHeight = p_pixmap.height() - pixmapStartY + 1;
1314
1315 QRect rect(0, 0, p_pixmap.width(), p_pixmap.height());
1316 QPixmap pixmapCopy = p_pixmap.copy();
1317
1318 QPainter painter(&p_pixmap);
1319 painter.fillRect(rect, QBrush(p_bgColor));
1320 painter.drawPixmap(drawStartX, drawStartY,
1321 pixmapCopy,
1322 pixmapStartX, pixmapStartY,
1323 pixmapDrawWidth, pixmapDrawHeight);
1324 painter.end();
1325
1326 // Now fill in the left or right side
1327 QRect xFillRect;
1328 QRect yFillRect;
1329
1330 if(dx > 0) {
1331 xFillRect = QRect(QPoint(0, 0),
1332 QPoint(dx, p_pixmap.height()));
1333 }
1334 else {
1335 if(dx < 0){
1336 xFillRect = QRect(QPoint(p_pixmap.width() + dx, 0),
1337 QPoint(p_pixmap.width(), p_pixmap.height()));
1338 }
1339 }
1340
1341 // Fill in the top or bottom side
1342 if(dy > 0) {
1343 yFillRect = QRect(QPoint(0, 0),
1344 QPoint(p_pixmap.width(), dy));
1345 }
1346 else {
1347 if(dy < 0){
1348 yFillRect = QRect(QPoint(0, p_pixmap.height() + dy),
1349 QPoint(p_pixmap.width(), p_pixmap.height()));
1350 }
1351 }
1352
1353 if(dx != 0) {
1354 paintPixmap(xFillRect);
1355 }
1356
1357 if(dy != 0) {
1358 paintPixmap(yFillRect);
1359 }
1360
1361 viewport()->update();
1362 }
1363
1372 {
1373 // Get Cube Info
1374 PvlObject whatsThisObj = PvlObject("WhatsThis");
1375 whatsThisObj += PvlKeyword("Cube", p_cube->fileName());
1376
1377 PvlGroup cubeGrp("CubeDimensions");
1378 cubeGrp += PvlKeyword("Samples", toString(p_cube->sampleCount()));
1379 cubeGrp += PvlKeyword("Lines", toString(p_cube->lineCount()));
1380 cubeGrp += PvlKeyword("Bands", toString(p_cube->bandCount()));
1381 whatsThisObj += cubeGrp;
1382
1383 // Get Viewport Info
1384 PvlGroup viewportGrp("ViewportDimensions");
1385 viewportGrp += PvlKeyword("Samples", toString(viewport()->width()));
1386 viewportGrp += PvlKeyword("Lines", toString(viewport()->height()));
1387 whatsThisObj += viewportGrp;
1388
1389 // Get Cube area Info
1390 PvlObject cubeAreaPvl("CubeArea");
1391 PvlGroup bandGrp("Bands");
1392
1393 PvlKeyword filterName;
1394 getBandFilterName(filterName);
1395 int iFilterSize = filterName.size();
1396
1397 // color
1398 if(p_color ) {
1399 PvlKeyword virtualKey("Virtual"), physicalKey("Physical"), filterNameKey;
1400 int iRedBand = p_redBuffer->getBand();
1401 int iGreenBand = p_greenBuffer->getBand();
1402 int iBlueBand = p_blueBuffer->getBand();
1403
1404 bandGrp += PvlKeyword("Color", "RGB");
1405
1406 virtualKey = toString(iRedBand);
1407 virtualKey += toString(iGreenBand);
1408 virtualKey += toString(iBlueBand);
1409 bandGrp += virtualKey;
1410
1411 physicalKey = toString(p_cube->physicalBand(iRedBand));
1412 physicalKey += toString(p_cube->physicalBand(iGreenBand));
1413 physicalKey += toString(p_cube->physicalBand(iBlueBand));
1414 bandGrp += physicalKey;
1415
1416 if(iFilterSize) {
1417 if(iRedBand <= iFilterSize) {
1418 filterNameKey += filterName[iRedBand-1];
1419 }
1420 else {
1421 filterNameKey += "None";
1422 }
1423
1424 if(iGreenBand <= iFilterSize) {
1425 filterNameKey += filterName[iGreenBand-1];
1426 }
1427 else {
1428 filterNameKey += "None";
1429 }
1430
1431 if(iBlueBand <= iFilterSize) {
1432 filterNameKey += filterName[iBlueBand-1];
1433 }
1434 else {
1435 filterNameKey += "None";
1436 }
1437 bandGrp += filterNameKey;
1438 }
1439 }
1440 else { // gray
1441 int iGrayBand = p_grayBuffer->getBand();
1442
1443 bandGrp += PvlKeyword("Color", "Gray");
1444
1445 bandGrp += PvlKeyword("Virtual", toString(iGrayBand));
1446 bandGrp += PvlKeyword("Physical", toString(p_cube->physicalBand(iGrayBand)));
1447
1448 if(iFilterSize && iGrayBand <= iFilterSize) {
1449 bandGrp += PvlKeyword("FilterName", filterName[iGrayBand-1]);
1450 }
1451 }
1452
1453 //start, end line and sample
1454 double sl, ss, es, el;
1455 getCubeArea(ss, es, sl, el);
1456 cubeAreaPvl += PvlKeyword("StartSample", toString(int(ss + 0.5)));
1457 cubeAreaPvl += PvlKeyword("EndSample", toString(int(es + 0.5)));
1458 cubeAreaPvl += PvlKeyword("StartLine", toString(int(sl + 0.5)));
1459 cubeAreaPvl += PvlKeyword("EndLine", toString(int(el + 0.5)));
1460 cubeAreaPvl += bandGrp;
1461 whatsThisObj += cubeAreaPvl;
1462 pWhatsThisPvl += whatsThisObj;
1463 }
1464
1474 {
1475 // get the band info
1476 Pvl* cubeLbl = p_cube->label();
1477 PvlObject isisObj = cubeLbl->findObject("IsisCube");
1478 if (isisObj.hasGroup("BandBin")) {
1479 PvlGroup bandBinGrp = isisObj.findGroup("BandBin");
1480 if(bandBinGrp.hasKeyword("FilterName")) {
1481 pFilterNameKey =bandBinGrp.findKeyword("FilterName") ;
1482 }
1483 }
1484 }
1485
1494 void CubeViewport::getCubeArea(double & pdStartSample, double & pdEndSample,
1495 double & pdStartLine, double & pdEndLine)
1496 {
1497 viewportToCube(0, 0, pdStartSample, pdStartLine);
1498 if(pdStartSample < 1.0){
1499 pdStartSample = 1.0;
1500 }
1501 if(pdStartLine < 1.0){
1502 pdStartLine = 1.0;
1503 }
1504
1505 //end line and samples
1506 viewportToCube(viewport()->width() - 1, viewport()->height() - 1, pdEndSample, pdEndLine);
1507 if(pdEndSample > cubeSamples()){
1508 pdEndSample = cubeSamples();
1509 }
1510 if(pdEndLine > cubeLines()){
1511 pdEndLine = cubeLines();
1512 }
1513 }
1514
1520 //start, end line and sample
1521 double sl, ss, es, el;
1522 getCubeArea(ss, es, sl, el);
1523
1524 QString sBandInfo ;
1525 PvlKeyword filterNameKey;
1526 getBandFilterName(filterNameKey);
1527 int iFilterSize = filterNameKey.size();
1528
1529 // color
1530 if(p_color ) {
1531 int iRedBand = p_redBuffer->getBand();
1532 int iGreenBand = p_greenBuffer->getBand();
1533 int iBlueBand = p_blueBuffer->getBand();
1534
1535 sBandInfo = "Bands(RGB)&nbsp;Virtual = " +
1536 QString::number(iRedBand) + ", ";
1537 sBandInfo += QString::number(iGreenBand) + ", ";
1538 sBandInfo += QString::number(iBlueBand) + " ";
1539
1540 sBandInfo += "Physical = " +
1541 QString::number(p_cube->physicalBand(iRedBand)) + ", ";
1542 sBandInfo += QString::number(p_cube->physicalBand(iGreenBand)) + ", ";
1543 sBandInfo += QString::number(p_cube->physicalBand(iBlueBand));
1544
1545 if(iFilterSize) {
1546 sBandInfo += "<br>FilterName = ";
1547 if(iRedBand <= iFilterSize) {
1548 sBandInfo += QString(filterNameKey[iRedBand-1]);
1549 }
1550 else {
1551 sBandInfo += "None";
1552 }
1553 sBandInfo += ", ";
1554
1555 if(iGreenBand <= iFilterSize) {
1556 sBandInfo += QString(filterNameKey[iGreenBand-1]);
1557 }
1558 else {
1559 sBandInfo += "None";
1560 }
1561 sBandInfo += ", ";
1562
1563 if(iBlueBand <= iFilterSize) {
1564 sBandInfo += QString(filterNameKey[iBlueBand-1]);
1565 }
1566 else {
1567 sBandInfo += "None";
1568 }
1569 }
1570 }
1571 else { // gray
1572 int iGrayBand = p_grayBuffer->getBand();
1573
1574 sBandInfo = "Band(Gray)&nbsp;Virtual = " + QString::number(iGrayBand) + " ";
1575
1576 sBandInfo += "Physical = " + QString::number(p_cube->physicalBand(iGrayBand));
1577
1578 if(iFilterSize && iGrayBand <= iFilterSize) {
1579 sBandInfo += "<br>FilterName = " + QString(filterNameKey[iGrayBand-1]);
1580 }
1581 }
1582
1583 QString area =
1584 "<p><b>Visible Cube Area:</b><blockQuote> \
1585 Samples = " + QString::number(int(ss + 0.5)) + "-" +
1586 QString::number(int(es + 0.5)) + "<br> \
1587 Lines = " + QString::number(int(sl + 0.5)) + "-" +
1588 QString::number(int(el + 0.5)) + "<br> " +
1589 sBandInfo + "</blockQuote></p>";
1590
1591 QString fullWhatsThis = p_whatsThisText + area + p_cubeWhatsThisText + p_viewportWhatsThisText;
1592 setWhatsThis(fullWhatsThis);
1593 viewport()->setWhatsThis(fullWhatsThis);
1594 }
1595
1605 double CubeViewport::redPixel(int sample, int line) {
1606 p_pntBrick->SetBasePosition(sample, line, p_red.band);
1608 return (*p_pntBrick)[0];
1609 }
1610
1611
1621 double CubeViewport::greenPixel(int sample, int line) {
1622 p_pntBrick->SetBasePosition(sample, line, p_green.band);
1624 return (*p_pntBrick)[0];
1625 }
1626
1627
1637 double CubeViewport::bluePixel(int sample, int line) {
1638 p_pntBrick->SetBasePosition(sample, line, p_blue.band);
1640 return (*p_pntBrick)[0];
1641 }
1642
1643
1653 double CubeViewport::grayPixel(int sample, int line) {
1654 p_pntBrick->SetBasePosition(sample, line, p_gray.band);
1656 return (*p_pntBrick)[0];
1657 }
1658
1659
1664
1665
1668 return p_red.getStretch();
1669 };
1670
1671
1676
1677
1680 return p_blue.getStretch();
1681 };
1682
1683
1694 // Handle standard mouse tracking on the viewport
1695 if(o == viewport()) {
1696 switch(e->type()) {
1697 case QEvent::Enter: {
1698 viewport()->setMouseTracking(true);
1699 emit mouseEnter();
1700 return true;
1701 }
1702
1703 case QEvent::MouseMove: {
1704 QMouseEvent *m = (QMouseEvent *) e;
1705 emit mouseMove(m->pos());
1706 emit mouseMove(m->pos(), (Qt::MouseButton)(m->button() +
1707 m->modifiers()));
1708 return true;
1709 }
1710
1711 case QEvent::Leave: {
1712 viewport()->setMouseTracking(false);
1713 emit mouseLeave();
1714 return true;
1715 }
1716
1717 case QEvent::MouseButtonPress: {
1718 QMouseEvent *m = (QMouseEvent *) e;
1719 emit mouseButtonPress(m->pos(),
1720 (Qt::MouseButton)(m->button() + m->modifiers()));
1721 return true;
1722 }
1723
1724 case QEvent::MouseButtonRelease: {
1725 QMouseEvent *m = (QMouseEvent *) e;
1726 emit mouseButtonRelease(m->pos(),
1727 (Qt::MouseButton)(m->button() + m->modifiers()));
1728 return true;
1729 }
1730
1731 case QEvent::MouseButtonDblClick: {
1732 QMouseEvent *m = (QMouseEvent *) e;
1733 emit mouseDoubleClick(m->pos());
1734 return true;
1735 }
1736
1737 default: {
1738 return false;
1739 }
1740 }
1741 }
1742 else {
1743 return QAbstractScrollArea::eventFilter(o, e);
1744 }
1745 }
1746
1747
1758 void CubeViewport::keyPressEvent(QKeyEvent *e) {
1759 if(e->key() == Qt::Key_Plus) {
1760 double scale = p_scale * 2.0;
1761 setScale(scale);
1762 e->accept();
1763 }
1764 else if(e->key() == Qt::Key_Minus) {
1765 double scale = p_scale / 2.0;
1766 setScale(scale);
1767 e->accept();
1768 }
1769 else if(e->key() == Qt::Key_Up) {
1770 moveCursor(0, -1);
1771 e->accept();
1772 }
1773 else if(e->key() == Qt::Key_Down) {
1774 moveCursor(0, 1);
1775 e->accept();
1776 }
1777 else if(e->key() == Qt::Key_Left) {
1778 moveCursor(-1, 0);
1779 e->accept();
1780 }
1781 else if(e->key() == Qt::Key_Right) {
1782 moveCursor(1, 0);
1783 e->accept();
1784 }
1785 else if ((e->key() == Qt::Key_C) &&
1786 QApplication::keyboardModifiers() &
1787 Qt::ControlModifier) {
1788
1789 //QString fileName = p_cube->fileName();
1790 QFileInfo fileName = p_cube->fileName();
1791
1792 // Grabs the clipboard and copies the file name into it.
1793 QClipboard *clipboard = QApplication::clipboard();
1794 clipboard->setText(fileName.absoluteFilePath());
1795 }
1796 else {
1797 QAbstractScrollArea::keyPressEvent(e);
1798 }
1799 }
1800
1801
1809 QPoint g = QCursor::pos();
1810 QPoint v = viewport()->mapFromGlobal(g);
1811 if(v.x() < 0){
1812 return false;
1813 }
1814 if(v.y() < 0){
1815 return false;
1816 }
1817 if(v.x() >= viewport()->width()){
1818 return false;
1819 }
1820 if(v.y() >= viewport()->height()){
1821 return false;
1822 }
1823 return true;
1824 }
1825
1826
1834 QPoint g = QCursor::pos();
1835 return viewport()->mapFromGlobal(g);
1836 }
1837
1838
1846 void CubeViewport::moveCursor(int x, int y) {
1847 QPoint g = QCursor::pos();
1848 g += QPoint(x, y);
1849 QPoint v = viewport()->mapFromGlobal(g);
1850 if(v.x() < 0){
1851 return;
1852 }
1853 if(v.y() < 0){
1854 return;
1855 }
1856 if(v.x() >= viewport()->width()){
1857 return;
1858 }
1859 if(v.y() >= viewport()->height()){
1860 return;
1861 }
1862 QCursor::setPos(g);
1863 }
1864
1865
1874 QPoint g(x, y);
1875 QPoint v = viewport()->mapToGlobal(g);
1876 QCursor::setPos(v);
1877 }
1878
1879
1888 viewport()->blockSignals(true);
1889
1890 verticalScrollBar()->setValue(1);
1891 verticalScrollBar()->setMinimum(1);
1892 verticalScrollBar()->setMaximum((int)(ceil(cubeLines() * p_scale) + 0.5));
1893 verticalScrollBar()->setPageStep(viewport()->height() / 2);
1894
1895 horizontalScrollBar()->setValue(1);
1896 horizontalScrollBar()->setMinimum(1);
1897 horizontalScrollBar()->setMaximum((int)(ceil(cubeSamples() * p_scale) + 0.5));
1898 horizontalScrollBar()->setPageStep(viewport()->width() / 2);
1899
1900 if(horizontalScrollBar()->value() != x || verticalScrollBar()->value() != y) {
1901 horizontalScrollBar()->setValue(x);
1902 verticalScrollBar()->setValue(y);
1903 emit scaleChanged();
1904 }
1905
1906 QApplication::sendPostedEvents(viewport(), 0);
1907 viewport()->blockSignals(false);
1908 }
1909
1910
1917 void CubeViewport::viewGray(int band) {
1918 p_gray.band = band;
1919 p_color = false;
1920 setCaption();
1921
1922 if(!p_grayBuffer){
1924 p_cubeId);
1925 }
1926
1927 if(p_redBuffer){
1928 delete p_redBuffer;
1929 }
1930 p_redBuffer = NULL;
1931
1932 if(p_greenBuffer){
1933 delete p_greenBuffer;
1934 }
1935 p_greenBuffer = NULL;
1936
1937 if(p_blueBuffer){
1938 delete p_blueBuffer;
1939 }
1940 p_blueBuffer = NULL;
1941
1942 if(p_grayBuffer->getBand() != band) {
1943 int oldBand = p_grayBuffer->getBand();
1944
1945 if(oldBand >= 0) {
1946 if((*p_knownStretches)[oldBand - 1]) {
1947 delete(*p_knownStretches)[oldBand - 1];
1948 }
1949
1950 (*p_knownStretches)[oldBand - 1] = new Stretch(p_gray.getStretch());
1951 }
1952
1953 p_grayBuffer->setBand(band);
1954 p_gray.band = band;
1955
1956 if((*p_knownStretches)[band - 1]) {
1957 stretchGray(*(*p_knownStretches)[band - 1]);
1958 }
1959 else {
1961 }
1962 }
1963
1964 if(p_camera) {
1965 p_camera->SetBand(band);
1966 }
1967
1968 viewport()->repaint();
1969 }
1970
1971
1973 for(int stretch = 0; stretch < p_knownStretches->size(); stretch++) {
1974 if((*p_knownStretches)[stretch]) {
1975 delete(*p_knownStretches)[stretch];
1976 (*p_knownStretches)[stretch] = NULL;
1977 }
1978 }
1979 }
1980
1981
1983 for(int index = 0; index < p_knownStretches->size(); index ++) {
1984 if((*p_knownStretches)[index]) {
1985 delete(*p_knownStretches)[index];
1986 }
1987
1988 (*p_knownStretches)[index] = new Stretch(stretch);
1989 }
1990 }
1991
1992
2001 void CubeViewport::viewRGB(int rband, int gband, int bband) {
2002 p_red.band = rband;
2003 p_green.band = gband;
2004 p_blue.band = bband;
2005 p_color = true;
2006 setCaption();
2007
2008 if(!p_redBuffer) {
2010 }
2011
2012 if(!p_greenBuffer) {
2014 }
2015
2016 if(!p_blueBuffer) {
2018 }
2019
2020 if(p_redBuffer->getBand() != rband) {
2021 int oldBand = p_redBuffer->getBand();
2022
2023 // Remember current stretch for future band changes
2024 if(oldBand >= 0) {
2025 if((*p_knownStretches)[oldBand - 1]) {
2026 delete(*p_knownStretches)[oldBand - 1];
2027 }
2028
2029 (*p_knownStretches)[oldBand - 1] = new Stretch(p_red.getStretch());
2030 }
2031
2032 p_redBuffer->setBand(rband);
2033 p_red.band = rband;
2034
2035 if((*p_knownStretches)[rband - 1]) {
2036 p_red.setStretch(*(*p_knownStretches)[rband - 1]);
2037 }
2038 else {
2040 }
2041 }
2042
2043 if(p_greenBuffer->getBand() != gband) {
2044 int oldBand = p_greenBuffer->getBand();
2045
2046 // Remember current stretch for future band changes
2047 if(oldBand >= 0) {
2048 if((*p_knownStretches)[oldBand - 1]) {
2049 delete(*p_knownStretches)[oldBand - 1];
2050 }
2051
2052 (*p_knownStretches)[oldBand - 1] = new Stretch(p_green.getStretch());
2053 }
2054
2055 p_greenBuffer->setBand(gband);
2056 p_green.band = gband;
2057
2058 if((*p_knownStretches)[gband - 1]) {
2059 p_green.setStretch(*(*p_knownStretches)[gband - 1]);
2060 }
2061 else {
2063 }
2064 }
2065
2066 if(p_blueBuffer->getBand() != bband) {
2067 int oldBand = p_blueBuffer->getBand();
2068
2069 // Remember current stretch for future band changes
2070 if(oldBand >= 0) {
2071 if((*p_knownStretches)[oldBand - 1]) {
2072 delete(*p_knownStretches)[oldBand - 1];
2073 }
2074
2075 (*p_knownStretches)[oldBand - 1] = new Stretch(p_blue.getStretch());
2076 }
2077
2078 p_blueBuffer->setBand(bband);
2079 p_blue.band = bband;
2080
2081 if((*p_knownStretches)[bband - 1]) {
2082 p_blue.setStretch(*(*p_knownStretches)[bband - 1]);
2083 }
2084 else {
2086 }
2087 }
2088
2089 if(p_grayBuffer){
2090 delete p_grayBuffer;
2091 }
2092 p_grayBuffer = NULL;
2093
2094 if(p_camera) {
2095 p_camera->SetBand(rband);
2096 }
2097 }
2098
2099
2106 void CubeViewport::stretchGray(const QString &string) {
2107 Stretch stretch;
2108 stretch.Parse(string);
2109 stretchGray(stretch);
2110 }
2111
2112
2118 void CubeViewport::stretchRed(const QString &string) {
2119 Stretch stretch;
2120 stretch.Parse(string);
2121 stretchRed(stretch);
2122 }
2123
2124
2130 void CubeViewport::stretchGreen(const QString &string) {
2131 Stretch stretch;
2132 stretch.Parse(string);
2133 stretchGreen(stretch);
2134 }
2135
2136
2142 void CubeViewport::stretchBlue(const QString &string) {
2143 Stretch stretch;
2144 stretch.Parse(string);
2145 stretchBlue(stretch);
2146 }
2147
2148
2153 if(!p_globalStretches){
2154 return;
2155 }
2156
2157 if(isGray()) {
2158 if((*p_globalStretches)[grayBand() - 1]) {
2160 }
2161 }
2162 else {
2163 if((*p_globalStretches)[redBand() - 1]) {
2165 }
2166
2167 if((*p_globalStretches)[greenBand() - 1]) {
2169 }
2170
2171 if((*p_globalStretches)[blueBand() - 1]) {
2173 }
2174 }
2175 }
2176
2177
2183 void CubeViewport::stretchGray(const Stretch &stretch) {
2184 // Assume first stretch is always the global stretch (and it should be)
2185 if((*p_globalStretches)[grayBand() - 1] == NULL && stretch.Pairs()) {
2186 (*p_globalStretches)[grayBand() - 1] = new Stretch(stretch);
2187 }
2188
2189 p_gray.setStretch(stretch);
2190
2191 Stretch newRed(p_red.getStretch());
2192 newRed.CopyPairs(stretch);
2193 p_red.setStretch(newRed);
2194
2195 Stretch newGreen(p_green.getStretch());
2196 newGreen.CopyPairs(stretch);
2197 p_green.setStretch(newGreen);
2198
2199 Stretch newBlue(p_blue.getStretch());
2200 newBlue.CopyPairs(stretch);
2201 p_blue.setStretch(newBlue);
2202
2203 paintPixmap();
2204 viewport()->update();
2205 }
2206
2207
2213 void CubeViewport::stretchRed(const Stretch &stretch) {
2214 p_red.setStretch(stretch);
2215
2216 // Assume first stretch is always the global stretch (and it should be)
2217 if((*p_globalStretches)[redBand() - 1] == NULL && stretch.Pairs()) {
2218 (*p_globalStretches)[redBand() - 1] = new Stretch(p_red.getStretch());
2219 }
2220
2221 paintPixmap();
2222 viewport()->update();
2223 }
2224
2225
2232 p_green.setStretch(stretch);
2233
2234 // Assume first stretch is always the global stretch (and it should be)
2235 if((*p_globalStretches)[greenBand() - 1] == NULL && stretch.Pairs()) {
2236 (*p_globalStretches)[greenBand() - 1] = new Stretch(p_green.getStretch());
2237 }
2238
2239 paintPixmap();
2240 viewport()->update();
2241 }
2242
2243
2249 void CubeViewport::stretchBlue(const Stretch &stretch) {
2250 p_blue.setStretch(stretch);
2251
2252 // Assume first stretch is always the global stretch (and it should be)
2253 if((*p_globalStretches)[blueBand() - 1] == NULL && stretch.Pairs()) {
2254 (*p_globalStretches)[blueBand() - 1] = new Stretch(p_blue.getStretch());
2255 }
2256
2257 paintPixmap();
2258 viewport()->update();
2259 }
2260
2261
2269 double CubeViewport::fitScale() const {
2270 double sampScale = (double) viewport()->width() / (double) cubeSamples();
2271 double lineScale = (double) viewport()->height() / (double) cubeLines();
2272 double scale = sampScale < lineScale ? sampScale : lineScale;
2273// scale = floor(scale * 100.0) / 100.0;
2274 return scale;
2275 }
2276
2277
2285 double scale = (double) viewport()->width() / (double) cubeSamples();
2286
2287// scale = floor(scale * 100.0) / 100.0;
2288 return scale;
2289 }
2290
2298 double scale = (double) viewport()->height() / (double) cubeLines();
2299
2300// scale = floor(scale * 100.0) / 100.0;
2301 return scale;
2302 }
2303
2312 //start sample/line and end sample/line
2313 double ss, sl, es, el;
2314 ss = (double)(rect.left()) - 1.;
2315 sl = (double)(rect.top()) - 1.;
2316 es = (double)(rect.right()) + 1.;
2317 el = (double)(rect.bottom()) + 1.;
2318 if(ss < 1){
2319 ss = 0.5;
2320 }
2321 if(sl < 1){
2322 sl = 0.5;
2323 }
2324 if(es > cube()->sampleCount()){
2325 es = cube()->sampleCount() + 0.5;
2326 }
2327 if(el > cube()->lineCount()){
2328 el = cube()->lineCount() + 0.5;
2329 }
2330
2331 //start x/y and end x/y
2332 int sx, sy, ex, ey;
2333
2334 cubeToViewport(ss, sl, sx, sy);
2335 cubeToViewport(es, el, ex, ey);
2336 if(sx < 0){
2337 sx = 0;
2338 }
2339 if(sy < 0){
2340 sy = 0;
2341 }
2342 if(ex > viewport()->width()){
2343 ex = viewport()->width();
2344 }
2345 if(ey > viewport()->height()){
2346 ey = viewport()->height();
2347 }
2348 QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
2349
2350 p_updatingBuffers = true;
2351 if(p_grayBuffer){
2352 p_grayBuffer->fillBuffer(vpRect);
2353 }
2354 if(p_redBuffer){
2355 p_redBuffer->fillBuffer(vpRect);
2356 }
2357 if(p_greenBuffer){
2358 p_greenBuffer->fillBuffer(vpRect);
2359 }
2360 if(p_blueBuffer){
2361 p_blueBuffer->fillBuffer(vpRect);
2362 }
2363 p_updatingBuffers = false;
2364
2366 }
2367
2368
2375 PvlGroup trackingGroup = p_cube->group("Tracking");
2376 //Because the tracking group does not have a path, get the path from the main cube
2377 FileName cubeName(p_cube->fileName());
2378 QString trackingCubeName = trackingGroup.findKeyword("Filename")[0];
2379 FileName trackingCubeFileName(cubeName.path() + "/" + trackingCubeName);
2380 Cube *trackingCube = new Cube(trackingCubeFileName);
2381 p_trackingCube = trackingCube;
2382 }
2383
2384
2391 void CubeViewport::changeCursor(QCursor cursor) {
2392 viewport()->setCursor(cursor);
2393 }
2394
2395
2396 CubeViewport::BandInfo::BandInfo() : band(1), stretch(NULL) {
2397 stretch = new CubeStretch;
2398 stretch->SetNull(0.0);
2399 stretch->SetLis(0.0);
2400 stretch->SetLrs(0.0);
2401 stretch->SetHis(255.0);
2402 stretch->SetHrs(255.0);
2403 stretch->SetMinimum(0.0);
2404 stretch->SetMaximum(255.0);
2405 };
2406
2407
2408 CubeViewport::BandInfo::BandInfo(const CubeViewport::BandInfo &other) :
2409 band(other.band) {
2410 stretch = NULL;
2411 stretch = new CubeStretch(*other.stretch);
2412 }
2413
2414
2416 if(stretch) {
2417 delete stretch;
2418 stretch = NULL;
2419 }
2420 }
2421
2422
2424 return *stretch;
2425 }
2426
2427
2429 *stretch = newStretch;
2430 }
2431
2432
2434 CubeViewport::BandInfo other) {
2435
2436 stretch = NULL;
2437 stretch = new CubeStretch;
2438 *stretch = *other.stretch;
2439 band = other.band;
2440
2441 return *this;
2442 }
2443
2444}
Buffer for containing a three dimensional section of an image.
Definition Brick.h:45
void SetBasePosition(const int start_sample, const int start_line, const int start_band)
This method is used to set the base position of the shape buffer.
Definition Brick.h:120
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
Definition Buffer.cpp:145
int LineDimension() const
Returns the number of lines in the shape buffer.
Definition Buffer.h:79
int SampleDimension() const
Returns the number of samples in the shape buffer.
Definition Buffer.h:70
int Sample(const int index=0) const
Returns the sample position associated with a shape buffer index.
Definition Buffer.cpp:127
bool HasProjection()
Checks to see if the camera object has a projection.
Definition Camera.cpp:2668
virtual void SetBand(const int band)
Virtual method that sets the band number.
Definition Camera.cpp:2710
Encapsulation of Cube I/O with Change Notifications.
void RemoveChangeListener()
You must call this method after disconnecting from the BrickChanged signal, otherwise bricks cannot b...
int AddCube(const FileName &fileName, bool mustOpenReadWrite=false)
This method is designed to be callable from any thread before data is requested, though no known side...
int FindCubeId(const Cube *) const
Given a Cube pointer, return the cube ID associated with it.
void AddChangeListener()
You must call this method after connecting to the BrickChanged signal, otherwise you are not guarante...
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
PvlGroup & group(const QString &group) const
Read a group from the cube into a Label.
Definition Cube.cpp:1997
int sampleCount() const
Definition Cube.cpp:1813
bool isOpen() const
Test if a cube file has been opened/created.
Definition Cube.cpp:182
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
virtual int physicalBand(const int &virtualBand) const
This method will return the physical band number given a virtual band number.
Definition Cube.cpp:1779
bool hasGroup(const QString &group) const
Return if the cube has a specified group in the labels.
Definition Cube.cpp:2010
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1569
Projection * projection()
Definition Cube.cpp:1800
virtual int bandCount() const
Returns the number of virtual bands for the cube.
Definition Cube.cpp:1416
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
Stores stretch information for a cube.
Definition CubeStretch.h:27
const BandInfo & operator=(BandInfo other)
The BandInfo for the Cube.
CubeStretch getStretch() const
void setStretch(const Stretch &newStretch)
CubeStretch * stretch
The Stretch.
bool p_cubeShown
Is the cube visible?
void stretchGray(const QString &string)
Apply stretch pairs to gray band.
void getCubeArea(double &pdStartSample, double &pdEndSample, double &pdStartLine, double &pdEndLine)
Get Cube area corresponding to the viewport's dimension.
double bluePixel(int sample, int line)
Gets the blue pixel.
void updateScrollBars(int x, int y)
Update the scroll bar.
CubeViewport(Cube *cube, CubeDataThread *cdt=0, QWidget *parent=0)
Constructor for the CubeViewport.
Brick * p_pntBrick
Bricks for every color.
double scale() const
void stretchBlue(const QString &string)
Apply stretch pairs to blue bands.
Cube * p_cube
The cube associated with the viewport.
CubeStretch grayStretch() const
Return the gray band stretch.
void doneWithData(int, const Isis::Brick *)
Emitted when a brick is no longer needed, should only be sent to cube data thread.
void showEvent(QShowEvent *)
This method is called to initially show the viewport.
void getBandFilterName(PvlKeyword &pFilterNameKey)
Get Band Filter name from the Isis cube label.
Brick * p_redBrick
Bricks for every color.
int cubeLines() const
Return the number of lines in the cube.
void discardChanges(CubeViewport *)
Emitted when changes should be discarded.
double greenPixel(int sample, int line)
Gets the green pixel.
int greenBand() const
ViewportBuffer * p_grayBuffer
Viewport Buffer to manage gray band.
int cubeBands() const
Return the number of bands in the cube.
QString p_whatsThisText
The text for What's this.
ViewportBuffer * p_redBuffer
Viewport Buffer to manage red band.
bool p_color
Is the viewport in color?
bool p_updatingBuffers
Changing RGB and need to not repaint pixmap?
void setCursorPosition(int x, int y)
Set the cursor position to x/y in the viewport.
QList< QRect * > * p_pixmapPaintRects
A list of rects that the viewport buffers have requested painted.
CubeStretch redStretch() const
Return the red band stretch.
void scaleChanged()
Emitted when zoom factor changed just before the repaint event.
int redBand() const
bool p_thisOwnsCubeData
if true then this owns the CubeDataThread, and should thus delete it
void setCube(Cube *cube)
This method sets the viewports cube.
virtual void resizeEvent(QResizeEvent *e)
The viewport is being resized.
virtual void paintEvent(QPaintEvent *e)
Repaint the viewport.
void contentsToCube(int x, int y, double &sample, double &line) const
Turns contents to a cube.
QSize sizeHint() const
Make viewports show up as 512 by 512.
void changeCursor(QCursor cursor)
Allows users to change the cursor type on the viewport.
Projection * p_projection
The projection from the cube.
void updateWhatsThis()
Update the What's This text.
virtual bool eventFilter(QObject *o, QEvent *e)
Event filter to watch for mouse events on viewport.
bool cursorInside() const
Is cursor inside viewport.
QPoint cursorPosition() const
Return the cursor position in the viewport.
virtual ~CubeViewport()
Deconstructor for the Cubeviewport.
virtual void viewRGB(int redBand, int greenBand, int blueBand)
View cube as color.
int p_comboIndex
Current element chosen from combo box.
double fitScaleHeight() const
Determine the scale of cube in heighth to fit in the viewport.
void paintPixmapRects()
Goes through the list of requested paints, from the viewport buffer, and paints them.
int cubeSamples() const
Return the number of samples in the cube.
void mouseDoubleClick(QPoint)
Emitted when double click happens.
void progressComplete()
Emitted when the current progress is complete (100)
void stretchKnownGlobal()
List<Tool *> p This stretches to the global stretch.
QPixmap p_pixmap
The qpixmap.
void stretchGreen(const QString &string)
Apply stretch pairs to green bands.
void scrollContentsBy(int dx, int dy)
Scroll the viewport contents by dx/dy screen pixels.
Brick * p_grnBrick
Bricks for every color.
QString p_viewportWhatsThisText
The text for the viewport's what's this.
double grayPixel(int sample, int line)
Gets the gray pixel.
Cube * trackingCube() const
void setTrackingCube()
Finds the Tracking group from p_cube and stores the tracking cube name so that we can grab it in Adva...
void cubeChanged(bool changed)
This method is called when the cube has changed or changes have been finalized.
void cubeToContents(double sample, double line, int &x, int &y) const
Turns a cube into contents.
bool p_saveEnabled
Has the cube changed?
QString p_cubeWhatsThisText
The text for the cube's What's this.
virtual void keyPressEvent(QKeyEvent *e)
Process arrow keystrokes on cube.
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
QColor p_bgColor
The color to paint the background of the viewport.
void cubeToViewport(double sample, double line, int &x, int &y) const
Turns a cube into a viewport.
void mouseButtonRelease(QPoint, Qt::MouseButton)
Emitted when mouse button released.
BandInfo p_blue
Blue band info.
void mouseButtonPress(QPoint, Qt::MouseButton)
Emitted when mouse button pressed.
void mouseLeave()
Emitted when the mouse leaves the viewport.
double fitScale() const
Determine the scale that causes the full cube to fit in the viewport.
CubeDataThread * p_cubeData
Does all the cube I/O.
void stretchRed(const QString &string)
Apply stretch pairs to red bands.
bool confirmClose()
This method should be called during a close event that would cause this viewport to close.
Brick * p_bluBrick
Bricks for every color.
CubeStretch greenStretch() const
Return the green band stretch.
BandInfo p_green
Green band info.
void saveChanges(CubeViewport *)
Emitted when changes should be saved.
void setScale(double scale)
Change the scale of the cube to the given parameter value.
void forgetStretches()
Resets all remembered stretches.
int grayBand() const
Camera * p_camera
The camera from the cube.
ViewportBuffer * p_greenBuffer
Viewport Buffer to manage green band.
QTimer * p_progressTimer
Activated to update progress bar.
QImage * p_image
The qimage.
void paintPixmap()
Paint the whole pixmap.
void getAllWhatsThisInfo(Pvl &pWhatsThisPvl)
Get All WhatsThis info - viewport, cube, area in PVL format.
BandInfo p_gray
Gray band info.
Cube * cube() const
void mouseEnter()
Emitted when the mouse enters the viewport.
int p_comboCount
Number of elements in band bin combo box.
double redPixel(int sample, int line)
Gets the red pixel.
void enableProgress()
This restarts the progress bar.
virtual void viewGray(int band)
View cube as gray.
BandInfo p_red
Red band info.
void windowTitleChanged()
Emitted when window title changes.
UniversalGroundMap * p_groundMap
The universal ground map from the cube.
void scrollBy(int dx, int dy)
Move the scrollbars by dx/dy screen pixels.
QVector< Stretch * > * p_globalStretches
Global stretches for each stretched band.
void shiftPixmap(int dx, int dy)
Shifts the pixels on the pixmap without reading new data.
void progressChanged(int)
Emitted with current progress (0 to 100) when working.
QVector< Stretch * > * p_knownStretches
Stretches for each previously stretched band.
void onProgressTimer()
This updates the progress bar visually.
void screenPixelsChanged()
Emitted when cube pixels that should be on the screen change.
Brick * p_gryBrick
Bricks for every color.
void setAllBandStretches(Stretch stretch)
Sets a stretch for all bands.
void moveCursor(int x, int y)
Move the cursor by x,y if possible.
int p_cubeId
Cube ID given from cube data thread for I/O.
void cubeContentsChanged(QRect rect)
Calle dhwen the contents of the cube changes.
bool p_paintPixmap
Paint the pixmap?
bool isGray() const
void setCaption()
Change the caption on the viewport title bar.
double p_scale
The scale number.
virtual void cubeDataChanged(int cubeId, const Isis::Brick *)
This method updates the internal viewport buffer based on changes in cube DN values.
int blueBand() const
void mouseMove(QPoint)
Emitted when the mouse moves.
double fitScaleWidth() const
Determine the scale of cube in the width to fit in the viewport.
CubeStretch blueStretch() const
Return the blue band stretch.
void center(int x, int y)
Bring the cube pixel under viewport x/y to the center.
ViewportBuffer * p_blueBuffer
Viewport Buffer to manage blue band.
void bufferUpdated(QRect rect)
This method is called by ViewportBuffer upon successful completion of all operations and gives the ap...
File name manipulation and expansion.
Definition FileName.h:100
Isis exception class.
Definition IException.h:91
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
PvlKeyword & findKeyword(const QString &name)
Find a keyword with a specified name.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition PvlObject.h:276
Pixel value mapper.
Definition Stretch.h:58
void Parse(const QString &pairs)
Parses a string of the form "i1:o1 i2:o2...iN:oN" where each i:o represents an input:output pair.
Definition Stretch.cpp:181
void SetNull(const double value)
Sets the mapping for NULL pixels.
Definition Stretch.h:94
double Map(const double value) const
Maps an input value to an output value based on the stretch pairs and/or special pixel mappings.
Definition Stretch.cpp:69
int Pairs() const
Returns the number of stretch pairs.
Definition Stretch.h:162
Universal Ground Map.
Isis::Projection * Projection() const
Return the projection associated with the ground map (NULL implies none)
Isis::Camera * Camera() const
Return the camera associated with the ground map (NULL implies none)
Reads and stores visible DN values.
void addStretchAction()
When all current operations finish the cube viewport will be asked to do a stretch if you call this.
const std::vector< double > & getLine(int line)
Retrieves a line from the buffer.
void setBand(int band)
Sets the band to read from, the buffer will be re-read if the band changes.
double currentProgress()
Returns the viewport buffer's loading progress.
void enable(bool enabled)
This turns on or off reading from the cube.
QRect bufferXYRect()
Returns a rect, in screen pixels, of the area this buffer covers.
void resizedViewport()
Call this when the viewport is resized (not zoomed).
bool enabled()
Returns whether the buffer is enabled (reading data) or not.
void fillBuffer(QRect rect)
This method will convert the rect to sample/line positions and read from the cube into the buffer.
bool working()
This tests if queued actions exist in the viewport buffer.
int getBand()
Return the band associated with this viewport buffer.
void pan(int deltaX, int deltaY)
Call this when the viewport is panned.
void scaleChanged()
Call this when zoomed, re-reads visible area.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
Namespace for the standard library.