USGS

Isis 3.0 Object Programmers' Reference

Home

CubeViewport.cpp
Go to the documentation of this file.
1 
20 #include "IsisDebug.h"
21 #include "CubeViewport.h"
22 
23 #include <iomanip>
24 #include <iostream>
25 #include <QApplication>
26 #include <QCloseEvent>
27 #include <QCursor>
28 #include <QDebug>
29 #include <QIcon>
30 #include <QPen>
31 #include <QPainter>
32 #include <QFileInfo>
33 #include <QMessageBox>
34 #include <QMouseEvent>
35 #include <QRgb>
36 #include <QScrollBar>
37 #include <QString>
38 #include <QTimer>
39 
40 #include "Brick.h"
41 #include "Camera.h"
42 #include "CubeDataThread.h"
43 #include "IException.h"
44 #include "IString.h"
45 #include "FileName.h"
46 #include "Histogram.h"
47 #include "Pvl.h"
48 #include "PvlGroup.h"
49 #include "PvlKeyword.h"
50 #include "PvlObject.h"
51 #include "Stretch.h"
52 #include "StretchTool.h"
53 #include "Tool.h"
54 #include "UniversalGroundMap.h"
55 #include "ViewportBuffer.h"
56 
57 
58 using namespace std;
59 
60 
61 namespace Isis {
69  CubeViewport::CubeViewport(Cube *cube, CubeDataThread * cubeData,
70  QWidget *parent) : QAbstractScrollArea(parent) {
71  // Is the cube usable?
72  if(cube == NULL) {
74  "Can not view NULL cube pointer",
75  _FILEINFO_);
76  }
77  else if(!cube->isOpen()) {
79  "Can not view unopened cube",
80  _FILEINFO_);
81  }
82 
83  p_cube = cube;
84  p_cubeData = NULL;
85 
86  if (cubeData)
87  {
88  p_cubeData = cubeData;
89  p_thisOwnsCubeData = false;
91  }
92  else
93  {
94  p_cubeData = new CubeDataThread();
95  p_thisOwnsCubeData = true;
97  }
98 
99 
100  connect(p_cubeData, SIGNAL(BrickChanged(int, const Isis::Brick *)),
101  this, SLOT(cubeDataChanged(int, const Isis::Brick *)));
102  connect(this, SIGNAL(doneWithData(int, const Isis::Brick *)),
103  p_cubeData, SLOT(DoneWithData(int, const Isis::Brick *)));
104 
106 
107  void doneWithData(int, const Brick *);
108 
109  // Set up the scroll area
110  setAttribute(Qt::WA_DeleteOnClose);
111  setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
112  setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
113  viewport()->setObjectName("viewport");
114  viewport()->setCursor(QCursor(Qt::CrossCursor));
115  viewport()->installEventFilter(this);
116  viewport()->setAttribute(Qt::WA_OpaquePaintEvent);
117 
118  setAttribute(Qt::WA_NoSystemBackground);
119  setFrameShadow(QFrame::Plain);
120  setFrameShape(QFrame::NoFrame);
121  setAutoFillBackground(false);
122 
123 // viewport()->setAttribute(Qt::WA_NoSystemBackground);
124 // viewport()->setAttribute(Qt::WA_PaintOnScreen,false);
125 
126  p_saveEnabled = false;
127  // Save off info about the cube
128  p_scale = -1.0;
129  p_color = false;
130 
131 
132  setCaption();
133 
134  p_redBrick = new Brick(4, 1, 1, cube->pixelType());
135  p_grnBrick = new Brick(4, 1, 1, cube->pixelType());
136  p_bluBrick = new Brick(4, 1, 1, cube->pixelType());
137  p_gryBrick = new Brick(4, 1, 1, cube->pixelType());
138  p_pntBrick = new Brick(4, 1, 1, cube->pixelType());
139 
140  p_paintPixmap = false;
141  p_image = NULL;
142  p_cubeShown = true;
143  p_updatingBuffers = false;
144 
145  //updateScrollBars(1,1);
146 
147  p_groundMap = NULL;
148  p_projection = NULL;
149  p_camera = NULL;
150 
151  // Setup a universal ground map
152  try {
154  }
155  catch(IException &) {
156  }
157 
158  if(p_groundMap != NULL) {
159  // Setup the camera or the projection
160  if(p_groundMap->Camera() != NULL) {
162  if(p_camera->HasProjection()) {
163  try {
164  p_projection = cube->projection();
165  }
166  catch(IException &) {
167  }
168  }
169  }
170  else {
172  }
173  }
174 
175 
176  // Setup context sensitive help
177  QString cubeFileName = p_cube->fileName();
178  p_whatsThisText = QString("<b>Function: </b>Viewport to ") + cubeFileName;
179 
181  "<p><b>Cube Dimensions:</b> \
182  <blockQuote>Samples = " +
183  QString::number(cube->sampleCount()) + "<br>" +
184  "Lines = " +
185  QString::number(cube->lineCount()) + "<br>" +
186  "Bands = " +
187  QString::number(cube->bandCount()) + "</blockquote></p>";
188 
189  /*setting up the qlist of CubeBandsStretch objs.
190  for( int b = 0; b < p_cube->bandCount(); b++) {
191  CubeBandsStretch *stretch = new CubeBandsStretch();
192  p_bandsStretchList.push_back(stretch);
193  }*/
194 
196  p_grayBuffer->enable(false);
197  p_grayBuffer->setBand(1);
198 
199  p_redBuffer = NULL;
200  p_greenBuffer = NULL;
201  p_blueBuffer = NULL;
202  p_pixmapPaintRects = NULL;
203 
205  p_progressTimer = new QTimer();
206  p_progressTimer->setInterval(250);
207 
210 
211  while(p_cube->bandCount() > p_knownStretches->size()) {
212  p_knownStretches->push_back(NULL);
213  p_globalStretches->push_back(NULL);
214  }
215 
216  connect(p_progressTimer, SIGNAL(timeout()), this, SLOT(onProgressTimer()));
217 
218  p_bgColor = Qt::black;
219 
220  p_comboCount = 0;
221  p_comboIndex = 0;
222 
223  p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
224  }
225 
226 
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, cubeLines() / 2.0);
241  }
242 
243  if(p_grayBuffer && !p_grayBuffer->enabled()) {
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 screenPixelsChanged();
292  }
293  else if(realProgress == 100) {
294  realProgress = 99;
295  }
296 
297  emit progressChanged(realProgress);
298  }
299 
300 
306  if(p_redBrick) {
307  delete p_redBrick;
308  p_redBrick = NULL;
309  }
310 
311  if(p_grnBrick) {
312  delete p_grnBrick;
313  p_grnBrick = NULL;
314  }
315 
316  if(p_bluBrick) {
317  delete p_bluBrick;
318  p_bluBrick = NULL;
319  }
320 
321  if(p_gryBrick) {
322  delete p_gryBrick;
323  p_gryBrick = NULL;
324  }
325 
326  if(p_pntBrick) {
327  delete p_pntBrick;
328  p_pntBrick = NULL;
329  }
330 
331  if(p_groundMap) {
332  delete p_groundMap;
333  p_groundMap = NULL;
334  }
335 
336  if(p_grayBuffer) {
337  delete p_grayBuffer;
338  p_grayBuffer = NULL;
339  }
340 
341  if(p_redBuffer) {
342  delete p_redBuffer;
343  p_redBuffer = NULL;
344  }
345 
346  if(p_greenBuffer) {
347  delete p_greenBuffer;
348  p_greenBuffer = NULL;
349  }
350 
351  if(p_blueBuffer) {
352  delete p_blueBuffer;
353  p_blueBuffer = NULL;
354  }
355 
356  // p_cubeData MUST be deleted AFTER all viewport buffers!!!
357  if(p_cubeData) {
359 
361  delete p_cubeData;
362 
363  p_cubeData = NULL;
364  }
365 
366  p_cube = NULL;
367 
368  if(p_progressTimer) {
369  delete p_progressTimer;
370  p_progressTimer = NULL;
371  }
372 
373  if(p_image) {
374  delete p_image;
375  p_image = NULL;
376  }
377 
378  if(p_pixmapPaintRects) {
379  for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
380  delete(*p_pixmapPaintRects)[rect];
381  }
382 
383  delete p_pixmapPaintRects;
384  p_pixmapPaintRects = NULL;
385  }
386 
387  if(p_knownStretches) {
388  for(int stretch = 0; stretch < p_knownStretches->size(); stretch ++) {
389  if((*p_knownStretches)[stretch] != NULL) {
390  delete(*p_knownStretches)[stretch];
391  (*p_knownStretches)[stretch] = NULL;
392  }
393  }
394 
395  p_knownStretches->clear();
396 
397  delete p_knownStretches;
398  p_knownStretches = NULL;
399  }
400 
401  if(p_globalStretches) {
402  for(int stretch = 0; stretch < p_globalStretches->size(); stretch ++) {
403  if((*p_globalStretches)[stretch] != NULL) {
404  delete(*p_globalStretches)[stretch];
405  (*p_globalStretches)[stretch] = NULL;
406  }
407  }
408 
409  p_globalStretches->clear();
410 
411  delete p_globalStretches;
412  p_globalStretches = NULL;
413  }
414  }
415 
422  p_cube = cube;
423  setCaption();
424  }
425 
426 
429  return p_cube->sampleCount();
430  }
431 
432 
435  return p_cube->lineCount();
436  }
437 
438 
441  return p_cube->bandCount();
442  }
443 
444 
452  void CubeViewport::cubeDataChanged(int cubeId, const Brick *data) {
453  if(cubeId == p_cubeId) {
454  double ss, sl, es, el;
455  ss = data->Sample();
456  sl = data->Line();
457  es = data->Sample() + data->SampleDimension();
458  el = data->Line() + data->LineDimension();
459  if(ss < 0.5){
460  ss = 0.5;
461  }
462  if(sl < 0.5){
463  sl = 0.5;
464  }
465  if(es > cube()->sampleCount() + 0.5){
466  es = cube()->sampleCount() + 0.5;
467  }
468  if(el > cube()->lineCount() + 0.5){
469  el = cube()->lineCount() + 0.5;
470  }
471 
472  int sx, sy, ex, ey;
473 
474  cubeToViewport(ss, sl, sx, sy);
475  cubeToViewport(es, el, ex, ey);
476  if(sx < 0){
477  sx = 0;
478  }
479  if(sy < 0){
480  sy = 0;
481  }
482  if(ex > viewport()->width()){
483  ex = viewport()->width();
484  }
485  if(ey > viewport()->height()){
486  ey = viewport()->height();
487  }
488  QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
489 
490  p_updatingBuffers = true;
491  if(p_grayBuffer){
492  p_grayBuffer->fillBuffer(vpRect, data);
493  }
494  if(p_redBuffer){
495  p_redBuffer->fillBuffer(vpRect, data);
496  }
497  if(p_greenBuffer){
498  p_greenBuffer->fillBuffer(vpRect, data);
499  }
500  if(p_blueBuffer){
501  p_blueBuffer->fillBuffer(vpRect, data);
502  }
503  p_updatingBuffers = false;
504 
506  }
507 
508  emit doneWithData(cubeId, data);
509  }
510 
511 
521  bool canClose = true;
522  if(p_saveEnabled) {
523  // Enter == button 0, Escape == button 2
524  switch(QMessageBox::information(this, tr("Confirm Save"),
525  tr("The cube [<font color='red'>%1</font>] contains unsaved changes. "
526  "Do you want to save the changes before exiting?").arg(cube()->fileName()),
527  QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel)) {
528  //Save changes and close viewport
529  case QMessageBox::Save:
530  emit saveChanges(this);
531  break;
532 
533  //Discard changes and close viewport
534  case QMessageBox::Discard:
535  emit discardChanges(this);
536  break;
537 
538  //Cancel, don't close viewport
539  case QMessageBox::Cancel:
540  default:
541  canClose = false;
542  break;
543  }
544  }
545 
546 // if (canClose) emit viewportClosed(this);
547  return canClose;
548  }
549 
556  void CubeViewport::cubeChanged(bool changed) {
557  p_saveEnabled = changed;
558  }
559 
566  QSize CubeViewport::sizeHint() const {
567  QSize s(512, 512);
568  return s;
569  }
570 
571 
583  void CubeViewport::setScale(double scale) {
584  // Sanitize the scale value
585  if(scale == p_scale){
586  return;
587  }
588 
589  if (viewport()->width() && viewport()->height()) {
590  // don't let zoom scale be larger than the viewport size
591  double maxScale = max(viewport()->width(),viewport()->height());
592  if (scale > maxScale) {
593  scale = maxScale;
594  }
595  // don't let zoom scale be smaller than one pixel high/wide showing
596  double minScale = 1.0 / (min(cubeSamples(),cubeLines()));
597  if (scale < minScale) {
598  scale = minScale;
599  }
600  }
601 
602  // Resize the scrollbars to reflect the new scale
603  double samp, line;
604  contentsToCube(horizontalScrollBar()->value(), verticalScrollBar()->value(),
605  samp, line);
606  p_scale = scale;
607  updateScrollBars(1, 1); // Setting to 1,1 make sure we don't have bad values
608 
609  // Now update the scroll bar value to the old line/sample
610  int x, y;
611  cubeToContents(samp, line, x, y);
612  updateScrollBars(x, y);
613 
614  p_updatingBuffers = true;
615  if(p_grayBuffer){
617  }
618  if(p_redBuffer){
620  }
621  if(p_greenBuffer){
623  }
624  if(p_blueBuffer){
626  }
627  p_updatingBuffers = false;
628 
630 
631  // Notify other tools about the scale change
632  emit scaleChanged();
633 
634  // Update the display
635  setCaption();
636  paintPixmap(); // Will get rid of old data in the display
637 
638  viewport()->repaint();
639  emit screenPixelsChanged();
640  }
641 
650  void CubeViewport::setScale(double scale, int x, int y) {
651  double samp, line;
652  viewportToCube(x, y, samp, line);
653  setScale(scale, samp, line);
654  }
655 
656 
666  void CubeViewport::setScale(double scale, double sample, double line) {
667  viewport()->setUpdatesEnabled(false);
668 
669  bool wasEnabled = false;
670 
671  if((p_grayBuffer && p_grayBuffer->enabled()) ||
672  (p_redBuffer && p_redBuffer->enabled())) {
673  wasEnabled = true;
674  }
675 
676  if(p_grayBuffer){
677  p_grayBuffer->enable(false);
678  }
679  if(p_redBuffer){
680  p_redBuffer->enable(false);
681  }
682  if(p_greenBuffer){
683  p_greenBuffer->enable(false);
684  }
685  if(p_blueBuffer){
686  p_blueBuffer->enable(false);
687  }
688  if(p_paintPixmap) {
689  p_paintPixmap = false;
690  setScale(scale);
691  p_paintPixmap = true;
692  }
693  else {
694  setScale(scale);
695  }
696 
697  center(sample, line);
698 
699  if(p_grayBuffer){
700  p_grayBuffer->enable(wasEnabled);
701  }
702  if(p_redBuffer){
703  p_redBuffer->enable(wasEnabled);
704  }
705  if(p_greenBuffer){
706  p_greenBuffer->enable(wasEnabled);
707  }
708  if(p_blueBuffer){
709  p_blueBuffer->enable(wasEnabled);
710  }
711 
712  paintPixmap();
713  viewport()->setUpdatesEnabled(true);
714  viewport()->update();
715  emit screenPixelsChanged();
716  }
717 
718 
726  void CubeViewport::center(int x, int y) {
727  double sample, line;
728  viewportToCube(x, y, sample, line);
729  center(sample, line);
730  }
731 
732 
740  void CubeViewport::center(double sample, double line) {
741  int x, y;
742  cubeToContents(sample, line, x, y);
743 
744  x ++;
745  y ++;
746 
747  int panX = horizontalScrollBar()->value() - x;
748  int panY = verticalScrollBar()->value() - y;
749 
750  updateScrollBars(x, y);
751 
752  p_updatingBuffers = true;
753  if(p_grayBuffer){
754  p_grayBuffer->pan(panX, panY);
755  }
756  if(p_redBuffer){
757  p_redBuffer->pan(panX, panY);
758  }
759  if(p_greenBuffer){
760  p_greenBuffer->pan(panX, panY);
761  }
762  if(p_blueBuffer){
763  p_blueBuffer->pan(panX, panY);
764  }
765  p_updatingBuffers = false;
766 
768 
769  shiftPixmap(panX, panY);
770 
771  emit screenPixelsChanged();
772  }
773 
774 
780  for(int rect = 0; rect < p_pixmapPaintRects->size(); rect++) {
781  paintPixmap(*(*p_pixmapPaintRects)[rect]);
782  }
783 
784  p_pixmapPaintRects->clear();
785  }
786 
787 
798  void CubeViewport::contentsToCube(int x, int y,
799  double &sample, double &line) const {
800  sample = x / p_scale;
801  line = y / p_scale;
802  }
803 
804 
815  void CubeViewport::viewportToCube(int x, int y,
816  double &sample, double &line) const {
817  x += horizontalScrollBar()->value();
818  x -= viewport()->width() / 2;
819  y += verticalScrollBar()->value();
820  y -= viewport()->height() / 2;
821  contentsToCube(x, y, sample, line);
822  }
823 
824 
835  void CubeViewport::cubeToContents(double sample, double line,
836  int &x, int &y) const {
837  x = (int)(sample * p_scale + 0.5);
838  y = (int)(line * p_scale + 0.5);
839  }
840 
841 
852  void CubeViewport::cubeToViewport(double sample, double line,
853  int &x, int &y) const {
854  cubeToContents(sample, line, x, y);
855  x -= horizontalScrollBar()->value();
856  x += viewport()->width() / 2;
857  y -= verticalScrollBar()->value();
858  y += viewport()->height() / 2;
859  }
860 
861 
869  void CubeViewport::scrollBy(int dx, int dy) {
870  // Make sure we don't generate bad values outside of the scroll range
871  int x = horizontalScrollBar()->value() + dx;
872  if(x <= 1) {
873  dx = 1 - horizontalScrollBar()->value();
874  }
875  else if(x >= horizontalScrollBar()->maximum()) {
876  dx = horizontalScrollBar()->maximum() - horizontalScrollBar()->value();
877  }
878 
879  // Make sure we don't generate bad values outside of the scroll range
880  int y = verticalScrollBar()->value() + dy;
881  if(y <= 1) {
882  dy = 1 - verticalScrollBar()->value();
883  }
884  else if(y >= verticalScrollBar()->maximum()) {
885  dy = verticalScrollBar()->maximum() - verticalScrollBar()->value();
886  }
887 
888  // Do we do anything?
889  if((dx == 0) && (dy == 0)){
890  return;
891  }
892 
893  // We do so update the scroll bars
894  updateScrollBars(horizontalScrollBar()->value() + dx,
895  verticalScrollBar()->value() + dy);
896 
897  // Scroll the the pixmap
898  scrollContentsBy(-dx, -dy);
899  }
900 
901 
909  void CubeViewport::scrollContentsBy(int dx, int dy) {
910 
911  // We shouldn't do anything if scrollbars are being updated
912  if(viewport()->signalsBlocked()) {
913  return;
914  }
915 
916  // Tell the buffers to update appropriate for the pan and upon completion
917  // they will call bufferUpdated. We don't want bufferUpdated to happen
918  // until afterwards. If only shrinking and no new data then the viewport
919  // buffers will complete immediately. When all buffers don't have their
920  // appropriate actions queued bufferUpdated can't succeed.
921 
922  // Also block paints because we'll repaint it all when we're done
923  // telling each buffer about the pan.
924  bool panQueued = false;
925  QRect bufferXYRect;
926 
927  p_updatingBuffers = true;
928 
929  if(p_grayBuffer) {
930  p_grayBuffer->pan(dx, dy);
931  panQueued |= p_grayBuffer->working();
932  bufferXYRect = p_grayBuffer->bufferXYRect();
933  }
934 
935  if(p_redBuffer) {
936  p_redBuffer->pan(dx, dy);
937  panQueued |= p_redBuffer->working();
938  bufferXYRect = p_redBuffer->bufferXYRect();
939  }
940 
941  if(p_greenBuffer) {
942  p_greenBuffer->pan(dx, dy);
943  panQueued |= p_greenBuffer->working();
944  }
945 
946  if(p_blueBuffer) {
947  p_blueBuffer->pan(dx, dy);
948  panQueued |= p_blueBuffer->working();
949  }
950 
951  p_updatingBuffers = false;
952 
953  // shift the pixmap by x,y if the viewport buffer didn't do it immediately
954  if(panQueued) {
955  shiftPixmap(dx, dy);
956  }
957  else {
958  // Need to do this to clear area outside of cube
959  p_pixmapPaintRects->clear();
960  paintPixmap();
961  }
962 
963  viewport()->update();
964  emit screenPixelsChanged();
965  }
966 
967 
973  if(!p_progressTimer->isActive()) {
974  p_progressTimer->start();
975 
976  emit progressChanged(0);
977  }
978  }
979 
980 
986  QString cubeFileName = p_cube->fileName();
987  QString str = QFileInfo(cubeFileName).fileName();
988  str += QString(" @ ");
989  str += QString::number(p_scale * 100.0);
990  str += QString("% ");
991 
992  if(p_color) {
993  str += QString("(RGB = ");
994  str += QString::number(p_red.band);
995  str += QString(",");
996  str += QString::number(p_green.band);
997  str += QString(",");
998  str += QString::number(p_blue.band);
999  str += QString(")");
1000  }
1001  else {
1002  str += QString("(Gray = ");
1003  str += QString::number(p_gray.band);
1004  str += QString(")");
1005  }
1006 
1007  //If changes have been made make sure to add '*' to the end
1008  if(p_saveEnabled) {
1009  str += "*";
1010  }
1011 
1012  parentWidget()->setWindowTitle(str);
1013  emit windowTitleChanged();
1014  }
1015 
1016 
1023  void CubeViewport::resizeEvent(QResizeEvent *e) {
1024  p_paintPixmap = false;
1025 
1026  // Tell the buffers to update their coefficients to reinitialize
1027  // and have their immediate paint events happen afterwards. Should not
1028  // happen, but if buffers have actions complete immediately and call
1029  // bufferUpdated. We don't want to have bufferUpdated ever when all
1030  // buffers don't have their appropriate actions queued. It can't succeed.
1031  p_updatingBuffers = true;
1032  if(p_grayBuffer){
1034  }
1035  if(p_redBuffer){
1037  }
1038  if(p_greenBuffer){
1040  }
1041  if(p_blueBuffer){
1043  }
1044  p_updatingBuffers = false;
1045 
1046  paintPixmapRects();
1047 
1048  // Change the size of the image and pixmap
1049  if(p_image) {
1050  delete p_image;
1051  p_image = NULL;
1052  }
1053 
1054  p_image = new QImage(viewport()->size(), QImage::Format_RGB32);
1055  p_pixmap = QPixmap(viewport()->size());
1056 
1057  p_paintPixmap = true;
1058 
1059  // Fixup the scroll bars
1060  updateScrollBars(horizontalScrollBar()->value(),
1061  verticalScrollBar()->value());
1062 
1064  "<p><b>Viewport Dimensions:</b> \
1065  <blockQuote>Samples = " +
1066  QString::number(viewport()->width()) + "<br>" +
1067  "Lines = " +
1068  QString::number(viewport()->height()) + "</blockquote></p>";
1069 
1070  // Repaint the pixmap
1071  paintPixmap();
1072 
1073  // Repaint the internal viewport and scroll bars
1074  viewport()->update();
1075  emit screenPixelsChanged();
1076  }
1077 
1078 
1089  void CubeViewport::paintEvent(QPaintEvent *e) {
1090  if(!p_cubeShown || !viewport()->isVisible()){
1091  return;
1092  }
1093  }
1094 
1095 
1104  void CubeViewport::bufferUpdated(QRect rect) {
1105  paintPixmap(rect);
1106 
1107  // Don't repaint from buffer updates if any buffers are working...
1108  // This set of statements fixes a flash of black when in RGB mode
1109  // and a pan (or other operation?) completes. What would happen is
1110  // the first would reset to black then other buffers still working so
1111  // not restored to DN values.
1112  if(p_grayBuffer && p_grayBuffer->working()){
1113  return;
1114  }
1115  if(p_redBuffer && p_redBuffer->working()){
1116  return;
1117  }
1119  return;
1120  }
1121  if(p_blueBuffer && p_blueBuffer->working()){
1122  return;
1123  }
1124 
1125  viewport()->repaint(rect);
1126  }
1127 
1130  QRect rect(0, 0, p_image->width(), p_image->height());
1131  paintPixmap(rect);
1132  }
1133 
1134 
1141  void CubeViewport::paintPixmap(QRect rect) {
1142  if(!p_paintPixmap) {
1143  return;
1144  }
1145 
1146  if(p_updatingBuffers) {
1147  p_pixmapPaintRects->push_back(new QRect(rect));
1148  return;
1149  }
1150 
1151  if(p_pixmap.isNull()){
1152  return;
1153  }
1154 
1155  QPainter p(&p_pixmap);
1156 
1157  p.fillRect(rect, QBrush(p_bgColor));
1158 
1159  QRect dataArea;
1160 
1161  if(p_grayBuffer && p_grayBuffer->enabled()) {
1162  if(p_grayBuffer->working()){
1163  return;
1164  }
1165 
1166  dataArea = QRect(p_grayBuffer->bufferXYRect().intersected(rect));
1167 
1168  for(int y = dataArea.top();
1169  !dataArea.isNull() && y <= dataArea.bottom();
1170  y++) {
1171  const vector< double > & line =
1173 
1174  if(line.size() == 0) {
1175  break;
1176  }
1177 
1178  if(y >= p_image->height()) {
1179  throw IException(IException::Programmer, "y too big", _FILEINFO_);
1180  }
1181 
1182  QRgb *rgb = (QRgb *) p_image->scanLine(y);
1183 
1184  for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1185  int bufferLeft = p_grayBuffer->bufferXYRect().left();
1186  int bufferX = x - bufferLeft;
1187 
1188  if(bufferX >= (int)line.size()){
1189  break;
1190  }
1191 
1192  if(bufferX < 0) {
1193  throw IException(IException::Programmer, "bufferX < 0", _FILEINFO_);
1194  }
1195 
1196  if(x >= p_image->width()) {
1197  throw IException(IException::Programmer, "x too big", _FILEINFO_);
1198  }
1199 
1200  double bufferVal = line.at(bufferX);
1201 
1202  // This is still RGB; the pairs are identical but the boundary
1203  // conditions are different. Display saturations cause this.
1204  int redPix = (int)(p_red.getStretch().Map(bufferVal) + 0.5);
1205  int greenPix = (int)(p_green.getStretch().Map(bufferVal) + 0.5);
1206  int bluePix = (int)(p_blue.getStretch().Map(bufferVal) + 0.5);
1207  rgb[x] = qRgb(redPix, greenPix, bluePix);
1208  }
1209  }
1210  }
1211  else {
1212  if(p_redBuffer && p_redBuffer->enabled()) {
1213  if(p_redBuffer->working() || p_greenBuffer->working() ||
1214  p_blueBuffer->working()) {
1215  return;
1216  }
1217 
1218 
1219  if((p_greenBuffer->bufferXYRect().top() !=
1220  p_redBuffer->bufferXYRect().top()) ||
1221  (p_greenBuffer->bufferXYRect().top() !=
1222  p_blueBuffer->bufferXYRect().top())) {
1224  "Buffer rects mismatched",
1225  _FILEINFO_);
1226  }
1227 
1228  if((p_greenBuffer->bufferXYRect().left() !=
1229  p_redBuffer->bufferXYRect().left()) ||
1230  (p_greenBuffer->bufferXYRect().left() !=
1231  p_blueBuffer->bufferXYRect().left())) {
1233  "Buffer rects mismatched",
1234  _FILEINFO_);
1235  }
1236 
1237  dataArea = QRect(p_redBuffer->bufferXYRect().intersected(rect));
1238 
1239  for(int y = dataArea.top();
1240  !dataArea.isNull() && y <= dataArea.bottom();
1241  y++) {
1242  int bufferLine = y - p_redBuffer->bufferXYRect().top();
1243 
1244  const vector<double> &redLine = p_redBuffer->getLine(bufferLine);
1245  const vector<double> &greenLine = p_greenBuffer->getLine(bufferLine);
1246  const vector<double> &blueLine = p_blueBuffer->getLine(bufferLine);
1247 
1248  if((int)redLine.size() < dataArea.width() ||
1249  (int)greenLine.size() < dataArea.width() ||
1250  (int)blueLine.size() < dataArea.width()) {
1252  "Empty buffer line",
1253  _FILEINFO_);
1254  }
1255 
1256  QRgb *rgb = (QRgb *) p_image->scanLine(y);
1257 
1258  for(int x = dataArea.left(); x <= dataArea.right(); x++) {
1259  int redPix = (int)(p_red.getStretch().Map(redLine[ x - p_redBuffer->bufferXYRect().left()]) + 0.5);
1260  int greenPix = (int)(p_green.getStretch().Map(greenLine[ x - p_greenBuffer->bufferXYRect().left()]) + 0.5);
1261  int bluePix = (int)(p_blue.getStretch().Map(blueLine[ x - p_blueBuffer->bufferXYRect().left()]) + 0.5);
1262 
1263  rgb[x] = qRgb(redPix, greenPix, bluePix);
1264  }
1265  }
1266  }
1267  }
1268 
1269  if(!dataArea.isNull()){
1270  p.drawImage(dataArea.topLeft(), *p_image, dataArea);
1271  }
1272 
1273  // Change whats this info
1274  updateWhatsThis();
1275  }
1276 
1277 
1284  void CubeViewport::shiftPixmap(int dx, int dy) {
1285  if(!p_paintPixmap || !p_pixmap){
1286  return;
1287  }
1288 
1289  // Prep to scroll the pixmap
1290  int drawStartX = dx;
1291  int pixmapStartX = 0;
1292  if(drawStartX < 0) {
1293  drawStartX = 0;
1294  pixmapStartX = -dx;
1295  }
1296 
1297  int drawStartY = dy;
1298  int pixmapStartY = 0;
1299  if(dy < 0) {
1300  drawStartY = 0;
1301  pixmapStartY = -dy;
1302  }
1303 
1304  // Ok we can shift the pixmap and filling
1305  int pixmapDrawWidth = p_pixmap.width() - pixmapStartX + 1;
1306  int pixmapDrawHeight = p_pixmap.height() - pixmapStartY + 1;
1307 
1308  QRect rect(0, 0, p_pixmap.width(), p_pixmap.height());
1309  QPixmap pixmapCopy = p_pixmap.copy();
1310 
1311  QPainter painter(&p_pixmap);
1312  painter.fillRect(rect, QBrush(p_bgColor));
1313  painter.drawPixmap(drawStartX, drawStartY,
1314  pixmapCopy,
1315  pixmapStartX, pixmapStartY,
1316  pixmapDrawWidth, pixmapDrawHeight);
1317  painter.end();
1318 
1319  // Now fill in the left or right side
1320  QRect xFillRect;
1321  QRect yFillRect;
1322 
1323  if(dx > 0) {
1324  xFillRect = QRect(QPoint(0, 0),
1325  QPoint(dx, p_pixmap.height()));
1326  }
1327  else {
1328  if(dx < 0){
1329  xFillRect = QRect(QPoint(p_pixmap.width() + dx, 0),
1330  QPoint(p_pixmap.width(), p_pixmap.height()));
1331  }
1332  }
1333 
1334  // Fill in the top or bottom side
1335  if(dy > 0) {
1336  yFillRect = QRect(QPoint(0, 0),
1337  QPoint(p_pixmap.width(), dy));
1338  }
1339  else {
1340  if(dy < 0){
1341  yFillRect = QRect(QPoint(0, p_pixmap.height() + dy),
1342  QPoint(p_pixmap.width(), p_pixmap.height()));
1343  }
1344  }
1345 
1346  if(dx != 0) {
1347  paintPixmap(xFillRect);
1348  }
1349 
1350  if(dy != 0) {
1351  paintPixmap(yFillRect);
1352  }
1353 
1354  viewport()->update();
1355  }
1356 
1365  {
1366  // Get Cube Info
1367  PvlObject whatsThisObj = PvlObject("WhatsThis");
1368  whatsThisObj += PvlKeyword("Cube", p_cube->fileName());
1369 
1370  PvlGroup cubeGrp("CubeDimensions");
1371  cubeGrp += PvlKeyword("Samples", toString(p_cube->sampleCount()));
1372  cubeGrp += PvlKeyword("Lines", toString(p_cube->lineCount()));
1373  cubeGrp += PvlKeyword("Bands", toString(p_cube->bandCount()));
1374  whatsThisObj += cubeGrp;
1375 
1376  // Get Viewport Info
1377  PvlGroup viewportGrp("ViewportDimensions");
1378  viewportGrp += PvlKeyword("Samples", toString(viewport()->width()));
1379  viewportGrp += PvlKeyword("Lines", toString(viewport()->height()));
1380  whatsThisObj += viewportGrp;
1381 
1382  // Get Cube area Info
1383  PvlObject cubeAreaPvl("CubeArea");
1384  PvlGroup bandGrp("Bands");
1385 
1386  PvlKeyword filterName;
1387  getBandFilterName(filterName);
1388  int iFilterSize = filterName.size();
1389 
1390  // color
1391  if(p_color ) {
1392  PvlKeyword virtualKey("Virtual"), physicalKey("Physical"), filterNameKey;
1393  int iRedBand = p_redBuffer->getBand();
1394  int iGreenBand = p_greenBuffer->getBand();
1395  int iBlueBand = p_blueBuffer->getBand();
1396 
1397  bandGrp += PvlKeyword("Color", "RGB");
1398 
1399  virtualKey = toString(iRedBand);
1400  virtualKey += toString(iGreenBand);
1401  virtualKey += toString(iBlueBand);
1402  bandGrp += virtualKey;
1403 
1404  physicalKey = toString(p_cube->physicalBand(iRedBand));
1405  physicalKey += toString(p_cube->physicalBand(iGreenBand));
1406  physicalKey += toString(p_cube->physicalBand(iBlueBand));
1407  bandGrp += physicalKey;
1408 
1409  if(iFilterSize) {
1410  if(iRedBand <= iFilterSize) {
1411  filterNameKey += filterName[iRedBand-1];
1412  }
1413  else {
1414  filterNameKey += "None";
1415  }
1416 
1417  if(iGreenBand <= iFilterSize) {
1418  filterNameKey += filterName[iGreenBand-1];
1419  }
1420  else {
1421  filterNameKey += "None";
1422  }
1423 
1424  if(iBlueBand <= iFilterSize) {
1425  filterNameKey += filterName[iBlueBand-1];
1426  }
1427  else {
1428  filterNameKey += "None";
1429  }
1430  bandGrp += filterNameKey;
1431  }
1432  }
1433  else { // gray
1434  int iGrayBand = p_grayBuffer->getBand();
1435 
1436  bandGrp += PvlKeyword("Color", "Gray");
1437 
1438  bandGrp += PvlKeyword("Virtual", toString(iGrayBand));
1439  bandGrp += PvlKeyword("Physical", toString(p_cube->physicalBand(iGrayBand)));
1440 
1441  if(iFilterSize && iGrayBand <= iFilterSize) {
1442  bandGrp += PvlKeyword("FilterName", filterName[iGrayBand-1]);
1443  }
1444  }
1445 
1446  //start, end line and sample
1447  double sl, ss, es, el;
1448  getCubeArea(ss, es, sl, el);
1449  cubeAreaPvl += PvlKeyword("StartSample", toString(int(ss + 0.5)));
1450  cubeAreaPvl += PvlKeyword("EndSample", toString(int(es + 0.5)));
1451  cubeAreaPvl += PvlKeyword("StartLine", toString(int(sl + 0.5)));
1452  cubeAreaPvl += PvlKeyword("EndLine", toString(int(el + 0.5)));
1453  cubeAreaPvl += bandGrp;
1454  whatsThisObj += cubeAreaPvl;
1455  pWhatsThisPvl += whatsThisObj;
1456  }
1457 
1467  {
1468  // get the band info
1469  Pvl* cubeLbl = p_cube->label();
1470  PvlObject isisObj = cubeLbl->findObject("IsisCube");
1471  if (isisObj.hasGroup("BandBin")) {
1472  PvlGroup bandBinGrp = isisObj.findGroup("BandBin");
1473  if(bandBinGrp.hasKeyword("FilterName")) {
1474  pFilterNameKey =bandBinGrp.findKeyword("FilterName") ;
1475  }
1476  }
1477  }
1478 
1487  void CubeViewport::getCubeArea(double & pdStartSample, double & pdEndSample,
1488  double & pdStartLine, double & pdEndLine)
1489  {
1490  viewportToCube(0, 0, pdStartSample, pdStartLine);
1491  if(pdStartSample < 1.0){
1492  pdStartSample = 1.0;
1493  }
1494  if(pdStartLine < 1.0){
1495  pdStartLine = 1.0;
1496  }
1497 
1498  //end line and samples
1499  viewportToCube(viewport()->width() - 1, viewport()->height() - 1, pdEndSample, pdEndLine);
1500  if(pdEndSample > cubeSamples()){
1501  pdEndSample = cubeSamples();
1502  }
1503  if(pdEndLine > cubeLines()){
1504  pdEndLine = cubeLines();
1505  }
1506  }
1507 
1513  //start, end line and sample
1514  double sl, ss, es, el;
1515  getCubeArea(ss, es, sl, el);
1516 
1517  QString sBandInfo ;
1518  PvlKeyword filterNameKey;
1519  getBandFilterName(filterNameKey);
1520  int iFilterSize = filterNameKey.size();
1521 
1522  // color
1523  if(p_color ) {
1524  int iRedBand = p_redBuffer->getBand();
1525  int iGreenBand = p_greenBuffer->getBand();
1526  int iBlueBand = p_blueBuffer->getBand();
1527 
1528  sBandInfo = "Bands(RGB)&nbsp;Virtual = " +
1529  QString::number(iRedBand) + ", ";
1530  sBandInfo += QString::number(iGreenBand) + ", ";
1531  sBandInfo += QString::number(iBlueBand) + " ";
1532 
1533  sBandInfo += "Physical = " +
1534  QString::number(p_cube->physicalBand(iRedBand)) + ", ";
1535  sBandInfo += QString::number(p_cube->physicalBand(iGreenBand)) + ", ";
1536  sBandInfo += QString::number(p_cube->physicalBand(iBlueBand));
1537 
1538  if(iFilterSize) {
1539  sBandInfo += "<br>FilterName = ";
1540  if(iRedBand <= iFilterSize) {
1541  sBandInfo += QString(filterNameKey[iRedBand-1]);
1542  }
1543  else {
1544  sBandInfo += "None";
1545  }
1546  sBandInfo += ", ";
1547 
1548  if(iGreenBand <= iFilterSize) {
1549  sBandInfo += QString(filterNameKey[iGreenBand-1]);
1550  }
1551  else {
1552  sBandInfo += "None";
1553  }
1554  sBandInfo += ", ";
1555 
1556  if(iBlueBand <= iFilterSize) {
1557  sBandInfo += QString(filterNameKey[iBlueBand-1]);
1558  }
1559  else {
1560  sBandInfo += "None";
1561  }
1562  }
1563  }
1564  else { // gray
1565  int iGrayBand = p_grayBuffer->getBand();
1566 
1567  sBandInfo = "Band(Gray)&nbsp;Virtual = " + QString::number(iGrayBand) + " ";
1568 
1569  sBandInfo += "Physical = " + QString::number(p_cube->physicalBand(iGrayBand));
1570 
1571  if(iFilterSize && iGrayBand <= iFilterSize) {
1572  sBandInfo += "<br>FilterName = " + QString(filterNameKey[iGrayBand-1]);
1573  }
1574  }
1575 
1576  QString area =
1577  "<p><b>Visible Cube Area:</b><blockQuote> \
1578  Samples = " + QString::number(int(ss + 0.5)) + "-" +
1579  QString::number(int(es + 0.5)) + "<br> \
1580  Lines = " + QString::number(int(sl + 0.5)) + "-" +
1581  QString::number(int(el + 0.5)) + "<br> " +
1582  sBandInfo + "</blockQuote></p>";
1583 
1584  QString fullWhatsThis = p_whatsThisText + area + p_cubeWhatsThisText + p_viewportWhatsThisText;
1585  setWhatsThis(fullWhatsThis);
1586  viewport()->setWhatsThis(fullWhatsThis);
1587  }
1588 
1598  double CubeViewport::redPixel(int sample, int line) {
1599  p_pntBrick->SetBasePosition(sample, line, p_red.band);
1600  p_cube->read(*p_pntBrick);
1601  return (*p_pntBrick)[0];
1602  }
1603 
1604 
1614  double CubeViewport::greenPixel(int sample, int line) {
1615  p_pntBrick->SetBasePosition(sample, line, p_green.band);
1616  p_cube->read(*p_pntBrick);
1617  return (*p_pntBrick)[0];
1618  }
1619 
1620 
1630  double CubeViewport::bluePixel(int sample, int line) {
1631  p_pntBrick->SetBasePosition(sample, line, p_blue.band);
1632  p_cube->read(*p_pntBrick);
1633  return (*p_pntBrick)[0];
1634  }
1635 
1636 
1646  double CubeViewport::grayPixel(int sample, int line) {
1647  p_pntBrick->SetBasePosition(sample, line, p_gray.band);
1648  p_cube->read(*p_pntBrick);
1649  return (*p_pntBrick)[0];
1650  }
1651 
1652 
1655  return p_gray.getStretch();
1656  }
1657 
1658 
1661  return p_red.getStretch();
1662  };
1663 
1664 
1667  return p_green.getStretch();
1668  };
1669 
1670 
1673  return p_blue.getStretch();
1674  };
1675 
1676 
1686  bool CubeViewport::eventFilter(QObject *o, QEvent *e) {
1687  // Handle standard mouse tracking on the viewport
1688  if(o == viewport()) {
1689  switch(e->type()) {
1690  case QEvent::Enter: {
1691  viewport()->setMouseTracking(true);
1692  emit mouseEnter();
1693  return true;
1694  }
1695 
1696  case QEvent::MouseMove: {
1697  QMouseEvent *m = (QMouseEvent *) e;
1698  emit mouseMove(m->pos());
1699  emit mouseMove(m->pos(), (Qt::MouseButton)(m->button() +
1700  m->modifiers()));
1701  return true;
1702  }
1703 
1704  case QEvent::Leave: {
1705  viewport()->setMouseTracking(false);
1706  emit mouseLeave();
1707  return true;
1708  }
1709 
1710  case QEvent::MouseButtonPress: {
1711  QMouseEvent *m = (QMouseEvent *) e;
1712  emit mouseButtonPress(m->pos(),
1713  (Qt::MouseButton)(m->button() + m->modifiers()));
1714  return true;
1715  }
1716 
1717  case QEvent::MouseButtonRelease: {
1718  QMouseEvent *m = (QMouseEvent *) e;
1719  emit mouseButtonRelease(m->pos(),
1720  (Qt::MouseButton)(m->button() + m->modifiers()));
1721  return true;
1722  }
1723 
1724  case QEvent::MouseButtonDblClick: {
1725  QMouseEvent *m = (QMouseEvent *) e;
1726  emit mouseDoubleClick(m->pos());
1727  return true;
1728  }
1729 
1730  default: {
1731  return false;
1732  }
1733  }
1734  }
1735  else {
1736  return QAbstractScrollArea::eventFilter(o, e);
1737  }
1738  }
1739 
1740 
1747  void CubeViewport::keyPressEvent(QKeyEvent *e) {
1748  if(e->key() == Qt::Key_Plus) {
1749  double scale = p_scale * 2.0;
1750  setScale(scale);
1751  e->accept();
1752  }
1753  else if(e->key() == Qt::Key_Minus) {
1754  double scale = p_scale / 2.0;
1755  setScale(scale);
1756  e->accept();
1757  }
1758  else if(e->key() == Qt::Key_Up) {
1759  moveCursor(0, -1);
1760  e->accept();
1761  }
1762  else if(e->key() == Qt::Key_Down) {
1763  moveCursor(0, 1);
1764  e->accept();
1765  }
1766  else if(e->key() == Qt::Key_Left) {
1767  moveCursor(-1, 0);
1768  e->accept();
1769  }
1770  else if(e->key() == Qt::Key_Right) {
1771  moveCursor(1, 0);
1772  e->accept();
1773  }
1774  else {
1775  QAbstractScrollArea::keyPressEvent(e);
1776  }
1777  }
1778 
1779 
1787  QPoint g = QCursor::pos();
1788  QPoint v = viewport()->mapFromGlobal(g);
1789  if(v.x() < 0){
1790  return false;
1791  }
1792  if(v.y() < 0){
1793  return false;
1794  }
1795  if(v.x() >= viewport()->width()){
1796  return false;
1797  }
1798  if(v.y() >= viewport()->height()){
1799  return false;
1800  }
1801  return true;
1802  }
1803 
1804 
1812  QPoint g = QCursor::pos();
1813  return viewport()->mapFromGlobal(g);
1814  }
1815 
1816 
1824  void CubeViewport::moveCursor(int x, int y) {
1825  QPoint g = QCursor::pos();
1826  g += QPoint(x, y);
1827  QPoint v = viewport()->mapFromGlobal(g);
1828  if(v.x() < 0){
1829  return;
1830  }
1831  if(v.y() < 0){
1832  return;
1833  }
1834  if(v.x() >= viewport()->width()){
1835  return;
1836  }
1837  if(v.y() >= viewport()->height()){
1838  return;
1839  }
1840  QCursor::setPos(g);
1841  }
1842 
1843 
1851  void CubeViewport::setCursorPosition(int x, int y) {
1852  QPoint g(x, y);
1853  QPoint v = viewport()->mapToGlobal(g);
1854  QCursor::setPos(v);
1855  }
1856 
1857 
1865  void CubeViewport::updateScrollBars(int x, int y) {
1866  viewport()->blockSignals(true);
1867 
1868  verticalScrollBar()->setValue(1);
1869  verticalScrollBar()->setMinimum(1);
1870  verticalScrollBar()->setMaximum((int)(ceil(cubeLines() * p_scale) + 0.5));
1871  verticalScrollBar()->setPageStep(viewport()->height() / 2);
1872 
1873  horizontalScrollBar()->setValue(1);
1874  horizontalScrollBar()->setMinimum(1);
1875  horizontalScrollBar()->setMaximum((int)(ceil(cubeSamples() * p_scale) + 0.5));
1876  horizontalScrollBar()->setPageStep(viewport()->width() / 2);
1877 
1878  if(horizontalScrollBar()->value() != x || verticalScrollBar()->value() != y) {
1879  horizontalScrollBar()->setValue(x);
1880  verticalScrollBar()->setValue(y);
1881  emit scaleChanged();
1882  }
1883 
1884  QApplication::sendPostedEvents(viewport(), 0);
1885  viewport()->blockSignals(false);
1886  }
1887 
1888 
1895  void CubeViewport::viewGray(int band) {
1896  p_gray.band = band;
1897  p_color = false;
1898  setCaption();
1899 
1900  if(!p_grayBuffer){
1902  p_cubeId);
1903  }
1904 
1905  if(p_redBuffer){
1906  delete p_redBuffer;
1907  }
1908  p_redBuffer = NULL;
1909 
1910  if(p_greenBuffer){
1911  delete p_greenBuffer;
1912  }
1913  p_greenBuffer = NULL;
1914 
1915  if(p_blueBuffer){
1916  delete p_blueBuffer;
1917  }
1918  p_blueBuffer = NULL;
1919 
1920  if(p_grayBuffer->getBand() != band) {
1921  int oldBand = p_grayBuffer->getBand();
1922 
1923  if(oldBand >= 0) {
1924  if((*p_knownStretches)[oldBand - 1]) {
1925  delete(*p_knownStretches)[oldBand - 1];
1926  }
1927 
1928  (*p_knownStretches)[oldBand - 1] = new Stretch(p_gray.getStretch());
1929  }
1930 
1931  p_grayBuffer->setBand(band);
1932  p_gray.band = band;
1933 
1934  if((*p_knownStretches)[band - 1]) {
1935  stretchGray(*(*p_knownStretches)[band - 1]);
1936  }
1937  else {
1939  }
1940  }
1941 
1942 
1943  if(p_camera) {
1944  p_camera->SetBand(band);
1945  }
1946 
1947  viewport()->repaint();
1948  }
1949 
1951  for(int stretch = 0; stretch < p_knownStretches->size(); stretch++) {
1952  if((*p_knownStretches)[stretch]) {
1953  delete(*p_knownStretches)[stretch];
1954  (*p_knownStretches)[stretch] = NULL;
1955  }
1956  }
1957  }
1958 
1959 
1961  for(int index = 0; index < p_knownStretches->size(); index ++) {
1962  if((*p_knownStretches)[index]) {
1963  delete(*p_knownStretches)[index];
1964  }
1965 
1966  (*p_knownStretches)[index] = new Stretch(stretch);
1967  }
1968  }
1969 
1970 
1979  void CubeViewport::viewRGB(int rband, int gband, int bband) {
1980  p_red.band = rband;
1981  p_green.band = gband;
1982  p_blue.band = bband;
1983  p_color = true;
1984  setCaption();
1985 
1986  if(!p_redBuffer) {
1988  }
1989 
1990  if(!p_greenBuffer) {
1992  }
1993 
1994  if(!p_blueBuffer) {
1996  }
1997 
1998  if(p_redBuffer->getBand() != rband) {
1999  int oldBand = p_redBuffer->getBand();
2000 
2001  // Remember current stretch for future band changes
2002  if(oldBand >= 0) {
2003  if((*p_knownStretches)[oldBand - 1]) {
2004  delete(*p_knownStretches)[oldBand - 1];
2005  }
2006 
2007  (*p_knownStretches)[oldBand - 1] = new Stretch(p_red.getStretch());
2008  }
2009 
2010  p_redBuffer->setBand(rband);
2011  p_red.band = rband;
2012 
2013  if((*p_knownStretches)[rband - 1]) {
2014  p_red.setStretch(*(*p_knownStretches)[rband - 1]);
2015  }
2016  else {
2018  }
2019  }
2020 
2021  if(p_greenBuffer->getBand() != gband) {
2022  int oldBand = p_greenBuffer->getBand();
2023 
2024  // Remember current stretch for future band changes
2025  if(oldBand >= 0) {
2026  if((*p_knownStretches)[oldBand - 1]) {
2027  delete(*p_knownStretches)[oldBand - 1];
2028  }
2029 
2030  (*p_knownStretches)[oldBand - 1] = new Stretch(p_green.getStretch());
2031  }
2032 
2033  p_greenBuffer->setBand(gband);
2034  p_green.band = gband;
2035 
2036  if((*p_knownStretches)[gband - 1]) {
2037  p_green.setStretch(*(*p_knownStretches)[gband - 1]);
2038  }
2039  else {
2041  }
2042  }
2043 
2044  if(p_blueBuffer->getBand() != bband) {
2045  int oldBand = p_blueBuffer->getBand();
2046 
2047  // Remember current stretch for future band changes
2048  if(oldBand >= 0) {
2049  if((*p_knownStretches)[oldBand - 1]) {
2050  delete(*p_knownStretches)[oldBand - 1];
2051  }
2052 
2053  (*p_knownStretches)[oldBand - 1] = new Stretch(p_blue.getStretch());
2054  }
2055 
2056  p_blueBuffer->setBand(bband);
2057  p_blue.band = bband;
2058 
2059  if((*p_knownStretches)[bband - 1]) {
2060  p_blue.setStretch(*(*p_knownStretches)[bband - 1]);
2061  }
2062  else {
2064  }
2065  }
2066 
2067  if(p_grayBuffer){
2068  delete p_grayBuffer;
2069  }
2070  p_grayBuffer = NULL;
2071 
2072  if(p_camera) {
2073  p_camera->SetBand(rband);
2074  }
2075  }
2076 
2077 
2084  void CubeViewport::stretchGray(const QString &string) {
2085  Stretch stretch;
2086  stretch.Parse(string);
2087  stretchGray(stretch);
2088  }
2089 
2090 
2096  void CubeViewport::stretchRed(const QString &string) {
2097  Stretch stretch;
2098  stretch.Parse(string);
2099  stretchRed(stretch);
2100  }
2101 
2102 
2108  void CubeViewport::stretchGreen(const QString &string) {
2109  Stretch stretch;
2110  stretch.Parse(string);
2111  stretchGreen(stretch);
2112  }
2113 
2114 
2120  void CubeViewport::stretchBlue(const QString &string) {
2121  Stretch stretch;
2122  stretch.Parse(string);
2123  stretchBlue(stretch);
2124  }
2125 
2126 
2131  if(!p_globalStretches){
2132  return;
2133  }
2134 
2135  if(isGray()) {
2136  if((*p_globalStretches)[grayBand() - 1]) {
2138  }
2139  }
2140  else {
2141  if((*p_globalStretches)[redBand() - 1]) {
2142  stretchRed(*(*p_globalStretches)[redBand() - 1]);
2143  }
2144 
2145  if((*p_globalStretches)[greenBand() - 1]) {
2147  }
2148 
2149  if((*p_globalStretches)[blueBand() - 1]) {
2151  }
2152  }
2153  }
2154 
2155 
2161  void CubeViewport::stretchGray(const Stretch &stretch) {
2162  // Assume first stretch is always the global stretch (and it should be)
2163  if((*p_globalStretches)[grayBand() - 1] == NULL && stretch.Pairs()) {
2164  (*p_globalStretches)[grayBand() - 1] = new Stretch(stretch);
2165  }
2166 
2167  p_gray.setStretch(stretch);
2168 
2169  Stretch newRed(p_red.getStretch());
2170  newRed.CopyPairs(stretch);
2171  p_red.setStretch(newRed);
2172 
2173  Stretch newGreen(p_green.getStretch());
2174  newGreen.CopyPairs(stretch);
2175  p_green.setStretch(newGreen);
2176 
2177  Stretch newBlue(p_blue.getStretch());
2178  newBlue.CopyPairs(stretch);
2179  p_blue.setStretch(newBlue);
2180 
2181  paintPixmap();
2182  viewport()->update();
2183  }
2184 
2185 
2191  void CubeViewport::stretchRed(const Stretch &stretch) {
2192  p_red.setStretch(stretch);
2193 
2194  // Assume first stretch is always the global stretch (and it should be)
2195  if((*p_globalStretches)[redBand() - 1] == NULL && stretch.Pairs()) {
2196  (*p_globalStretches)[redBand() - 1] = new Stretch(p_red.getStretch());
2197  }
2198 
2199  paintPixmap();
2200  viewport()->update();
2201  }
2202 
2203 
2209  void CubeViewport::stretchGreen(const Stretch &stretch) {
2210  p_green.setStretch(stretch);
2211 
2212  // Assume first stretch is always the global stretch (and it should be)
2213  if((*p_globalStretches)[greenBand() - 1] == NULL && stretch.Pairs()) {
2214  (*p_globalStretches)[greenBand() - 1] = new Stretch(p_green.getStretch());
2215  }
2216 
2217  paintPixmap();
2218  viewport()->update();
2219  }
2220 
2221 
2227  void CubeViewport::stretchBlue(const Stretch &stretch) {
2228  p_blue.setStretch(stretch);
2229 
2230  // Assume first stretch is always the global stretch (and it should be)
2231  if((*p_globalStretches)[blueBand() - 1] == NULL && stretch.Pairs()) {
2232  (*p_globalStretches)[blueBand() - 1] = new Stretch(p_blue.getStretch());
2233  }
2234 
2235  paintPixmap();
2236  viewport()->update();
2237  }
2238 
2239 
2247  double CubeViewport::fitScale() const {
2248  double sampScale = (double) viewport()->width() / (double) cubeSamples();
2249  double lineScale = (double) viewport()->height() / (double) cubeLines();
2250  double scale = sampScale < lineScale ? sampScale : lineScale;
2251 // scale = floor(scale * 100.0) / 100.0;
2252  return scale;
2253  }
2254 
2255 
2263  double scale = (double) viewport()->width() / (double) cubeSamples();
2264 
2265 // scale = floor(scale * 100.0) / 100.0;
2266  return scale;
2267  }
2268 
2276  double scale = (double) viewport()->height() / (double) cubeLines();
2277 
2278 // scale = floor(scale * 100.0) / 100.0;
2279  return scale;
2280  }
2281 
2289  void CubeViewport::cubeContentsChanged(QRect cubeRect) {
2290  //start sample/line and end sample/line
2291  double ss, sl, es, el;
2292  ss = (double)(cubeRect.left()) - 1.;
2293  sl = (double)(cubeRect.top()) - 1.;
2294  es = (double)(cubeRect.right()) + 1.;
2295  el = (double)(cubeRect.bottom()) + 1.;
2296  if(ss < 1){
2297  ss = 0.5;
2298  }
2299  if(sl < 1){
2300  sl = 0.5;
2301  }
2302  if(es > cube()->sampleCount()){
2303  es = cube()->sampleCount() + 0.5;
2304  }
2305  if(el > cube()->lineCount()){
2306  el = cube()->lineCount() + 0.5;
2307  }
2308 
2309  //start x/y and end x/y
2310  int sx, sy, ex, ey;
2311 
2312  cubeToViewport(ss, sl, sx, sy);
2313  cubeToViewport(es, el, ex, ey);
2314  if(sx < 0){
2315  sx = 0;
2316  }
2317  if(sy < 0){
2318  sy = 0;
2319  }
2320  if(ex > viewport()->width()){
2321  ex = viewport()->width();
2322  }
2323  if(ey > viewport()->height()){
2324  ey = viewport()->height();
2325  }
2326  QRect vpRect(sx, sy, ex - sx + 1, ey - sy + 1);
2327 
2328  p_updatingBuffers = true;
2329  if(p_grayBuffer){
2330  p_grayBuffer->fillBuffer(vpRect);
2331  }
2332  if(p_redBuffer){
2333  p_redBuffer->fillBuffer(vpRect);
2334  }
2335  if(p_greenBuffer){
2336  p_greenBuffer->fillBuffer(vpRect);
2337  }
2338  if(p_blueBuffer){
2339  p_blueBuffer->fillBuffer(vpRect);
2340  }
2341  p_updatingBuffers = false;
2342 
2343  paintPixmapRects();
2344  }
2345 
2346 
2353  void CubeViewport::changeCursor(QCursor cursor) {
2354  viewport()->setCursor(cursor);
2355  }
2356 
2357 
2358  CubeViewport::BandInfo::BandInfo() : band(1), stretch(NULL) {
2359  stretch = new Stretch;
2360  stretch->SetNull(0.0);
2361  stretch->SetLis(0.0);
2362  stretch->SetLrs(0.0);
2363  stretch->SetHis(255.0);
2364  stretch->SetHrs(255.0);
2365  stretch->SetMinimum(0.0);
2366  stretch->SetMaximum(255.0);
2367  };
2368 
2369 
2370  CubeViewport::BandInfo::BandInfo(const CubeViewport::BandInfo &other) :
2371  band(other.band) {
2372  stretch = NULL;
2373  stretch = new Stretch(*other.stretch);
2374  }
2375 
2376 
2377  CubeViewport::BandInfo::~BandInfo() {
2378  if(stretch) {
2379  delete stretch;
2380  stretch = NULL;
2381  }
2382  }
2383 
2384 
2385  Stretch CubeViewport::BandInfo::getStretch() const {
2386  ASSERT_PTR(stretch);
2387 
2388  return *stretch;
2389  }
2390 
2391 
2392  void CubeViewport::BandInfo::setStretch(const Stretch &newStretch) {
2393  *stretch = newStretch;
2394  }
2395 
2396 
2397  const CubeViewport::BandInfo &CubeViewport::BandInfo::operator=(
2398  CubeViewport::BandInfo other) {
2399  ASSERT_PTR(other.stretch);
2400 
2401  stretch = NULL;
2402  stretch = new Stretch;
2403  *stretch = *other.stretch;
2404  band = other.band;
2405 
2406  return *this;
2407  }
2408 
2409 }