//******************************************************************* // Copyright (C) 2001 ImageLinks Inc. // // License: MIT // // See LICENSE.txt file in the top level directory for more details. // // Author: Garrett Potts // //******************************************************************* // $Id: ossimImageRenderer.h 23664 2015-12-14 14:17:27Z dburken $ #ifndef ossimImageRenderer_HEADER #define ossimImageRenderer_HEADER #include #include #include #include #include #include class ossimImageData; class ossimDiscreteConvolutionKernel; class ossimFilterResampler; class OSSIMDLLEXPORT ossimImageRenderer : public ossimImageSourceFilter, public ossimViewInterface { public: ossimImageRenderer(); ossimImageRenderer(ossimImageSource* inputSource, ossimImageViewTransform* imageViewTrans = NULL); virtual ossimString getLongName() const; virtual ossimString getShortName() const; /** * the resampler will need the tile request to come from the view. * It will use the view to transoform this to world and then use the * image's projection to get it into final line sample. This way * the resampler can fill a tile width by height on the screen * correctly. */ virtual ossimRefPtr getTile(const ossimIrect& origin, ossim_uint32 resLevel=0); virtual void initialize(); /** * m_Resampler will adjust the rect to whatever the view is. So it * will project the full image rect onto the view and return the upright * bounding rect. */ virtual ossimIrect getBoundingRect(ossim_uint32 resLevel=0)const; /** * @brief Gets the bounding rectangle of the source. * * This is the output view bounds. * * @param rect Initialized with bounding rectangle by this. * @param resLevel Reduced resolution level if applicable. */ virtual void getBoundingRect(ossimIrect& rect, ossim_uint32 resLevel=0) const; /** * Method to save the state of an object to a keyword list. * Return true if ok or false on error. */ virtual bool saveState(ossimKeywordlist& kwl, const char* prefix=0)const; /** * Method to the load (recreate) the state of an object from a keyword * list. Return true if ok or false on error. */ virtual bool loadState(const ossimKeywordlist& kwl, const char* prefix=0); void setImageViewTransform(ossimImageViewTransform* transform); ossimImageViewTransform* getImageViewTransform() { return m_ImageViewTransform.get(); } //! Returns instance to the input image geometry. This may be a NULL pointer. //! This is only valid if the IVT is a projection type IVT (IVPT) virtual ossimRefPtr getImageGeometry(); virtual bool setView(ossimObject* baseObject); ossimFilterResampler* getResampler() { return m_Resampler; } virtual ossimObject* getView(); virtual const ossimObject* getView()const; virtual void getDecimationFactor(ossim_uint32 resLevel, ossimDpt& result)const; virtual void getDecimationFactors(vector& decimations)const; virtual ossim_uint32 getNumberOfDecimationLevels()const; virtual void setAutoUpdateInputTransformFlag(bool flag){ m_AutoUpdateInputTransform = flag; } /** * ordering specifies how the vertices should be arranged. * valid image vertices is basically the tightly fit convex hull * of the image. Usually an image has NULL values and are * internally not upright rectangular. This can cause * problems some spatial filters. * * We need to make sure that the resampler overrides this method. * it needs to transform the vertices to the view's side. */ virtual void getValidImageVertices(vector& validVertices, ossimVertexOrdering ordering=OSSIM_CLOCKWISE_ORDER, ossim_uint32 resLevel=0)const; void setMaxLevelsToCompute(ossim_uint32 maxLevels); ossim_uint32 getMaxLevelsToCompute()const; void connectInputEvent(ossimConnectionEvent& event); void disconnectInputEvent(ossimConnectionEvent& event); void propertyEvent(ossimPropertyEvent& event); virtual void refreshEvent(ossimRefreshEvent& event); virtual void setProperty(ossimRefPtr property); virtual ossimRefPtr getProperty(const ossimString& name)const; virtual void getPropertyNames(std::vector& propertyNames)const; /** * @brief Enables source. * * Overrides ossimSource::enableSource so bounding rects are recomputed on * state change. */ virtual void enableSource(); /** * @brief Disables source. * * Overrides ossimSource::disableSource so bounding rects are recomputed on * state change. */ virtual void disableSource(); /** * @brief Sets the enable flag. * * @param flag True to enable, false to disable. * * Overrides ossimSource::setEnableFlag so bounding rects are recomputed on * state change. */ virtual void setEnableFlag(bool flag); protected: virtual ~ossimImageRenderer(); private: class ossimRendererSubRectInfo { enum SplitFlag{ SPLIT_NONE = 0, UPPER_LEFT_SPLIT_FLAG = 1, UPPER_RIGHT_SPLIT_FLAG = 2, LOWER_RIGHT_SPLIT_FLAG = 4, LOWER_LEFT_SPLIT_FLAG = 8, SPLIT_ALL = UPPER_LEFT_SPLIT_FLAG|UPPER_RIGHT_SPLIT_FLAG|LOWER_RIGHT_SPLIT_FLAG|LOWER_LEFT_SPLIT_FLAG }; public: friend std::ostream& operator <<(std::ostream& out, const ossimRendererSubRectInfo& rhs) { return out << "vul: " << rhs.m_Vul << endl << "vur: " << rhs.m_Vur << endl << "vlr: " << rhs.m_Vlr << endl << "vll: " << rhs.m_Vll << endl << "iul: " << rhs.m_Iul << endl << "iur: " << rhs.m_Iur << endl << "ilr: " << rhs.m_Ilr << endl << "ill: " << rhs.m_Ill << endl << "scale: " << rhs.m_ViewToImageScale << endl; } ossimRendererSubRectInfo(ossimImageViewTransform* transform=0); ossimRendererSubRectInfo(ossimImageViewTransform* transform, const ossimDpt& vul, const ossimDpt& vur, const ossimDpt& vlr, const ossimDpt& vll); bool imageHasNans()const; bool imageIsNan()const; bool viewHasNans()const; bool viewIsNan()const; void splitView(std::vector& result)const; //void splitView(ossimRendererSubRectInfo& ulRect, // ossimRendererSubRectInfo& urRect, // ossimRendererSubRectInfo& lrRect, // ossimRendererSubRectInfo& llRect)const; void transformViewToImage(); void transformImageToView(); bool tooBig()const; void roundToInteger(); void stretchImageOut(bool enableRound=false); ossimDrect getViewRect()const; ossimDrect getImageRect()const; void roundImageToInteger(); void roundViewToInteger(); bool isViewEqual(const ossimRendererSubRectInfo& infoRect)const; bool isViewEqual(const ossimDrect& viewRect)const; ossimDpt computeViewToImageScale(const ossimDpt& viewPt, const ossimDpt& delta=ossimDpt(1.0,1.0))const; ossimDpt getAbsValueViewToImageScales()const; ossimDpt getAbsValueImageToViewScales()const; ossimDpt computeRoundTripErrorViewPt(const ossimDpt& dpt)const; bool isViewAPoint()const; bool isIdentity()const; bool canBilinearInterpolate(double error)const; ossimDpt getParametricCenter(const ossimDpt& ul, const ossimDpt& ur, const ossimDpt& lr, const ossimDpt& ll)const; void getViewMids(ossimDpt& upperMid, ossimDpt& rightMid, ossimDpt& bottomMid, ossimDpt& leftMid, ossimDpt& center)const; void getImageMids(ossimDpt& upperMid, ossimDpt& rightMid, ossimDpt& bottomMid, ossimDpt& leftMid, ossimDpt& center)const; ossim_uint16 getSplitFlags()const; ossimDpt m_Iul; ossimDpt m_Iur; ossimDpt m_Ilr; ossimDpt m_Ill; ossimIpt m_Vul; ossimIpt m_Vur; ossimIpt m_Vlr; ossimIpt m_Vll; ossimDpt m_ViewToImageScale; ossimDpt m_ImageToViewScale; ossimDpt m_VulScale; ossimDpt m_VurScale; ossimDpt m_VlrScale; ossimDpt m_VllScale; ossimDpt m_ulRoundTripError; ossimDpt m_urRoundTripError; ossimDpt m_lrRoundTripError; ossimDpt m_llRoundTripError; mutable ossimRefPtr m_transform; mutable const ossimPolyArea2d* m_viewBounds; private: void splitHorizontal(std::vector& result)const; void splitVertical(std::vector& result)const; void splitAll(std::vector& result)const; }; void recursiveResample(ossimRefPtr outputData, const ossimRendererSubRectInfo& rectInfo, ossim_uint32 level); void fillTile(ossimRefPtr outputData, const ossimRendererSubRectInfo& rectInfo); ossimIrect getBoundingImageRect()const; //! this is called on a property event and on input connection changes. void checkIVT(); /** * @brief Initializes m_inputR0Rect and m_viewBoundingRect and sets * m_rectsDirty appropriately. */ void initializeBoundingRects(); ossimRefPtr getTileAtResLevel(const ossimIrect& boundingRect, ossim_uint32 resLevel); template void resampleTileToDecimation(T dummyVariable, ossimRefPtr result, ossimRefPtr tile, ossim_uint32 multiplier); long computeClosestResLevel(const std::vector& decimationFactors, double scale)const; void stretchQuadOut(const ossimDpt& amount, ossimDpt& ul, ossimDpt& ur, ossimDpt& lr, ossimDpt& ll); /** * Called on first getTile, will initialize all data needed. */ void allocate(); /** * Deletes all allocated tiles. */ void deallocate(); ossimFilterResampler* m_Resampler; ossimRefPtr m_BlankTile; ossimRefPtr m_Tile; ossimRefPtr m_TemporaryBuffer; /** * This is going to allow us to chain multiple * renderers together. So if we have one * renderer doing a scale and they pass an r-level * down and we have another renderer within the * chain he will be starting at a different r-level. * The default will be r-level 0 request coming * from the right. */ ossim_uint32 m_StartingResLevel; ossimRefPtr m_ImageViewTransform; ossimIrect m_inputR0Rect; ossimIrect m_viewRect; bool m_rectsDirty; ossim_uint32 m_MaxRecursionLevel; bool m_AutoUpdateInputTransform; ossim_uint32 m_MaxLevelsToCompute; ossimPolyArea2d m_viewArea; TYPE_DATA }; inline ossimImageRenderer::ossimRendererSubRectInfo::ossimRendererSubRectInfo(ossimImageViewTransform* transform) :m_transform(transform), m_viewBounds(0) { m_Vul.makeNan(); m_Vur.makeNan(); m_Vlr.makeNan(); m_Vll.makeNan(); m_Iul.makeNan(); m_Iur.makeNan(); m_Ilr.makeNan(); m_Ill.makeNan(); m_ViewToImageScale.makeNan(); m_ImageToViewScale.makeNan(); } inline ossimImageRenderer::ossimRendererSubRectInfo::ossimRendererSubRectInfo(ossimImageViewTransform* transform, const ossimDpt& vul, const ossimDpt& vur, const ossimDpt& vlr, const ossimDpt& vll) :m_Vul(vul), m_Vur(vur), m_Vlr(vlr), m_Vll(vll), m_transform(transform), m_viewBounds(0) { m_Iul.makeNan(); m_Iur.makeNan(); m_Ilr.makeNan(); m_Ill.makeNan(); m_ViewToImageScale.makeNan(); m_ImageToViewScale.makeNan(); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::imageHasNans()const { return ( m_Iul.hasNans()|| m_Iur.hasNans()|| m_Ilr.hasNans()|| m_Ill.hasNans()); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::imageIsNan()const { return ( m_Iul.hasNans()&& m_Iur.hasNans()&& m_Ilr.hasNans()&& m_Ill.hasNans()); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::viewHasNans()const { return ( m_Vul.hasNans()|| m_Vur.hasNans()|| m_Vlr.hasNans()|| m_Vll.hasNans()); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::viewIsNan()const { return ( m_Vul.hasNans()&& m_Vur.hasNans()&& m_Vlr.hasNans()&& m_Vll.hasNans()); } inline void ossimImageRenderer::ossimRendererSubRectInfo::roundToInteger() { m_Iul = ossimIpt(m_Iul); m_Iur = ossimIpt(m_Iur); m_Ilr = ossimIpt(m_Ilr); m_Ill = ossimIpt(m_Ill); m_Vul = ossimIpt(m_Vul); m_Vur = ossimIpt(m_Vur); m_Vlr = ossimIpt(m_Vlr); m_Vll = ossimIpt(m_Vll); } inline ossimDrect ossimImageRenderer::ossimRendererSubRectInfo::getViewRect()const { return ossimDrect(m_Vul, m_Vur, m_Vlr, m_Vll); } inline ossimDrect ossimImageRenderer::ossimRendererSubRectInfo::getImageRect()const { return ossimDrect(m_Iul, m_Iur, m_Ilr, m_Ill); } inline void ossimImageRenderer::ossimRendererSubRectInfo::roundImageToInteger() { m_Iul = ossimIpt(m_Iul); m_Iur = ossimIpt(m_Iur); m_Ilr = ossimIpt(m_Ilr); m_Ill = ossimIpt(m_Ill); } inline void ossimImageRenderer::ossimRendererSubRectInfo::roundViewToInteger() { m_Vul = ossimIpt(m_Vul); m_Vur = ossimIpt(m_Vur); m_Vlr = ossimIpt(m_Vlr); m_Vll = ossimIpt(m_Vll); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::isViewEqual(const ossimRendererSubRectInfo& infoRect)const { return ( (m_Vul == infoRect.m_Vul)&& (m_Vur == infoRect.m_Vur)&& (m_Vlr == infoRect.m_Vlr)&& (m_Vll == infoRect.m_Vll)); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::isViewEqual(const ossimDrect& viewRect)const { return ( (m_Vul == viewRect.ul())&& (m_Vur == viewRect.ur())&& (m_Vlr == viewRect.lr())&& (m_Vll == viewRect.ll())); } inline ossimDpt ossimImageRenderer::ossimRendererSubRectInfo::getAbsValueViewToImageScales()const { if(m_ViewToImageScale.hasNans()) { return m_ImageToViewScale; } return ossimDpt(fabs(m_ViewToImageScale.x), fabs(m_ViewToImageScale.y)); } inline ossimDpt ossimImageRenderer::ossimRendererSubRectInfo::getAbsValueImageToViewScales()const { if(m_ImageToViewScale.hasNans()) { return m_ImageToViewScale; } return ossimDpt(fabs(m_ImageToViewScale.x), fabs(m_ImageToViewScale.y)); } inline bool ossimImageRenderer::ossimRendererSubRectInfo::isViewAPoint()const { return ((m_Vul == m_Vur)&& (m_Vul == m_Vlr)&& (m_Vul == m_Vll)); } #endif