OSSIM - Open Source Software Image Map  Version 1.9.0 (20180803)
ossimHdf5ImageHandler.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: David Burken
8 //
9 // Description: OSSIM HDF5 Reader.
10 //
11 //----------------------------------------------------------------------------
12 // $Id: ossimHdf5ImageHandler.cpp 19878 2011-07-28 16:27:26Z dburken $
13 
14 //#include "ossimH5GridModel.h"
15 
18 #include <ossim/base/ossimTrace.h>
19 #include <ossim/base/ossimIpt.h>
20 #include <ossim/base/ossimDpt.h>
21 #include <ossim/base/ossimEndian.h>
22 #include <ossim/base/ossimGpt.h>
23 #include <ossim/base/ossimIrect.h>
26 #include <ossim/base/ossimNotify.h>
29 #include <ossim/base/ossimString.h>
31 #include <ossim/base/ossimTrace.h>
41 static const ossimTrace traceDebug("ossimHdf5ImageHandler:debug");
42 
43 RTTI_DEF1(ossimHdf5ImageHandler, "ossimHdf5ImageHandler", ossimImageHandler)
44 
45 using namespace std;
46 using namespace H5;
47 
48 static const string LAYER_KW = "layer";
49 
52  m_entries(),
53  m_currentEntry(0),
54  m_tile(0),
55  m_mutex()
56 {
57 }
58 
60 {
61  if (isOpen())
62  {
63  close();
64  }
65 }
66 
68 {
69  m_mutex.lock();
71  m_tile->initialize();
72  m_mutex.unlock();
73 }
74 
76  ossim_uint32 resLevel)
77 {
78  if ( m_tile.valid() == false ) // First time through.
79  {
80  allocate();
81  }
82 
83  if (m_tile.valid())
84  {
85  // Image rectangle must be set prior to calling getTile.
86  m_mutex.lock();
88  m_mutex.unlock();
89 
90  if ( getTile( m_tile.get(), resLevel ) == false )
91  {
92  m_mutex.lock();
94  {
95  m_tile->makeBlank();
96  }
97  m_mutex.unlock();
98  }
99  }
100 
101  return m_tile;
102 }
103 
105 {
106  bool status = false;
107 
108  m_mutex.lock();
109 
110  //---
111  // Not open, this tile source bypassed, or invalid res level,
112  // return a blank tile.
113  //---
114  if( isOpen() && isSourceEnabled() && isValidRLevel(resLevel) &&
115  result && (result->getNumberOfBands() == getNumberOfOutputBands()) )
116  {
117  result->ref(); // Increment ref count.
118 
119  //---
120  // Check for overview tile. Some overviews can contain r0 so always
121  // call even if resLevel is 0. Method returns true on success, false
122  // on error.
123  //---
124  status = getOverviewTile(resLevel, result);
125 
126  if (!status) // Did not get an overview tile.
127  {
128  status = true;
129 
130  ossimIrect tile_rect = result->getImageRectangle();
131 
132  if ( ! tile_rect.completely_within(getImageRectangle(0)) )
133  {
134  // We won't fill totally so make blank first.
135  result->makeBlank();
136  }
137 
138  if (getImageRectangle(0).intersects(tile_rect))
139  {
140  // Make a clip rect.
141  ossimIrect clipRect = tile_rect.clipToRect(getImageRectangle(0));
142 
143  if (tile_rect.completely_within( clipRect) == false)
144  {
145  // Not filling whole tile so blank it out first.
146  result->makeBlank();
147  }
148 
149  // Create buffer to hold the clip rect for a single band.
150  ossim_uint32 clipRectSizeInBytes = clipRect.area() *
152  vector<char> dataBuffer(clipRectSizeInBytes);
153 
154  // Get the data.
155  for (ossim_uint32 band = 0; band < getNumberOfInputBands(); ++band)
156  {
157  // Hdf5 file to buffer:
158  m_entries[m_currentEntry]->getTileBuf(&dataBuffer.front(), clipRect, band);
159 #if 0
160  // Scan and fix non-standard null value:
162  {
163  const ossim_float32 NP = getNullPixelValue(band);
164  const ossim_uint32 COUNT = clipRect.area();
165  ossim_float32* float_buffer = (ossim_float32*)&dataBuffer.front();
166  for ( ossim_uint32 i = 0; i < COUNT; ++i )
167  {
168  if ( float_buffer[i] < -999.0 )
169  float_buffer[i] = NP;
170  }
171  }
172 #endif
173  // Buffer to tile:
174  result->loadBand((void*)&dataBuffer.front(), clipRect, band);
175  }
176 
177  // Validate the tile, i.e. full, partial, empty.
178  result->validate();
179  }
180  else // No intersection...
181  {
182  result->makeBlank();
183  }
184  }
185 
186  result->unref(); // Decrement ref count.
187  }
188 
189  m_mutex.unlock();
190 
191  return status;
192 }
193 
196 {
197  return ossimIrect(0,
198  0,
199  getNumberOfSamples(reduced_res_level) - 1,
200  getNumberOfLines(reduced_res_level) - 1);
201 }
202 
204  const char* prefix) const
205 {
206  return ossimImageHandler::saveState(kwl, prefix);
207 }
208 
210  const char* prefix)
211 {
212  if (ossimImageHandler::loadState(kwl, prefix))
213  {
214  return open();
215  }
216 
217  return false;
218 }
219 
221 {
222  m_tile = 0;
224 }
225 
227 {
228  static const char* M = "ossimHdf5ImageHandler::open(filename) -- ";
229  if(traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M <<" Entering..." << std::endl;
230 
231  // Start with a clean slate.
232  if (isOpen())
233  {
234  close();
235  }
236 
237  // Check for empty filename.
238  if (theImageFile.empty())
239  return false;
240 
242  m_hdf5 = new ossimHdf5;
243  if (!m_hdf5->open(theImageFile))
244  {
245  if(traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M <<" Unable to open image Leaving..." << std::endl;
246  m_hdf5 = 0;
247  return false;
248  }
249 
250  if(traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M <<" Opened Image..." << std::endl;
251 
252  vector<H5::DataSet> datasetList;
253  H5::Group root;
254  m_hdf5->getRoot(root);
255  m_hdf5->getNdimDatasets(root, datasetList, true);
256 
257  if ( datasetList.empty() )
258  {
259  return false;
260  m_hdf5->close();
261  m_hdf5 = 0;
262  }
263  // Filter for specified renderable datasets:
264  if (m_renderableNames.size())
265  {
266  std::vector<H5::DataSet>::iterator dataset = datasetList.begin();
267  while (dataset != datasetList.end())
268  {
269  bool found=false;
270  ossimString dsName = dataset->getObjName();
271  std::vector<ossimString>::iterator name = m_renderableNames.begin();
272  while (name != m_renderableNames.end())
273  {
274  if (dsName.contains(*name))
275  {
276  found = true;
277  break;
278  }
279  ++name;
280  }
281  if (!found)
282  datasetList.erase(dataset);
283  else
284  ++dataset;
285  }
286  }
287 #if 0
288  ossimNotify(ossimNotifyLevel_DEBUG)<< "ossimHdf5ImageHandler:"<<__LINE__ << " DEBUG\nDataset names:\n";
289  for ( ossim_uint32 i = 0; i < datasetList.size(); ++i )
290  {
291  ossimNotify(ossimNotifyLevel_DEBUG)<< "dataset[" << i << "]: "
292  << datasetList[i].getObjName() << "\n";
293  }
294 #endif
295  if ( datasetList.empty() )
296  {
297  m_hdf5 = 0;
298  return false;
299  }
300 
301  // Add the image dataset entries.
302  std::vector<H5::DataSet>::iterator dataset = datasetList.begin();
303  while (dataset != datasetList.end())
304  {
306  oimgset->initialize(*dataset);
307  m_entries.push_back(oimgset);
308  ++dataset;
309  }
310 
311  // Initialize the current entry to be 0:
312  m_currentEntry = 999; // Forces init on change of index
313  setCurrentEntry(0);
314 
315  // Establish a common geometry for all entries. TODO: Need to verify if this is a kosher thing
316  // to do. It may be that multiple entries have different geometries associated.
318  if (!theGeometry.valid())
319  return false;
320 
321 #if 0 /* Please leave for debug. (drb) */
322  std::vector<ossimHdf5ImageDataset>::const_iterator i = m_entries.begin();
323  while ( i != m_entries.end() )
324  {
325  std::cout << (*i) << endl;
326  ++i;
327  }
328 #endif
329  if(traceDebug()) ossimNotify(ossimNotifyLevel_DEBUG) << M <<" Leaving..." << std::endl;
330 
331  return true;
332 }
333 
334 
336 {
337  ossim_uint32 r = 0;
338  if (reduced_res_level == 0)
339  {
340  if (m_currentEntry < m_entries.size())
342  }
343  else if ( theOverview.valid() )
344  {
345  r = theOverview->getNumberOfLines(reduced_res_level);
346  }
347 
348  return r;
349 }
350 
352 {
353  ossim_uint32 r = 0;
354  if (reduced_res_level == 0)
355  {
356  if (m_currentEntry < m_entries.size())
358  }
359  else if ( theOverview.valid() )
360  {
361  r = theOverview->getNumberOfSamples(reduced_res_level);
362  }
363 
364  return r;
365 }
366 
368 {
369  return 0; // Not tiled format.
370 }
371 
373 {
374  return 0; // Not tiled format.
375 }
376 
378 {
379  return ossimString("ossim_hdf5_reader");
380 }
381 
383 {
384  return ossimString("ossim hdf5 reader");
385 }
386 
388 {
389  return ossimString("ossimHdf5ImageHandler");
390 }
391 
393 {
394  ossim_uint32 result = 1;
395 
396  if ( m_currentEntry < m_entries.size() )
397  result = m_entries[m_currentEntry]->getNumberOfBands();
398 
399  return result;
400 }
401 
403 {
404  // Currently not band selectable.
405  return getNumberOfInputBands();
406 }
407 
409 {
411 
412  if ( m_currentEntry < m_entries.size() )
413  {
414  result = m_entries[m_currentEntry]->getScalarType();
415  }
416 
417  return result;
418 }
419 
421 {
422  return ( m_hdf5.valid() && m_entries.size() && (m_currentEntry < m_entries.size()));
423 }
424 
426 {
427  // Close the datasets.
428  m_entries.clear();
429 
430  // Then the file.
431  if ( m_hdf5.valid() )
432  m_hdf5 = 0;
433 
434  // ossimRefPtr so assign to 0(unreferencing) will handle memory.
435  m_tile = 0;
436 
438 }
439 
441 {
442  return (ossim_uint32)m_entries.size();
443 }
444 
445 void ossimHdf5ImageHandler::getEntryNames(std::vector<ossimString>& entryNames) const
446 {
447  entryNames.clear();
448  for (ossim_uint32 i=0; i<m_entries.size(); ++i )
449  {
450  entryNames.push_back(m_entries[i]->getName());
451  }
452 }
453 
454 void ossimHdf5ImageHandler::getEntryList(std::vector<ossim_uint32>& entryList) const
455 {
456  const ossim_uint32 SIZE = m_entries.size();
457  entryList.resize( SIZE );
458  for ( ossim_uint32 i = 0; i < SIZE; ++i )
459  {
460  entryList[i] = i;
461  }
462 }
463 
465 {
466  bool result = true;
467  if (m_currentEntry != entryIdx)
468  {
469  // Entries always start at zero and increment sequentially..
470  if ( entryIdx < m_entries.size() )
471  {
473  m_currentEntry = entryIdx;
474  m_tile = 0;
475  ossimIrect validRect = m_entries[entryIdx]->getValidImageRect();
476  theValidImageVertices.clear();
477  theValidImageVertices.push_back(validRect.ul());
478  theValidImageVertices.push_back(validRect.ur());
479  theValidImageVertices.push_back(validRect.lr());
480  theValidImageVertices.push_back(validRect.ll());
481 
482  if ( isOpen() )
483  completeOpen();
484  }
485  else
486  {
487  result = false; // Entry index out of range.
488  }
489  }
490 
491  return result;
492 }
493 
495 {
496  return m_currentEntry;
497 }
498 
500 {
501  if ( m_currentEntry >= m_entries.size() )
502  return 0;
503 
504  return m_entries[m_currentEntry];
505 }
506 
508 {
510 }
511 
513 {
514  if ( m_currentEntry >= m_entries.size() )
515  {
516  if(m_entries[m_currentEntry]->isMaxPixelSet())
517  {
518  return m_entries[m_currentEntry]->getMaxPixelValue(band);
519  }
520  }
522 }
523 
525 {
526  if ( m_currentEntry >= m_entries.size() )
527  {
528  if(m_entries[m_currentEntry]->isMinPixelSet())
529  {
530  return m_entries[m_currentEntry]->getMinPixelValue(band);
531  }
532  }
534 }
535 
537 {
538  if ( !property.valid() )
539  return;
540 
541  if ( property->getName().string() == LAYER_KW )
542  {
543  ossimString s;
544  property->valueToString(s);
545  ossim_uint32 SIZE = (ossim_uint32)m_entries.size();
546  for ( ossim_uint32 i = 0; i < SIZE; ++i )
547  {
548  if ( m_entries[i]->getName() == s.string() )
549  {
550  setCurrentEntry( i );
551  }
552  }
553  }
554  else
555  {
557  }
558 }
559 
561 {
563  if ( name.string() == LAYER_KW )
564  {
565  if ( m_currentEntry < m_entries.size() )
566  {
567  ossimString value = m_entries[m_currentEntry]->getName();
568  prop = new ossimStringProperty(name, value);
569  }
570  }
571  else
572  {
573  prop = ossimImageHandler::getProperty(name);
574  }
575  return prop;
576 }
577 
578 void ossimHdf5ImageHandler::getPropertyNames(std::vector<ossimString>& propertyNames)const
579 {
580  propertyNames.push_back( ossimString("layer") );
582 }
583 
virtual void loadBand(const void *src, const ossimIrect &src_rect, ossim_uint32 band)
void clear()
Erases the entire container.
Definition: ossimString.h:432
bool initialize(const H5::DataSet &dataset)
Opens datasetName and initializes all data members on success.
virtual bool isSourceEnabled() const
Definition: ossimSource.cpp:79
ossimRefPtr< ossimImageGeometry > theGeometry
void allocate()
Allocates the tile.
ossimRefPtr< ossimImageData > m_tile
virtual ossim_uint32 getNumberOfBands() const
std::vector< ossimRefPtr< ossimHdf5ImageDataset > > m_entries
virtual ossim_uint32 getNumberOfEntries() const
ossimFilename theImageFile
virtual void setImageRectangle(const ossimIrect &rect)
bool getRoot(H5::Group &root) const
Assigns the root group.
Definition: ossimHdf5.cpp:93
virtual ossimIrect getImageRectangle(ossim_uint32 reduced_res_level=0) const
Returns the zero based image rectangle for the reduced resolution data set (rrds) passed in...
Represents serializable keyword/value map.
bool valid() const
Definition: ossimRefPtr.h:75
ossimFilename expand() const
Method to do file name expansion.
float ossim_float32
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
virtual ossim_uint32 getNumberOfLines(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
virtual bool open()
The derived class needs to initialize the raster dataset names m_renderableNames in their constructor...
This is the base class for all imagery using HDF5 as the file format.
bool contains(char aChar) const
Definition: ossimString.h:58
ossimScalarType getScalarType(const H5::DataSet *dataset)
const ossimIpt & ul() const
Definition: ossimIrect.h:274
virtual ossimDataObjectStatus getDataObjectStatus() const
ossimRefPtr< ossimHdf5 > m_hdf5
virtual double getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
32 bit floating point
virtual ossimString getShortName() const
virtual void setProperty(ossimRefPtr< ossimProperty > property)
virtual ossim_uint32 getImageTileWidth() const
Returns the tile width of the image or 0 if the image is not tiled.
const ossimIpt & ll() const
Definition: ossimIrect.h:277
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
bool open(const ossimFilename &hdf5File)
Opens specified HDF5 file.
Definition: ossimHdf5.cpp:29
void ref() const
increment the reference count by one, indicating that this object has another pointer which is refere...
virtual void initialize()
Initialize the data buffer.
virtual bool isValidRLevel(ossim_uint32 resLevel) const
Determines if the passed in reslution level is valid.
virtual double getMinPixelValue(ossim_uint32 band=0) const
Retuns the min pixel value.
bool completely_within(const ossimIrect &rect) const
Definition: ossimIrect.cpp:425
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
virtual ~ossimHdf5ImageHandler()
virtual destructor
virtual bool getOverviewTile(ossim_uint32 resLevel, ossimImageData *result)
Method to get an overview tile.
static ossimImageDataFactory * instance()
ossimHdf5ImageHandler()
default constructor
bool close()
Closes the file and deletes all pointers.
Definition: ossimHdf5.cpp:72
virtual ossimDataObjectStatus validate() const
virtual ossimRefPtr< ossimImageGeometry > getImageGeometry()
Returns the image geometry object associated with this tile source or NULL if non defined...
virtual ossimRefPtr< ossimImageData > getTile(const ossimIrect &rect, ossim_uint32 resLevel=0)
Returns a pointer to a tile given an origin representing the upper left corner of the tile to grab fr...
virtual ossimString getClassName() const
virtual ossim_uint32 getNumberOfInputBands() const
Returns the number of bands in the image.
virtual void loadMetaData()
There is an external file with an omd extension.
unsigned int ossim_uint32
virtual ossim_uint32 getCurrentEntry() const
virtual ossimIrect getImageRectangle() const
vector< ossimIpt > theValidImageVertices
OSSIM_DLL ossim_uint32 scalarSizeInBytes(ossimScalarType scalarType)
virtual void getPropertyNames(std::vector< ossimString > &propertyNames) const
Get propterty names.
const ossimIpt & lr() const
Definition: ossimIrect.h:276
virtual void close()
Deletes the overview and clears the valid image vertices.
virtual void close()
Close method.
ossimRefPtr< ossimHdf5ImageDataset > getCurrentDataset()
virtual ossimRefPtr< ossimImageData > create(ossimSource *owner, ossimScalarType scalar, ossim_uint32 bands=1) const
ossimIrect clipToRect(const ossimIrect &rect) const
Definition: ossimIrect.cpp:501
virtual ossim_uint32 getNumberOfLines(ossim_uint32 reduced_res_level=0) const
Returns the number of lines in the image.
virtual bool isOpen() const
Derived classes must implement this method to be concrete.
virtual bool setCurrentEntry(ossim_uint32 entryIdx)
const ossimIpt & ur() const
Definition: ossimIrect.h:275
ossimScalarType
void unref() const
decrement the reference count by one, indicating that a pointer to this object is referencing it...
Low-level OSSIM interface to HDF5 libraries.
Definition: ossimHdf5.h:27
return status
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
virtual void makeBlank()
Initializes data to null pixel values.
virtual void completeOpen()
Will complete the opening process.
ossimRefPtr< ossimImageHandler > theOverview
virtual ossim_uint32 getNumberOfOutputBands() const
Returns the number of bands in a tile returned from this TileSource.
This class defines an abstract Handler which all image handlers(loaders) should derive from...
virtual void loadMetaData()
There is an external file with an omd extension.
virtual void getEntryNames(std::vector< ossimString > &entryNames) const
Get the name of entry as a string.
ossim_uint32 area() const
Definition: ossimIrect.h:396
bool empty() const
Definition: ossimString.h:411
ossimFilename theOverviewFile
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 reduced_res_level=0) const
Returns the number of samples in the image.
virtual ossim_uint32 getNumberOfSamples(ossim_uint32 resLevel=0) const =0
Pure virtual, derived classes must implement.
virtual ossimString getLongName() const
virtual double getMaxPixelValue(ossim_uint32 band=0) const
Returns the max pixel of the band.
virtual bool loadState(const ossimKeywordlist &kwl, const char *prefix=0)
Method to the load (recreate) the state of an object from a keyword list.
#define RTTI_DEF1(cls, name, b1)
Definition: ossimRtti.h:485
virtual double getNullPixelValue(ossim_uint32 band=0) const
static bool getNdimDatasets(H5::Group group, std::vector< H5::DataSet > &datasetList, bool recursive=false)
Assigns list of all multi-dimensional datasets under current active group.
Definition: ossimHdf5.cpp:188
virtual ossimRefPtr< ossimProperty > getProperty(const ossimString &name) const
Get propterty method.
virtual ossimScalarType getOutputScalarType() const
Returns the output pixel type of the tile source.
std::vector< ossimString > m_renderableNames
virtual double getNullPixelValue(ossim_uint32 band=0) const
Each band has a null pixel associated with it.
OSSIMDLLEXPORT std::ostream & ossimNotify(ossimNotifyLevel level=ossimNotifyLevel_WARN)
virtual ossim_uint32 getImageTileHeight() const
Returns the tile width of the image or 0 if the image is not tiled.
virtual bool saveState(ossimKeywordlist &kwl, const char *prefix=0) const
Method to save the state of an object to a keyword list.
virtual void setProperty(ossimRefPtr< ossimProperty > property)
Set propterty method.
const ossimString & getName() const
virtual void getEntryList(std::vector< ossim_uint32 > &entryList) const
const std::string & string() const
Definition: ossimString.h:414