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