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.
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.
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/>.
19 * @author Martial Tola (\c martial.tola@liris.cnrs.fr )
23 * Implementation of inline methods defined in HDF5Reader.h
25 * This file is part of the DGtal library.
28///////////////////////////////////////////////////////////////////////////////
29// IMPLEMENTATION of inline methods.
30///////////////////////////////////////////////////////////////////////////////
32//////////////////////////////////////////////////////////////////////////////
38#include "DGtal/kernel/SpaceND.h"
39#include "DGtal/kernel/domains/HyperRectDomain.h"
43//////////////////////////////////////////////////////////////////////////////
47///////////////////////////////////////////////////////////////////////////////
48// Implementation of inline methods //
51///////////////////////////////////////////////////////////////////////////////
52// Implementation of inline functions and external operators //
54template <typename TImageContainer, typename TFunctor>
57DGtal::HDF5Reader<TImageContainer, TFunctor>::importHDF5(const std::string & aFilename, const std::string & aDataset,
58 const Functor & aFunctor, bool topbotomOrder)
60 DGtal::IOException dgtalio;
62 BOOST_STATIC_ASSERT( (ImageContainer::Domain::dimension == 2));
71 unsigned char *imgBuf; // 'unsigned char' is mandated by the HDF5 library
73 // Load the library -- not required on most platforms
75 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
77 // Open an existing file
78 fileID = H5Fopen(aFilename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT);
79 if (fileID < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
81 // Figure out if the data is an image or not
82 hErrVal = H5IMis_image(fileID, aDataset.c_str());
83 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
85 trace.error() << "The data is NOT an image" << std::endl;
89 // Get info about the image
91 hErrVal = H5IMget_image_info (fileID, aDataset.c_str(), &width, &height, &planes, interlace, &npals);
92 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
94 // If the image is the wrong type, then throw exception
95 if( !( ((planes==1) && (npals==1)) || ((planes==3) && (npals==0) && (strcmp(interlace, "INTERLACE_PIXEL")==0)) ) ) {
96 trace.error() << "ERROR: Image is not 8-bit with palette or image is not 24-bit truecolor with INTERLACE_PIXEL pixel layout" << std::endl;
100 // Allocate space for the image
101 imgBuf = (unsigned char*) malloc (width * height * planes * sizeof( unsigned char ));
102 if (imgBuf == NULL) {
103 trace.error() << "ERROR: Could not allocate space for image" << std::endl;
107 // Read the data from the file
108 hErrVal = H5IMread_image (fileID, aDataset.c_str(), imgBuf);
109 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
112 hErrVal = H5Fclose(fileID);
113 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
115 // Unload the library and free any remaining resources
117 if (hErrVal < 0) { trace.error() << "HDF5 ERROR: " << std::endl; H5Eprint2(H5E_DEFAULT, stderr); throw dgtalio; }
121 typename TImageContainer::Point firstPoint;
122 typename TImageContainer::Point lastPoint;
124 firstPoint = TImageContainer::Point::zero;
125 lastPoint[0] = width-1;
126 lastPoint[1] = height-1;
128 typename TImageContainer::Domain domain(firstPoint,lastPoint);
129 TImageContainer image(domain);
131 for(hsize_t y=0; y<height; y++)
132 for(hsize_t x=0; x<width; x++)
134 typename TImageContainer::Point pt;
136 pt[0]=x; pt[1]=height-1-y;
141 if( ((planes==1) && (npals==1)) )
142 image.setValue(pt, aFunctor(imgBuf[ y*width+x ]));
143 else if( ((planes==3) && (npals==0) && (strcmp(interlace, "INTERLACE_PIXEL")==0)) )
144 image.setValue(pt, aFunctor(imgBuf[ ( (y*planes*width+x*planes)+(y*planes*width+x*planes+1)+(y*planes*width+x*planes+2) )/3 ]));
152template <typename TImageContainer, typename TFunctor>
155DGtal::HDF5Reader<TImageContainer, TFunctor>::importHDF5_3D(const std::string & aFilename, const std::string & aDataset,
156 const Functor & aFunctor)
158 DGtal::IOException dgtalio;
160 BOOST_STATIC_ASSERT( (ImageContainer::Domain::dimension == 3));
162 const int ddim = ImageContainer::Domain::dimension;
170 hid_t datatype, dataspace;
172 hsize_t dims_out[ddim]; // dataset dimensions
174 // Open the file and the dataset.
175 file = H5Fopen(aFilename.c_str(), H5F_ACC_RDWR, H5P_DEFAULT);
176 dataset = H5Dopen2(file, aDataset.c_str(), H5P_DEFAULT);
178 // Get datatype and dataspace handles and then query dataset class, order, size, rank and dimensions.
179 datatype = H5Dget_type(dataset); // datatype handle
181 dataspace = H5Dget_space(dataset); // dataspace handle
183 H5Sget_simple_extent_dims(dataspace, dims_out, NULL);
187 typedef SpaceND<ddim> TSpace;
188 typename TSpace::Point low, up;
190 typename Domain::Integer d;
191 for(d=0; d<ddim; d++)
194 up[d]=dims_out[ddim-d-1]-1;
197 myDomain = new Domain(low, up);
198 aDomain = *myDomain; // because here we want the full image
200 /* - reading HDF5- */
201 hsize_t offset[ddim]; // hyperslab offset in the file
202 hsize_t count[ddim]; // size of the hyperslab in the file
205 hsize_t dimsm[ddim]; // memory space dimensions
208 hsize_t offset_out[ddim]; // hyperslab offset in memory
209 hsize_t count_out[ddim]; // size of the hyperslab in memory
215 for(d=0; d<ddim; d++)
217 N_SUB[d] = (aDomain.upperBound()[ddim-d-1]-aDomain.lowerBound()[ddim-d-1])+1;
218 malloc_size = malloc_size*N_SUB[d];
221 Value *data_out = (Value*) malloc (malloc_size * sizeof(Value)); // output buffer
222 if (data_out == NULL)
224 trace.error() << "data_out malloc error in importHDF5_3D: " << (malloc_size * sizeof(Value)) << std::endl;
228 // Define hyperslab in the dataset.
229 for(d=0; d<ddim; d++)
230 offset[d] = aDomain.lowerBound()[ddim-d-1]-myDomain->lowerBound()[ddim-d-1];
231 for(d=0; d<ddim; d++)
233 status = H5Sselect_hyperslab(dataspace, H5S_SELECT_SET, offset, NULL, count, NULL);
236 trace.error() << " H5Sselect_hyperslab from dataspace error" << std::endl;
240 // Define the memory dataspace.
241 for(d=0; d<ddim; d++)
243 memspace = H5Screate_simple(ddim,dimsm,NULL);
245 // Define memory hyperslab.
246 for(d=0; d<ddim; d++)
248 for(d=0; d<ddim; d++)
249 count_out[d] = N_SUB[d];
250 status = H5Sselect_hyperslab(memspace, H5S_SELECT_SET, offset_out, NULL, count_out, NULL);
253 trace.error() << " H5Sselect_hyperslab from memspace error" << std::endl;
257 // Read data from hyperslab in the file into the hyperslab in memory.
258 status = H5Dread(dataset, H5T_NATIVE_UINT8, memspace, dataspace, H5P_DEFAULT, data_out);
261 trace.error() << " H5Dread error" << std::endl;
265 OutputImage outputImage(aDomain);
267 typedef SpaceND<ddim> TSpace;
268 typename TSpace::Point a, b;
269 for(d=0; d<ddim; d++)
271 a[d]=offset[ddim-d-1]+myDomain->lowerBound()[d];
272 b[d]=a[d]+N_SUB[ddim-d-1]-1;
274 HyperRectDomain<TSpace> domain(a,b);
277 for( typename HyperRectDomain<TSpace>/*::ConstSubRange*/::ConstIterator
278 it = domain/*.subRange(v, a)*/.begin(), itend = domain/*.subRange(v, a)*/.end();
282 outputImage.setValue((*it), aFunctor(data_out[ p++ ]));
288 /* - reading HDF5- */
292 // Close/release resources.
302///////////////////////////////////////////////////////////////////////////////