DGtal  1.5.beta
HDF5Writer.ih
1 /**
2  * This program is free software: you can redistribute it and/or modify
3  * it under the terms of the GNU Lesser General Public License as
4  * published by the Free Software Foundation, either version 3 of the
5  * License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program. If not, see <http://www.gnu.org/licenses/>.
14  *
15  **/
16 
17 /**
18  * @file HDF5Writer.ih
19  * @author Martial Tola (\c martial.tola@liris.cnrs.fr )
20  * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
21  *
22  * @date 2013/09/11
23  *
24  * Implementation of inline methods defined in HDF5Writer.h
25  *
26  * This file is part of the DGtal library.
27  */
28 
29 
30 //////////////////////////////////////////////////////////////////////////////
31 #include <cstdlib>
32 #include <fstream>
33 #include "DGtal/io/Color.h"
34 
35 #include <hdf5.h>
36 //////////////////////////////////////////////////////////////////////////////
37 
38 ///////////////////////////////////////////////////////////////////////////////
39 // IMPLEMENTATION of inline methods.
40 ///////////////////////////////////////////////////////////////////////////////
41 
42 #define RANK_3D 3
43 #define SIZE_CHUNK 10 // for compressed dataset
44 
45 namespace DGtal {
46  template<typename I,typename F>
47  bool
48  HDF5Writer<I,F>::exportHDF5_3D(const std::string & filename, const I & aImage, const std::string & aDataset,
49  const Functor & aFunctor)
50  {
51  DGtal::IOException dgtalio;
52 
53  typename I::Domain::Vector size;
54  const typename I::Domain::Point &upBound = aImage.domain().upperBound();
55  const typename I::Domain::Point &lowBound = aImage.domain().lowerBound();
56  size[0]=upBound[0]-lowBound[0]+1;
57  size[1]=upBound[1]-lowBound[1]+1;
58  size[2]=upBound[2]-lowBound[2]+1;
59 
60  typename I::Domain domain = aImage.domain();
61  typename I::Value val;
62 
63  hid_t file, dataset; // file and dataset handles
64  hid_t datatype, dataspace; // handles
65  hsize_t dimsf[RANK_3D]; // dataset dimensions
66  herr_t status;
67  DGtal::uint8_t *data;
68  int i;
69 
70  // compressed dataset
71  hid_t plist_id;
72  hsize_t cdims[RANK_3D];
73  // compressed dataset
74 
75  try
76  {
77  data = (DGtal::uint8_t*)malloc(size[2]*size[1]*size[0] * sizeof(DGtal::uint8_t));
78  if (data == NULL)
79  {
80  trace.error() << " malloc error" << std::endl;
81  return false;
82  }
83 
84  // We scan the domain instead of the image because we cannot
85  // trust the image container Iterator
86  i=0;
87  for(typename I::Domain::ConstIterator it = domain.begin(), itend=domain.end();
88  it!=itend;
89  ++it)
90  {
91  val = aImage( (*it) );
92  data[i++] = aFunctor(val);
93  }
94 
95  /*
96  * Create a new file using H5F_ACC_TRUNC access,
97  * default file creation properties, and default file
98  * access properties.
99  */
100  file = H5Fcreate(filename.c_str(), H5F_ACC_TRUNC, H5P_DEFAULT, H5P_DEFAULT);
101 
102  // Describe the size of the array and create the data space for fixed size dataset.
103  dimsf[0] = size[2];
104  dimsf[1] = size[1];
105  dimsf[2] = size[0];
106  dataspace = H5Screate_simple(RANK_3D, dimsf, NULL);
107 
108  // compressed dataset
109  plist_id = H5Pcreate(H5P_DATASET_CREATE);
110 
111  // Dataset must be chunked for compression.
112  cdims[0] = SIZE_CHUNK;
113  cdims[1] = SIZE_CHUNK;
114  cdims[2] = SIZE_CHUNK;
115  status = H5Pset_chunk(plist_id, RANK_3D, cdims);
116 
117  // --> Compression levels :
118  // 0 No compression
119  // 1 Best compression speed; least compression
120  // 2 through 8 Compression improves; speed degrades
121  // 9 Best compression ratio; slowest speed
122  //
123  // Set ZLIB / DEFLATE Compression using compression level 6.
124  status = H5Pset_deflate(plist_id, 6);
125  // compressed dataset
126 
127  /*
128  * Define datatype for the data in the file.
129  */
130  datatype = H5Tcopy(H5T_NATIVE_UINT8);
131  status = H5Tset_order(datatype, H5T_ORDER_LE);
132 
133  /*
134  * Create a new dataset within the file using defined dataspace and
135  * datatype and default dataset creation properties.
136  */
137  dataset = H5Dcreate2(file, aDataset.c_str(), datatype, dataspace,
138  H5P_DEFAULT, /*H5P_DEFAULT*/plist_id, H5P_DEFAULT); // here to activate compressed dataset
139 
140  // Write the data to the dataset using default transfer properties.
141  status = H5Dwrite(dataset, H5T_NATIVE_UINT8, H5S_ALL, H5S_ALL, H5P_DEFAULT, data);
142  if (status)
143  {
144  trace.error() << " H5Dwrite error" << std::endl;
145  free(data);
146  return false;
147  }
148 
149  // Close/release resources.
150  H5Sclose(dataspace);
151  H5Tclose(datatype);
152  H5Dclose(dataset);
153  // compressed dataset
154  H5Pclose(plist_id);
155  // compressed dataset
156  H5Fclose(file);
157 
158  free(data);
159  }
160  catch( ... )
161  {
162  trace.error() << "HDF5 writer IO error on export " << filename << std::endl;
163  throw dgtalio;
164  }
165  return true;
166  }
167 
168 }//namespace