From aec8abdf5fb2069e0af3db0c66e8ae3fd26033f9 Mon Sep 17 00:00:00 2001 From: Julien Michel <julien.michel@c-s.fr> Date: Fri, 16 Feb 2007 17:15:28 +0000 Subject: [PATCH] Nouvelle visu. --- Code/Visu/otbImageViewer.h | 165 ++++++++ Code/Visu/otbImageViewer.txx | 528 ++++++++++++++++++++++++ Code/Visu/otbImageViewerScrollWidget.h | 138 +++++++ Code/Visu/otbImageViewerZoomWidget.h | 157 +++++++ Testing/Code/Visu/otbImageViewer.cxx | 66 +++ Testing/Code/Visu/otbImageViewerNew.cxx | 47 +++ 6 files changed, 1101 insertions(+) create mode 100644 Code/Visu/otbImageViewer.h create mode 100644 Code/Visu/otbImageViewer.txx create mode 100644 Code/Visu/otbImageViewerScrollWidget.h create mode 100644 Code/Visu/otbImageViewerZoomWidget.h create mode 100644 Testing/Code/Visu/otbImageViewer.cxx create mode 100644 Testing/Code/Visu/otbImageViewerNew.cxx diff --git a/Code/Visu/otbImageViewer.h b/Code/Visu/otbImageViewer.h new file mode 100644 index 0000000000..0b4b1798a6 --- /dev/null +++ b/Code/Visu/otbImageViewer.h @@ -0,0 +1,165 @@ +/*========================================================================= + +Program: ORFEO Toolbox +Language: C++ +Date: $Date$ +Version: $Revision$ + + +Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. +See OTBCopyright.txt for details. + + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef __otbImageViewer_h +#define __otbImageViewer_h + +#include <string> +#include "itkObject.h" +#include "otbImageViewerScrollWidget.h" +#include "otbImageViewerZoomWidget.h" +#include "otbImageViewerFullWidget.h" +#include "otbStreamingShrinkImageFilter.h" +#include "otbImageWidgetBoxForm.h" +#include "itkListSample.h" +#include "itkCovarianceCalculator.h" +#include "itkMacro.h" +#include <FL/Fl_Output.H> + + +namespace otb +{ + /** + * + */ +template <class TPixel> +class ITK_EXPORT ImageViewer + : public itk::ProcessObject +{ + public: + /** Standard class typedefs */ + typedef ImageViewer Self; + typedef itk::ProcessObject Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImageViewer,itk::ProcessObject); + + /// Template pixel type + typedef TPixel InputPixelType; + typedef otb::ImageViewerScrollWidget<InputPixelType> ScrollWidgetType; + typedef otb::ImageViewerZoomWidget<InputPixelType> ZoomWidgetType; + typedef otb::ImageViewerFullWidget<InputPixelType> FullWidgetType; + + typedef typename ScrollWidgetType::ImageType ImageType; + typedef typename ImageType::Pointer ImagePointerType; + typedef typename ImageType::IndexType IndexType; + typedef typename ImageType::SizeType SizeType; + typedef typename ImageType::PixelType PixelType; + typedef typename ImageType::RegionType RegionType; + typedef typename ScrollWidgetType::VectorPixelType VectorPixelType; + typedef typename ScrollWidgetType::Pointer ScrollWidgetPointerType; + typedef typename ZoomWidgetType::Pointer ZoomWidgetPointerType; + typedef typename FullWidgetType::Pointer FullWidgetPointerType; + + + typedef itk::Vector<InputPixelType,3> MeasurementVectorType; + typedef itk::Statistics::ListSample<VectorPixelType> ListSampleType; + typedef itk::Statistics::CovarianceCalculator<ListSampleType> CovarianceCalculatorType; + + typedef otb::StreamingShrinkImageFilter<ImageType,ImageType> ShrinkFilterType; + typedef typename ShrinkFilterType::Pointer ShrinkFilterPointerType; + + typedef otb::ImageWidgetBoxForm BoxType; + typedef typename BoxType::Pointer BoxPointerType; + typedef typename BoxType::ColorType ColorType; + + itkGetMacro(Built,bool); + itkGetMacro(ShrinkFactor,unsigned int); + itkSetMacro(RedChannelIndex,unsigned int); + itkGetMacro(RedChannelIndex,unsigned int); + itkSetMacro(GreenChannelIndex,unsigned int); + itkGetMacro(GreenChannelIndex,unsigned int); + itkSetMacro(BlueChannelIndex,unsigned int); + itkGetMacro(BlueChannelIndex,unsigned int); + + + /** Set the input image */ + virtual void SetImage(itk::ImageBase<2> * img); + /** Show the viewer (Update) */ + virtual void Show(void); + + virtual void ComputeNormalizationFactors(void); + + void Build(void); + virtual void Update(void); + + virtual void UpdateFullWidget(void); + virtual void UpdateScrollWidget(void); + virtual void UpdateZoomWidget(void); + + virtual void ChangeZoomViewedRegion(IndexType clickedIndex); + virtual void ChangeFullViewedRegion(IndexType clickedIndex); + virtual RegionType ComputeConstrainedRegion(RegionType smallRegion, RegionType bigRegion); + + virtual void PrintPixLocVal(std::string str); + +protected: + // Constructor and destructor + ImageViewer(); + ~ImageViewer(); + + /** Hide all Image View Windows */ + virtual void Hide(void); + + private: + /// zoom widget component + ZoomWidgetPointerType m_ZoomWidget; + /// scroll widget component + ScrollWidgetPointerType m_ScrollWidget; + /// full widget component + FullWidgetPointerType m_FullWidget; + /// The image to view + ImagePointerType m_InputImage; + bool m_UseScroll; + unsigned int m_ScrollMaxInitialSize; + unsigned int m_FullMaxInitialSize; + unsigned m_ZoomMaxInitialSize; + double m_ImageGeometry; + unsigned int m_ScrollLimitSize; + Fl_Window * m_FullWindow; + Fl_Window * m_ScrollWindow; + Fl_Window * m_ZoomWindow; + Fl_Window * m_PixLocWindow; + Fl_Output * m_PixLocOutput; + + ShrinkFilterPointerType m_Shrink; + unsigned int m_ShrinkFactor; + ColorType m_Color; + bool m_Built; + + VectorPixelType m_MinComponentValue; + VectorPixelType m_MaxComponentValue; + + unsigned int m_RedChannelIndex; + unsigned int m_GreenChannelIndex; + unsigned int m_BlueChannelIndex; + +}; + + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbImageViewer.txx" +#endif + +#endif diff --git a/Code/Visu/otbImageViewer.txx b/Code/Visu/otbImageViewer.txx new file mode 100644 index 0000000000..b2791dbe1e --- /dev/null +++ b/Code/Visu/otbImageViewer.txx @@ -0,0 +1,528 @@ +/*========================================================================= + +Program: ORFEO Toolbox +Language: C++ +Date: $Date$ +Version: $Revision$ + + +Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. +See OTBCopyright.txt for details. + + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef _otbImageViewer_txx +#define _otbImageViewer_txx + + +#include "otbImageViewer.h" +#include "otbFltkFilterWatcher.h" +#include "otbMacro.h" +#include "itkMacro.h" +#include <sstream> +#include "itkImageRegionIterator.h" + +namespace otb +{ + /// Constructor + template <class TPixel> + ImageViewer<TPixel> + ::ImageViewer() + { + m_UseScroll = false; + m_ScrollMaxInitialSize = 300; + m_FullMaxInitialSize = 600; + m_ZoomMaxInitialSize = 200; + m_ImageGeometry = 1.0; + m_ScrollLimitSize = 600; + m_Color[0]=1.0; + m_Color[1]=0; + m_Color[2]=0; + m_Color[3]=1.0; + m_ShrinkFactor=1; + m_RedChannelIndex = 0; + m_GreenChannelIndex = 1; + m_BlueChannelIndex = 2; + m_Built=false; + m_Shrink = ShrinkFilterType::New(); + m_FullWindow=NULL; + m_ZoomWindow=NULL; + m_ScrollWindow=NULL; + m_PixLocWindow=NULL; + m_PixLocOutput=NULL; + } + /// Destructor + template <class TPixel> + ImageViewer<TPixel> + ::~ImageViewer() + { + if (m_FullWindow!=NULL) + delete m_FullWindow; + if(m_ZoomWindow!=NULL) + delete m_ZoomWindow; + if(m_ScrollWindow!=NULL) + delete m_ScrollWindow; + if(m_PixLocWindow!=NULL) + delete m_PixLocWindow; + if(m_PixLocOutput!=NULL) + delete m_PixLocOutput; + } + + /// Compute the normalization factor + template <class TPixel> + void + ImageViewer<TPixel> + ::ComputeNormalizationFactors(void) + { + typedef itk::ImageRegionIterator<ImageType> IteratorType; + typename ListSampleType::Pointer listSample = ListSampleType::New(); + unsigned int nbComponents = m_InputImage->GetNumberOfComponentsPerPixel(); + listSample->SetMeasurementVectorSize(nbComponents); + m_MinComponentValue.SetSize(nbComponents); + m_MaxComponentValue.SetSize(nbComponents); + VectorPixelType absolutMax; + VectorPixelType absolutMin; + absolutMax.SetSize(nbComponents); + absolutMin.SetSize(nbComponents); + absolutMax.Fill(0); + absolutMin.Fill(0); + IteratorType it; + // if scroll is activated, compute the factors from the quicklook + if(m_UseScroll) + { + it = IteratorType(m_Shrink->GetOutput(),m_Shrink->GetOutput()->GetLargestPossibleRegion()); + it.GoToBegin(); + } + // else, compute the factors from the full viewed region + else + { + m_InputImage->SetRequestedRegion(m_FullWidget->GetViewedRegion()); + m_InputImage->PropagateRequestedRegion(); + m_InputImage->UpdateOutputData(); + it = IteratorType(m_InputImage,m_FullWidget->GetViewedRegion()); + it.GoToBegin(); + } + while(!it.IsAtEnd()) + { + listSample->PushBack(it.Get()); + for(unsigned int i = 0; i<nbComponents;++i) + { + if(it.Get()[i]>absolutMax[i]) + absolutMax[i]=it.Get()[i]; + if(it.Get()[i]<absolutMin[i]) + absolutMin[i]=it.Get()[i]; + } + ++it; + } + otbMsgDebugMacro(<<"Sample list generated."); + typename CovarianceCalculatorType::Pointer calc = CovarianceCalculatorType::New(); + calc->SetInputSample(listSample); + calc->Update(); + otbMsgDebugMacro(<<"Statistics computed."); + typename CovarianceCalculatorType::OutputType cov = *(calc->GetOutput()); + for(unsigned int i = 0; i<nbComponents;++i) + { + m_MinComponentValue[i] = static_cast<InputPixelType>((calc->GetMean())->GetElement(i)-2.8*vcl_sqrt(cov(i,i))); + m_MaxComponentValue[i] = static_cast<InputPixelType>((calc->GetMean())->GetElement(i)+2.8*vcl_sqrt(cov(i,i))); + if(m_MinComponentValue[i]<absolutMin[i]) + m_MinComponentValue[i]=absolutMin[i]; + if(m_MaxComponentValue[i]>absolutMax[i]) + m_MaxComponentValue[i]=absolutMax[i]; + } + + // InputPixelType min,max; +// max = (m_MaxComponentValue[m_RedChannelIndex] +// +m_MaxComponentValue[m_GreenChannelIndex] +// +m_MaxComponentValue[m_BlueChannelIndex])/2; +// min = (m_MinComponentValue[m_RedChannelIndex] +// +m_MinComponentValue[m_GreenChannelIndex] +// +m_MinComponentValue[m_BlueChannelIndex])/2; + + + // otbMsgDebugMacro(<<"Normalization between: "<<m_MinComponentValue<<" and "<<m_MaxComponentValue); +// for(unsigned int i = 1; i<nbComponents;++i) +// { +// if(min>m_MinComponentValue[i]) +// min=m_MinComponentValue[i]; +// if(max<m_MaxComponentValue[i]) +// max=m_MaxComponentValue[i]; +// } + + // m_MinComponentValue.Fill(min); +// m_MaxComponentValue.Fill(max); + + otbMsgDebugMacro(<<"Data min: "<<absolutMin<<", Data max: "<<absolutMax); + otbMsgDebugMacro(<<"Normalization between: "<<m_MinComponentValue<<" and "<<m_MaxComponentValue); + } + + + /// Build the HMI + template <class TPixel> + void + ImageViewer<TPixel> + ::Build(void) + { + otbMsgDebugMacro(<<"Entering build method"); + if(!m_InputImage) + { + itkExceptionMacro(<<"No input image !"); + } + // Get the image dimension + typename ImageType::SizeType size = m_InputImage->GetLargestPossibleRegion().GetSize(); + m_ImageGeometry = static_cast<double>(size[0])/static_cast<double>(size[1]); + + // initiate windows dimensions + int wscroll=0; + int hscroll=0; + int wfull = (size[0]<m_FullMaxInitialSize ? size[0] : m_FullMaxInitialSize); + int hfull = (size[1]<m_FullMaxInitialSize ? size[1] : m_FullMaxInitialSize); + + // Create full windows + m_FullWindow = new Fl_Window(0,0,wfull,hfull,"Full Resolution Window"); + m_FullWidget = FullWidgetType::New(); + m_FullWindow->resizable(m_FullWidget); + m_FullWidget->SetParent(this); + m_FullWindow->size_range(0,0,size[0],size[1]); + m_FullWindow->end(); + m_FullWidget->SetInput(m_InputImage); + m_FullWidget->Init(0,0,wfull,hfull,"Full Resolution Window"); + m_FullWidget->box( FL_EMBOSSED_BOX ); + m_FullWidget->SetFormOverlayVisible(true); + + // decide wether to use scroll view or not + if(size[0]<m_ScrollLimitSize&&size[1]<m_ScrollLimitSize) + { + m_UseScroll=false; + } + else + { + m_UseScroll=true; + // Compute scroll size : + if(m_ImageGeometry<1) + { + hscroll = m_ScrollMaxInitialSize; + wscroll = static_cast<int>(static_cast<double>(m_ScrollMaxInitialSize)*m_ImageGeometry); + } + else + { + wscroll = m_ScrollMaxInitialSize; + hscroll = static_cast<int>(static_cast<double>(m_ScrollMaxInitialSize)/m_ImageGeometry); + } + // Create the quicklook + m_Shrink->SetInput(m_InputImage); + m_ShrinkFactor = (size[0]/hscroll < size[1]/wscroll ? size[0]/hscroll : size[1]/wscroll)/2; + otbMsgDebugMacro("Shrink factor: "<<m_ShrinkFactor); + m_Shrink->SetShrinkFactor(m_ShrinkFactor); + typedef otb::FltkFilterWatcher WatcherType; + WatcherType watcher(m_Shrink,wfull-200,hfull/2,200,20, "Generating Quicklook ..."); + m_Shrink->Update(); + + // Create the scroll windows + m_ScrollWindow = new Fl_Window(wfull+15,0,wscroll,hscroll,"Scroll Window"); + m_ScrollWidget = ScrollWidgetType::New(); + m_ScrollWindow->resizable(m_ScrollWidget); + m_ScrollWindow->size_range(wscroll,hscroll,size[0],size[1],0,0,1); + m_ScrollWindow->end(); + m_ScrollWidget->SetInput(m_Shrink->GetOutput()); + m_ScrollWidget->SetParent(this); + m_ScrollWidget->Init(0,0,wscroll,hscroll,"Scroll window"); + m_ScrollWidget->box( FL_EMBOSSED_BOX ); + m_ScrollWidget->SetFormOverlayVisible(true); + + // Create the scroll selection box + BoxPointerType box = BoxType::New(); + SizeType scrollBoxSize; + IndexType scrollBoxIndex; + scrollBoxSize[0]=(m_FullWidget->GetViewedRegion().GetSize()[0]/m_ShrinkFactor)+1; + scrollBoxSize[1]=(m_FullWidget->GetViewedRegion().GetSize()[1]/m_ShrinkFactor)+1; + scrollBoxIndex[0]=(m_FullWidget->GetViewedRegion().GetIndex()[0]/m_ShrinkFactor)+1; + scrollBoxIndex[1]=(m_FullWidget->GetViewedRegion().GetIndex()[1]/m_ShrinkFactor)+1; + otbMsgDebugMacro(<<"Scroll box: "<<scrollBoxIndex<<" "<<scrollBoxSize); + box->SetSize(scrollBoxSize); + box->SetIndex(scrollBoxIndex); + box->SetColor(m_Color); + m_ScrollWidget->GetFormList()->PushBack(box); + + // Set the view model + if(m_InputImage->GetNumberOfComponentsPerPixel()<=2) + { + m_ScrollWidget->SetViewModelToGrayscale(); + m_ScrollWidget->SetRedChannelIndex(m_RedChannelIndex); + } + else + { + m_ScrollWidget->SetRedChannelIndex(m_RedChannelIndex); + m_ScrollWidget->SetGreenChannelIndex(m_GreenChannelIndex); + m_ScrollWidget->SetBlueChannelIndex(m_BlueChannelIndex); + } + } + // Create the zoom window + m_ZoomWindow = new Fl_Window(wfull+15,hscroll+45,m_ZoomMaxInitialSize,m_ZoomMaxInitialSize,"Zoom Window"); + m_ZoomWidget = ZoomWidgetType::New(); + m_ZoomWidget->SetParent(this); + m_ZoomWindow->resizable(m_ZoomWidget); + m_ZoomWindow->size_range(0,0,size[0],size[1]); + m_ZoomWindow->end(); + m_ZoomWidget->SetZoomFactor(4.0); + m_ZoomWidget->SetInput(m_InputImage); + m_ZoomWidget->Init(0,0,m_ZoomMaxInitialSize,m_ZoomMaxInitialSize,"Zoom Window"); + m_ZoomWidget->box( FL_EMBOSSED_BOX ); + m_ZoomWidget->SetFormOverlayVisible(true); + + // Create the zoom selection mode + BoxPointerType zoomBox = BoxType::New(); + SizeType zoomBoxSize; + IndexType zoomBoxIndex; + zoomBoxSize[0]=(m_ZoomWidget->GetViewedRegion().GetSize()[0])+1; + zoomBoxSize[1]=(m_ZoomWidget->GetViewedRegion().GetSize()[1])+1; + zoomBoxIndex[0]=(m_ZoomWidget->GetViewedRegion().GetIndex()[0])+1; + zoomBoxIndex[1]=(m_ZoomWidget->GetViewedRegion().GetIndex()[1])+1; + zoomBox->SetIndex(zoomBoxIndex); + zoomBox->SetSize(zoomBoxSize); + zoomBox->SetColor(m_Color); + m_FullWidget->GetFormList()->PushBack(zoomBox); + + // Set the view model + if(m_InputImage->GetNumberOfComponentsPerPixel()<=2) + { + m_FullWidget->SetViewModelToGrayscale(); + m_ZoomWidget->SetViewModelToGrayscale(); + otbMsgDebugMacro(<<"View model set to grayscale. Channel: "<<m_RedChannelIndex); + m_ZoomWidget->SetRedChannelIndex(m_RedChannelIndex); + m_FullWidget->SetRedChannelIndex(m_RedChannelIndex); + } + else + { + otbMsgDebugMacro(<<"View model set to RGB Composition. R: "<<m_RedChannelIndex<<", G: "<<m_GreenChannelIndex<<", B: "<<m_BlueChannelIndex); + m_ZoomWidget->SetRedChannelIndex(m_RedChannelIndex); + m_ZoomWidget->SetGreenChannelIndex(m_GreenChannelIndex); + m_ZoomWidget->SetBlueChannelIndex(m_BlueChannelIndex); + m_FullWidget->SetRedChannelIndex(m_RedChannelIndex); + m_FullWidget->SetGreenChannelIndex(m_GreenChannelIndex); + m_FullWidget->SetBlueChannelIndex(m_BlueChannelIndex); + + } + + // Compute the normalization factors + ComputeNormalizationFactors(); + + // Set the normalization factors + m_ZoomWidget->SetMinComponentValues(m_MinComponentValue); + m_ZoomWidget->SetMaxComponentValues(m_MaxComponentValue); + m_FullWidget->SetMinComponentValues(m_MinComponentValue); + m_FullWidget->SetMaxComponentValues(m_MaxComponentValue); + if(m_UseScroll) + { + m_ScrollWidget->SetMinComponentValues(m_MinComponentValue); + m_ScrollWidget->SetMaxComponentValues(m_MaxComponentValue); + } + + m_PixLocWindow= new Fl_Window(0,hfull+15,250,30,"Pixel location & values"); + m_PixLocOutput = new Fl_Output(0,0,250,30,"Pixel location & values"); + m_PixLocWindow->resizable(m_PixLocOutput); + m_PixLocOutput->box(FL_EMBOSSED_BOX ); + m_PixLocWindow->end(); + + // Built done + m_Built=true; + otbMsgDebugMacro(<<"Leaving build method"); + } + /// Set the left image + template <class TPixel> + void + ImageViewer<TPixel> + ::SetImage(itk::ImageBase<2> * img) + { + m_InputImage = dynamic_cast<ImageType *>( img ); + } + /// Show the app + template <class TPixel> + void + ImageViewer<TPixel> + ::Show(void) + { + otbMsgDebugMacro(<<"Entering show method."); + Fl::check(); + if(m_UseScroll) + { + otbMsgDebugMacro(<<"Showing scroll widget."); + m_ScrollWindow->show(); + m_ScrollWidget->Show(); + } + otbMsgDebugMacro(<<"Showing full widget."); + m_FullWindow->show(); + m_FullWidget->Show(); + otbMsgDebugMacro(<<"Showing zoom widget."); + m_ZoomWindow->show(); + m_ZoomWidget->Show(); + otbMsgDebugMacro(<<"Between show and check"); + m_PixLocWindow->show(); + m_PixLocOutput->show(); + Fl::check(); + otbMsgDebugMacro(<<"Leaving Show method."); + } + /// Hide the app + template <class TPixel> + void + ImageViewer<TPixel> + ::Hide(void) + {} + /// Update the display + template <class TPixel> + void + ImageViewer<TPixel> + ::Update(void) + { + Fl::check(); + UpdateScrollWidget(); + UpdateFullWidget(); + UpdateZoomWidget(); + Fl::check(); + } + + template <class TPixel> + void + ImageViewer<TPixel> + ::PrintPixLocVal(std::string str) + { + m_PixLocOutput->value(str.c_str()); + m_PixLocOutput->redraw(); + Fl::check(); + } + + template <class TPixel> + void + ImageViewer<TPixel> + ::UpdateZoomWidget(void) + { + std::stringstream oss; + oss<<"Zoom Window (X"<<m_ZoomWidget->GetOpenGlIsotropicZoom()<<")"; + m_ZoomWindow->label(oss.str().c_str()); + m_ZoomWindow->redraw(); + m_ZoomWidget->redraw(); + } + + template <class TPixel> + void + ImageViewer<TPixel> + ::UpdateFullWidget(void) + { + BoxPointerType zoomBox = BoxType::New(); + SizeType zoomBoxSize; + IndexType zoomBoxIndex; + zoomBoxSize[0]=(m_ZoomWidget->GetViewedRegion().GetSize()[0]); + zoomBoxSize[1]=(m_ZoomWidget->GetViewedRegion().GetSize()[1]); + zoomBoxIndex[0]=(m_ZoomWidget->GetViewedRegion().GetIndex()[0])+1; + zoomBoxIndex[1]=(m_ZoomWidget->GetViewedRegion().GetIndex()[1])+1; + zoomBox->SetIndex(zoomBoxIndex); + zoomBox->SetSize(zoomBoxSize); + zoomBox->SetColor(m_Color); + m_FullWidget->GetFormList()->SetNthElement(0,zoomBox); + m_FullWidget->redraw(); + } + + template <class TPixel> + void + ImageViewer<TPixel> + ::UpdateScrollWidget(void) + { + if(m_UseScroll) + { + BoxPointerType box = BoxType::New(); + SizeType scrollBoxSize; + IndexType scrollBoxIndex; + scrollBoxSize[0]=(m_FullWidget->GetViewedRegion().GetSize()[0]/m_ShrinkFactor)-1; + scrollBoxSize[1]=(m_FullWidget->GetViewedRegion().GetSize()[1]/m_ShrinkFactor)-1; + scrollBoxIndex[0]=(m_FullWidget->GetViewedRegion().GetIndex()[0]/m_ShrinkFactor)+1; + scrollBoxIndex[1]=(m_FullWidget->GetViewedRegion().GetIndex()[1]/m_ShrinkFactor)+1; + box->SetSize(scrollBoxSize); + box->SetIndex(scrollBoxIndex); + box->SetColor(m_Color); + m_ScrollWidget->GetFormList()->SetNthElement(0,box); + m_ScrollWidget->redraw(); + } + } + +template <class TPixel> +typename ImageViewer<TPixel> +::RegionType +ImageViewer<TPixel> +::ComputeConstrainedRegion(RegionType smallRegion, RegionType bigRegion) +{ + // This function assumes that smallRegion is inside huge region + if(smallRegion.GetSize()[0]>bigRegion.GetSize()[0] + ||smallRegion.GetSize()[1]>bigRegion.GetSize()[1]) + { + itkExceptionMacro("Small region not inside big region !"); + } + else + { + RegionType resp; + IndexType index = smallRegion.GetIndex(); + SizeType size = smallRegion.GetSize(); + + if(smallRegion.GetIndex()[0]<bigRegion.GetIndex()[0]) + { + index[0]=bigRegion.GetIndex()[0]; + } + if(smallRegion.GetIndex()[1]<bigRegion.GetIndex()[1]) + { + index[1]=bigRegion.GetIndex()[1]; + } + if(index[0]+size[0]>=bigRegion.GetIndex()[0]+bigRegion.GetSize()[0]) + { + index[0]=bigRegion.GetIndex()[0]+bigRegion.GetSize()[0]-size[0]-2; + } + if(index[1]+size[1]>=bigRegion.GetIndex()[1]+bigRegion.GetSize()[1]) + { + index[1]=bigRegion.GetIndex()[1]+bigRegion.GetSize()[1]-size[1]-2; + } + resp.SetSize(size); + resp.SetIndex(index); + return resp; + } +} + +template <class TPixel> + void + ImageViewer<TPixel> +::ChangeFullViewedRegion(IndexType clickedIndex) +{ + RegionType region = m_FullWidget->GetViewedRegion(); + IndexType newIndex; + newIndex[0]=clickedIndex[0]-region.GetSize()[0]/2; + newIndex[1]=clickedIndex[1]-region.GetSize()[1]/2; + + + region.SetIndex(newIndex); + otbMsgDebugMacro(<<"New region: "<<region); + + RegionType newRegion = ComputeConstrainedRegion(region,m_InputImage->GetLargestPossibleRegion()); + otbMsgDebugMacro(<<"Constrained region: "<<newRegion); + m_FullWidget->SetUpperLeftCorner(newRegion.GetIndex()); + this->UpdateScrollWidget(); +} + +template <class TPixel> + void + ImageViewer<TPixel> +::ChangeZoomViewedRegion(IndexType clickedIndex) +{ + RegionType region = m_ZoomWidget->GetViewedRegion(); + IndexType newIndex; + newIndex[0]=clickedIndex[0]-region.GetSize()[0]/2; + newIndex[1]=clickedIndex[1]-region.GetSize()[1]/2; + + region.SetIndex(newIndex); + RegionType newRegion = ComputeConstrainedRegion(region,m_FullWidget->GetViewedRegion()); + m_ZoomWidget->SetZoomUpperLeftCorner(newRegion.GetIndex()); + m_ZoomWidget->redraw(); + this->UpdateFullWidget(); +} +} // end namespace otb +#endif + diff --git a/Code/Visu/otbImageViewerScrollWidget.h b/Code/Visu/otbImageViewerScrollWidget.h new file mode 100644 index 0000000000..06cdad1c5d --- /dev/null +++ b/Code/Visu/otbImageViewerScrollWidget.h @@ -0,0 +1,138 @@ +/*========================================================================= + +Program: ORFEO Toolbox +Language: C++ +Date: $Date$ +Version: $Revision$ + + +Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. +See OTBCopyright.txt for details. + + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef _otbImageViewerScrollWidget_h +#define _otbImageViewerScrollWidget_h + +#include "otbFixedSizeFullImageWidget.h" +#include "otbImageWidgetRectangleForm.h" +#include "otbImageWidgetBoxForm.h" +#include "otbImageWidgetPointForm.h" +#include <FL/Fl.H> + +namespace otb +{ +template <class TPixel> class ImageViewer; + + +template <class TPixel> +class ITK_EXPORT ImageViewerScrollWidget + : public FixedSizeFullImageWidget<TPixel> +{ + public: + /** Standard class typedefs */ + typedef ImageViewerScrollWidget Self; + typedef FixedSizeFullImageWidget<TPixel> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImageViewerScrollWidget, FixedSizeFullImageWidget); + + typedef TPixel PixelType; + typedef typename Superclass::IndexType IndexType; + typedef typename Superclass::SizeType SizeType; + + typedef ImageViewer<PixelType> ParentType; + typedef typename ParentType::Pointer ParentPointerType; + + typedef otb::ImageWidgetBoxForm BoxType; + typedef BoxType::ColorType ColorType; + + itkSetObjectMacro(Parent,ParentType); + itkGetObjectMacro(Parent,ParentType); + /** Handle method */ + virtual int handle(int event) + { + switch(event) + { + case FL_PUSH: + { + int x = Fl::event_x(); + int y = Fl::event_y(); + IndexType clickedIndex; + clickedIndex[0]=x; + clickedIndex[1]=y; + clickedIndex=this->WindowToImageCoordinates(clickedIndex); + clickedIndex[0]=clickedIndex[0]*m_Parent->GetShrinkFactor(); + clickedIndex[1]=clickedIndex[1]*m_Parent->GetShrinkFactor(); + m_Parent->ChangeFullViewedRegion(clickedIndex); + m_Parent->ChangeZoomViewedRegion(clickedIndex); + return 1; + } + case FL_ENTER: + { + m_MouseIn = true; + return 1; + } + case FL_LEAVE: + { + m_MouseIn = false; + m_Parent->PrintPixLocVal(""); + return 1; + } + case FL_MOVE: + { + m_MouseIn=true; + if(m_MouseMoveCount%m_ValueUpdateFrequency==0) + { + m_MousePos[0]=Fl::event_x(); + m_MousePos[1]=Fl::event_y(); + IndexType newIndex = this->WindowToImageCoordinates(m_MousePos); + IndexType realIndex; + realIndex[0]=newIndex[0]*m_Parent->GetShrinkFactor(); + realIndex[1]=newIndex[1]*m_Parent->GetShrinkFactor(); + std::stringstream oss; + oss<<"Location: "<<realIndex<<", Values: "<<this->GetInput()->GetPixel(newIndex); + m_Parent->PrintPixLocVal(oss.str()); + m_MouseMoveCount=0; + } + m_MouseMoveCount++; + return 1; + } + } + return 0; + } + protected: + /** + * Constructor. + */ + ImageViewerScrollWidget() + { + m_MouseIn = false; + m_MousePos.Fill(0); + m_MouseMoveCount = 0; + m_ValueUpdateFrequency = 5; + }; + /** + * Destructor. + */ + ~ImageViewerScrollWidget(){}; + + private: + ParentPointerType m_Parent; + IndexType m_MousePos; + bool m_MouseIn; + unsigned int m_MouseMoveCount; + unsigned int m_ValueUpdateFrequency; + +}; +} // end namespace otb +#endif diff --git a/Code/Visu/otbImageViewerZoomWidget.h b/Code/Visu/otbImageViewerZoomWidget.h new file mode 100644 index 0000000000..ca3e425304 --- /dev/null +++ b/Code/Visu/otbImageViewerZoomWidget.h @@ -0,0 +1,157 @@ +/*========================================================================= + +Program: ORFEO Toolbox +Language: C++ +Date: $Date$ +Version: $Revision$ + + +Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. +See OTBCopyright.txt for details. + + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#ifndef _otbImageViewerZoomWidget_h +#define _otbImageViewerZoomWidget_h + +#include "otbZoomableImageWidget.h" +#include "otbImageWidgetRectangleForm.h" +#include "otbImageWidgetBoxForm.h" +#include "otbImageWidgetPointForm.h" +#include <Fl/fl_draw.H> + +namespace otb +{ +template <class TPixel> class ImageViewer; + + +template <class TPixel> +class ITK_EXPORT ImageViewerZoomWidget + : public ZoomableImageWidget<TPixel> +{ + public: + /** Standard class typedefs */ + typedef ImageViewerZoomWidget Self; + typedef ZoomableImageWidget<TPixel> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Run-time type information (and related methods). */ + itkTypeMacro(ImageViewerZoomWidget, FullResolutionImageWidget); + + typedef TPixel PixelType; + typedef typename Superclass::IndexType IndexType; + typedef typename Superclass::SizeType SizeType; + + typedef ImageViewer<PixelType> ParentType; + typedef typename ParentType::Pointer ParentPointerType; + + itkSetObjectMacro(Parent,ParentType); + itkGetObjectMacro(Parent,ParentType); + /** Handle method */ + virtual int handle(int event) + { + switch(event) + { + case FL_ENTER: + { + m_MouseIn = true; + // otbMsgDebugMacro(<<"Mouse in"); + return 1; + } + case FL_LEAVE: + { + m_MouseIn = false; + m_Parent->UpdateZoomWidget(); + m_Parent->PrintPixLocVal(""); + // otbMsgDebugMacro(<<"Mouse out"); + return 1; + } + case FL_MOVE: + { + m_MouseIn=true; + if(m_MouseMoveCount%m_ValueUpdateFrequency==0) + { + m_MousePos[0]=Fl::event_x(); + m_MousePos[1]=Fl::event_y(); + IndexType newIndex = this->WindowToImageCoordinates(m_MousePos); + std::stringstream oss; + oss<<"Location: "<<newIndex<<", Values: "<<this->GetInput()->GetPixel(newIndex); + m_Parent->PrintPixLocVal(oss.str()); + m_MouseMoveCount=0; + } + m_MouseMoveCount++; + return 1; + } + case FL_MOUSEWHEEL: + { + int dy = Fl::event_dy(); + if(dy<0) + { + this->SetZoomFactor(this->GetOpenGlIsotropicZoom()+m_ZoomStep); + } + else + { + if(this->GetOpenGlIsotropicZoom()-m_ZoomStep>=1) + { + this->SetZoomFactor(this->GetOpenGlIsotropicZoom()-m_ZoomStep); + } + else + { + this->SetZoomFactor(1.0); + } + } + m_Parent->UpdateFullWidget(); + m_Parent->UpdateZoomWidget(); + return 1; + } + } + return 0; + } + + + virtual void resize(int x,int y, int w, int h) + { + Superclass::resize(x,y,w,h); + if(m_Parent->GetBuilt()) + m_Parent->UpdateFullWidget(); + } + + + + protected: + /** + * Constructor. + */ + ImageViewerZoomWidget() + { + m_ZoomStep = 0.2; + m_MouseIn = false; + m_MousePos.Fill(0); + m_MouseMoveCount = 0; + m_ValueUpdateFrequency = 5; + }; + /** + * Destructor. + */ + ~ImageViewerZoomWidget(){}; + + private: + ParentPointerType m_Parent; + double m_ZoomStep; + IndexType m_MousePos; + bool m_MouseIn; + unsigned int m_MouseMoveCount; + unsigned int m_ValueUpdateFrequency; + +}; + +} // end namespace otb +#endif diff --git a/Testing/Code/Visu/otbImageViewer.cxx b/Testing/Code/Visu/otbImageViewer.cxx new file mode 100644 index 0000000000..bf1cfe6372 --- /dev/null +++ b/Testing/Code/Visu/otbImageViewer.cxx @@ -0,0 +1,66 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "itkExceptionObject.h" +#include "otbImageFileReader.h" +#include "otbImageViewer.h" +#include "otbMacro.h" + +int otbImageViewer( int argc, char * argv[] ) +{ + try + { + char * filename = argv[1]; + + // Parse command line parameters + typedef double PixelType; + typedef otb::ImageViewer<PixelType> ImageViewerType; + typedef ImageViewerType::ImageType ImageType; + typedef otb::ImageFileReader<ImageType> ReaderType; + + // instantiation + ImageViewerType::Pointer viewer = ImageViewerType::New(); + + // check for input images + ReaderType::Pointer reader = ReaderType::New(); + reader->SetFileName(filename); + reader->GenerateOutputInformation(); + viewer->SetImage(reader->GetOutput()); + + // build the app + otbMsgDebugMacro(<<"Build."); + viewer->Build(); + otbMsgDebugMacro(<<"Show"); + viewer->Show(); + viewer->Update(); + Fl::check(); + } + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + + diff --git a/Testing/Code/Visu/otbImageViewerNew.cxx b/Testing/Code/Visu/otbImageViewerNew.cxx new file mode 100644 index 0000000000..76754e526b --- /dev/null +++ b/Testing/Code/Visu/otbImageViewerNew.cxx @@ -0,0 +1,47 @@ +/*========================================================================= + + Program: ORFEO Toolbox + Language: C++ + Date: $Date$ + Version: $Revision$ + + + Copyright (c) Centre National d'Etudes Spatiales. All rights reserved. + See OTBCopyright.txt for details. + + + This software is distributed WITHOUT ANY WARRANTY; without even + the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ +#include "itkExceptionObject.h" +#include "otbImageFileReader.h" +#include "otbImageViewer.h" +#include "otbMacro.h" + +int otbImageViewerNew( int argc, char * argv[] ) +{ + try + { + // Parse command line parameters + typedef double PixelType; + typedef otb::ImageViewer<PixelType> ImageViewerType; + // instantiation + ImageViewerType::Pointer viewer = ImageViewerType::New(); + } + catch( itk::ExceptionObject & err ) + { + std::cout << "Exception itk::ExceptionObject levee !" << std::endl; + std::cout << err << std::endl; + return EXIT_FAILURE; + } + catch( ... ) + { + std::cout << "Exception levee inconnue !" << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + + -- GitLab