1 //*******************************************************************
2 //
3 // License: See top level LICENSE.txt file.
4 //
5 // Author: Garrett Potts <gpotts@imagelinks.com>
6 //
7 // Description:
8 //*******************************************************************
9 // $Id: ossimAtCorrGridRemapper.cpp 21631 2012-09-06 18:10:55Z dburken $
10 #include <ossim/imaging/ossimAtCorrGridRemapper.h>
11 #include <ossim/imaging/ossimImageData.h>
12
13 RTTI_DEF1(ossimAtCorrGridRemapper, "ossimAtCorrGridRemapper", ossimAtCorrRemapper);
14
15 using namespace std;
16
ossimAtCorrGridRemapper(ossimObject * owner,ossimImageSource * inputSource,const ossimString & sensorType)17 ossimAtCorrGridRemapper::ossimAtCorrGridRemapper(ossimObject* owner,
18 ossimImageSource* inputSource,
19 const ossimString& sensorType)
20 :ossimAtCorrRemapper(owner, inputSource, sensorType)
21 {
22 theUseInterpolationFlag = true;
23 }
24
~ossimAtCorrGridRemapper()25 ossimAtCorrGridRemapper::~ossimAtCorrGridRemapper()
26 {
27 }
28
interpolate(const ossimDpt & pt,int band,double & a,double & b,double & c) const29 void ossimAtCorrGridRemapper::interpolate(const ossimDpt& pt,
30 int band,
31 double& a,
32 double& b,
33 double& c)const
34 {
35 if(theGridBounds.pointWithin(pt))
36 {
37 double x = (((double)(pt.x - theUlGridBound.x))/theGridBounds.width())*(theGridSize.x-1);
38 double y = (((double)(pt.y - theUlGridBound.y))/theGridBounds.height())*(theGridSize.y-1);
39
40 int xidx = (int)x;
41 int yidx = (int)y;
42
43 double xt = x - xidx;
44 double yt = y - yidx;
45
46 double va00 = theAGrid[band][yidx][xidx];
47 double va01 = theAGrid[band][yidx][xidx+1];
48 double va11 = theAGrid[band][yidx+1][xidx+1];
49 double va10 = theAGrid[band][yidx+1][xidx];
50 double vb00 = theBGrid[band][yidx][xidx];
51 double vb01 = theBGrid[band][yidx][xidx+1];
52 double vb11 = theBGrid[band][yidx+1][xidx+1];
53 double vb10 = theBGrid[band][yidx+1][xidx];
54 double vc00 = theCGrid[band][yidx][xidx];
55 double vc01 = theCGrid[band][yidx][xidx+1];
56 double vc11 = theCGrid[band][yidx+1][xidx+1];
57 double vc10 = theCGrid[band][yidx+1][xidx];
58
59 double vaInterpH1 = va00 + (va01-va00)*xt;
60 double vaInterpH2 = va10 + (va11-va10)*xt;
61 double vbInterpH1 = vb00 + (vb01-vb00)*xt;
62 double vbInterpH2 = vb10 + (vb11-vb10)*xt;
63 double vcInterpH1 = vc00 + (vc01-vc00)*xt;
64 double vcInterpH2 = vc10 + (vc11-vc10)*xt;
65
66 a = vaInterpH1 + (vaInterpH2-vaInterpH1)*yt;
67 b = vbInterpH1 + (vbInterpH2-vbInterpH1)*yt;
68 c = vcInterpH1 + (vcInterpH2-vcInterpH1)*yt;
69 }
70 else
71 {
72 ossimAtCorrRemapper::interpolate(pt,
73 band,
74 a,
75 b,
76 c);
77 }
78 }
79
initialize()80 void ossimAtCorrGridRemapper::initialize()
81 {
82 ossimAtCorrRemapper::initialize();
83
84 if(theInputConnection)
85 {
86 theGridBounds = theInputConnection->getBoundingRect();
87 theUlGridBound = theGridBounds.ul();
88 }
89 else
90 {
91 theGridBounds.makeNan();
92 }
93
94 if(!theAGrid.size()||
95 !theBGrid.size()||
96 !theCGrid.size())
97 {
98 theUseInterpolationFlag=false;
99 }
100 setBaseToAverage();
101 }
102
setGridSize(ossim_uint32 numberOfBands,const ossimIpt & gridSize)103 void ossimAtCorrGridRemapper::setGridSize(ossim_uint32 numberOfBands, const ossimIpt& gridSize)
104 {
105
106 if((theGridSize!=gridSize)||(numberOfBands != theAGrid.size()))
107 {
108 theAGrid.resize(numberOfBands);
109 theBGrid.resize(numberOfBands);
110 theCGrid.resize(numberOfBands);
111
112 for(ossim_uint32 b = 0; b < numberOfBands;++b)
113 {
114 theAGrid[b].resize(gridSize.y);
115 theBGrid[b].resize(gridSize.y);
116 theCGrid[b].resize(gridSize.y);
117 for(int r = 0; r < gridSize.y; ++r)
118 {
119 theAGrid[b][r].resize(gridSize.x);
120 theBGrid[b][r].resize(gridSize.x);
121 theCGrid[b][r].resize(gridSize.x);
122 }
123
124 }
125 theGridSize = gridSize;
126 }
127
128 }
129
130
setBaseToAverage()131 void ossimAtCorrGridRemapper::setBaseToAverage()
132 {
133 ossim_uint32 idxBand;
134 vector<double> xaAverage(theAGrid.size());
135 vector<double> xcAverage(theBGrid.size());
136 vector<double> xbAverage(theCGrid.size());
137 // double aAverage=0.0, bAverage=0.0, cAverag=0.0;
138
139
140 if((theAGrid.size() != theBGrid.size())||
141 (theAGrid.size() != theCGrid.size())||
142 (theAGrid.size() == 0))
143 {
144 return;
145 }
146
147 for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand)
148 {
149 ossim_uint32 idxRow = 0;
150 xaAverage[idxBand] = 0.0;
151 xbAverage[idxBand] = 0.0;
152 xcAverage[idxBand] = 0.0;
153 for(idxRow = 0; idxRow < theAGrid[idxBand].size();++idxRow)
154 {
155 ossim_uint32 idxCol = 0;
156 for(idxCol = 0; idxCol < theAGrid[idxBand][idxRow].size();++idxCol)
157 {
158 xaAverage[idxBand] += theAGrid[idxBand][idxRow][idxCol];
159
160 }
161 }
162 for(idxRow = 0; idxRow < theBGrid[idxBand].size();++idxRow)
163 {
164 ossim_uint32 idxCol = 0;
165 for(idxCol = 0; idxCol < theBGrid[idxBand][idxRow].size();++idxCol)
166 {
167 xbAverage[idxBand] += theBGrid[idxBand][idxRow][idxCol];
168 }
169 }
170 for(idxRow = 0; idxRow < theCGrid[idxBand].size();++idxRow)
171 {
172 ossim_uint32 idxCol = 0;
173 for(idxCol = 0; idxCol < theCGrid[idxBand][idxRow].size();++idxCol)
174 {
175 xaAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
176 xbAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
177 xcAverage[idxBand] += theCGrid[idxBand][idxRow][idxCol];
178
179 }
180 }
181 }
182
183 for(idxBand = 0; idxBand < theAGrid.size(); ++idxBand)
184 {
185 xaAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
186 xbAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
187 xcAverage[idxBand] /=(double)(theGridSize.x*theGridSize.y);
188 }
189
190 theXaArray = xaAverage;
191 theXbArray = xbAverage;
192 theXcArray = xcAverage;
193 }
194
195 /*!
196 * Method to the load (recreate) the state of an object from a keyword
197 * list. Return true if ok or false on error.
198 */
loadState(const ossimKeywordlist & kwl,const char * prefix)199 bool ossimAtCorrGridRemapper::loadState(const ossimKeywordlist& kwl,
200 const char* prefix)
201 {
202 const char* MODULE = "ossimAtCorrGridRemapper::loadState";
203 theAGrid.clear();
204 theBGrid.clear();
205 theCGrid.clear();
206
207 if (!theTile || !theSurfaceReflectance)
208 {
209 cerr << MODULE << " ERROR:"
210 << "Not initialized..." << endl;
211 return false;
212 }
213 theUseInterpolationFlag=true;
214 ossim_uint32 bands = theTile->getNumberOfBands();
215
216 theAGrid.resize(bands);
217 theBGrid.resize(bands);
218 theCGrid.resize(bands);
219
220
221 const char* rowsLookup = NULL;
222 const char* colsLookup = NULL;
223 for(ossim_uint32 band = 0; band < bands; ++band)
224 {
225 ossim_uint32 r = 0;
226 ossim_uint32 c = 0;
227 ossimString gridString = "band";
228 gridString += ossimString::toString(band+1);
229 gridString += ".grid";
230
231 rowsLookup = kwl.find(prefix,
232 gridString + ".rows");
233
234 colsLookup = kwl.find(prefix,
235 gridString + ".cols");
236 if(rowsLookup&&colsLookup)
237 {
238 cout << "both keywords needed: " << (gridString+".rows") << endl
239 << (gridString+".cols") << endl;
240
241 theUseInterpolationFlag=false;
242 return false;
243 }
244
245 ossim_uint32 rows = ossimString(rowsLookup).toULong();
246 ossim_uint32 cols = ossimString(colsLookup).toULong();
247
248 if(cols&&rows)
249 {
250 cout << "value for cols and rows keyword have 0" << endl;
251 theUseInterpolationFlag=false;
252 return false;
253 }
254
255 theAGrid[band].resize(rows);
256 theBGrid[band].resize(rows);
257 theCGrid[band].resize(rows);
258 for(r = 0; r < rows; ++r)
259 {
260 theAGrid[band][r].resize(cols);
261 theBGrid[band][r].resize(cols);
262 theCGrid[band][r].resize(cols);
263 }
264
265 ossim_uint32 idx = 1;
266 const char* aLookup;
267 const char* bLookup;
268 const char* cLookup;
269 for(r = 0; r < rows; ++r)
270 {
271 for(c = 0; c < cols; ++c)
272 {
273 aLookup = kwl.find(prefix, gridString+".a"+ossimString::toString(idx));
274 bLookup = kwl.find(prefix, gridString+".b"+ossimString::toString(idx));
275 cLookup = kwl.find(prefix, gridString+".c"+ossimString::toString(idx));
276 theAGrid[band][r][c] = ossimString(aLookup).toDouble();
277 theBGrid[band][r][c] = ossimString(bLookup).toDouble();
278 theCGrid[band][r][c] = ossimString(cLookup).toDouble();
279
280 ++idx;
281 }
282 }
283
284 theGridSize.x = cols;
285 theGridSize.y = rows;
286 setBaseToAverage();
287 }
288
289 return true;
290 }
291
saveState(ossimKeywordlist & kwl,const char * prefix) const292 bool ossimAtCorrGridRemapper::saveState(ossimKeywordlist& kwl,
293 const char* prefix)const
294 {
295
296 ossim_uint32 bands = (ossim_uint32)theAGrid.size();
297
298 for(ossim_uint32 band = 0; band < bands; ++band)
299 {
300 int idx = 1;
301 int r = 0;
302 int c = 0;
303 ossimString gridString = "band";
304 gridString += ossimString::toString(band+1);
305 gridString += ".grid";
306
307 ossim_uint32 rows = (ossim_uint32)theAGrid[band].size();
308 kwl.add(prefix,
309 gridString+".rows",
310 rows,
311 true);
312 ossim_uint32 cols = (ossim_uint32)theAGrid[band][0].size();
313 kwl.add(prefix,
314 gridString+".cols",
315 cols,
316 true);
317 for(r = 0; r < theGridSize.y; ++r)
318 {
319 for(c = 0; c < theGridSize.x; ++c)
320 {
321 kwl.add(prefix,
322 gridString+".a"+ossimString::toString(idx),
323 theAGrid[band][r][c],
324 true);
325 kwl.add(prefix,
326 gridString+".b"+ossimString::toString(idx),
327 theAGrid[band][r][c],
328 true);
329 kwl.add(prefix,
330 gridString+".c"+ossimString::toString(idx),
331 theAGrid[band][r][c],
332 true);
333
334 ++idx;
335 }
336 }
337 }
338
339 return ossimAtCorrRemapper::saveState(kwl, prefix);
340 }
341