OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimImageCacheBase.cpp
Go to the documentation of this file.
1 //*******************************************************************
2 //
3 // License: LGPL
4 //
5 // See LICENSE.txt file in the top level directory for more details.
6 //
7 // Author: Mingjie Su
8 //
9 //********************************************************************
10 // $Id: ossimImageCacheBase.cpp 2685 2011-06-07 16:24:41Z david.burken $
11 #include <algorithm>
12 using namespace std;
13 
15 
21 #include <ossim/base/ossimCommon.h>
27 #include <ossim/base/ossimDatum.h>
28 #include <ossim/base/ossimNotify.h>
36 #include <ossim/base/ossimEndian.h>
37 #include <ossim/base/ossimTrace.h>
39 
40 static ossimTrace traceDebug = ossimTrace("ossimImageCacheBase:debug");
41 
42 #ifdef OSSIM_ID_ENABLED
43 static const char OSSIM_ID[] = "$Id: ossimImageCacheBase.cpp 2685 2011-06-07 16:24:41Z david.burken $";
44 #endif
45 
46 RTTI_DEF1(ossimImageCacheBase, "ossimImageCacheBase", ossimImageHandler)
47 
49  :
51  m_actualImageRect(),
52  m_numberOfLines(0),
53  m_numberOfSamples(0),
54  m_numberOfBands(0),
55  m_fileNames(),
56  m_tileSize(128, 128),
57  m_workFrame(new ossimRpfFrame),
58  m_bBox_LL_Lon(0.0),
59  m_bBox_LL_Lat(0.0),
60  m_bBox_UR_Lon(0.0),
61  m_bBox_UR_Lat(0.0),
62  m_numOfFramesVertical(0),
63  m_numOfFramesHorizontal(0),
64  m_frame_width(0),
65  m_frame_height(0),
66  m_frameEntryArray()
67 {
68  if (traceDebug())
69  {
71  << "ossimImageCacheBase::ossimImageCacheBase entered...\n";
72 #ifdef OSSIM_ID_ENABLED
74  << "OSSIM_ID: " << OSSIM_ID << "\n";
75 #endif
76  }
77 
78  m_actualImageRect.makeNan();
79 
80 }
81 
83 {
84  if(m_workFrame)
85  {
86  delete m_workFrame;
87  m_workFrame = 0;
88  }
89  close();
90 }
91 
93 {
94  deleteAll();
95 }
96 
98 {
99  //return (theTableOfContents!=0);
100  ossimString ext = theImageFile.ext().downcase();
101 
102  if(ext == "rpf")
103  {
104  return true;
105  }
106  else
107  {
108  return false;
109  }
110 }
111 
113  ossim_uint32 frameWidth,
114  ossim_uint32 frameHeight)
115 {
116  static const char MODULE[] = "ossimImageCacheBase::buildFrameEntryArray";
117  if ( traceDebug() )
118  {
119  ossimNotify(ossimNotifyLevel_DEBUG) << MODULE << " entered..." << endl;
120  }
121 
122  // use to check if tiles have overlap pixels
123  ossim_float64 avgLat = 0.0;
124  ossim_float64 avgLon = 0.0;
125 
126  m_frame_width = frameWidth;
127  m_frame_height = frameHeight;
128 
129  std::ifstream in((imageFile).c_str() );
130 
131  std::string line;
132  ossim_uint32 index = 0; // used throughout
133  while( in.good() )
134  {
135  // Read in a line.
136  std::getline(in, line);
137 
138  ossimString tmpStr = ossimString(line);
139  if (!tmpStr.empty())
140  {
141  if (index == 0)
142  {
143  std::vector<ossimString> box_lat_lon;
144  tmpStr.split(box_lat_lon, "|");
145 
146  if (box_lat_lon.size() > 2)
147  {
148  std::vector<ossimString> ll;
149  std::vector<ossimString> ur;
150 
151  box_lat_lon[0].split(ll, ",");
152  box_lat_lon[1].split(ur, ",");
153  ossimString bandStr = box_lat_lon[2];
154 
155  m_bBox_LL_Lon = ll[0].toFloat64();
156  m_bBox_LL_Lat = ll[1].toFloat64();
157  m_bBox_UR_Lon = ur[0].toFloat64();
158  m_bBox_UR_Lat = ur[1].toFloat64();
159 
160  checkLongitude(m_bBox_LL_Lon, m_bBox_UR_Lon);
161 
162  m_numberOfBands = ossimString(bandStr).toInt32();
163  }
164  else
165  {
166  return false;
167  }
168  }
169  else if (index == 1)
170  {
171  m_fileNames.push_back(tmpStr);
172  std::vector<ossimString> frame_lat_lon = tmpStr.split("|");
173  if (frame_lat_lon.size() > 2)
174  {
175  ossimString ll_lon_lat = frame_lat_lon[1];
176  ossimString ur_lon_lat = frame_lat_lon[2];
177  ossim_float64 ll_lon = ossimString(ll_lon_lat.split(",")[0]).toDouble();
178  ossim_float64 ll_lat = ossimString(ll_lon_lat.split(",")[1]).toDouble();
179  ossim_float64 ur_lon = ossimString(ur_lon_lat.split(",")[0]).toDouble();
180  ossim_float64 ur_lat = ossimString(ur_lon_lat.split(",")[1]).toDouble();
181 
182  checkLongitude(ll_lon, ur_lon);
183 
184  ossim_float64 bBox_lat_diff = std::fabs(m_bBox_UR_Lat - m_bBox_LL_Lat);
185  ossim_float64 bBox_lon_diff = std::fabs(m_bBox_UR_Lon - m_bBox_LL_Lon);
186 
187  ossim_float64 lat_diff = std::fabs(ur_lat - ll_lat);
188  ossim_float64 lon_diff = std::fabs(ur_lon - ll_lon);
189 
190  m_numOfFramesVertical = static_cast<ossim_uint32>(bBox_lat_diff/lat_diff + 0.5);
191  m_numOfFramesHorizontal = static_cast<ossim_uint32>(bBox_lon_diff/lon_diff + 0.5);
192 
193  avgLon = std::fabs(bBox_lon_diff/m_numOfFramesHorizontal);
194  avgLat = std::fabs(bBox_lat_diff/m_numOfFramesVertical);
195 
196  m_numberOfLines = m_numOfFramesVertical*m_frame_height;
197  m_numberOfSamples = m_numOfFramesHorizontal*m_frame_width;
198 
199  if ( traceDebug() )
200  {
202  << "\nscene height in degrees: " << bBox_lat_diff
203  << "\nscene width in degrees: " << bBox_lon_diff
204  << "\nframe height in degrees: " << lat_diff
205  << "\nframe width in degrees: " << lon_diff
206  << "\nframes vertical: " << m_numOfFramesVertical
207  << "\nframes horizontal: " << m_numOfFramesHorizontal
208  << "\nlines: " << m_numberOfLines
209  << "\nsamples: " << m_numberOfSamples << "\n";
210  }
211  }
212  else
213  {
214  return false;
215  }
216  }
217  else
218  {
219  m_fileNames.push_back(tmpStr);
220  }
221 
222  } // matches: if (!tmpStr.empty())
223 
224  ++index;
225 
226  } // matches: while( in.good() )
227  in.close();
228 
229  m_frameEntryArray.resize(m_numOfFramesVertical);
230  for(index = 0; index < m_frameEntryArray.size(); ++index)
231  {
232  m_frameEntryArray[index].resize(m_numOfFramesHorizontal);
233  }
234 
235  for(index = 0; index < m_fileNames.size(); ++index)
236  {
237  ossimString tmpStr = m_fileNames[index];
238  std::vector<ossimString> frameInfos = tmpStr.split("|");
239  if (frameInfos.size() > 1)
240  {
241  ossimString fileName = frameInfos[0];
242  ossimString ll_lon_lat = frameInfos[1];
243  ossimString ur_lon_lat = frameInfos[2];
244  double ll_lon = ossimString(ll_lon_lat.split(",")[0]).toDouble();
245  double ll_lat = ossimString(ll_lon_lat.split(",")[1]).toDouble();
246  double ur_lon = ossimString(ur_lon_lat.split(",")[0]).toDouble();
247  double ur_lat = ossimString(ur_lon_lat.split(",")[1]).toDouble();
248 
249  checkLongitude(ll_lon, ur_lon);
250 
251  ossim_float64 tmpColPostion = std::fabs(ll_lon - m_bBox_LL_Lon);
252  ossim_float64 tmpFrameLon = std::fabs(ur_lon - ll_lon);
253 
254  if (std::fabs(tmpFrameLon - avgLon) > 0.002)
255  {
256  ossimNotify(ossimNotifyLevel_WARN) << fileName << " has overlap pixels with other image." << std::endl;
257  return false;
258  }
259 
260  ossim_float64 tmpRowPostion = std::fabs(m_bBox_UR_Lat - ur_lat);
261  ossim_float64 tmpFrameLat = std::fabs(ur_lat - ll_lat);
262 
263  if (std::fabs(tmpFrameLat - avgLat) > 0.002)
264  {
265  ossimNotify(ossimNotifyLevel_WARN) << fileName << " has overlap pixels with other image." << std::endl;
266  return false;
267  }
268 
269  ossim_uint32 colNum = static_cast<ossim_uint32>(tmpColPostion/tmpFrameLon + 0.5);
270  ossim_uint32 rowNum = static_cast<ossim_uint32>(tmpRowPostion/tmpFrameLat + 0.5);
271 
272  if (colNum >= m_numOfFramesHorizontal)
273  {
274  colNum = m_numOfFramesHorizontal-1; // Clamp to last column.
275  }
276 
277  if (rowNum >= m_numOfFramesVertical)
278  {
279  rowNum = m_numOfFramesVertical-1; // Clamp to last row.
280  }
281 
282  ossimRpfFrameEntry tempEntry;
283  tempEntry.setEntry(ossimFilename(""), fileName);
284  m_frameEntryArray[rowNum][colNum] = tempEntry;
285  }
286  else
287  {
288  return false;
289  }
290  }
291 
292  return true;
293 }
294 
296  const ossim_float64& rightLon) const
297 {
298  //---
299  // Test for scene coordinates being 180 to 180 and adjust leftLon to -180
300  // if so.
301  //
302  // NOTE:
303  // Setting tolerance to 1/7200 about 15 meters.
304  // Not sure if this is too loose or not. (drb)
305  //---
306  const ossim_float64 TOLERANCE = 0.000138889; // 1/7200 about 15 meters.
307 
308  if ( ossim::almostEqual(leftLon, 180.0, TOLERANCE) )
309  {
310  if ( ossim::almostEqual(rightLon, 180.0, TOLERANCE) )
311  {
312  leftLon = -180.0;
313  }
314  }
315 }
316 
318 {
319  return m_numberOfBands;
320 }
321 
323 {
324  return m_numberOfBands;
325 }
326 
328 {
329  if (reduced_res_level == 0)
330  {
331  return m_numberOfLines;
332  }
333  else if (theOverview.valid())
334  {
335  return theOverview->getNumberOfLines(reduced_res_level);
336  }
337 
338  return 0;
339 }
340 
342 {
343  if (reduced_res_level == 0)
344  {
345  return m_numberOfSamples;
346  }
347  else if (theOverview.valid())
348  {
349  return theOverview->getNumberOfSamples(reduced_res_level);
350  }
351 
352  return 0;
353 }
354 
356 {
357  m_actualImageRect = ossimIrect(0,0,m_numberOfLines, m_numberOfSamples);
358 }
359 
361 {
362  return ossimIrect(0, // upper left x
363  0, // upper left y
364  getNumberOfSamples(reduced_res_level) - 1, // lower right x
365  getNumberOfLines(reduced_res_level) - 1); // lower right y
366 }
367 
368 
369 
371 {
372  return m_tileSize.x;
373 }
374 
376 {
377  return m_tileSize.y;
378 }
379 
380 void ossimImageCacheBase::getEntryList(std::vector<ossim_uint32>& entryList)const
381 {
382  entryList.push_back(0);
383 }
384 
386 {
387  if (reduced_res_level == 0)
388  {
389  return true;
390  }
391  else if (theOverview.valid())
392  {
393  return theOverview->isValidRLevel(reduced_res_level);
394  }
395  else
396  {
397  return false;
398  }
399 }
400 
401 vector<ossimImageCacheBase::ossimFrameEntryData> ossimImageCacheBase::getIntersectingEntries(const ossimIrect& rect)
402 {
403  vector<ossimFrameEntryData> result;
404 
405  // make sure we have the Toc entry to render
406  if(!isOpen()) return result;
407 
408  ossimIrect imageRect = getImageRectangle();
409  if(rect.intersects(imageRect))
410  {
411  ossimIrect clipRect = rect.clipToRect(imageRect);
412  ossimIrect frameRect(clipRect.ul().x/m_frame_width,
413  clipRect.ul().y/m_frame_height,
414  clipRect.lr().x/m_frame_width,
415  clipRect.lr().y/m_frame_height);
416 
417  for(ossim_int32 row = frameRect.ul().y; row <= frameRect.lr().y; ++row)
418  {
419  for(ossim_int32 col = frameRect.ul().x; col <= frameRect.lr().x; ++col)
420  {
421  ossimRpfFrameEntry tempEntry = m_frameEntryArray[row][col];
422  if(tempEntry.exists())
423  {
424  result.push_back(ossimFrameEntryData(row,
425  col,
426  row*m_frame_height,
427  col*m_frame_width,
428  tempEntry));
429  }
430  }
431  }
432  }
433 
434  return result;
435 }
436 
438 {
439  theOverview = 0;
440 }
441 
443  const char* prefix)const
444 {
445  bool result = ossimImageHandler::saveState(kwl, prefix);
446 
447  return result;
448 }
449 
451  const char* prefix)
452 {
453  const char* MODULE = "ossimImageCacheBase::loadState";
454 
455  if(traceDebug())
456  {
457  CLOG << "Entering..." << endl;
458  }
459  bool result = ossimImageHandler::loadState(kwl, prefix);
460 
461  if(!result)
462  {
463  if(traceDebug())
464  {
465  CLOG << "Leaving..." << endl;
466  }
467  return false;
468  }
469  const char* lookup = 0;
470  lookup = kwl.find(ossimString(prefix), "entry");
471  ossim_int32 entry = ossimString(lookup).toInt32();
472 
473  // if an entry is specified then
474  // call the open with an entry number
475  if(lookup)
476  {
477  if(traceDebug())
478  {
479  CLOG << "Leaving..." << endl;
480  }
481  result = ossimImageHandler::open(theImageFile);
482  setCurrentEntry(entry);
483  return result;
484  }
485 
486  result = ossimImageHandler::open(theImageFile);
487 
488  return result;
489 }
490 
492 {
493  return 256;
494 }
495 
497 {
498  return 256;
499 }
500 
502 {
503  theDecimationFactors.clear();
504 
505  // Just needed to set the first R level here, the base class can do the rest:
507 }
508 
510 {
511  if (theGeometry.valid()) return theGeometry;
512 
513  // datum
514  // WGS 84
515  ossimKeywordlist kwl;
516  const char* prefix = 0; // legacy
517  kwl.add(prefix,
519  "WGE",
520  true);
521 
522  ossimGpt ul(m_bBox_UR_Lat,m_bBox_LL_Lon);
523  ossimGpt ll(m_bBox_LL_Lat,m_bBox_LL_Lon);
524  ossimGpt ur(m_bBox_UR_Lat,m_bBox_UR_Lon);
525  ossimGpt lr(m_bBox_LL_Lat,m_bBox_UR_Lon);
526 
527  double latInterval = fabs(ul.latd() - lr.latd())/ getNumberOfLines();
528  double lonInterval = fabs(ul.lond() - ur.lond())/ getNumberOfSamples();
529 
530  kwl.add(prefix,
532  ul.latd(),//-(latInterval/2.0),
533  true);
534 
535  kwl.add(prefix,
537  ul.lond(),//+(lonInterval/2.0),
538  true);
539 
540  kwl.add(prefix,
542  ll.latd(),//+(latInterval/2.0),
543  true);
544 
545  kwl.add(prefix,
547  ll.lond(),//+(lonInterval/2.0),
548  true);
549 
550  kwl.add(prefix,
552  lr.latd(),//+(latInterval/2.0),
553  true);
554 
555  kwl.add(prefix,
557  lr.lond(),//-(lonInterval/2.0),
558  true);
559 
560  kwl.add(prefix,
562  ur.latd(),//-(latInterval/2.0),
563  true);
564 
565  kwl.add(prefix,
567  ur.lond(),//-(latInterval/2.0),
568  true);
569 
570  kwl.add(prefix,
572  getNumberOfInputBands(),
573  true);
574 
575  kwl.add(prefix,
577  getNumberOfOutputBands(),
578  true);
579 
580  kwl.add(prefix,
582  getNumberOfLines(),
583  true);
584 
585  kwl.add(prefix,
587  getNumberOfSamples(),
588  true);
589 
590 
591  //---
592  // Make a projection to get the easting / northing of the tie point and
593  // the scale in meters. This will only be used by the CIB.
594  //---
595  kwl.add(prefix,
597  "WGE",
598  true);
599 
600  ossimGpt origin((ul.latd()+lr.latd())*.5,
601  (ul.lond()+lr.lond())*.5,
602  0.0);
603 
604  double deltaLatPerPixel = latInterval;
605  double deltaLonPerPixel = lonInterval;
606 
607  ossimDpt tie;
608 
609  tie.lat = ul.latd() - deltaLatPerPixel/2.0;
610  tie.lon = ul.lond() + deltaLonPerPixel/2.0;
611 
612  kwl.add(prefix,
614  tie.toString(),
615  true);
616 
617  kwl.add(prefix,
619  deltaLatPerPixel,
620  true);
621 
622  kwl.add(prefix,
624  deltaLonPerPixel,
625  true);
626 
627  kwl.add(prefix,
629  origin.latd(),
630  true);
631 
632  kwl.add(prefix,
634  origin.lond(),
635  true);
636 
637  kwl.add(prefix,
639  ul.latd()-(deltaLatPerPixel/2.0),
640  true);
641 
642  kwl.add(prefix,
644  ul.lond()+(deltaLonPerPixel/2.0),
645  true);
646 
647  kwl.add(prefix,
649  "ossimEquDistCylProjection",
650  true);
651 
652  // Capture this for next time.
653  theGeometry = new ossimImageGeometry;
654  theGeometry->loadState(kwl, prefix);
655 
656  // Set image things the geometry object should know about.
657  initImageParameters( theGeometry.get() );
658 
659  return theGeometry;
660 }
661 
virtual bool open()=0
Pure virtual open.
virtual ossim_uint32 getNumberOfInputBands() const
This method allows you to query the number of input bands.
static const char * DECIMAL_DEGREES_PER_PIXEL_LAT
static const char * DATUM_KW
#define CLOG
Definition: ossimTrace.h:23
double lond() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:97
static const char * CENTRAL_MERIDIAN_KW
Represents serializable keyword/value map.
static const char * UL_LAT_KW
std::basic_ifstream< char > ifstream
Class for char input file streams.
Definition: ossimIosFwd.h:44
bool isValidRLevel(ossim_uint32 reduced_res_level) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Attempts to initialize a transform and a projection given the KWL.
const char * find(const char *key) const
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
bool almostEqual(T x, T y, T tolerance=FLT_EPSILON)
Definition: ossimCommon.h:53
virtual ossim_uint32 getImageTileWidth() const
Returns the tile width of the image or 0 if the image is not tiled.
Protected structure that is only used internally by this class.
static const char * NUMBER_LINES_KW
static const char * TIE_POINT_LON_KW
static const char * NUMBER_INPUT_BANDS_KW
const ossimIpt & ul() const
Definition: ossimIrect.h:274
static const char * LR_LON_KW
void split(std::vector< ossimString > &result, const ossimString &separatorList, bool skipBlankFields=false) const
Splits this string into a vector of strings (fields) using the delimiter list specified.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to load the state of an object from a keyword list.
std::istream & getline(std::istream &is, ossimString &str, char delim)
Definition: ossimString.h:916
virtual ossim_uint32 getNumberOfOutputBands() const
This method allows one to query the number of output bands.
bool intersects(const ossimIrect &rect) const
Definition: ossimIrect.cpp:183
double latd() const
Will convert the radian measure to degrees.
Definition: ossimGpt.h:87
static const char * TYPE_KW
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level=0) const
Satisfies pure virtual requirement from ImageHandler class.
virtual ossim_uint32 getTileHeight() const
Returns the height of the output tile.
vector< ossimFrameEntryData > getIntersectingEntries(const ossimIrect &rect)
It is important to note that each frame is organized into an easting northing type orientation...
ossim_int32 toInt32() const
double ossim_float64
void add(const char *prefix, const ossimKeywordlist &kwl, bool overwrite=true)
static const char * LR_LAT_KW
double lat
Definition: ossimDpt.h:165
virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level=0) const
static const char * TIE_POINT_XY_KW
void setActualImageRect()
Will shift the rect and clamp it so not to go outside the -180 to 180 degree range.
static const char * LL_LON_KW
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Populates the geometry object with image geometry information.
unsigned int ossim_uint32
static const char * NUMBER_OUTPUT_BANDS_KW
void setEntry(const ossimFilename &rootDirectory, const ossimFilename &pathToFrameFileFromRoot)
ossim_float64 toFloat64() const
void checkLongitude(ossim_float64 &leftLon, const ossim_float64 &rightLon) const
Method to test for 180.0 <–> 180.00 and set leftLon to -180 if both left and right are 180...
static const char * DECIMAL_DEGREES_PER_PIXEL_LON
static const char * LL_LAT_KW
const ossimIpt & lr() const
Definition: ossimIrect.h:276
static ossimString downcase(const ossimString &aString)
Definition: ossimString.cpp:48
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
bool isOpen() const
Determines if its open if there eists a table of contents object.
double lon
Definition: ossimDpt.h:164
virtual ossim_uint32 getImageTileHeight() const
Returns the tile width of the image or 0 if the image is not tiled.
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
Container class that holds both 2D transform and 3D projection information for an image Only one inst...
virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level=0) const
Satisfies pure virtual requirement from ImageHandler class.
static const char * ORIGIN_LATITUDE_KW
virtual void close()
Closes this image handler and deletes any allocated data.
ossimString toString(ossim_uint32 precision=15) const
Definition: ossimDpt.cpp:160
This class defines an abstract Handler which all image handlers(loaders) should derive from...
bool buildFrameEntryArray(ossimFilename imageFile, ossim_uint32 frameWidth, ossim_uint32 frameHeight)
ossim_int32 y
Definition: ossimIpt.h:142
static const char * UL_LON_KW
virtual ~ossimImageCacheBase()
Destructor.
static const char * UR_LAT_KW
static const char * UR_LON_KW
bool empty() const
Definition: ossimString.h:411
virtual void establishDecimationFactors()
Virtual method determines the decimation factors at each resolution level.
ossim_int32 x
Definition: ossimIpt.h:141
static const char * TIE_POINT_LAT_KW
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual void getEntryList(std::vector< ossim_uint32 > &entryList) const
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
static const char * NUMBER_SAMPLES_KW
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
int ossim_int32
virtual ossim_uint32 getTileWidth() const
Returns the width of the output tile.