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