DGtal  0.9.4beta
ImageFactoryFromHDF5.h
1 
17 #pragma once
18 
31 #if defined(ImageFactoryFromHDF5_RECURSES)
32 #error Recursive header files inclusion detected in ImageFactoryFromHDF5.h
33 #else // defined(ImageFactoryFromHDF5_RECURSES)
34 
35 #define ImageFactoryFromHDF5_RECURSES
36 
37 #if !defined ImageFactoryFromHDF5_h
38 
39 #define ImageFactoryFromHDF5_h
40 
42 // Inclusions
43 #include <iostream>
44 #include "DGtal/base/Common.h"
45 #include "DGtal/base/ConceptUtils.h"
46 #include "DGtal/images/CImage.h"
47 #include "DGtal/base/Alias.h"
48 #include "DGtal/kernel/CBoundedNumber.h"
49 
50 #include "hdf5.h"
52 
53 namespace DGtal
54 {
55 
57  // template class H5DSpecializations
65  template <typename TImageFactory, typename T>
67  {
68  // ----------------------- Standard services ------------------------------
69 
70  typedef TImageFactory ImageFactory;
71  typedef typename ImageFactory::OutputImage::Value Value;
72 
73  static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out);
74  static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in);
75 
76  }; // end of class H5DSpecializations
77 
79  // template class H5DSpecializations
84  template <typename TImageFactory>
85  struct H5DSpecializations<TImageFactory, DGtal::uint8_t>
86  {
87  // ----------------------- Standard services ------------------------------
88 
89  typedef TImageFactory ImageFactory;
90  typedef typename ImageFactory::OutputImage::Value Value;
91 
92  static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
93  {
94  return H5Dread(anImageFactory.dataset, H5T_NATIVE_UINT8, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_out);
95  }
96 
97  static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
98  {
99  return H5Dwrite(anImageFactory.dataset, H5T_NATIVE_UINT8, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_in);
100  }
101 
102  }; // end of class H5DSpecializations
103 
105  // template class H5DSpecializations
110  template <typename TImageFactory>
111  struct H5DSpecializations<TImageFactory, DGtal::int32_t>
112  {
113  // ----------------------- Standard services ------------------------------
114 
115  typedef TImageFactory ImageFactory;
116  typedef typename ImageFactory::OutputImage::Value Value;
117 
118  static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
119  {
120  return H5Dread(anImageFactory.dataset, H5T_NATIVE_INT32, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_out);
121  }
122 
123  static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
124  {
125  return H5Dwrite(anImageFactory.dataset, H5T_NATIVE_INT32, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_in);
126  }
127 
128  }; // end of class H5DSpecializations
129 
131  // template class H5DSpecializations
136  template <typename TImageFactory>
137  struct H5DSpecializations<TImageFactory, DGtal::int64_t>
138  {
139  // ----------------------- Standard services ------------------------------
140 
141  typedef TImageFactory ImageFactory;
142  typedef typename ImageFactory::OutputImage::Value Value;
143 
144  static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
145  {
146  return H5Dread(anImageFactory.dataset, H5T_NATIVE_INT64, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_out);
147  }
148 
149  static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
150  {
151  return H5Dwrite(anImageFactory.dataset, H5T_NATIVE_INT64, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_in);
152  }
153 
154  }; // end of class H5DSpecializations
155 
157  // template class H5DSpecializations
162  template <typename TImageFactory>
163  struct H5DSpecializations<TImageFactory, double>
164  {
165  // ----------------------- Standard services ------------------------------
166 
167  typedef TImageFactory ImageFactory;
168  typedef typename ImageFactory::OutputImage::Value Value;
169 
170  static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
171  {
172  return H5Dread(anImageFactory.dataset, H5T_NATIVE_DOUBLE, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_out);
173  }
174 
175  static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
176  {
177  return H5Dwrite(anImageFactory.dataset, H5T_NATIVE_DOUBLE, memspace, anImageFactory.dataspace, H5P_DEFAULT, data_in);
178  }
179 
180  }; // end of class H5DSpecializations
181 
183  // Template class ImageFactoryFromHDF5
195  template <typename TImageContainer>
197  {
198 
199  // ----------------------- Types ------------------------------
200 
201  public:
203 
206 
208  typedef TImageContainer ImageContainer;
209  typedef typename ImageContainer::Domain Domain;
210 
212  typedef ImageContainer OutputImage;
213  typedef typename OutputImage::Value Value;
214 
216 
217  // ----------------------- Standard services ------------------------------
218 
219  public:
220 
226  ImageFactoryFromHDF5(const std::string & aFilename, const std::string & aDataset):
227  myFilename(aFilename), myDataset(aDataset)
228  {
229  const int ddim = Domain::dimension;
230 
231  hsize_t dims_out[ddim]; // dataset dimensions
232 
233  // Open the file and the dataset.
234  file = H5Fopen(myFilename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
235  dataset = H5Dopen2(file, myDataset.c_str(), H5P_DEFAULT);
236 
237  // Get datatype and dataspace handles and then query dataset class, order, size, rank and dimensions.
238  datatype = H5Dget_type(dataset); // datatype handle
239 
240  dataspace = H5Dget_space(dataset); // dataspace handle
241 
242  H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
243 
244  // --
245 
246  typedef SpaceND<ddim> TSpace;
247  typename TSpace::Point low, up;
248 
249  typename Domain::Integer d;
250  for(d=0; d<ddim; d++)
251  {
252  low[d]=0;
253  up[d]=dims_out[ddim-d-1]-1;
254  }
255 
256  myDomain = new Domain(low, up);
257  }
258 
263  {
264  delete myDomain;
265 
266  // --
267 
268  // Close/release resources.
269  H5Tclose(datatype);
270  H5Dclose(dataset);
271  H5Sclose(dataspace);
272  H5Fclose(file);
273  }
274 
275  private:
276 
278 
280 
281  // ----------------------- Interface --------------------------------------
282  public:
283 
285 
291  const Domain & domain() const
292  {
293  return *myDomain;
294  }
295 
297 
298 
300 
305  void selfDisplay ( std::ostream & out ) const;
306 
311  bool isValid() const
312  {
313  return (myDomain->isValid());
314  }
315 
323  OutputImage * requestImage(const Domain &aDomain) // time consuming
324  {
325  DGtal::IOException dgtalio;
326 
327  const int ddim = Domain::dimension;
328 
329  // --
330 
331  hsize_t offset[ddim]; // hyperslab offset in the file
332  hsize_t count[ddim]; // size of the hyperslab in the file
333 
334  herr_t status;
335  hsize_t dimsm[ddim]; // memory space dimensions
336  hid_t memspace;
337 
338  hsize_t offset_out[ddim]; // hyperslab offset in memory
339  hsize_t count_out[ddim]; // size of the hyperslab in memory
340 
341  int N_SUB[ddim];
342  typename Domain::Integer d;
343 
344  int malloc_size=1;
345  for(d=0; d<ddim; d++)
346  {
347  N_SUB[d] = (aDomain.upperBound()[ddim-d-1]-aDomain.lowerBound()[ddim-d-1])+1;
348  malloc_size = malloc_size*N_SUB[d];
349  }
350 
351  Value *data_out = (Value*) malloc (malloc_size * sizeof(Value)); // output buffer
352  if (data_out == NULL)
353  {
354  trace.error() << "data_out malloc error in requestImage: " << (malloc_size * sizeof(Value)) << std::endl;
355  throw dgtalio;
356  }
357 
358  // Define hyperslab in the dataset.
359  for(d=0; d<ddim; d++)
360  offset[d] = aDomain.lowerBound()[ddim-d-1]-myDomain->lowerBound()[ddim-d-1];
361  for(d=0; d<ddim; d++)
362  count[d] = N_SUB[d];
363  status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
364  if (status)
365  {
366  trace.error() << " H5Sselect_hyperslab from dataspace error" << std::endl;
367  throw dgtalio;
368  }
369 
370  // Define the memory dataspace.
371  for(d=0; d<ddim; d++)
372  dimsm[d] = N_SUB[d];
373  memspace = H5Screate_simple(ddim,dimsm,NULL);
374 
375  // Define memory hyperslab.
376  for(d=0; d<ddim; d++)
377  offset_out[d] = 0;
378  for(d=0; d<ddim; d++)
379  count_out[d] = N_SUB[d];
380  status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, count_out, NULL);
381  if (status)
382  {
383  trace.error() << " H5Sselect_hyperslab from memspace error" << std::endl;
384  throw dgtalio;
385  }
386 
387  // Read data from hyperslab in the file into the hyperslab in memory.
388  //status = H5Dread(dataset, H5T_NATIVE_INT, memspace, dataspace, H5P_DEFAULT, data_out);
389  status = H5DSpecializations<Self, Value>::H5DreadS(*this, memspace, data_out);
390  if (status)
391  {
392  trace.error() << " H5DSpecializations/H5DreadS error" << std::endl;
393  throw dgtalio;
394  }
395 
396  OutputImage* outputImage = new OutputImage(aDomain);
397  if (outputImage == NULL)
398  {
399  trace.error() << "outputImage new error in requestImage: " << std::endl;
400  throw dgtalio;
401  }
402 
403  typedef SpaceND<ddim> TSpace;
404  typename TSpace::Point a, b;
405  for(d=0; d<ddim; d++)
406  {
407  a[d]=offset[ddim-d-1]+myDomain->lowerBound()[d];
408  b[d]=a[d]+N_SUB[ddim-d-1]-1;
409  }
410  HyperRectDomain<TSpace> hrdomain(a,b);
411 
412  int p=0;
414  it = hrdomain.begin(), itend = hrdomain.end();
415  it != itend;
416  ++it)
417  {
418  outputImage->setValue((*it), data_out[ p++ ]);
419  }
420 
421  H5Sclose(memspace);
422 
423  // --
424 
425  free(data_out);
426 
427  return outputImage;
428  }
429 
435  void flushImage(OutputImage* outputImage)
436  {
437  DGtal::IOException dgtalio;
438 
439  const int ddim = Domain::dimension;
440 
441  // --
442 
443  hsize_t offset[ddim]; // hyperslab offset in the file
444  hsize_t count[ddim]; // size of the hyperslab in the file
445 
446  herr_t status;
447  hsize_t dimsm[ddim]; // memory space dimensions
448  hid_t memspace;
449 
450  hsize_t offset_in[ddim]; // hyperslab offset in memory
451  hsize_t count_in[ddim]; // size of the hyperslab in memory
452 
453  //int i[ddim];
454  int N_SUB[ddim];
455  typename Domain::Integer d;
456 
457  int malloc_size=1;
458  for(d=0; d<ddim; d++)
459  {
460  N_SUB[d] = (outputImage->domain().upperBound()[ddim-d-1]-outputImage->domain().lowerBound()[ddim-d-1])+1;
461  malloc_size = malloc_size*N_SUB[d];
462  }
463 
464  Value *data_in = (Value*) malloc (malloc_size * sizeof(Value)); // input buffer
465  if (data_in == NULL)
466  {
467  trace.error() << "data_in malloc error in flushImage: " << (malloc_size * sizeof(Value)) << std::endl;
468  throw dgtalio;
469  }
470 
471  // Define hyperslab in the dataset.
472  for(d=0; d<ddim; d++)
473  offset[d] = outputImage->domain().lowerBound()[ddim-d-1]-myDomain->lowerBound()[ddim-d-1];
474  for(d=0; d<ddim; d++)
475  count[d] = N_SUB[d];
476  status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
477  if (status)
478  {
479  trace.error() << " H5Sselect_hyperslab from dataspace error" << std::endl;
480  throw dgtalio;
481  }
482 
483  // Define the memory dataspace.
484  for(d=0; d<ddim; d++)
485  dimsm[d] = N_SUB[d];
486  memspace = H5Screate_simple(ddim,dimsm,NULL);
487 
488  // Define memory hyperslab.
489  for(d=0; d<ddim; d++)
490  offset_in[d] = 0;
491  for(d=0; d<ddim; d++)
492  count_in[d] = N_SUB[d];
493  status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_in, NULL, count_in, NULL);
494  if (status)
495  {
496  trace.error() << " H5Sselect_hyperslab from memspace error" << std::endl;
497  throw dgtalio;
498  }
499 
500  typedef SpaceND<ddim> TSpace;
501  typename TSpace::Point a, b;
502  for(d=0; d<ddim; d++)
503  {
504  a[d]=offset[ddim-d-1]+myDomain->lowerBound()[d];
505  b[d]=a[d]+N_SUB[ddim-d-1]-1;
506  }
507  HyperRectDomain<TSpace> hrdomain(a,b);
508 
509  std::vector<typename TSpace::Dimension> v(ddim);
510  for(d=0; d<ddim; d++)
511  v[d]=d;
512 
513  int p=0;
515  it = hrdomain.subRange(v, a).begin(), itend = hrdomain.subRange(v, a).end();
516  it != itend;
517  ++it)
518  {
519  data_in[ p++ ] = outputImage->operator()((*it));
520  }
521 
522  // Write data from hyperslab in memory into the hyperslab in the file.
523  //status = H5Dwrite(dataset, H5T_NATIVE_INT, memspace, dataspace, H5P_DEFAULT, data_in);
524  status = H5DSpecializations<Self, Value>::H5DwriteS(*this, memspace, data_in);
525  if (status)
526  {
527  trace.error() << " H5DSpecializations/H5DwriteS error" << std::endl;
528  throw dgtalio;
529  }
530 
531  H5Sclose(memspace);
532 
533  // --
534 
535  free(data_in);
536  }
537 
543  void detachImage(OutputImage* outputImage)
544  {
545  delete outputImage;
546  }
547 
548  // ------------------------- Protected Datas ------------------------------
549  private:
553  //ImageFactoryFromHDF5() {}
554 
555  // ------------------------- Private Datas --------------------------------
556  protected:
557 
559  Domain *myDomain;
560 
562  const std::string myFilename;
563  const std::string myDataset;
564 
565  public:
566 
567  // HDF5 handles
568  hid_t file, dataset;
570 
571  // ------------------------- Internals ------------------------------------
572  private:
573 
574  }; // end of class ImageFactoryFromHDF5
575 
576 
583  template <typename TImageContainer>
584  std::ostream&
585  operator<< ( std::ostream & out, const ImageFactoryFromHDF5<TImageContainer> & object );
586 
587 } // namespace DGtal
588 
589 
591 // Includes inline functions.
592 #include "DGtal/images/ImageFactoryFromHDF5.ih"
593 
594 // //
596 
597 #endif // !defined ImageFactoryFromHDF5_h
598 
599 #undef ImageFactoryFromHDF5_RECURSES
600 #endif // else defined(ImageFactoryFromHDF5_RECURSES)
const ConstIterator & begin() const
const ConstIterator & end() const
static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
Trace trace
Definition: Common.h:137
ImageContainer::Domain Domain
Aim: SpaceND is a utility class that defines the fundamental structure of a Digital Space in ND...
Definition: SpaceND.h:95
static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
Aim: Parallelepidec region of a digital space, model of a 'CDomain'.
ImageFactoryFromHDF5 & operator=(const ImageFactoryFromHDF5 &other)
TImageContainer ImageContainer
Types copied from the container.
static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
const Domain & domain() const
ImageContainer OutputImage
New types.
static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
const std::string myFilename
HDF5 filename and datasetname.
void detachImage(OutputImage *outputImage)
static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
BOOST_CONCEPT_ASSERT((concepts::CImage< TImageContainer >))
Checking concepts.
static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
ConstSubRange subRange(const std::vector< Dimension > &permutation) const
DGtal is the top-level namespace which contains all DGtal functions and types.
boost::uint8_t uint8_t
unsigned 8-bit integer.
Definition: BasicTypes.h:59
static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
void flushImage(OutputImage *outputImage)
static int H5DwriteS(ImageFactory &anImageFactory, hid_t memspace, Value *data_in)
ImageFactoryFromHDF5< TImageContainer > Self
OutputImage * requestImage(const Domain &aDomain)
ImageFactory::OutputImage::Value Value
void selfDisplay(std::ostream &out) const
static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
Domain * myDomain
Alias on the image domain.
boost::int32_t int32_t
signed 32-bit integer.
Definition: BasicTypes.h:72
Aim: Defines the concept describing a read/write image, having an output iterator.
Definition: CImage.h:102
std::ostream & error()
Aim: implements a factory from an HDF5 file.
boost::int64_t int64_t
signed 94-bit integer.
Definition: BasicTypes.h:74
Aim: The concept CBoundedNumber specifies what are the bounded numbers. Models of this concept should...
static int H5DreadS(ImageFactory &anImageFactory, hid_t memspace, Value *data_out)
Aim: implements HDF5 reading and writing for specialized type T.
ImageFactoryFromHDF5(const std::string &aFilename, const std::string &aDataset)