1 //*******************************************************************
2 //
3 // License:  See top level LICENSE.txt file.
4 //
5 // Author:  RP
6 //
7 // Description:
8 //
9 //
10 //*******************************************************************
11 //  $Id$
12 #include <ossim/imaging/ossimElevRemapper.h>
13 #include <ossim/imaging/ossimImageGeometry.h>
14 #include <ossim/base/ossimGeoidManager.h>
15 #include <ossim/base/ossimTrace.h>
16 
17 RTTI_DEF1(ossimElevRemapper, "ossimElevRemapper", ossimImageSourceFilter);
18 static ossimTrace traceDebug("ossimElevRemapper::debug");
19 
20 const char ossimElevRemapper::REMAP_MODE_KW[]  = "remap_mode";
21 
22 using namespace std;
23 
ossimElevRemapper()24 ossimElevRemapper::ossimElevRemapper()
25 :m_replacementType(ReplacementType_ELLIPSOID)
26 {
27 }
28 
~ossimElevRemapper()29 ossimElevRemapper::~ossimElevRemapper()
30 {
31   m_imageGeometry = 0;
32 }
33 
initialize()34 void ossimElevRemapper::initialize()
35 {
36    if (theInputConnection && (!m_imageGeometry.valid() || !m_imageGeometry->getProjection()))
37    {
38      m_imageGeometry = theInputConnection->getImageGeometry();
39    }
40 }
41 
getTile(const ossimIrect & tile_rect,ossim_uint32 resLevel)42 ossimRefPtr<ossimImageData> ossimElevRemapper::getTile(const ossimIrect& tile_rect,
43                                                         ossim_uint32 resLevel)
44 {
45    if (traceDebug())
46    {
47      ossimNotify(ossimNotifyLevel_DEBUG)
48          << "ossimElevRemapper::getTile entered..." << endl;
49    }
50 
51    ossimRefPtr<ossimImageData> result = ossimImageSourceFilter::getTile(tile_rect, resLevel);
52    if(!isSourceEnabled()||!result.valid())
53    {
54       return result.get();
55    }
56    ossimDataObjectStatus status =  result->getDataObjectStatus();
57 
58    if(status == OSSIM_NULL)
59    {
60 	return result.get();
61    }
62    // Call the appropriate load method.
63    switch (result->getScalarType())
64    {
65       case OSSIM_UCHAR:
66       {
67          elevRemap(ossim_uint8(0), result.get(), resLevel);
68          break;
69       }
70 
71       case OSSIM_UINT16:
72       case OSSIM_USHORT11:
73       case OSSIM_USHORT12:
74       case OSSIM_USHORT13:
75       case OSSIM_USHORT14:
76       case OSSIM_USHORT15:
77       {
78          elevRemap(ossim_uint16(0), result.get(), resLevel);
79          break;
80       }
81 
82       case OSSIM_SSHORT16:
83       {
84          elevRemap(ossim_sint16(0), result.get(), resLevel);
85          break;
86       }
87       case OSSIM_UINT32:
88       {
89          elevRemap(ossim_uint32(0), result.get(), resLevel);
90          break;
91       }
92       case OSSIM_SINT32:
93       {
94          elevRemap(ossim_sint32(0), result.get(), resLevel);
95          break;
96       }
97       case OSSIM_FLOAT32:
98       case OSSIM_NORMALIZED_FLOAT:
99       {
100          elevRemap(ossim_float32(0), result.get(), resLevel);
101          break; } case OSSIM_NORMALIZED_DOUBLE: case OSSIM_FLOAT64:
102       {
103          elevRemap(ossim_float64(0), result.get(), resLevel);
104          break;
105       }
106 
107       case OSSIM_SCALAR_UNKNOWN:
108       default:
109       {
110          ossimNotify(ossimNotifyLevel_WARN)
111          << "ossimElevRemapper::getTile Unsupported scalar type!" << endl;
112          break;
113       }
114    }
115    if (traceDebug())
116    {
117      ossimNotify(ossimNotifyLevel_DEBUG)
118          << "ossimElevRemapper::getTile leaving..." << endl;
119    }
120 
121    return result;
122 }
123 
124 template <class T>
elevRemap(T,ossimImageData * inputTile,ossim_uint32 resLevel)125 void ossimElevRemapper::elevRemap(T /* dummy */,
126                                    ossimImageData* inputTile,
127                                    ossim_uint32 resLevel)
128 {
129    if (!inputTile) return;
130    ossimIrect rect = inputTile->getImageRectangle();
131    ossimIrect imageBounds = getBoundingRect(resLevel);
132    ossimIrect clipRect;
133    if(!rect.intersects(imageBounds))
134    {
135       return;
136    }
137    clipRect = rect.clipToRect(imageBounds);
138 
139    if (m_imageGeometry.valid() && m_imageGeometry->getProjection())
140    {
141       ossimGpt ul, ll, lr, ur;
142       ossim_float32 hul, hll, hlr, hur;
143       ossim_float32 height = 0.0, xpercent, ypercent, uppery, lowery;
144 
145       m_imageGeometry->rnToWorld(clipRect.ul(), resLevel, ul);
146       m_imageGeometry->rnToWorld(clipRect.ur(), resLevel, ur);
147       m_imageGeometry->rnToWorld(clipRect.ll(), resLevel, ll);
148       m_imageGeometry->rnToWorld(clipRect.lr(), resLevel, lr);
149 
150       //std::cout << "UL: " << clipRect.ul() << " RES: " << ossimString::toString(resLevel) << " ULGROUND: " << ul << "\n";
151 
152       hul = ossimGeoidManager::instance()->offsetFromEllipsoid(ul);
153       hll = ossimGeoidManager::instance()->offsetFromEllipsoid(ll);
154       hlr = ossimGeoidManager::instance()->offsetFromEllipsoid(lr);
155       hur = ossimGeoidManager::instance()->offsetFromEllipsoid(ur);
156 
157 //	std::cout << "HUL: " << ossimString::toString(hul) << " HUR: " << ossimString::toString(hur) << " HLR: " << ossimString::toString(hlr) << " HUR: " << ossimString::toString(hur) << "\n";
158 
159      if(!rect.completely_within(imageBounds))
160      {
161         ossim_uint32 bands = inputTile->getNumberOfBands();
162         ossimIpt origin = clipRect.ul() - rect.ul();
163         ossim_uint32 bandIdx = 0;
164         ossim_uint32 inputW = inputTile->getWidth();
165         ossim_uint32 originOffset = origin.y*inputW + origin.x;
166         ossim_uint32 w = clipRect.width();
167         ossim_uint32 h = clipRect.height();
168         ossim_uint32 x = 0;
169         ossim_uint32 y = 0;
170         ossim_float32 height = 0.0, xpercent, ypercent, uppery, lowery;
171         for(bandIdx = 0; bandIdx < bands; ++bandIdx)
172         {
173            T* bandPtr = static_cast<T*>(inputTile->getBuf(bandIdx)) + originOffset;
174            for(y = 0; y < h; ++y)
175            {
176               for(x = 0; x < w; ++x)
177               {
178 	         xpercent = x / clipRect.width();
179 	         ypercent = y / clipRect.height();
180 	         uppery = hul + xpercent * ( hur - hul);
181 	         lowery = hll + xpercent * ( hlr - hll);
182 	         height = uppery + ypercent * ( lowery - uppery );
183 		 if (m_replacementType==ReplacementType_GEOID) height*=-1.0;
184 
185 	         bandPtr[x] += height;
186               }
187               bandPtr += inputW;
188            }
189         }
190      }
191      else
192      {
193         ossim_uint32 bands = inputTile->getNumberOfBands();
194         ossim_uint32 bandIdx = 0;
195         ossim_uint32 size = inputTile->getWidth()*inputTile->getHeight();
196         ossim_float32 height = 0.0;
197         for(bandIdx = 0; bandIdx < bands; ++bandIdx)
198         {
199            T* bandPtr = static_cast<T*>(inputTile->getBuf(bandIdx));
200 
201            ossim_uint32 idx = 0;
202            for(idx = 0; idx < size;++idx)
203            {
204 	      ossim_uint32 y = idx / rect.width();
205               ossim_uint32 x = idx % rect.width();
206 	      xpercent = x / clipRect.width();
207               ypercent = y / clipRect.height();
208               uppery = hul + xpercent * ( hur - hul);
209               lowery = hll + xpercent * ( hlr - hll);
210               height = uppery + ypercent * ( lowery - uppery );
211 	      if (m_replacementType==ReplacementType_GEOID) height*=-1.0;
212 
213 	      (*bandPtr) += height;
214 	      ++bandPtr;
215            }
216         }
217      }
218    }
219 }
220 
saveState(ossimKeywordlist & kwl,const char * prefix) const221 bool ossimElevRemapper::saveState(ossimKeywordlist& kwl,
222                                    const char* prefix)const
223 {
224    bool result = ossimImageSourceFilter::saveState(kwl, prefix);
225    ossimString remapMode = "";
226    switch(m_replacementType)
227    {
228       case ReplacementType_ELLIPSOID:
229          remapMode = "ellipsoid";
230 	 break;
231       case ReplacementType_GEOID:
232          remapMode = "geoid";
233 	 break;
234       default:
235 	 remapMode = "ellipsoid";
236          break;
237    }
238    kwl.add(prefix, REMAP_MODE_KW,  remapMode.c_str());
239 
240    ossimString imagePrefix = ossimString(prefix)+"image_geometry.";
241 
242    if(m_imageGeometry.valid())
243    {
244       m_imageGeometry->saveState(kwl, imagePrefix.c_str());
245    }
246    //std::cout << kwl << " SAVESTATE\n";
247    return result;
248 }
249 
loadState(const ossimKeywordlist & kwl,const char * prefix)250 bool ossimElevRemapper::loadState(const ossimKeywordlist& kwl,
251                                    const char* prefix)
252 {
253    //std::cout << kwl << " LOADSTATE\n";
254    if (traceDebug())
255    {
256      ossimNotify(ossimNotifyLevel_DEBUG)
257          << "ossimElevRemapper::loadState entered..." << endl;
258    }
259    bool result = ossimImageSourceFilter::loadState(kwl, prefix);
260 
261    const char* lookup;
262    lookup = kwl.find(prefix, REMAP_MODE_KW);
263    if(lookup)
264    {
265       ossimString mode = lookup;
266       mode.upcase();
267       if (mode == "ELLIPSOID")
268       {
269          m_replacementType = ReplacementType_ELLIPSOID;
270       }
271       else if (mode == "GEOID")
272       {
273 	 m_replacementType = ReplacementType_GEOID;
274       }
275    }
276 
277    ossimString imagePrefix = ossimString(prefix)+"image_geometry.";
278    if(kwl.numberOf(imagePrefix.c_str())>0)
279    {
280       m_imageGeometry = new ossimImageGeometry();
281       m_imageGeometry->loadState(kwl, imagePrefix.c_str());
282       //setImageGeometry(m_igeometry.get());
283    }
284 
285    return result;
286 }
287