DGtal 2.1.0
Loading...
Searching...
No Matches
VolReader.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 VolReader.ih
19 * @author David Coeurjolly (\c david.coeurjolly@liris.cnrs.fr )
20 * Laboratoire d'InfoRmatique en Image et Systèmes d'information - LIRIS (CNRS, UMR 5205), CNRS, France
21 *
22 * @date 2010/07/25
23 *
24 * Implementation of inline methods defined in VolReader.h
25 *
26 * This file is part of the DGtal library.
27 */
28
29
30//////////////////////////////////////////////////////////////////////////////
31#include <cstdlib>
32
33#if defined(__GNUC__) || defined(__clang__)
34#pragma GCC diagnostic push
35#pragma GCC diagnostic ignored "-Wall"
36#pragma GCC diagnostic ignored "-Wextra"
37#pragma GCC diagnostic ignored "-Wpedantic"
38#pragma GCC diagnostic ignored "-Wshadow"
39#pragma GCC diagnostic ignored "-Wtype-limits"
40#pragma GCC diagnostic ignored "-Wtautological-compare"
41#endif
42#include <boost/iostreams/filtering_streambuf.hpp>
43#include <boost/iostreams/copy.hpp>
44#include <boost/iostreams/filter/zlib.hpp>
45#if defined(__GNUC__) || defined(__clang__)
46#pragma GCC diagnostic pop
47#endif
48
49
50//////////////////////////////////////////////////////////////////////////////
51
52
53///////////////////////////////////////////////////////////////////////////////
54// Interface - public :
55
56
57#define MAX_HEADERNUMLINES 64
58
59
60
61template <typename T, typename TFunctor>
62inline
63T
64DGtal::VolReader<T, TFunctor>::importVol( const std::string & filename,
65 const Functor & aFunctor)
66{
67 FILE * fin;
68 DGtal::IOException dgtalexception;
69
70
71 typename T::Point firstPoint( 0, 0, 0 );
72 typename T::Point lastPoint( 0, 0, 0 );
73 T nullImage( typename T::Domain( firstPoint, lastPoint ));
74
75 HeaderField header[ MAX_HEADERNUMLINES ];
76
77#ifdef WIN32
78 errno_t err;
79 err = fopen_s( &fin, filename.c_str() , "rb" );
80 if ( err )
81 {
82 trace.error() << "VolReader : can't open " << filename << std::endl;
83 throw dgtalexception;
84 }
85#else
86 fin = fopen( filename.c_str() , "rb" );
87#endif
88
89 if ( fin == NULL )
90 {
91 trace.error() << "VolReader : can't open " << filename << std::endl;
92 throw dgtalexception;
93 }
94
95
96 // Read header
97 // Buf for a line
98 char buf[128];
99 int linecount = 1;
100 int fieldcount = 0;
101 char *line;
102 // Read the file line by line until ".\n" is found
103 for ( line = fgets( buf, 128, fin );
104 line && strcmp( line, ".\n" ) != 0 ;
105 line = fgets( line, 128, fin ), ++linecount
106 )
107 {
108
109 if ( line[strlen( line ) - 1] != '\n' )
110 {
111 trace.error() << "VolReader: Line " << linecount << " too long" << std::endl;
112 throw dgtalexception;
113 }
114
115 int i;
116 for ( i = 0; line[i] && line[i] != ':'; ++i )
117 ;
118
119 if ( i == 0 || i >= 126 || line[i] != ':' )
120 {
121 trace.error() << "VolReader: Invalid header read at line " << linecount << std::endl;
122 throw dgtalexception;
123 }
124 else
125 {
126
127 if ( fieldcount == MAX_HEADERNUMLINES )
128 {
129 trace.warning() << "VolReader: Too many lines in HEADER, ignoring\n";
130 continue;
131 }
132 if ( fieldcount > MAX_HEADERNUMLINES )
133 continue;
134
135 // Remove \n from end of line
136 if ( line[ strlen( line ) - 1 ] == '\n' )
137 line[ strlen( line ) - 1 ] = 0;
138
139 // hack : split line into two str ...
140 line[i] = 0;
141 header[ fieldcount++ ] = HeaderField( line, line + i + 2 );
142 // +2 cause we skip the space
143 // following the colon
144 }
145 }
146
147 // Check required headers
148 for ( int i = 0; requiredHeaders[i]; ++i )
149 {
150 if ( getHeaderValue( "Version" , header ) != NULL &&
151 ( strcmp( requiredHeaders[i], "Int-Endian" ) == 0 ||
152 strcmp( requiredHeaders[i], "Voxel-Endian" ) == 0 ) )
153 {
154 continue;
155 }
156 if ( getHeaderField( requiredHeaders[i] , header ) == -1 )
157 {
158 trace.error() << "VolReader: Required Header Field missing: "
159 << requiredHeaders[i] << std::endl;
160 throw dgtalexception;
161
162 }
163 }
164
165 int sx = 0, sy= 0, sz= 0;
166 int cx = 0, cy= 0, cz= 0;
167 int version = -1;
168
169 getHeaderValueAsInt( "X", &sx, header );
170 getHeaderValueAsInt( "Y", &sy, header );
171 getHeaderValueAsInt( "Z", &sz, header );
172 getHeaderValueAsInt( "Version", &version, header);
173
174 if (! ((version == 2) || (version == 3)))
175 {
176 trace.error() << "VolReader: invalid Version header (must be either 2 or 3)\n";
177 throw dgtalexception;
178 }
179
180
181 //Raw Data
182 if( getHeaderValueAsInt( "Center-X", &cx, header ) == 0 )
183 {
184 getHeaderValueAsInt( "Center-Y", &cy, header );
185 getHeaderValueAsInt( "Center-Z", &cz, header );
186
187 firstPoint[0] = cx - (sx - 1)/2;
188 firstPoint[1] = cy - (sy - 1)/2;
189 firstPoint[2] = cz - (sz - 1)/2;
190 lastPoint[0] = cx + sx/2;
191 lastPoint[1] = cy + sy/2;
192 lastPoint[2] = cz + sz/2;
193 }
194 else
195 {
196 firstPoint = T::Point::zero;
197 lastPoint[0] = sx - 1;
198 lastPoint[1] = sy - 1;
199 lastPoint[2] = sz - 1;
200 }
201
202 typename T::Domain domain( firstPoint, lastPoint );
203
204 try
205 {
206 T image( domain );
207
208 size_t count = 0;
209 unsigned char val;
210 typename T::Domain::ConstIterator it = domain.begin();
211 size_t total = sx * sy * sz;
212 std::stringstream main;
213
214 //main read loop
215 while (( count < total ) && ( fin ) )
216 {
217 val = getc( fin );
218 main << val;
219 count++;
220 }
221
222 if ( count != total )
223 {
224 trace.error() << "VolReader: can't read file (raw data). I read "<<count<<" bytes instead of "<<total<<".\n";
225 throw dgtalexception;
226 }
227
228 //Uncompress if needed
229 if(version == 3)
230 {
231 std::stringstream uncompressed;
232 boost::iostreams::filtering_streambuf<boost::iostreams::input> in;
233 in.push(boost::iostreams::zlib_decompressor());
234 in.push(main);
235 boost::iostreams::copy(in, uncompressed);
236 //Apply to the image structure
237 for(size_t i=0; i < total; ++i)
238 {
239 val = uncompressed.get();
240 image.setValue(( *it ), aFunctor(val) );
241 it++;
242 }
243 }
244 else
245 {
246 //Apply to the image structure
247 for(size_t i=0; i < total; ++i)
248 {
249 val = main.get();
250 image.setValue(( *it ), aFunctor(val) );
251 it++;
252 }
253 }
254 fclose( fin );
255 return image;
256 }
257 catch ( ... )
258 {
259 trace.error() << "VolReader: not enough memory\n" ;
260 throw dgtalexception;
261 }
262
263 }
264
265
266
267 template <typename T, typename TFunctor>
268 const char *DGtal::VolReader<T, TFunctor>::requiredHeaders[] =
269 {
270 "X", "Y", "Z", "Voxel-Size", "Int-Endian", "Voxel-Endian", "Alpha-Color", NULL
271 };
272
273
274
275
276 template<typename T, typename TFunctor>
277 inline
278 int
279 DGtal::VolReader<T, TFunctor>::getHeaderField( const char *type, const HeaderField * header )
280 {
281
282
283 for ( int i = 0; i < MAX_HEADERNUMLINES; ++i )
284 {
285 if ( header[i].type != NULL && strcmp( header[i].type, type ) == 0 )
286 {
287 return i;
288 }
289 }
290 return -1;
291 }
292
293
294 template<typename T, typename TFunctor>
295 inline
296 const char *
297 DGtal::VolReader<T, TFunctor>::getHeaderValue( const char *type, const HeaderField * header )
298 {
299
300 int i = getHeaderField( type, header );
301 if ( i == -1 )
302 return NULL;
303 return header[i].value;
304
305 }
306
307
308 template<typename T, typename TFunctor>
309 inline
310 int
311 DGtal::VolReader<T, TFunctor>::getHeaderValueAsInt( const char *type, int *dest, const HeaderField * header )
312 {
313 int i = getHeaderField( type, header );
314 if ( i == -1 )
315 return 1;
316
317 return sscanf( header[i].value, "%d", dest ) == 0;
318 }
319