DGtal  0.9.2
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 
34 
35 ///////////////////////////////////////////////////////////////////////////////
36 // Interface - public :
37 
38 
39 #define MAX_HEADERNUMLINES 64
40 
41 
42 
43 template <typename T, typename TFunctor>
44 inline
45 T
46 DGtal::VolReader<T, TFunctor>::importVol( const std::string & filename,
47  const Functor & aFunctor) throw( DGtal::IOException )
48 {
49  FILE * fin;
50  DGtal::IOException dgtalexception;
51 
52 
53  typename T::Point firstPoint( 0, 0, 0 );
54  typename T::Point lastPoint( 0, 0, 0 );
55  T nullImage( typename T::Domain( firstPoint, lastPoint ));
56 
57  HeaderField header[ MAX_HEADERNUMLINES ];
58 
59 #ifdef WIN32
60  errno_t err;
61  err = fopen_s( &fin, filename.c_str() , "rb" );
62  if ( err )
63  {
64  trace.error() << "VolReader : can't open " << filename << std::endl;
65  throw dgtalexception;
66  }
67 #else
68  fin = fopen( filename.c_str() , "rb" );
69 #endif
70 
71  if ( fin == NULL )
72  {
73  trace.error() << "VolReader : can't open " << filename << std::endl;
74  throw dgtalexception;
75  }
76 
77 
78  // Read header
79  // Buf for a line
80  char buf[128];
81  int linecount = 1;
82  int fieldcount = 0;
83 
84  // Read the file line by line until ".\n" is found
85  for ( char *line = fgets( buf, 128, fin );
86  line && strcmp( line, ".\n" ) != 0 ;
87  line = fgets( line, 128, fin ), ++linecount
88  )
89  {
90 
91  if ( line[strlen( line ) - 1] != '\n' )
92  {
93  trace.error() << "VolReader: Line " << linecount << " too long" << std::endl;
94  throw dgtalexception;
95  }
96 
97  int i;
98  for ( i = 0; line[i] && line[i] != ':'; ++i )
99  ;
100 
101  if ( i == 0 || i >= 126 || line[i] != ':' )
102  {
103  trace.error() << "VolReader: Invalid header read at line " << linecount << std::endl;
104  throw dgtalexception;
105  }
106  else
107  {
108 
109  if ( fieldcount == MAX_HEADERNUMLINES )
110  {
111  trace.warning() << "VolReader: Too many lines in HEADER, ignoring\n";
112  continue;
113  }
114  if ( fieldcount > MAX_HEADERNUMLINES )
115  continue;
116 
117  // Remove \n from end of line
118  if ( line[ strlen( line ) - 1 ] == '\n' )
119  line[ strlen( line ) - 1 ] = 0;
120 
121  // hack : split line in two str ...
122  line[i] = 0;
123  header[ fieldcount++ ] = HeaderField( line, line + i + 2 );
124  // +2 cause we skip the space
125  // following the colon
126  }
127  }
128 
129  // Check required headers
130  for ( int i = 0; requiredHeaders[i]; ++i )
131  {
132  if ( getHeaderValue( "Version" , header ) != NULL &&
133  ( strcmp( requiredHeaders[i], "Int-Endian" ) == 0 ||
134  strcmp( requiredHeaders[i], "Voxel-Endian" ) == 0 ) )
135  {
136  continue;
137  }
138  if ( getHeaderField( requiredHeaders[i] , header ) == -1 )
139  {
140  trace.error() << "VolReader: Required Header Field missing: "
141  << requiredHeaders[i] << std::endl;
142  throw dgtalexception;
143 
144  }
145  }
146 
147  int sx = 0, sy= 0, sz= 0;
148  int cx = 0, cy= 0, cz= 0;
149 
150  getHeaderValueAsInt( "X", &sx, header );
151  getHeaderValueAsInt( "Y", &sy, header );
152  getHeaderValueAsInt( "Z", &sz, header );
153 
154  if ( getHeaderValue( "Version", header ) == NULL )
155  {
156  int rawsx=0, rawsy=0, rawsz=0;
157  long int count = 0;
158  // Size of the volume
159  count += (long)fread( &rawsx, sizeof( int ), 1, fin );
160  count += (long)fread( &rawsy, sizeof( int ), 1, fin );
161  count += (long)fread( &rawsz, sizeof( int ), 1, fin );
162 
163  if ( count != 3 )
164  {
165  trace.error() << "VolReader: can't read file (raw header)\n";
166  throw dgtalexception;
167  }
168 
169 
170  if ( (sx != rawsx) || (sy != rawsy) || (sz != rawsz) )
171  {
172  trace.warning() << "VolReader: Warning : Incoherent vol header with raw header !\n";
173  }
174 
175  int voxsize;
176  if ( getHeaderValueAsInt( "Voxel-Size", &voxsize, header ) == 0 && voxsize != sizeof( voxel ) )
177  {
178  trace.error() << "VolReader: This file was generated with a voxel-size that we do not support.\n";
179  throw dgtalexception;
180  }
181 
182  // We should have a useless \n in the file at this point
183  char tmp;
184  count = (long)fread( &tmp, sizeof( char ), 1, fin );
185 
186  if ( count != 1 || tmp != '\n' )
187  {
188  trace.error() << "VolReader: I thouhgt I would have read a \\n !\n";
189  throw dgtalexception;
190  }
191  }
192 
193  //Raw Data
194 
195  if( getHeaderValueAsInt( "Center-X", &cx, header ) == 0 )
196  {
197  getHeaderValueAsInt( "Center-Y", &cy, header );
198  getHeaderValueAsInt( "Center-Z", &cz, header );
199 
200  firstPoint[0] = cx - (sx - 1)/2;
201  firstPoint[1] = cy - (sy - 1)/2;
202  firstPoint[2] = cz - (sz - 1)/2;
203  lastPoint[0] = cx + sx/2;
204  lastPoint[1] = cy + sy/2;
205  lastPoint[2] = cz + sz/2;
206  }
207  else
208  {
209  firstPoint = T::Point::zero;
210  lastPoint[0] = sx - 1;
211  lastPoint[1] = sy - 1;
212  lastPoint[2] = sz - 1;
213  }
214 
215  typename T::Domain domain( firstPoint, lastPoint );
216 
217  try
218  {
219  T image( domain );
220 
221  long count = 0;
222  unsigned char val;
223  typename T::Domain::ConstIterator it = domain.begin();
224  long int total = sx * sy * sz;
225 
226  while (( count < total ) && ( fin ) )
227  {
228  val = getc( fin );
229  image.setValue(( *it ), aFunctor(val) );
230  it++;
231  count++;
232  }
233 
234  if ( count != total )
235  {
236  trace.error() << "VolReader: can't read file (raw data) !\n";
237  throw dgtalexception;
238  }
239 
240  fclose( fin );
241  return image;
242  }
243  catch ( ... )
244  {
245  trace.error() << "VolReader: not enough memory\n" ;
246  throw dgtalexception;
247  }
248 
249 }
250 
251 
252 
253 template <typename T, typename TFunctor>
254 const char *DGtal::VolReader<T, TFunctor>::requiredHeaders[] =
255 {
256  "X", "Y", "Z", "Voxel-Size", "Int-Endian", "Voxel-Endian", "Alpha-Color", NULL
257 };
258 
259 
260 
261 
262 template<typename T, typename TFunctor>
263 inline
264 int
265 DGtal::VolReader<T, TFunctor>::getHeaderField( const char *type, const HeaderField * header )
266 {
267 
268 
269  for ( int i = 0; i < MAX_HEADERNUMLINES; ++i )
270  {
271  if ( header[i].type != NULL && strcmp( header[i].type, type ) == 0 )
272  {
273  return i;
274  }
275  }
276  return -1;
277 }
278 
279 
280 template<typename T, typename TFunctor>
281 inline
282 const char *
283 DGtal::VolReader<T, TFunctor>::getHeaderValue( const char *type, const HeaderField * header )
284 {
285 
286  int i = getHeaderField( type, header );
287  if ( i == -1 )
288  return NULL;
289  return header[i].value;
290 
291 }
292 
293 
294 template<typename T, typename TFunctor>
295 inline
296 int
297 DGtal::VolReader<T, TFunctor>::getHeaderValueAsInt( const char *type, int *dest, const HeaderField * header )
298 {
299  int i = getHeaderField( type, header );
300  if ( i == -1 )
301  return 1;
302 
303  return sscanf( header[i].value, "%d", dest ) == 0;
304 }
305