diff --git a/Code/BasicFilters/otbMeanShiftImageFilter.txx b/Code/BasicFilters/otbMeanShiftImageFilter.txx index 9d8614950eadd46135dcd357fe596d61b9ca16f1..1bd3aa742e13f6f475fc51356f41dfe62fdeaef8 100644 --- a/Code/BasicFilters/otbMeanShiftImageFilter.txx +++ b/Code/BasicFilters/otbMeanShiftImageFilter.txx @@ -192,7 +192,7 @@ MeanShiftImageFilter<TInputImage, TOutputImage, TLabeledOutput, TBufferConverter template <class TInputImage, class TOutputImage, class TLabeledOutput, class TBufferConverter> void MeanShiftImageFilter<TInputImage, TOutputImage, TLabeledOutput, TBufferConverter> -::ThreadedGenerateData(const RegionType& outputRegionForThread, int threadId) +::ThreadedGenerateData(const RegionType& outputRegionForThread, int itkNotUsed(threadId)) { // Input and output pointers typename InputImageType::ConstPointer inputPtr = this->GetInput(); diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx b/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..3d4bd8d9e92b175790fb5236b101caa10bd7bf1e --- /dev/null +++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.cxx @@ -0,0 +1,103 @@ +/*========================================================================= + + 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 "otbStreamingShrinkImageFilter.h" + +namespace otb +{ + +unsigned int +StreamingShrinkImageRegionSplitter +::GetNumberOfSplits(const RegionType& region, unsigned int requestedNumber) +{ + unsigned int theoricalNbPixelPerTile = region.GetNumberOfPixels() / requestedNumber; + unsigned int theoricalTileDimension = static_cast<unsigned int> (vcl_sqrt(static_cast<double>(theoricalNbPixelPerTile)) ); + + // Take the previous multiple of m_TileSizeAlignment (eventually generate more splits than requested) + m_TileDimension = theoricalTileDimension / m_TileSizeAlignment * m_TileSizeAlignment; + + // Minimal tile size is m_TileSizeAlignment * m_TileSizeAlignment + if (m_TileDimension < m_TileSizeAlignment) + { + otbMsgDevMacro(<< "Using the minimal tile size : " << m_TileSizeAlignment << " * " << m_TileSizeAlignment); + m_TileDimension = m_TileSizeAlignment; + } + + // Use the computed tile size, and generate (m_TileDimension * 1) tiles + const SizeType& regionSize = region.GetSize(); + m_SplitsPerDimension[0] = (regionSize[0] + m_TileDimension - 1) / m_TileDimension; + m_SplitsPerDimension[1] = regionSize[1] / m_TileSizeAlignment; + + unsigned int numPieces = 1; + for (unsigned int j = 0; j < ImageDimension; ++j) + { + numPieces *= m_SplitsPerDimension[j]; + } + + otbMsgDevMacro(<< "Tile dimension : " << m_TileDimension) + otbMsgDevMacro(<< "Number of splits per dimension : " << m_SplitsPerDimension[0] << " " << m_SplitsPerDimension[1]) + + return numPieces; +} + +StreamingShrinkImageRegionSplitter::RegionType +StreamingShrinkImageRegionSplitter +::GetSplit(unsigned int i, unsigned int numberOfPieces, const RegionType& region) +{ + RegionType splitRegion; + IndexType splitIndex; + + // Compute the actual number of splits + unsigned int numPieces = 1; + for (unsigned int j = 0; j < ImageDimension; ++j) + { + numPieces *= m_SplitsPerDimension[j]; + } + + if (i >= numPieces) + { + itkExceptionMacro("Requested split number " << i << " but region contains only " << numPieces << " splits"); + } + + // Compute the split index in the streaming grid + splitIndex[1] = i / m_SplitsPerDimension[0]; + splitIndex[0] = i % m_SplitsPerDimension[0]; + + // Transform the split index to the actual coordinates + splitRegion.SetIndex(0, region.GetIndex(0) + m_TileDimension * splitIndex[0]); + splitRegion.SetIndex(1, region.GetIndex(1) + m_TileSizeAlignment * splitIndex[1]); + + splitRegion.SetSize(0, m_TileDimension); + splitRegion.SetSize(1, 1); + + // Handle the borders + splitRegion.Crop(region); + + return splitRegion; +} + +void +StreamingShrinkImageRegionSplitter +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + os << indent << "SplitsPerDimension : " << m_SplitsPerDimension << std::endl; + os << indent << "TileDimension : " << m_TileDimension << std::endl; + os << indent << "TileSizeAlignment : " << m_TileSizeAlignment << std::endl; +} + +} // End namespace otb diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.h b/Code/BasicFilters/otbStreamingShrinkImageFilter.h index c077557e021e7e242895479b509ad395c5efa305..b6b3e9eabc91da4b5c32fc56b3e5d7b8f29e407b 100644 --- a/Code/BasicFilters/otbStreamingShrinkImageFilter.h +++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.h @@ -25,11 +25,134 @@ #include "otbPersistentImageFilter.h" #include "otbPersistentFilterStreamingDecorator.h" -#include "itkTimeProbe.h" +#include "otbStreamingManager.h" namespace otb { +class ITK_EXPORT StreamingShrinkImageRegionSplitter : public itk::ImageRegionSplitter<2> +{ +public: + /** Standard class typedefs. */ + typedef StreamingShrinkImageRegionSplitter Self; + typedef itk::ImageRegionSplitter<2> 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(StreamingShrinkImageRegionSplitter, itk::Object); + + /** Dimension of the image available at compile time. */ + itkStaticConstMacro(ImageDimension, unsigned int, 2); + + /** Dimension of the image available at run time. */ + static unsigned int GetImageDimension() + { + return ImageDimension; + } + + /** Index typedef support. An index is used to access pixel values. */ + typedef itk::Index<ImageDimension> IndexType; + typedef IndexType::IndexValueType IndexValueType; + + /** Size typedef support. A size is used to define region bounds. */ + typedef itk::Size<ImageDimension> SizeType; + typedef SizeType::SizeValueType SizeValueType; + + /** Region typedef support. */ + typedef itk::ImageRegion<ImageDimension> RegionType; + + /** How many pieces can the specified region be split? A given region + * cannot always be divided into the requested number of pieces. For + * instance, if the numberOfPieces exceeds the number of pixels along + * a certain dimensions, then some splits will not be possible. + */ + virtual unsigned int GetNumberOfSplits(const RegionType& region, + unsigned int requestedNumber); + + /** Get a region definition that represents the ith piece a specified region. + * The "numberOfPieces" specified should be less than or equal to what + * GetNumberOfSplits() returns. */ + virtual RegionType GetSplit(unsigned int i, unsigned int numberOfPieces, + const RegionType& region); + + itkGetMacro(TileSizeAlignment, unsigned int); + itkSetMacro(TileSizeAlignment, unsigned int); + + itkGetMacro(TileDimension, unsigned int); + + itkSetMacro(ShrinkFactor, unsigned int); + itkGetMacro(ShrinkFactor, unsigned int); + +protected: + StreamingShrinkImageRegionSplitter() : m_SplitsPerDimension(0U), m_ShrinkFactor(10) {} + virtual ~StreamingShrinkImageRegionSplitter() {} + void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + StreamingShrinkImageRegionSplitter(const StreamingShrinkImageRegionSplitter &); //purposely not implemented + void operator =(const StreamingShrinkImageRegionSplitter&); //purposely not implemented + + itk::FixedArray<unsigned int, ImageDimension> m_SplitsPerDimension; + unsigned int m_TileDimension; + unsigned int m_TileSizeAlignment; + unsigned int m_ShrinkFactor; +}; + + +template <class TInputImage> +class ITK_EXPORT StreamingShrinkStreamingManager : public StreamingManager<TInputImage> +{ +public: + /** Standard class typedefs. */ + typedef StreamingShrinkStreamingManager Self; + typedef StreamingManager<TInputImage> Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + /** Method for creation through the object factory. */ + itkNewMacro(Self); + + /** Runtime information support. */ + itkTypeMacro(StreamingShrinkStreamingManager, StreamingManager); + + typedef TInputImage ImageType; + typedef typename ImageType::Pointer ImagePointerType; + typedef typename ImageType::RegionType RegionType; + typedef typename RegionType::IndexType IndexType; + typedef typename RegionType::SizeType SizeType; + typedef typename ImageType::InternalPixelType PixelType; + + itkStaticConstMacro(InputImageDimension, unsigned int, TInputImage::ImageDimension); + + /** Actually computes the stream divisions, according to the specified streaming mode, + * eventually using the input parameter to estimate memory consumption */ + virtual void PrepareStreaming(itk::DataObject * input, const RegionType ®ion); + + void SetShrinkFactor(unsigned int val) + { + m_ShrinkFactor = val; + } + + unsigned int GetShrinkFactor() const + { + return m_ShrinkFactor; + } + +protected: + StreamingShrinkStreamingManager(); + virtual ~StreamingShrinkStreamingManager(); + +private: + StreamingShrinkStreamingManager(const StreamingShrinkStreamingManager &); //purposely not implemented + void operator =(const StreamingShrinkStreamingManager&); //purposely not implemented + + unsigned int m_ShrinkFactor; +}; + /** \class PersistentShrinkImageFilter * \brief @@ -116,9 +239,6 @@ private: /** The shrink factor */ unsigned int m_ShrinkFactor; - - itk::TimeProbe m_Chrono; - }; // end of class PersistentStatisticsVectorImageFilter @@ -156,10 +276,14 @@ public: typedef TOutputImage OutputImageType; typedef typename Superclass::FilterType PersistentFilterType; + typedef StreamingShrinkStreamingManager<InputImageType> StreamingShrinkStreamingManagerType; + typedef typename StreamingShrinkStreamingManagerType::Pointer StreamingShrinkStreamingManagerPointerType; + void SetInput(InputImageType * input) { this->GetFilter()->SetInput(input); } + const InputImageType * GetInput() { return this->GetFilter()->GetInput(); @@ -173,15 +297,29 @@ public: otbSetObjectMemberMacro(Filter, ShrinkFactor, unsigned int); otbGetObjectMemberMacro(Filter, ShrinkFactor, unsigned int); + virtual void Update(void) + { + m_StreamingManager->SetShrinkFactor( this->GetFilter()->GetShrinkFactor() ); + Superclass::Update(); + } + protected: /** Constructor */ - StreamingShrinkImageFilter() {} + StreamingShrinkImageFilter() + { + // Use a specific StreamingManager implementation + m_StreamingManager = StreamingShrinkStreamingManagerType::New(); + this->GetStreamer()->SetStreamingManager( m_StreamingManager ); + } + /** Destructor */ virtual ~StreamingShrinkImageFilter() {} private: StreamingShrinkImageFilter(const Self &); //purposely not implemented void operator =(const Self&); //purposely not implemented + + StreamingShrinkStreamingManagerPointerType m_StreamingManager; }; } // End namespace otb diff --git a/Code/BasicFilters/otbStreamingShrinkImageFilter.txx b/Code/BasicFilters/otbStreamingShrinkImageFilter.txx index 4c7a810c1bf1d2ea5026ed9822ccd697cae73ca0..cd045e31f27cf8c625ed7bb97dda07de7a163956 100644 --- a/Code/BasicFilters/otbStreamingShrinkImageFilter.txx +++ b/Code/BasicFilters/otbStreamingShrinkImageFilter.txx @@ -26,6 +26,34 @@ namespace otb { +template <class TImage> +StreamingShrinkStreamingManager<TImage>::StreamingShrinkStreamingManager() +{ +} + +template <class TImage> +StreamingShrinkStreamingManager<TImage>::~StreamingShrinkStreamingManager() +{ +} + +template <class TImage> +void +StreamingShrinkStreamingManager<TImage>::PrepareStreaming( itk::DataObject * input, const RegionType ®ion ) +{ + typedef otb::StreamingShrinkImageRegionSplitter TileSplitterType; + TileSplitterType::Pointer splitter = TileSplitterType::New(); + splitter->SetTileSizeAlignment(m_ShrinkFactor); + this->m_Splitter = splitter; + + unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region); + this->m_ComputedNumberOfSplits = this->m_Splitter->GetNumberOfSplits(region, nbDivisions); + otbMsgDevMacro(<< "Number of split : " << this->m_ComputedNumberOfSplits) + + // Save the region to generate the splits later + this->m_Region = region; +} + + /** Constructor */ template <class TInputImage, class TOutputImage> PersistentShrinkImageFilter<TInputImage, TOutputImage> @@ -79,31 +107,22 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage> // Nothing that needs to be allocated for the remaining outputs } + template<class TInputImage, class TOutputImage> void PersistentShrinkImageFilter<TInputImage, TOutputImage> ::Reset() { - // Reinit the chrono - m_Chrono = itk::TimeProbe(); - - // get pointers to the input and output + // Get pointers to the input and output InputImageType* inputPtr = const_cast<InputImageType*>(this->GetInput()); inputPtr->UpdateOutputInformation(); m_ShrinkedOutput = OutputImageType::New(); - // we need to compute the output spacing, the output image size, and the - // output image start index const typename InputImageType::SpacingType& inputSpacing = inputPtr->GetSpacing(); const typename InputImageType::SizeType& inputSize = inputPtr->GetLargestPossibleRegion().GetSize(); - const typename InputImageType::IndexType& inputStartIndex - = inputPtr->GetLargestPossibleRegion().GetIndex(); - - otbMsgDebugMacro(<< "Input index " << inputStartIndex); - otbMsgDebugMacro(<< "Input size: " << inputSize); typename OutputImageType::SpacingType shrinkedOutputSpacing; typename OutputImageType::RegionType shrinkedOutputLargestPossibleRegion; @@ -113,9 +132,7 @@ PersistentShrinkImageFilter<TInputImage, TOutputImage> for (unsigned int i = 0; i < OutputImageType::ImageDimension; ++i) { shrinkedOutputSpacing[i] = inputSpacing[i] * static_cast<double>(m_ShrinkFactor); - //shrinkedOutputSize[i] = static_cast<int>(static_cast<double>(inputSize[i]) / static_cast<double>(m_ShrinkFactor)); shrinkedOutputSize[i] = inputSize[i] / m_ShrinkFactor; - //outputStartIndex[i] = inputStartIndex[i]; shrinkedOutputStartIndex[i] = 0; } @@ -134,7 +151,6 @@ void PersistentShrinkImageFilter<TInputImage, TOutputImage> ::Synthetize() { - otbMsgDevMacro( "Shrink time : " << m_Chrono.GetTotal() ) } template<class TInputImage, class TOutputImage> @@ -142,7 +158,6 @@ void PersistentShrinkImageFilter<TInputImage, TOutputImage> ::BeforeThreadedGenerateData() { - m_Chrono.Start(); } template<class TInputImage, class TOutputImage> @@ -175,7 +190,6 @@ void PersistentShrinkImageFilter<TInputImage, TOutputImage> ::AfterThreadedGenerateData() { - m_Chrono.Stop(); } template <class TImage, class TOutputImage> diff --git a/Code/Common/otbFilterWatcherBase.cxx b/Code/Common/otbFilterWatcherBase.cxx index 2e47d89fc3ba3fc19c98f3368af84b29b705ac8d..742eb90d370ac5ece85d2ae495e7a9e3a5bf48ca 100644 --- a/Code/Common/otbFilterWatcherBase.cxx +++ b/Code/Common/otbFilterWatcherBase.cxx @@ -46,11 +46,11 @@ FilterWatcherBase // Assign the callbacks m_StartFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::StartFilter); + &FilterWatcherBase::StartFilterCallback); m_EndFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::EndFilter); + &FilterWatcherBase::EndFilterCallback); m_ProgressFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::ShowProgress); + &FilterWatcherBase::ShowProgressCallback); // Add the commands as observers m_StartTag = m_Process->AddObserver(itk::StartEvent(), @@ -90,11 +90,11 @@ FilterWatcherBase // Assign the callbacks m_StartFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::StartFilter); + &FilterWatcherBase::StartFilterCallback); m_EndFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::EndFilter); + &FilterWatcherBase::EndFilterCallback); m_ProgressFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::ShowProgress); + &FilterWatcherBase::ShowProgressCallback); // Add the commands as observers m_StartTag = m_Process->AddObserver(itk::StartEvent(), m_StartFilterCommand); @@ -132,11 +132,11 @@ FilterWatcherBase // Assign the callbacks m_StartFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::StartFilter); + &FilterWatcherBase::StartFilterCallback); m_EndFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::EndFilter); + &FilterWatcherBase::EndFilterCallback); m_ProgressFilterCommand->SetCallbackFunction(this, - &FilterWatcherBase::ShowProgress); + &FilterWatcherBase::ShowProgressCallback); // Add the commands as observers m_StartTag = m_Process->AddObserver(itk::StartEvent(), m_StartFilterCommand); diff --git a/Code/Common/otbFilterWatcherBase.h b/Code/Common/otbFilterWatcherBase.h index 9e64c176323186f99f421e1e8bc31933df6fbf41..ef739e490c713ab76d91a39705275a4fbd4711ae 100644 --- a/Code/Common/otbFilterWatcherBase.h +++ b/Code/Common/otbFilterWatcherBase.h @@ -85,6 +85,24 @@ public: protected: + /** Callback method to show the ProgressEvent */ + virtual void ShowProgressCallback() + { + this->ShowProgress(); + } + + /** Callback method to show the StartEvent */ + virtual void StartFilterCallback() + { + this->StartFilter(); + } + + /** Callback method to show the EndEvent */ + virtual void EndFilterCallback() + { + this->EndFilter(); + } + /** Callback method to show the ProgressEvent */ virtual void ShowProgress() = 0; diff --git a/Code/Common/otbImageRegionSquareTileSplitter.h b/Code/Common/otbImageRegionSquareTileSplitter.h new file mode 100644 index 0000000000000000000000000000000000000000..10dd5b71e45436d6640a2e1f401d2a46d0ca59ed --- /dev/null +++ b/Code/Common/otbImageRegionSquareTileSplitter.h @@ -0,0 +1,146 @@ +/*========================================================================= + + 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 __otbImageRegionSquareTileSplitter_h +#define __otbImageRegionSquareTileSplitter_h + +#include "itkObject.h" +#include "itkRegion.h" +#include "itkImageRegion.h" +#include "itkImageRegionSplitter.h" +#include "itkObjectFactory.h" +#include "itkIndex.h" +#include "itkSize.h" + +namespace otb +{ + +/** \class ImageRegionSquareTileSplitter + * \brief Divide a region into several pieces. + * + * ImageRegionSquareTileSplitter divides an ImageRegion into smaller regions. + * ImageRegionSquareTileSplitter is used by the StreamingImageFilter to divide a + * requested output region into a series of smaller requests of the + * pipeline. This object has two basic methods: GetNumberOfSplits() + * and GetSplit(). + * + * GetNumberOfSplits() is used to determine how may subregions a given + * region can be divided. You call GetNumberOfSplits with an argument + * that is the number of subregions you want. If the image region can + * support that number of subregions, that number is returned. + * Otherwise, the maximum number of splits a region can support will + * be returned. For example, if a region splitter class only divides + * a region into horizontal slabs, then the maximum number of splits + * will be the number of rows in the region. + * + * GetSplit() returns the ith of N subregions (as an ImageRegion object). + * + * This ImageRegionSquareTileSplitter class divides a region along the outermost + * dimension. If the outermost dimension has size 1 (i.e. a volume + * with a single slice), the ImageRegionSquareTileSplitter will divide the + * region along the next outermost dimension. If that dimension has size 1, + * the process continues with the next outermost dimension. + * + * Regions obtained by the ImageRegionSquareTileSplitter are aligned on a grid + * with width of 256. Divisions can occur only at line defined as k*256. + * + * Other ImageRegionSquareTileSplitter subclasses could divide an image into + * more uniform shaped regions instead of slabs. + * + * \sa ImageRegionMultidimensionalSplitter + * + * \ingroup ITKSystemObjects + * \ingroup DataProcessing + */ + +template <unsigned int VImageDimension> +class ITK_EXPORT ImageRegionSquareTileSplitter : public itk::ImageRegionSplitter<VImageDimension> +{ +public: + /** Standard class typedefs. */ + typedef ImageRegionSquareTileSplitter Self; + typedef itk::ImageRegionSplitter<VImageDimension> 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(ImageRegionSquareTileSplitter, itk::Object); + + /** Dimension of the image available at compile time. */ + itkStaticConstMacro(ImageDimension, unsigned int, VImageDimension); + + /** Dimension of the image available at run time. */ + static unsigned int GetImageDimension() + { + return VImageDimension; + } + + /** Index typedef support. An index is used to access pixel values. */ + typedef itk::Index<VImageDimension> IndexType; + typedef typename IndexType::IndexValueType IndexValueType; + + /** Size typedef support. A size is used to define region bounds. */ + typedef itk::Size<VImageDimension> SizeType; + typedef typename SizeType::SizeValueType SizeValueType; + + /** Region typedef support. */ + typedef itk::ImageRegion<VImageDimension> RegionType; + + /** How many pieces can the specified region be split? A given region + * cannot always be divided into the requested number of pieces. For + * instance, if the numberOfPieces exceeds the number of pixels along + * a certain dimensions, then some splits will not be possible. + */ + virtual unsigned int GetNumberOfSplits(const RegionType& region, + unsigned int requestedNumber); + + /** Get a region definition that represents the ith piece a specified region. + * The "numberOfPieces" specified should be less than or equal to what + * GetNumberOfSplits() returns. */ + virtual RegionType GetSplit(unsigned int i, unsigned int numberOfPieces, + const RegionType& region); + + itkGetMacro(TileSizeAlignment, unsigned int); + itkSetMacro(TileSizeAlignment, unsigned int); + + itkGetMacro(TileDimension, unsigned int); + +protected: + ImageRegionSquareTileSplitter() : m_SplitsPerDimension(0U), m_TileDimension(0), m_TileSizeAlignment(16) {} + virtual ~ImageRegionSquareTileSplitter() {} + void PrintSelf(std::ostream& os, itk::Indent indent) const; + +private: + ImageRegionSquareTileSplitter(const ImageRegionSquareTileSplitter &); //purposely not implemented + void operator =(const ImageRegionSquareTileSplitter&); //purposely not implemented + + itk::FixedArray<unsigned int, VImageDimension> m_SplitsPerDimension; + unsigned int m_TileDimension; + unsigned int m_TileSizeAlignment; +}; + +} // end namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +# include "otbImageRegionSquareTileSplitter.txx" +#endif + +#endif diff --git a/Code/Common/otbImageRegionSquareTileSplitter.txx b/Code/Common/otbImageRegionSquareTileSplitter.txx new file mode 100644 index 0000000000000000000000000000000000000000..6870b8dd034b2cef25ba00ab21b28721a2aa40bd --- /dev/null +++ b/Code/Common/otbImageRegionSquareTileSplitter.txx @@ -0,0 +1,120 @@ +/*========================================================================= + + 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 __otbImageRegionSquareTileSplitter_txx +#define __otbImageRegionSquareTileSplitter_txx + +#include "otbImageRegionSquareTileSplitter.h" +#include "otbMath.h" +#include "otbMacro.h" + +namespace otb +{ + +template <unsigned int VImageDimension> +unsigned int +ImageRegionSquareTileSplitter<VImageDimension> +::GetNumberOfSplits(const RegionType& region, unsigned int requestedNumber) +{ + unsigned int theoricalNbPixelPerTile = region.GetNumberOfPixels() / requestedNumber; + unsigned int theoricalTileDimension = static_cast<unsigned int> (vcl_sqrt(static_cast<double>(theoricalNbPixelPerTile)) ); + + // Take the previous multiple of m_TileSizeAlignment (eventually generate more splits than requested) + m_TileDimension = theoricalTileDimension / m_TileSizeAlignment * m_TileSizeAlignment; + + // Minimal tile size is m_TileSizeAlignment * m_TileSizeAlignment + if (m_TileDimension < m_TileSizeAlignment) + { + otbMsgDevMacro(<< "Warning: clamping tile size to " << m_TileSizeAlignment << " * " << m_TileSizeAlignment); + m_TileDimension = m_TileSizeAlignment; + } + + unsigned int numPieces = 1; + const SizeType& regionSize = region.GetSize(); + for (unsigned int j = 0; j < VImageDimension; ++j) + { + m_SplitsPerDimension[j] = (regionSize[j] + m_TileDimension - 1) / m_TileDimension; + numPieces *= m_SplitsPerDimension[j]; + } + + otbMsgDevMacro(<< "Tile dimension : " << m_TileDimension) + otbMsgDevMacro(<< "Number of splits per dimension : " << m_SplitsPerDimension[0] << " " << m_SplitsPerDimension[1]) + + return numPieces; +} + +template <unsigned int VImageDimension> +itk::ImageRegion<VImageDimension> +ImageRegionSquareTileSplitter<VImageDimension> +::GetSplit(unsigned int i, unsigned int itkNotUsed(numberOfPieces), const RegionType& region) +{ + RegionType splitRegion; + IndexType splitIndex; + + // Compute the actual number of splits + unsigned int numPieces = 1; + for (unsigned int j = 0; j < VImageDimension; ++j) + { + numPieces *= m_SplitsPerDimension[j]; + } + + // Sanity check + if (i >= numPieces) + { + itkExceptionMacro("Asked for split number " << i << " but region contains only " << numPieces << " splits"); + } + + // Compute the split index in the streaming grid + unsigned int remaining = i; + for (unsigned int j = VImageDimension - 1; j > 0; --j) + { + splitIndex[j] = remaining / m_SplitsPerDimension[VImageDimension - 1 - j]; + remaining = remaining % m_SplitsPerDimension[VImageDimension - 1 - j]; + } + splitIndex[0] = remaining; + + // Transform the split index to the actual coordinates + for (unsigned int j = 0; j < VImageDimension; ++j) + { + splitRegion.SetIndex(j, region.GetIndex(j) + m_TileDimension * splitIndex[j]); + splitRegion.SetSize(j, m_TileDimension); + } + + // Handle the borders + splitRegion.Crop(region); + + return splitRegion; +} + +/** + * + */ +template <unsigned int VImageDimension> +void +ImageRegionSquareTileSplitter<VImageDimension> +::PrintSelf(std::ostream& os, itk::Indent indent) const +{ + Superclass::PrintSelf(os, indent); + os << indent << "SplitsPerDimension : " << m_SplitsPerDimension << std::endl; + os << indent << "TileDimension : " << m_TileDimension << std::endl; + os << indent << "TileSizeAlignment : " << m_TileSizeAlignment << std::endl; + +} + +} // end namespace itk + +#endif diff --git a/Code/Common/otbPersistentImageFilter.h b/Code/Common/otbPersistentImageFilter.h index ccea263130c7e5727c5757df6b5802dc8fc1a4b1..87d78f2202c5f16572dae4d689f5bc005c0e4ce6 100644 --- a/Code/Common/otbPersistentImageFilter.h +++ b/Code/Common/otbPersistentImageFilter.h @@ -66,7 +66,7 @@ public: protected: /** Constructor */ - PersistentImageFilter() {}; + PersistentImageFilter() {} /** Destructor */ virtual ~PersistentImageFilter() {} /**PrintSelf method */ diff --git a/Code/Common/otbPipelineMemoryPrintCalculator.cxx b/Code/Common/otbPipelineMemoryPrintCalculator.cxx index 397ba8b1126fbb30d860dccc6d5d8967c3cf5e6c..b8dff8c995087bc77f8d936ed71e8a3c18ad58d7 100644 --- a/Code/Common/otbPipelineMemoryPrintCalculator.cxx +++ b/Code/Common/otbPipelineMemoryPrintCalculator.cxx @@ -61,7 +61,7 @@ void PipelineMemoryPrintCalculator ::Compute() { - // Clear the visisted process objects set + // Clear the visited process objects set m_VisitedProcessObjects.clear(); // Dry run of pipeline synchronisation @@ -96,6 +96,7 @@ PipelineMemoryPrintCalculator::MemoryPrintType PipelineMemoryPrintCalculator ::EvaluateMemoryPrint(ProcessObjectType * process) { + otbMsgDevMacro(<< "EvaluateMemoryPrint for " << process->GetNameOfClass() << " (" << process << ")") // This variable will store the final print MemoryPrintType print = 0; @@ -150,6 +151,7 @@ PipelineMemoryPrintCalculator::MemoryPrintType PipelineMemoryPrintCalculator ::EvaluateDataObjectPrint(DataObjectType * data) const { + otbMsgDevMacro(<< "EvaluateMemoryPrint for " << data->GetNameOfClass() << " (" << data << ")") #define OTB_IMAGE_SIZE_BLOCK(type) \ if(dynamic_cast<itk::Image<type, 2> *>(data) != NULL) \ diff --git a/Code/Common/otbStandardFilterWatcher.cxx b/Code/Common/otbStandardFilterWatcher.cxx index 1fd3e7d4dc90205145af320af5f45e75f5238914..ce47e316a5e22818ab789ac98a6a59c4994f788e 100644 --- a/Code/Common/otbStandardFilterWatcher.cxx +++ b/Code/Common/otbStandardFilterWatcher.cxx @@ -29,6 +29,7 @@ StandardFilterWatcher : FilterWatcherBase(process, comment) { m_StarsCount = 50; + m_CurrentNbStars = -1; } StandardFilterWatcher @@ -80,9 +81,14 @@ StandardFilterWatcher progressPercent = 100; } - std::string stars(nbStars, '*'); - std::string blanks(nbBlanks, ' '); - std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::flush; + if (nbStars > m_CurrentNbStars) + { + std::string stars(nbStars, '*'); + std::string blanks(nbBlanks, ' '); + std::cout << "\rProcessing progress: " << progressPercent << "% [" << stars << blanks << "]" << std::flush; + } + + m_CurrentNbStars = nbStars; } } diff --git a/Code/Common/otbStandardFilterWatcher.h b/Code/Common/otbStandardFilterWatcher.h index 1f3cbe6e91d41608d74108a307b628b6e6f3198c..5e4fd7f69037855a477e3e2c9b89a0605bf2bc07 100644 --- a/Code/Common/otbStandardFilterWatcher.h +++ b/Code/Common/otbStandardFilterWatcher.h @@ -92,6 +92,8 @@ private: /** Stars coutning */ int m_StarsCount; + + int m_CurrentNbStars; }; } // end namespace otb diff --git a/Code/Common/otbStreamingManager.h b/Code/Common/otbStreamingManager.h new file mode 100644 index 0000000000000000000000000000000000000000..6d5d81b43aca507d7c8b05df9fb7ba93dc099047 --- /dev/null +++ b/Code/Common/otbStreamingManager.h @@ -0,0 +1,196 @@ +/*========================================================================= + + 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 __otbStreamingManager_h +#define __otbStreamingManager_h + +#include "otbMacro.h" +#include "otbConfigure.h" + +#include "itkLightObject.h" +#include "itkImageRegionSplitter.h" + +namespace otb +{ + +namespace StreamingManagement +{ + enum StreamingMode + { + /** Estimates the memory used by the pipeline + * and set the strips size to fit the specified + * available RAM + */ + STRIPPED_AVAILABLE_RAM, + + /** Force the use of a specific number of lines per strips + */ + STRIPPED_SET_NUMBEROFLINES, + + /** Estimates the memory used that will be used during the pipeline + * execution and set the tile size to fit the specified + * available RAM. + */ + TILED_AVAILABLE_RAM, + + /** Force the use of a specific tile dimension + * The associated parameter is the size used in each dimension + */ + TILED_SET_TILE_SIZE, + }; +} + +/** \class StreamingManager + * \brief This class handles the streaming process used in the writers implementation + * + * The streaming mode can be chosen with either SetStrippedRAMStreamingMode, SetStrippedNumberOfLinesStreamingMode, + * SetTiledRAMStreamingMode, or SetTiledTileDimensionStreamingMode. + * + * Then, PrepareStreaming must be called so that the stream type and dimensions are computed + * This involves passing the actual DataObject who will be written, since it will be used + * during memory estimation for some specific streaming modes. + * + * After PrepareStreaming has been called, the actual number of splits and streaming mode which will be used + * can be retrieved with GetStreamingMode and GetNumberOfSplits. + * The different splits can be retrieved with GetSplit + * + * \sa StreamingImageFileWriter + * \sa StreamingImageVirtualFileWriter + */ +template<class TImage> +class ITK_EXPORT StreamingManager : public itk::LightObject +{ +public: + /** Standard class typedefs. */ + typedef StreamingManager Self; + typedef itk::LightObject Superclass; + typedef itk::SmartPointer<Self> Pointer; + typedef itk::SmartPointer<const Self> ConstPointer; + + typedef TImage ImageType; + typedef typename ImageType::Pointer ImagePointerType; + typedef typename ImageType::RegionType RegionType; + typedef typename RegionType::IndexType IndexType; + typedef typename RegionType::SizeType SizeType; + typedef typename ImageType::InternalPixelType PixelType; + + typedef StreamingManagement::StreamingMode StreamingModeType; + + /** Creation through object factory macro */ + itkNewMacro(Self); + + /** Type macro */ + itkTypeMacro(StreamingManager, itk::LightObject); + + /** Dimension of input image. */ + itkStaticConstMacro(ImageDimension, unsigned int, ImageType::ImageDimension); + + /** Use stripped mode. + * The number of lines of the strips are computed by estimating the + * memory footprint of the pipeline, and chosen so that no more than + * availableRAM MBytes of memory are used. + * If no parameter is given, then the available RAM is retrieved from the + * OTB configuration file or build configuration option */ + virtual void SetStrippedRAMStreamingMode( unsigned int availableRAMInMB = 0 ); + + /** Use stripped mode. + * The number of lines of the strips are explicitely specified */ + virtual void SetStrippedNumberOfLinesStreamingMode( unsigned int numberOfLines ); + + /** Use tiled mode. + * The dimensions of the tiles are computed by estimating the + * memory footprint of the pipeline, and chosen so that no more than + * availableRAM MBytes of memory are used. + * + * If no parameter is given, then the available RAM is retrieved from the + * OTB configuration file or build configuration option. + * + * The tiles are set to be square, with dimension aligned with multiple of 16 */ + virtual void SetTiledRAMStreamingMode( unsigned int availableRAMInMB = 0 ); + + /** Use tiled mode. + * The dimension of the tile are explicitely specified. + * The parameter specifies the size of the tile in each dimension. */ + virtual void SetTiledTileDimensionStreamingMode( unsigned int tileDimension ); + + /** Actually computes the stream divisions, accorfing to the specified streaming mode, + * eventually using the input parameter to estimate memory consumption */ + virtual void PrepareStreaming(itk::DataObject * input, const RegionType ®ion); + + /** Returns the actual streaming mode that will be used to process the image. + * PrepareStreaming() must have been called before. + * This can be different than the required streaming mode. For example, if + * the input passed to PrepareStreaming() is fully buffered, then + * the STRIPPED_SET_NUMBEROFLINES mode is used with only one strip */ + virtual StreamingManagement::StreamingMode GetStreamingMode(); + + /** Returns the actual number of pieces that will be used to process the image. + * PrepareStreaming() must have been called before. + * This can be different than the requested number */ + virtual unsigned int GetNumberOfSplits(); + + /** Get a region definition that represents the ith piece a specified region. + * The "numberOfPieces" must be equal to what + * GetNumberOfSplits() returns. */ + virtual RegionType GetSplit(unsigned int i); + + +public: + StreamingManager(); + virtual ~StreamingManager(); + + virtual unsigned int EstimateOptimalNumberOfDivisions(itk::DataObject * input, const RegionType ®ion); + + /** The desired streaming mode specified by the user */ + StreamingManagement::StreamingMode m_DesiredMode; + + /** The actual streaming mode which will be used */ + StreamingManagement::StreamingMode m_ActualMode; + + /** The available RAM set as parameter when using the STRIPPED_AVAILABLE_RAM or TILED_AVAILABLE_RAM mode */ + unsigned int m_AvailableRAMInMB; + + /** The desired number of lines when using the STRIPPED_SET_NUMBEROFLINES streaming mode */ + unsigned int m_DesiredNumberOfLines; + + /** The desired tile dimension when using the TILED_SET_TILE_SIZE streaming mode */ + unsigned int m_DesiredTileDimension; + + /** The computed number of splits after PrepareStreaming has been called */ + unsigned int m_ComputedNumberOfSplits; + + /** The region to stream */ + RegionType m_Region; + + /** The splitter used to compute the different strips */ + typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)> AbstractSplitterType; + typedef typename AbstractSplitterType::Pointer AbstractSplitterPointerType; + AbstractSplitterPointerType m_Splitter; + +private: + StreamingManager(const StreamingManager &); //purposely not implemented + void operator =(const StreamingManager&); //purposely not implemented + +}; + +} // End namespace otb + +#ifndef OTB_MANUAL_INSTANTIATION +#include "otbStreamingManager.txx" +#endif + +#endif diff --git a/Code/Common/otbStreamingManager.txx b/Code/Common/otbStreamingManager.txx new file mode 100644 index 0000000000000000000000000000000000000000..5816141f677d42ef900cf42331ef8ae89ac12a7a --- /dev/null +++ b/Code/Common/otbStreamingManager.txx @@ -0,0 +1,291 @@ +/*========================================================================= + + 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 __otbStreamingManager_txx +#define __otbStreamingManager_txx + +#include "otbStreamingManager.h" +#include "otbMacro.h" +#include "otbConfigure.h" +#include "otbConfigurationFile.h" +#include "otbPipelineMemoryPrintCalculator.h" +#include "itkExtractImageFilter.h" + +#include "otbImageRegionSquareTileSplitter.h" +#include "itkImageRegionSplitter.h" + +namespace otb +{ + +template <class TImage> +StreamingManager<TImage>::StreamingManager() + : m_DesiredMode(StreamingManagement::TILED_AVAILABLE_RAM), + m_ActualMode(StreamingManagement::TILED_AVAILABLE_RAM), + m_AvailableRAMInMB(0), + m_DesiredNumberOfLines(0), + m_DesiredTileDimension(0), + m_ComputedNumberOfSplits(0) +{ +} + +template <class TImage> +StreamingManager<TImage>::~StreamingManager() +{ +} + +template <class TImage> +void +StreamingManager<TImage>::SetStrippedRAMStreamingMode( unsigned int availableRAMInMB ) +{ + m_DesiredMode = StreamingManagement::STRIPPED_AVAILABLE_RAM; + m_AvailableRAMInMB = availableRAMInMB; +} + +template <class TImage> +void +StreamingManager<TImage>::SetStrippedNumberOfLinesStreamingMode( unsigned int numberOfLines ) +{ + m_DesiredMode = StreamingManagement::STRIPPED_SET_NUMBEROFLINES; + m_DesiredNumberOfLines = numberOfLines; +} + +template <class TImage> +void +StreamingManager<TImage>::SetTiledRAMStreamingMode( unsigned int availableRAMInMB ) +{ + otbMsgDevMacro(<< "StreamingManager::SetTiledRAMStreamingMode " << availableRAMInMB) + m_DesiredMode = StreamingManagement::TILED_AVAILABLE_RAM; + m_AvailableRAMInMB = availableRAMInMB; +} + +template <class TImage> +void +StreamingManager<TImage>::SetTiledTileDimensionStreamingMode( unsigned int tileDimension ) +{ + m_DesiredMode = StreamingManagement::TILED_SET_TILE_SIZE; + m_DesiredTileDimension = tileDimension; +} + +template <class TImage> +void +StreamingManager<TImage>::PrepareStreaming( itk::DataObject * input, const RegionType ®ion ) +{ + switch (m_DesiredMode) + { + case StreamingManagement::STRIPPED_AVAILABLE_RAM: + { + otbMsgDevMacro(<< "Activating STRIPPED_AVAILABLE_RAM streaming mode") + unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region); + m_Splitter = itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)>::New(); + m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDivisions); + + otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits) + } + break; + + case StreamingManagement::STRIPPED_SET_NUMBEROFLINES: + { + otbMsgDevMacro(<< "Activating STRIPPED_SET_NUMBEROFLINES streaming mode") + if (m_DesiredNumberOfLines < 1) + { + itkWarningMacro(<< "DesiredNumberOfLines set to 0 : use 1 as strip number of lines") + m_DesiredNumberOfLines = 1; + } + + /* Calculate number of split */ + unsigned long numberLinesOfRegion = region.GetSize()[1]; // Y dimension + unsigned long nbSplit; + if (numberLinesOfRegion > m_DesiredNumberOfLines) + { + nbSplit = + static_cast<unsigned long>(vcl_ceil(static_cast<double>(numberLinesOfRegion) / + static_cast<double>(m_DesiredNumberOfLines))); + } + else + { + // Don't stream + nbSplit = 1; + } + + m_Splitter = itk::ImageRegionSplitter<itkGetStaticConstMacro(ImageDimension)>::New(); + m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbSplit); + otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits) + } + break; + + case StreamingManagement::TILED_AVAILABLE_RAM: + { + otbMsgDevMacro(<< "Activating TILED_AVAILABLE_RAM streaming mode") + unsigned long nbDivisions = EstimateOptimalNumberOfDivisions(input, region); + m_Splitter = otb::ImageRegionSquareTileSplitter<itkGetStaticConstMacro(ImageDimension)>::New(); + m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDivisions); + otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits) + } + break; + + case StreamingManagement::TILED_SET_TILE_SIZE: + { + otbMsgDevMacro(<< "Activating TILED_SET_TILE_SIZE streaming mode") + if (m_DesiredTileDimension < 16) + { + itkWarningMacro(<< "DesiredTileDimension inferior to 16 : use 16 as tile dimension") + m_DesiredTileDimension = 16; + } + + // Calculate number of split + m_Splitter = otb::ImageRegionSquareTileSplitter<itkGetStaticConstMacro(ImageDimension)>::New(); + unsigned int nbDesiredTiles = itk::Math::Ceil<unsigned int>( double(region.GetNumberOfPixels()) / (m_DesiredTileDimension * m_DesiredTileDimension) ); + m_ComputedNumberOfSplits = m_Splitter->GetNumberOfSplits(region, nbDesiredTiles); + otbMsgDevMacro(<< "Number of split : " << m_ComputedNumberOfSplits) + } + break; + } + + // Save the region to generate the splits later + m_Region = region; +} + + +template <class TImage> +unsigned int +StreamingManager<TImage>::EstimateOptimalNumberOfDivisions(itk::DataObject * input, const RegionType ®ion) +{ + otbMsgDevMacro(<< "m_AvailableRAMInMB " << m_AvailableRAMInMB) + unsigned int availableRAMInBytes = m_AvailableRAMInMB * 1024 * 1024; + + if (availableRAMInBytes == 0) + { + otbMsgDevMacro(<< "Retrieving available RAM size from configuration") + // Retrieve it from the configuration + try + { + typedef otb::ConfigurationFile ConfigurationType; + ConfigurationType::Pointer conf = ConfigurationType::GetInstance(); + + availableRAMInBytes = conf->GetParameter<unsigned int>( + "OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING"); + } + catch(...) + { + // We should never have to go here if the configuration file is + // correct and found. + // In case it is not fallback on the cmake + // defined constants. + availableRAMInBytes = OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING; + } + } + + otbMsgDevMacro("RAM used to estimate memory footprint : " << availableRAMInBytes / 1024 / 1024 << " MB") + + otb::PipelineMemoryPrintCalculator::Pointer memoryPrintCalculator; + memoryPrintCalculator = otb::PipelineMemoryPrintCalculator::New(); + + memoryPrintCalculator->SetAvailableMemory( availableRAMInBytes ); + + // Trick to avoid having the resampler compute the whole + // deformation field + double regionTrickFactor = 1; + ImageType* inputImage = dynamic_cast<ImageType*>(input); + //inputImage = 0; + if (inputImage) + { + + typedef itk::ExtractImageFilter<ImageType,ImageType> ExtractFilterType; + typename ExtractFilterType::Pointer extractFilter = ExtractFilterType::New(); + extractFilter->SetInput(inputImage); + + // Define a small region to run the memory footprint estimation, + // around the image center, 100 pixels wide in each dimension + SizeType smallSize; + smallSize.Fill(100); + IndexType index; + index[0] = region.GetIndex()[0] + region.GetSize()[0]/2 - 50; + index[1] = region.GetIndex()[1] + region.GetSize()[1]/2 - 50; + + RegionType smallRegion; + smallRegion.SetSize(smallSize); + smallRegion.SetIndex(index); + + // In case the image is smaller than 100 pixels in a direction + smallRegion.Crop(region); + + extractFilter->SetExtractionRegion(smallRegion); + + bool smallRegionSuccess = smallRegion.Crop(region); + + if (smallRegionSuccess) + { + otbMsgDevMacro("Using an extract to estimate memory : " << smallRegion) + // the region is well behaved, inside the largest possible region + memoryPrintCalculator->SetDataToWrite(extractFilter->GetOutput()); + regionTrickFactor = static_cast<double>( region.GetNumberOfPixels() ) + / static_cast<double>(smallRegion.GetNumberOfPixels()); + + memoryPrintCalculator->SetBiasCorrectionFactor(regionTrickFactor); + } + else + { + otbMsgDevMacro("Using the input region to estimate memory : " << region) + // the region is not well behaved + // use the full region + memoryPrintCalculator->SetDataToWrite(input); + memoryPrintCalculator->SetBiasCorrectionFactor(1.0); + } + + memoryPrintCalculator->Compute(); + } + else + { + // Use the original object to estimate memory footprint + memoryPrintCalculator->SetDataToWrite(input); + memoryPrintCalculator->SetBiasCorrectionFactor(1.0); + + memoryPrintCalculator->Compute(); + } + + otbMsgDevMacro( "Estimated Memory print for the full image : " + << static_cast<unsigned int>(memoryPrintCalculator->GetMemoryPrint() / 1024 / 1024 ) << std::endl) + otbMsgDevMacro( "Optimal number of stream divisions: " + << memoryPrintCalculator->GetOptimalNumberOfStreamDivisions() << std::endl) + + return memoryPrintCalculator->GetOptimalNumberOfStreamDivisions(); +} + +template <class TImage> +StreamingManagement::StreamingMode +StreamingManager<TImage>::GetStreamingMode() +{ + return m_ActualMode; +} + +template <class TImage> +unsigned int +StreamingManager<TImage>::GetNumberOfSplits() +{ + return m_ComputedNumberOfSplits; +} + +template <class TImage> +typename StreamingManager<TImage>::RegionType +StreamingManager<TImage>::GetSplit(unsigned int i) +{ + return m_Splitter->GetSplit(i, m_ComputedNumberOfSplits, m_Region); +} + +} // End namespace otb + +#endif diff --git a/Code/Gui/otbFltkFilterWatcher.cxx b/Code/Gui/otbFltkFilterWatcher.cxx index 65ef6e5452a735dac780f2733e76410593149bf7..8136428c449e14a816a93b49b6cf025d22edb686 100644 --- a/Code/Gui/otbFltkFilterWatcher.cxx +++ b/Code/Gui/otbFltkFilterWatcher.cxx @@ -27,7 +27,8 @@ FltkFilterWatcher ::FltkFilterWatcher(itk::ProcessObject* process, int x, int y, int w, int h, const char *comment) - : FilterWatcherBase(process, comment) + : FilterWatcherBase(process, comment), + m_CurrentProgress(0) { m_Window = new Fl_Window(x, y, w + 10, h + 10); m_Window->label(m_Comment.c_str()); @@ -46,4 +47,39 @@ FltkFilterWatcher delete m_Window; } +void +FltkFilterWatcher +::StartFilter() +{ + m_Window->show(); + m_Progress->value(0); + m_Progress->show(); + Fl::check(); +} + +void +FltkFilterWatcher +::ShowProgress() +{ + if (m_Process) + { + double progress = m_Process->GetProgress(); + + // Update only at each 0.5 percent + if (progress - m_CurrentProgress > 0.005) + { + m_Progress->value(progress); + m_CurrentProgress = progress; + Fl::check(); + } + } +} + +void +FltkFilterWatcher +::EndFilter() +{ + m_Window->hide(); +} + } // end namespace otb diff --git a/Code/Gui/otbFltkFilterWatcher.h b/Code/Gui/otbFltkFilterWatcher.h index f15a47bcf437d41aaf4bc240c279e1c384010451..c8bc02ce51516d685557265c15eee4f8f847fc77 100644 --- a/Code/Gui/otbFltkFilterWatcher.h +++ b/Code/Gui/otbFltkFilterWatcher.h @@ -38,9 +38,6 @@ namespace otb class ITK_EXPORT FltkFilterWatcher : public FilterWatcherBase { public: - /** Classes that need access to filter's private data */ - // friend class XMLFilterWatcher; - /** Constructor. Takes a ProcessObject to monitor and an optional * comment string that is prepended to each event message. */ FltkFilterWatcher(itk::ProcessObject * process, @@ -50,35 +47,21 @@ public: /** Destructor. */ virtual ~FltkFilterWatcher(); - /** Callback method to show the EndEvent */ - virtual void EndFilter() - { - m_Window->hide(); - } - protected: - /** Callback method to show the ProgressEvent */ - virtual void ShowProgress() - { - if (m_Process) - { - m_Progress->value(m_Process->GetProgress()); - Fl::check(); - } - } + virtual void ShowProgress(); /** Callback method to show the StartEvent */ - virtual void StartFilter() - { - m_Window->show(); - m_Progress->show(); - } + virtual void StartFilter(); -private: + /** Callback method to show the EndEvent */ + virtual void EndFilter(); +private: Fl_Window * m_Window; Fl_Progress * m_Progress; + + double m_CurrentProgress; }; } // end namespace otb diff --git a/Code/Gui/otbFltkWriterWatcher.cxx b/Code/Gui/otbFltkWriterWatcher.cxx index a3779c4ba24d427f5a20683485808ebaf9d2de2f..b99700274ff272789ca907bca81041a67e105b1f 100644 --- a/Code/Gui/otbFltkWriterWatcher.cxx +++ b/Code/Gui/otbFltkWriterWatcher.cxx @@ -27,7 +27,9 @@ FltkWriterWatcher ::FltkWriterWatcher(itk::ProcessObject* process, int x, int y, int w, int h, const char *comment) - : WriterWatcherBase(process, comment) + : WriterWatcherBase(process, comment), + m_CurrentFilterProgress(0), + m_CurrentWriterProgress(0) { this->BuildGUI(x, y, w, h, comment); } @@ -37,7 +39,9 @@ FltkWriterWatcher itk::ProcessObject* source, int x, int y, int w, int h, const char *comment) - : WriterWatcherBase(process, source, comment) + : WriterWatcherBase(process, source, comment), + m_CurrentFilterProgress(0), + m_CurrentWriterProgress(0) { this->BuildGUI(x, y, w, h, comment); } @@ -78,4 +82,74 @@ FltkWriterWatcher delete m_Window; } + +void +FltkWriterWatcher +::StartFilter() +{ + m_Window->show(); + m_FilterProgress->show(); + m_WriterProgress->show(); + Fl::check(); +} + +void +FltkWriterWatcher +::ShowFilterProgress() +{ + if (m_SourceProcess) + { + double progress = m_SourceProcess->GetProgress(); + + // Update only at each 0.5 percent + if (progress - m_CurrentFilterProgress > 0.005) + { + m_FilterProgress->value(progress); + m_CurrentFilterProgress = progress; + Fl::check(); + } + } +} + +void +FltkWriterWatcher +::EndFilter() +{ +} + +void +FltkWriterWatcher +::StartWriter() +{ + m_Window->show(); + m_FilterProgress->show(); + m_WriterProgress->show(); + Fl::check(); +} + +void +FltkWriterWatcher +::ShowWriterProgress() +{ + if (m_Process) + { + double progress = m_Process->GetProgress(); + + // Update only at each 0.5 percent + if (progress - m_CurrentWriterProgress > 0.005) + { + m_WriterProgress->value(progress); + m_CurrentWriterProgress = progress; + Fl::check(); + } + } +} + +void +FltkWriterWatcher +::EndWriter() +{ + m_Window->hide(); +} + } // end namespace otb diff --git a/Code/Gui/otbFltkWriterWatcher.h b/Code/Gui/otbFltkWriterWatcher.h index e03ecd03f0586060f5618936177461f1535c1814..224d69a6ea55db32fa13f022e5e5fc720ad8c1e1 100644 --- a/Code/Gui/otbFltkWriterWatcher.h +++ b/Code/Gui/otbFltkWriterWatcher.h @@ -55,54 +55,25 @@ public: /** Destructor. */ virtual ~FltkWriterWatcher(); - /** Callback method to show the EndEvent */ - virtual void EndWriter() - { - m_Window->hide(); - } +protected: - virtual void EndFilter() - {} + /** Callback method to show the ProgressEvent from the writer */ + virtual void ShowWriterProgress(); -protected: + /** Callback method to show the StartEvent from the writer*/ + virtual void StartWriter(); + + /** Callback method to show the EndEvent from the writer*/ + virtual void EndWriter(); - /** Callback method to show the ProgressEvent */ - virtual void ShowFilterProgress() - { - if (m_SourceProcess) - { - m_FilterProgress->value(m_SourceProcess->GetProgress()); - Fl::check(); - } - } - - /** Callback method to show the ProgressEvent */ - virtual void ShowWriterProgress() - { - if (m_Process) - { - m_WriterProgress->value(m_Process->GetProgress()); - Fl::check(); - } - } - - /** Callback method to show the StartEvent */ - virtual void StartWriter() - { - m_Window->show(); - m_FilterProgress->show(); - m_WriterProgress->show(); - Fl::check(); - } - - /** Callback method to show the StartEvent */ - virtual void StartFilter() - { - m_Window->show(); - m_FilterProgress->show(); - m_WriterProgress->show(); - Fl::check(); - } + /** Callback method to show the ProgressEvent from the filter */ + virtual void ShowFilterProgress(); + + /** Callback method to show the StartEvent from the filter*/ + virtual void StartFilter(); + + /** Callback method to show the EndEvent from the filter*/ + virtual void EndFilter(); void BuildGUI(int x, int y, int w, int h, const char * comment); @@ -111,6 +82,9 @@ private: Fl_Window * m_Window; Fl_Progress * m_WriterProgress; Fl_Progress * m_FilterProgress; + + double m_CurrentFilterProgress; + double m_CurrentWriterProgress; }; } // end namespace otb diff --git a/Code/IO/otbMapFileProductWriter.txx b/Code/IO/otbMapFileProductWriter.txx index 1463bb05def7feb40c1bb7f8079eb38dcff4f9b0..f74f55fff44dc25647c890a3cf25f03b7468a24e 100644 --- a/Code/IO/otbMapFileProductWriter.txx +++ b/Code/IO/otbMapFileProductWriter.txx @@ -237,6 +237,7 @@ MapFileProductWriter<TInputImage> m_StreamingShrinkImageFilter->SetShrinkFactor(sampleRatioValue); m_StreamingShrinkImageFilter->SetInput(m_VectorImage); + m_StreamingShrinkImageFilter->Update(); m_VectorRescaleIntensityImageFilter = VectorRescaleIntensityImageFilterType::New(); m_VectorRescaleIntensityImageFilter->SetInput(m_StreamingShrinkImageFilter->GetOutput()); diff --git a/Code/IO/otbStreamingImageVirtualWriter.h b/Code/IO/otbStreamingImageVirtualWriter.h index 9ae59e84295c01dce381482e85a1852d6378d888..99e72c1c06736795f2aedfb9f58b02bfa16a7e82 100644 --- a/Code/IO/otbStreamingImageVirtualWriter.h +++ b/Code/IO/otbStreamingImageVirtualWriter.h @@ -20,8 +20,7 @@ #include "itkMacro.h" #include "itkImageToImageFilter.h" -#include "itkImageRegionSplitter.h" -#include "otbStreamingTraits.h" +#include "otbStreamingManager.h" namespace otb { @@ -45,7 +44,7 @@ namespace otb * \sa PersistentStatisticsImageFilter * \sa PersistentImageStreamingDecorator. */ -template <class TInputImage> +template <class TInputImage, class TStreamingManager = StreamingManager<TInputImage> > class ITK_EXPORT StreamingImageVirtualWriter : public itk::ImageToImageFilter<TInputImage, TInputImage> { public: @@ -68,86 +67,62 @@ public: typedef typename InputImageType::PixelType InputImagePixelType; /** Streaming traits helper typedef */ - typedef StreamingTraits<InputImageType> StreamingTraitsType; + typedef TStreamingManager StreamingManagerType; + typedef typename StreamingManagerType::Pointer StreamingManagerPointerType; /** Dimension of input image. */ itkStaticConstMacro(InputImageDimension, unsigned int, InputImageType::ImageDimension); - /** Set/Get the image input of this writer. */ - void SetInput(const InputImageType *input); - const InputImageType * GetInput(void); - const InputImageType * GetInput(unsigned int idx); + StreamingManagerType* GetStreamingManager(void) + { + return m_StreamingManager; + } - void SetNthInput(unsigned int idx, const InputImageType *input); - - - /** SmartPointer to a region splitting object */ - typedef itk::ImageRegionSplitter<itkGetStaticConstMacro(InputImageDimension)> SplitterType; - typedef typename SplitterType::Pointer RegionSplitterPointer; - - /** Set buffer memory size (in bytes) use to calculate the number of stream divisions */ - void SetBufferMemorySize(unsigned long); - - /** Set the buffer number of lines use to calculate the number of stream divisions */ - void SetBufferNumberOfLinesDivisions(unsigned long); - - /** The number of stream divisions is calculate by using - * OTB_STREAM_IMAGE_SIZE_TO_ACTIVATE_STREAMING and - * OTB_STREAM_MAX_SIZE_BUFFER_FOR_STREAMING cmake variables. - */ - void SetAutomaticNumberOfStreamDivisions(void); - - /** Set the tiling automatic mode for streaming division */ - void SetTilingStreamDivisions(void); - /** Choose number of divisions in tiling streaming division */ - void SetTilingStreamDivisions(unsigned long); - - /** Return the string to indicate the method use to calculate number of stream divisions. */ - std::string GetMethodUseToCalculateNumberOfStreamDivisions(void); - - /** Set the number of pieces to divide the input. The upstream pipeline - * will be executed this many times. */ - void SetNumberOfStreamDivisions(unsigned long); - - /** Get the number of pieces to divide the input. The upstream pipeline - * will be executed this many times. */ - unsigned long GetNumberOfStreamDivisions(void); - - /** Set the helper class for dividing the input into chunks. */ - itkSetObjectMacro(RegionSplitter, SplitterType); - - /** Get the helper class for dividing the input into chunks. */ - itkGetObjectMacro(RegionSplitter, SplitterType); - - /** Type use to define number of divisions */ - typedef StreamingMode CalculationDivisionEnumType; - - virtual void GenerateInputRequestedRegion(void); + void SetStreamingManager(StreamingManagerType* streamingManager) + { + m_StreamingManager = streamingManager; + } protected: StreamingImageVirtualWriter(); + virtual ~StreamingImageVirtualWriter(); + void PrintSelf(std::ostream& os, itk::Indent indent) const; virtual void GenerateData(void); + virtual void GenerateInputRequestedRegion(void); + private: StreamingImageVirtualWriter(const StreamingImageVirtualWriter &); //purposely not implemented void operator =(const StreamingImageVirtualWriter&); //purposely not implemented - /** This method calculate the number of stream divisions, by using the CalculationDivision type */ - unsigned long CalculateNumberOfStreamDivisions(void); + void ObserveSourceFilterProgress(itk::Object* object, const itk::EventObject & event ) + { + if (typeid(event) != typeid(itk::ProgressEvent)) + { + return; + } + + itk::ProcessObject* processObject = dynamic_cast<itk::ProcessObject*>(object); + if (processObject) + m_DivisionProgress = processObject->GetProgress(); + + this->UpdateFilterProgress(); + } - /** Use to define the method used to calculate number of divisions */ - unsigned long m_BufferMemorySize; - unsigned long m_BufferNumberOfLinesDivisions; - unsigned long m_NumberOfStreamDivisions; + void UpdateFilterProgress() + { + this->UpdateProgress( (m_DivisionProgress + m_CurrentDivision) / m_NumberOfDivisions ); + } - RegionSplitterPointer m_RegionSplitter; + unsigned int m_NumberOfDivisions; + unsigned int m_CurrentDivision; + float m_DivisionProgress; - /** Use to determine method of calculation number of divisions */ - CalculationDivisionEnumType m_CalculationDivision; + StreamingManagerPointerType m_StreamingManager; }; } // end namespace otb diff --git a/Code/IO/otbStreamingImageVirtualWriter.txx b/Code/IO/otbStreamingImageVirtualWriter.txx index ce0b5938974e80d17265524e360b278f9aa013df..6ffd8621b5b05c4adf5c3439fb772b80694dcdd6 100644 --- a/Code/IO/otbStreamingImageVirtualWriter.txx +++ b/Code/IO/otbStreamingImageVirtualWriter.txx @@ -19,231 +19,55 @@ #define __otbStreamingImageVirtualWriter_txx #include "otbStreamingImageVirtualWriter.h" -#include "itkCommand.h" -#include "itkImageRegionIterator.h" -#include "itkObjectFactoryBase.h" -#include "itkImageFileWriter.h" -#include "itkImageRegionMultidimensionalSplitter.h" - #include "otbMacro.h" #include "otbConfigure.h" +#include "itkCommand.h" namespace otb { -/** - * - */ -template <class TInputImage> -StreamingImageVirtualWriter<TInputImage> + +template <class TInputImage, class TStreamingManager> +StreamingImageVirtualWriter<TInputImage,TStreamingManager> ::StreamingImageVirtualWriter() { - m_BufferMemorySize = 0; - m_BufferNumberOfLinesDivisions = 0; - // default to 10 divisions - m_NumberOfStreamDivisions = 0; - // default to AUTOMATIC_NUMBER_OF_DIVISIONS - m_CalculationDivision = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS; - - // create default region splitter - m_RegionSplitter = itk::ImageRegionSplitter<InputImageDimension>::New(); + m_StreamingManager = StreamingManagerType::New(); } -/** - * - */ -template <class TInputImage> -StreamingImageVirtualWriter<TInputImage> +template <class TInputImage, class TStreamingManager> +StreamingImageVirtualWriter<TInputImage,TStreamingManager> ::~StreamingImageVirtualWriter() { } -/** - * - */ -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetBufferMemorySize(unsigned long memory_size_divisions) -{ - m_BufferMemorySize = memory_size_divisions; - m_CalculationDivision = SET_BUFFER_MEMORY_SIZE; - this->Modified(); -} - -/** - * - */ -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetBufferNumberOfLinesDivisions(unsigned long nb_lines_divisions) -{ - m_BufferNumberOfLinesDivisions = nb_lines_divisions; - m_CalculationDivision = SET_BUFFER_NUMBER_OF_LINES; - this->Modified(); -} - -/** - * - */ -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetNumberOfStreamDivisions(unsigned long nb_divisions) -{ - m_NumberOfStreamDivisions = nb_divisions; - m_CalculationDivision = SET_NUMBER_OF_STREAM_DIVISIONS; - this->Modified(); -} - -/** - * - */ -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetAutomaticNumberOfStreamDivisions(void) -{ - m_CalculationDivision = SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS; - this->Modified(); -} - -/** - * - */ -template <class TInputImage> +template <class TInputImage, class TStreamingManager> void -StreamingImageVirtualWriter<TInputImage> -::SetTilingStreamDivisions(void) -{ - m_CalculationDivision = SET_TILING_WITH_SET_AUTOMATIC_NUMBER_OF_STREAM_DIVISIONS; - m_RegionSplitter = itk::ImageRegionMultidimensionalSplitter<InputImageDimension>::New(); - this->Modified(); -} - -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetTilingStreamDivisions(unsigned long nb_divisions) -{ - m_CalculationDivision = SET_TILING_WITH_SET_NUMBER_OF_STREAM_DIVISIONS; - m_NumberOfStreamDivisions = nb_divisions; - m_RegionSplitter = itk::ImageRegionMultidimensionalSplitter<InputImageDimension>::New(); - this->Modified(); -} - -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetInput(const InputImageType *input) -{ - this->SetNthInput(0, input); -} - -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::SetNthInput(unsigned int idx, const InputImageType *input) -{ - // ProcessObject is not const_correct so this cast is required here. - this->itk::ProcessObject::SetNthInput(idx, - const_cast<TInputImage *>(input)); -} - -template <class TInputImage> -const typename StreamingImageVirtualWriter<TInputImage>::InputImageType * -StreamingImageVirtualWriter<TInputImage> -::GetInput(void) -{ - if (this->GetNumberOfInputs() < 1) - { - return 0; - } - - return static_cast<TInputImage*> - (this->itk::ProcessObject::GetInput(0)); -} - -template <class TInputImage> -const typename StreamingImageVirtualWriter<TInputImage>::InputImageType * -StreamingImageVirtualWriter<TInputImage> -::GetInput(unsigned int idx) +StreamingImageVirtualWriter<TInputImage,TStreamingManager> +::PrintSelf(std::ostream& os, itk::Indent indent) const { - return static_cast<TInputImage*> (this->itk::ProcessObject::GetInput(idx)); + Superclass::PrintSelf(os, indent); } -template <class TInputImage> +template <class TInputImage, class TStreamingManager> void -StreamingImageVirtualWriter<TInputImage> +StreamingImageVirtualWriter<TInputImage,TStreamingManager> ::GenerateInputRequestedRegion(void) { InputImagePointer inputPtr = const_cast<InputImageType *>(this->GetInput(0)); + + InputImageRegionType region; typename InputImageRegionType::SizeType size; typename InputImageRegionType::IndexType index; - InputImageRegionType region; + index.Fill(0); size.Fill(0); region.SetSize(size); region.SetIndex(index); inputPtr->SetRequestedRegion(region); } -/** - * - */ -template <class TInputImage> -unsigned long -StreamingImageVirtualWriter<TInputImage> -::GetNumberOfStreamDivisions(void) -{ - return (CalculateNumberOfStreamDivisions()); -} -template<class TInputImage> -unsigned long -StreamingImageVirtualWriter<TInputImage> -::CalculateNumberOfStreamDivisions(void) -{ - return StreamingTraitsType - ::CalculateNumberOfStreamDivisions(this->GetInput(), - this->GetInput()->GetLargestPossibleRegion(), - m_RegionSplitter, - m_CalculationDivision, - m_NumberOfStreamDivisions, - m_BufferMemorySize, - m_BufferNumberOfLinesDivisions); -} -/** - * - */ -template <class TInputImage> -std::string -StreamingImageVirtualWriter<TInputImage> -::GetMethodUseToCalculateNumberOfStreamDivisions(void) -{ - return (StreamingTraitsType::GetMethodUseToCalculateNumberOfStreamDivisions(m_CalculationDivision)); -} -/** - * - */ -template <class TInputImage> -void -StreamingImageVirtualWriter<TInputImage> -::PrintSelf(std::ostream& os, itk::Indent indent) const -{ - Superclass::PrintSelf(os, indent); - os << indent << "Number of stream divisions: " << m_NumberOfStreamDivisions - << std::endl; - if (m_RegionSplitter) - { - os << indent << "Region splitter:" << m_RegionSplitter << std::endl; - } - else - { - os << indent << "Region splitter: (none)" << std::endl; - } -} -template<class TInputImage> + +template<class TInputImage, class TStreamingManager> void -StreamingImageVirtualWriter<TInputImage> +StreamingImageVirtualWriter<TInputImage,TStreamingManager> ::GenerateData(void) { /** @@ -257,6 +81,7 @@ StreamingImageVirtualWriter<TInputImage> * Tell all Observers that the filter is starting */ this->InvokeEvent(itk::StartEvent()); + /** * Grab the input */ @@ -267,25 +92,47 @@ StreamingImageVirtualWriter<TInputImage> * minimum of what the user specified via SetNumberOfStreamDivisions() * and what the Splitter thinks is a reasonable value. */ - unsigned int numDivisions; - numDivisions = static_cast<unsigned int>(CalculateNumberOfStreamDivisions()); + m_StreamingManager->PrepareStreaming(inputPtr, outputRegion); + m_NumberOfDivisions = m_StreamingManager->GetNumberOfSplits(); + + /** + * Register to the ProgressEvent of the source filter + */ + // Get the source process object + itk::ProcessObject* source = inputPtr->GetSource(); + + // Check if source exists + if(source) + { + typedef itk::MemberCommand<Self> CommandType; + typedef typename CommandType::Pointer CommandPointerType; + + CommandPointerType command = CommandType::New(); + command->SetCallbackFunction(this, &Self::ObserveSourceFilterProgress); + + source->AddObserver(itk::ProgressEvent(), command); + } + else + { + itkWarningMacro(<< "Could not get the source process object. Progress report might be buggy"); + } /** * Loop over the number of pieces, execute the upstream pipeline on each * piece, and copy the results into the output image. */ InputImageRegionType streamRegion; - unsigned int piece; - for (piece = 0; - piece < numDivisions && !this->GetAbortGenerateData(); - piece++) + for (m_CurrentDivision = 0; + m_CurrentDivision < m_NumberOfDivisions && !this->GetAbortGenerateData(); + m_CurrentDivision++, m_DivisionProgress = 0, this->UpdateFilterProgress()) { - streamRegion = m_RegionSplitter->GetSplit(piece, numDivisions, outputRegion); + streamRegion = m_StreamingManager->GetSplit(m_CurrentDivision); + otbMsgDevMacro(<< "Processing region : " << streamRegion ) inputPtr->ReleaseData(); inputPtr->SetRequestedRegion(streamRegion); inputPtr->Update(); - this->UpdateProgress((float) piece / numDivisions); } + /** * If we ended due to aborting, push the progress up to 1.0 (since * it probably didn't end there) @@ -308,11 +155,14 @@ StreamingImageVirtualWriter<TInputImage> this->GetOutput(idx)->DataHasBeenGenerated(); } } + /** * Release any inputs if marked for release */ this->ReleaseInputs(); } + + } // end namespace otb #endif diff --git a/Code/Projections/otbUtmMapProjection.h b/Code/Projections/otbUtmMapProjection.h index f30ba4e544d5556335f0d9dd1a83dba8b073404c..b031c63ba05f9d1af083d8a87db9774d4dd34a51 100644 --- a/Code/Projections/otbUtmMapProjection.h +++ b/Code/Projections/otbUtmMapProjection.h @@ -53,7 +53,7 @@ public: virtual void SetZone(long zone); virtual void SetHemisphere(char hemisphere); virtual int GetZone() const; - virtual const char GetHemisphere() const; + virtual char GetHemisphere() const; virtual void SetZoneAndHemisphereFromGeoPoint(const InputPointType& geoPoint); virtual int GetZoneFromGeoPoint(const InputPointType& geoPoint) const; diff --git a/Code/Projections/otbUtmMapProjection.txx b/Code/Projections/otbUtmMapProjection.txx index 6d1ffd46ea162ca99625b078f2b89c2b653aba1b..450e166099ed39206dfaeda9483066bc5a1e91db 100644 --- a/Code/Projections/otbUtmMapProjection.txx +++ b/Code/Projections/otbUtmMapProjection.txx @@ -68,7 +68,7 @@ int UtmMapProjection<TTransform> ///\return the hemisphere template <TransformDirection::TransformationDirection TTransform> -const char UtmMapProjection<TTransform> +char UtmMapProjection<TTransform> ::GetHemisphere() const { char hemisphere = this->m_MapProjection->getHemisphere(); diff --git a/Testing/Code/BasicFilters/otbMatrixImageFilterTest.cxx b/Testing/Code/BasicFilters/otbMatrixImageFilterTest.cxx index 60c2881d52cccbf547e65e3942088de115aacdb8..483d6afb84f6a5749726343a7fdcb0da0601e64f 100644 --- a/Testing/Code/BasicFilters/otbMatrixImageFilterTest.cxx +++ b/Testing/Code/BasicFilters/otbMatrixImageFilterTest.cxx @@ -28,9 +28,6 @@ int otbMatrixImageFilterNew(int argc, char * argv[]) { - const char * inputFilename = argv[1]; - const char * outputFilename = argv[2]; - typedef std::complex<double> PixelType; typedef otb::VectorImage<PixelType> ImageType; diff --git a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx index beebc71c1231462c0535364c697f48eab7e090c4..2d9a433f506d4827fd86b45a3c46b07c64c976b8 100644 --- a/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbMatrixTransposeMatrixImageFilter.cxx @@ -50,7 +50,7 @@ int otbMatrixTransposeMatrixImageFilter(int argc, char * argv[]) reader2->SetFileName(infname2); // filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); - filter->GetStreamer()->SetNumberOfStreamDivisions(200); + //filter->GetStreamer()->SetNumberOfStreamDivisions(200); filter->SetFirstInput(reader1->GetOutput()); filter->SetSecondInput(reader2->GetOutput()); filter->SetUsePadFirstInput(true); diff --git a/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx index 2987a0f63604e0d6c49050e4f7a50c7fef9babd6..bf4c392613c74d4c7786a4d823b0391e0c797bf2 100644 --- a/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbStreamingInnerProductVectorImageFilter.cxx @@ -40,7 +40,7 @@ int otbStreamingInnerProductVectorImageFilter(int argc, char* argv[]) // Instantiation object FilterType::Pointer filter = FilterType::New(); - filter->GetStreamer()->SetNumberOfStreamDivisions(10); + //filter->GetStreamer()->SetNumberOfStreamDivisions(10); filter->SetCenterData(centerdata); filter->SetInput(reader->GetOutput()); filter->Update(); diff --git a/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx index 0a4493c8306a063c2fb731fcc211a1684372a1a9..5f59b2d7f794a45b011c71968eb507af71c54355 100644 --- a/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbStreamingMinMaxImageFilter.cxx @@ -43,7 +43,7 @@ int otbStreamingMinMaxImageFilter(int argc, char * argv[]) reader->SetFileName(infname); //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); - filter->GetStreamer()->SetNumberOfStreamDivisions(200); + //filter->GetStreamer()->SetNumberOfStreamDivisions(200); filter->SetInput(reader->GetOutput()); otb::StandardFilterWatcher watcher(filter, "Min Max Computation"); filter->Update(); diff --git a/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx index 778df22c3a34f2eddc7ae02ed10113fb4bdd8985..f8f2e265fec84ee19cb7547e1ee2e4f52ca303a4 100644 --- a/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbStreamingMinMaxVectorImageFilter.cxx @@ -43,7 +43,7 @@ int otbStreamingMinMaxVectorImageFilter(int argc, char * argv[]) reader->SetFileName(infname); //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); - filter->GetStreamer()->SetNumberOfStreamDivisions(200); + //filter->GetStreamer()->SetNumberOfStreamDivisions(200); filter->SetInput(reader->GetOutput()); otb::StandardFilterWatcher watcher(filter, "Min Max Computation"); filter->Update(); diff --git a/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx index adb2fc6c71399e1afc7f9dd2c4d40aa702d292a5..22fae71fb8c86d644fc9d2c273cfb4b75d8fcacb 100644 --- a/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbStreamingStatisticsImageFilter.cxx @@ -43,7 +43,7 @@ int otbStreamingStatisticsImageFilter(int argc, char * argv[]) reader->SetFileName(infname); //filter->GetStreamer()->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); - filter->GetStreamer()->SetNumberOfStreamDivisions(200); + //filter->GetStreamer()->SetNumberOfStreamDivisions(200); filter->SetInput(reader->GetOutput()); filter->Update(); diff --git a/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx index e0c312c80be531fb50907cce675f0ec7d0bbd90a..8316823fb3a819eeac2e09edf5de9099875fd64f 100644 --- a/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx +++ b/Testing/Code/BasicFilters/otbStreamingStatisticsVectorImageFilter.cxx @@ -42,7 +42,7 @@ int otbStreamingStatisticsVectorImageFilter(int argc, char * argv[]) reader->SetFileName(infname); //filter->SetStreamingMode(otb::SET_NUMBER_OF_STREAM_DIVISIONS); - filter->GetStreamer()->SetNumberOfStreamDivisions(200); + //filter->GetStreamer()->SetNumberOfStreamDivisions(200); filter->SetInput(reader->GetOutput()); filter->Update(); diff --git a/Testing/Code/Common/CMakeLists.txt b/Testing/Code/Common/CMakeLists.txt index a598f4ed523f02bf5972055c2e6eaaef5588f577..ef1cf514ef8833f72f36486c0297351017271db5 100644 --- a/Testing/Code/Common/CMakeLists.txt +++ b/Testing/Code/Common/CMakeLists.txt @@ -736,6 +736,19 @@ ADD_TEST(coTvImageRegionTileMapSplitter ${COMMON_TESTS8} ${TEMP}/coImageRegionTileMapSplitter.txt ) +# ------------- otb::ImageRegionSquareTileSplitter ---------------------------- +ADD_TEST(coTuImageRegionSquareTileSplitterNew ${COMMON_TESTS8} + otbImageRegionSquareTileSplitterNew +) + +ADD_TEST(coTvImageRegionSquareTileSplitter ${COMMON_TESTS8} + --compare-ascii ${NOTOL} + ${BASELINE_FILES}/coImageRegionSquareTileSplitter.txt + ${TEMP}/coImageRegionSquareTileSplitter.txt + otbImageRegionSquareTileSplitter + ${TEMP}/coImageRegionSquareTileSplitter.txt +) + # ------------- otb::ImageOfVectorsToMonoChannelExtractROI ---------------------------- ADD_TEST(coTuImageOfVectorsToMonoChannelExtractROINew ${COMMON_TESTS8} otbImageOfVectorsToMonoChannelExtractROINew @@ -1103,6 +1116,7 @@ otbQuickLookImageGeneratorNew.cxx otbQuickLookImageGenerator.cxx otbImageRegionTileMapSplitterNew.cxx otbImageRegionTileMapSplitter.cxx +otbImageRegionSquareTileSplitter.cxx otbImageOfVectorsToMonoChannelExtractROINew.cxx otbImageOfVectorsToMonoChannelExtractROI.cxx otbImageRegionNonUniformMultidimensionalSplitterNew.cxx diff --git a/Testing/Code/Common/otbCommonTests8.cxx b/Testing/Code/Common/otbCommonTests8.cxx index 63e946336f54ae8d97a12ce41cfe3478225f0214..c948600503a217f1a6f89e33618659d644aab84a 100644 --- a/Testing/Code/Common/otbCommonTests8.cxx +++ b/Testing/Code/Common/otbCommonTests8.cxx @@ -30,6 +30,8 @@ void RegisterTests() REGISTER_TEST(otbQuickLookImageGenerator); REGISTER_TEST(otbImageRegionTileMapSplitterNew); REGISTER_TEST(otbImageRegionTileMapSplitter); + REGISTER_TEST(otbImageRegionSquareTileSplitterNew); + REGISTER_TEST(otbImageRegionSquareTileSplitter); REGISTER_TEST(otbImageOfVectorsToMonoChannelExtractROINew); REGISTER_TEST(otbImageOfVectorsToMonoChannelExtractROI); REGISTER_TEST(otbImageRegionNonUniformMultidimensionalSplitterNew); diff --git a/Testing/Code/Common/otbImageRegionSquareTileSplitter.cxx b/Testing/Code/Common/otbImageRegionSquareTileSplitter.cxx new file mode 100644 index 0000000000000000000000000000000000000000..89c790ebca52e0ceb456886d77d74b2a98bd1460 --- /dev/null +++ b/Testing/Code/Common/otbImageRegionSquareTileSplitter.cxx @@ -0,0 +1,146 @@ +/*========================================================================= + + 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 "otbImageRegionSquareTileSplitter.h" +#include <fstream> + +const int Dimension = 2; +typedef otb::ImageRegionSquareTileSplitter<Dimension> SquareTileSplitterType; +typedef SquareTileSplitterType::IndexType IndexType; +typedef SquareTileSplitterType::SizeType SizeType; +typedef SquareTileSplitterType::RegionType RegionType; + + +int otbImageRegionSquareTileSplitterNew(int argc, char * argv[]) +{ + SquareTileSplitterType::Pointer splitter = SquareTileSplitterType::New(); + + std::cout << splitter << std::endl; + + return EXIT_SUCCESS; +} + +int TestSplitter(const RegionType& region, unsigned int PixelSize, unsigned int MaxTileSize, std::ostream& os) +{ + os << "----------------------------------" << std::endl; + os << "Region : " << region << std::endl; + os << "PixelSize : " << PixelSize << std::endl; + os << "MaxTileSize : " << MaxTileSize << std::endl; + + SquareTileSplitterType::Pointer splitter; + splitter = SquareTileSplitterType::New(); + + unsigned int requestedNbSplits = region.GetNumberOfPixels() * PixelSize / MaxTileSize; + if (requestedNbSplits == 0) + requestedNbSplits = 1; + os << "Requested Number of splits : " << requestedNbSplits << std::endl; + + const unsigned int nbSplits = splitter->GetNumberOfSplits(region, requestedNbSplits); + os << "Actual Number of splits : " << nbSplits << std::endl; + + + RegionType split; + + // First split : + split = splitter->GetSplit(0, nbSplits, region); + os << "First Split : " << split + << "(" << split.GetNumberOfPixels() * PixelSize << " bytes)" << std::endl; + + if (nbSplits > 1) + { + // Second split : + split = splitter->GetSplit(1, nbSplits, region); + os << "Second Split : " << split + << "(" << split.GetNumberOfPixels() * PixelSize << " bytes)" << std::endl; + } + + if (nbSplits > 2) + { + // Last split : + split = splitter->GetSplit(nbSplits - 1, nbSplits, region); + os << "Last Split : " << split + << "(" << split.GetNumberOfPixels() * PixelSize << " bytes)" << std::endl; + } + + return EXIT_SUCCESS; +} + + +int otbImageRegionSquareTileSplitter(int argc, char * argv[]) +{ + std::ofstream outfile(argv[1]); + RegionType region; + + // Test with a 0-based indexed region + region.SetIndex(0, 0); + region.SetIndex(1, 0); + region.SetSize(0, 1024); + region.SetSize(1, 1024); + TestSplitter(region, 1, 128, outfile); + TestSplitter(region, 1, 512*512, outfile); + TestSplitter(region, 2, 512*512, outfile); + TestSplitter(region, 4, 512*512, outfile); + TestSplitter(region, 8, 512*512, outfile); + + // Test with a shifted region + region.SetIndex(0, 42); + region.SetIndex(1, 42); + region.SetSize(0, 1000); + region.SetSize(1, 1000); + TestSplitter(region, 1, 128, outfile); + TestSplitter(region, 1, 512*512, outfile); + TestSplitter(region, 2, 512*512, outfile); + TestSplitter(region, 4, 512*512, outfile); + TestSplitter(region, 8, 512*512, outfile); + + // Test with a negative shift + region.SetIndex(0, -42); + region.SetIndex(1, -42); + region.SetSize(0, 1000); + region.SetSize(1, 1000); + TestSplitter(region, 1, 128, outfile); + TestSplitter(region, 1, 512*512, outfile); + TestSplitter(region, 2, 512*512, outfile); + TestSplitter(region, 4, 512*512, outfile); + TestSplitter(region, 8, 512*512, outfile); + + // Test with a reduced size + region.SetIndex(0, 0); + region.SetIndex(1, 0); + region.SetSize(0, 1); + region.SetSize(1, 1); + TestSplitter(region, 1, 128, outfile); + TestSplitter(region, 1, 512*512, outfile); + TestSplitter(region, 2, 512*512, outfile); + TestSplitter(region, 4, 512*512, outfile); + TestSplitter(region, 8, 512*512, outfile); + + // Test with a reduced size, shifted + region.SetIndex(0, 42); + region.SetIndex(1, 42); + region.SetSize(0, 1); + region.SetSize(1, 1); + TestSplitter(region, 1, 128, outfile); + TestSplitter(region, 1, 512*512, outfile); + TestSplitter(region, 2, 512*512, outfile); + TestSplitter(region, 4, 512*512, outfile); + TestSplitter(region, 8, 512*512, outfile); + + outfile.close(); + + return EXIT_SUCCESS; +} diff --git a/Testing/Code/Common/otbQuickLookImageGenerator.cxx b/Testing/Code/Common/otbQuickLookImageGenerator.cxx index 071f7fd5c642a1bccebd3e308f9f994181a34261..8e86c247de19a0801e2741ae603c9c1805a68608 100644 --- a/Testing/Code/Common/otbQuickLookImageGenerator.cxx +++ b/Testing/Code/Common/otbQuickLookImageGenerator.cxx @@ -49,6 +49,8 @@ int otbQuickLookImageGenerator(int argc, char* argv[]) filter->SetMaximumKernelWidth(atoi(argv[6])); filter->UseImageSpacing(atoi(argv[7])); + filter->Update(); + writer->SetInput(filter->GetOutput()); writer->SetFileName(outputFileName); diff --git a/Testing/Code/IO/otbImageFileWriterTestWithoutInput.cxx b/Testing/Code/IO/otbImageFileWriterTestWithoutInput.cxx index d6576ab6e6be1de99c0fdb18cfc6ae756c807d08..6c9733dadd957382625aba51c521c9e133aae49b 100644 --- a/Testing/Code/IO/otbImageFileWriterTestWithoutInput.cxx +++ b/Testing/Code/IO/otbImageFileWriterTestWithoutInput.cxx @@ -70,9 +70,6 @@ int otbImageScalarFileWriterTestWithoutInputGeneric(int argc, char* argv[]) IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; - ImagePixelType pixVal; - while (!it.IsAtEnd()) { it.Set(static_cast<PixelType> (size[0] * it.GetIndex()[1] + it.GetIndex()[0])); diff --git a/Testing/Code/IO/otbImageStreamingFileWriterTestWithoutInput.cxx b/Testing/Code/IO/otbImageStreamingFileWriterTestWithoutInput.cxx index 372218fe4c2692489c0d638f1ff19d39c30f8507..cff8ed3b03c25fbcfde335d591029c4d29b541c4 100644 --- a/Testing/Code/IO/otbImageStreamingFileWriterTestWithoutInput.cxx +++ b/Testing/Code/IO/otbImageStreamingFileWriterTestWithoutInput.cxx @@ -71,9 +71,6 @@ int otbImageScalarStreamingFileWriterTestWithoutInputGeneric(int argc, char* arg IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; - ImagePixelType pixVal; - while (!it.IsAtEnd()) { it.Set(static_cast<PixelType> (size[0] * it.GetIndex()[1] + it.GetIndex()[0])); diff --git a/Testing/Code/IO/otbSarImageMetadataInterfaceTest.cxx b/Testing/Code/IO/otbSarImageMetadataInterfaceTest.cxx index 41b5e99ebdf81e7efd0e0eae6519102f3b39fff4..22531c528d8375652c9f8e4a4cbc87debbfef4b7 100644 --- a/Testing/Code/IO/otbSarImageMetadataInterfaceTest.cxx +++ b/Testing/Code/IO/otbSarImageMetadataInterfaceTest.cxx @@ -36,7 +36,9 @@ void printPointSet(otb::SarImageMetadataInterface::PointSetPointer pointSet, std { stream << "PointSet values :" << std::endl; otb::SarImageMetadataInterface::PointSetType::PointType point; + point.Fill(0); otb::SarImageMetadataInterface::PointSetType::PixelType pointValue; + pointValue.Fill(0); for (unsigned int i = 0; i < pointSet->GetNumberOfPoints(); ++i) { pointSet->GetPoint(i, &point); diff --git a/Testing/Code/IO/otbVectorImageFileWriterTestWithoutInput.cxx b/Testing/Code/IO/otbVectorImageFileWriterTestWithoutInput.cxx index fbb4b31b2992fd0911f2ff9ab669c934721448e4..00ce431586e39b497718303d0fcc25d1c691d5b6 100644 --- a/Testing/Code/IO/otbVectorImageFileWriterTestWithoutInput.cxx +++ b/Testing/Code/IO/otbVectorImageFileWriterTestWithoutInput.cxx @@ -84,7 +84,6 @@ int otbVectorImageFileWriterScalarTestWithoutInputGeneric(int argc, char* argv[] IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; ImagePixelType pixVal; pixVal.SetSize(atoi(argv[3])); @@ -179,7 +178,6 @@ int otbVectorImageFileWriterComplexTestWithoutInputGeneric(int argc, char* argv[ IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; ImagePixelType pixVal; pixVal.SetSize(atoi(argv[3])); diff --git a/Testing/Code/IO/otbVectorImageStreamingFileWriterTestWithoutInput.cxx b/Testing/Code/IO/otbVectorImageStreamingFileWriterTestWithoutInput.cxx index b5768ec8717bca133d584a2605f5cb3da1750502..023d3c6adb4941ae625c5d63d45370e3f3bc1ba5 100644 --- a/Testing/Code/IO/otbVectorImageStreamingFileWriterTestWithoutInput.cxx +++ b/Testing/Code/IO/otbVectorImageStreamingFileWriterTestWithoutInput.cxx @@ -84,7 +84,6 @@ int otbVectorImageStreamingFileWriterScalarTestWithoutInputGeneric(int argc, cha IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; ImagePixelType pixVal; pixVal.SetSize(atoi(argv[3])); @@ -105,7 +104,6 @@ int otbVectorImageStreamingFileWriterScalarTestWithoutInputGeneric(int argc, cha writer->SetInput(image); writer->Update(); - return EXIT_SUCCESS; } @@ -180,7 +178,6 @@ int otbVectorImageStreamingFileWriterComplexTestWithoutInputGeneric(int argc, ch IteratorType it(image, image->GetLargestPossibleRegion()); it.GoToBegin(); - double val = 0.; ImagePixelType pixVal; pixVal.SetSize(atoi(argv[3])); diff --git a/Testing/Code/Visualization/otbImageLayerScalar.cxx b/Testing/Code/Visualization/otbImageLayerScalar.cxx index d14ac1518b77547d8c0632cd6bc211dbe82fe467..515e5e8dd2209a42cf008fc5bc35693202113bc7 100644 --- a/Testing/Code/Visualization/otbImageLayerScalar.cxx +++ b/Testing/Code/Visualization/otbImageLayerScalar.cxx @@ -53,6 +53,7 @@ int otbImageLayerScalar(int argc, char * argv[]) // Quicklook shrinker->SetInput(reader->GetOutput()); shrinker->SetShrinkFactor(ssrate); + shrinker->Update(); // new layer LayerType::Pointer layer = LayerType::New(); diff --git a/Testing/Code/Visualization/otbImageLayerVector.cxx b/Testing/Code/Visualization/otbImageLayerVector.cxx index 04ab0b7ca10fd739ef33b9336cdf88fb10a9ad8d..94e46a11af24b5373a0fc062b236dc7152119f13 100644 --- a/Testing/Code/Visualization/otbImageLayerVector.cxx +++ b/Testing/Code/Visualization/otbImageLayerVector.cxx @@ -65,6 +65,7 @@ int otbImageLayerVector(int argc, char * argv[]) // Quicklook shrinker->SetInput(reader->GetOutput()); shrinker->SetShrinkFactor(ssrate); + shrinker->Update(); // new layer LayerType::Pointer layer = LayerType::New(); diff --git a/otbConfigure.h.in b/otbConfigure.h.in index ab1f7d425524181d86d0022f76f02bbb8822b9be..29e21a97c10853e99033fb7e2de510ead5f3b417 100644 --- a/otbConfigure.h.in +++ b/otbConfigure.h.in @@ -1,5 +1,5 @@ /* - * here is where system comupted values get stored these values should only + * here is where system computed values get stored these values should only * change when the target compile platform changes */