Fawkes API  Fawkes Development Version
fileloader.cpp
1 
2 /***************************************************************************
3  * fileloader.cpp - A camera which obtains its images from a single image
4  * file or from several image files in a directory
5  *
6  * Generated: Tue Feb 22 13:28:08 2005
7  * Copyright 2005-2007 Tim Niemueller [www.niemueller.de]
8  * 2008 Daniel Beck
9  *
10  ****************************************************************************/
11 
12 /* This program is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU General Public License as published by
14  * the Free Software Foundation; either version 2 of the License, or
15  * (at your option) any later version. A runtime exception applies to
16  * this software (see LICENSE.GPL_WRE file mentioned below for details).
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU Library General Public License for more details.
22  *
23  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
24  */
25 
26 #include <core/exception.h>
27 #include <core/exceptions/software.h>
28 #include <core/exceptions/system.h>
29 #include <fvcams/fileloader.h>
30 #include <fvutils/writers/fvraw.h>
31 #include <fvutils/system/filetype.h>
32 #include <fvutils/system/camargp.h>
33 #include <fvutils/colormap/cmfile.h>
34 #include <fvutils/colormap/colormap.h>
35 
36 #include <fvutils/readers/fvraw.h>
37 #ifdef HAVE_LIBJPEG
38 #include <fvutils/readers/jpeg.h>
39 #endif
40 #ifdef HAVE_LIBPNG
41 #include <fvutils/readers/png.h>
42 #endif
43 
44 #include <cstring>
45 #include <cstdlib>
46 #include <cstdio>
47 
48 #include <sys/types.h>
49 
50 using namespace fawkes;
51 
52 namespace firevision {
53 #if 0 /* just to make Emacs auto-indent happy */
54 }
55 #endif
56 
57 /** @class FileLoader <fvcams/fileloader.h>
58  * Load images from files.
59  * The file loader tries to determine the image format of the given image using
60  * the the file type utility. Currently it recognizes JPEG and FvRaw image files.
61  *
62  * @author Tim Niemueller
63  * @author Daniel Beck
64  */
65 
66 char* FileLoader::extension = NULL;
67 
68 #if defined(__GLIBC__) || defined(__FreeBSD__)
69 int file_select(const struct dirent* ent)
70 #else
71 int file_select(struct dirent *ent)
72 #endif
73 {
74  if ( !FileLoader::extension ) { return 1; }
75 
76  // NOTE: this only checks whether the filename contains the
77  // extension and not whether it ends with it.
78  if ( NULL != strstr(ent->d_name, FileLoader::extension) ) {
79  return 1;
80  }
81 
82  return 0;
83 }
84 
85 /** Constructor.
86  * @param filename name of file to open, full path or relative to working directory
87  */
88 FileLoader::FileLoader(const char *filename)
89 {
90  this->filename = strdup(filename);
91  this->dirname = NULL;
92  this->extension = NULL;
93  this->file_list = NULL;
94  num_files = 0;
95  cur_file = 0;
96  opened = started = false;
97  width = height = 0;
98  file_buffer = NULL;
99  this->cspace = CS_UNKNOWN;
100 }
101 
102 
103 /** Constructor.
104  * Initialize with the parameters from the given camera argument parser. The following
105  * parameters are supported:
106  * - file=FILENAME: open the given file
107  * - dir=DIRECTORY: sequentially open files in this directory
108  * - ext=EXTENSION: only open files with this extension
109  *
110  * @param cap camera argument parser
111  */
112 FileLoader::FileLoader(const CameraArgumentParser *cap)
113 {
114  filename = NULL;
115  dirname = NULL;
116 
117  if ( cap->has("file") ) {
118  this->filename = strdup(cap->get("file").c_str());
119  } else if ( cap->has("dir") ) {
120  this->dirname = strdup( cap->get("dir").c_str() );
121  if ( cap->has("ext") ) {
122  this->extension = strdup( cap->get("ext").c_str() );
123  }
124  } else {
125  throw MissingParameterException("Neither parameter file nor parameter directory are present");
126  }
127 
128  file_list = NULL;
129  num_files = 0;
130  cur_file = 0;
131  width = height = 0;
132  file_buffer = NULL;
133  this->cspace = CS_UNKNOWN;
134  opened = started = false;
135 }
136 
137 
138 /** Legacy constructor.
139  * Before FvRaw FireVision had the ability to store the pure buffer of an image
140  * without any header. Because of this additional information like colorspace,
141  * width and height of the image had to be supplied. The number of bytes that
142  * has to be read for the image is calculated from the given parameters.
143  * @param cspace color space of image
144  * @param filename filename to open
145  * @param width width of image
146  * @param height height of image
147  */
148 FileLoader::FileLoader(colorspace_t cspace, const char *filename,
149  unsigned int width, unsigned int height)
150 {
151  started = opened = false;
152  this->cspace = cspace;
153  this->width = width;
154  this->height = height;
155  this->filename = strdup(filename);
156  this->dirname = NULL;
157  this->extension = NULL;
158  this->file_list = NULL;
159  num_files = 0;
160  cur_file = 0;
161  file_buffer = NULL;
162 }
163 
164 
165 /** Destructor. */
166 FileLoader::~FileLoader()
167 {
168  for (int i = 0; i < num_files; ++i) {
169  free(file_list[i]);
170  }
171  free(file_list);
172  free(dirname);
173  free(extension);
174  free(filename);
175 }
176 
177 
178 void
179 FileLoader::open()
180 {
181  if (opened) return;
182 
183  if (dirname) {
184  num_files = scandir(dirname, &file_list, file_select, alphasort);
185 
186  if ( -1 == num_files ) {
187  throw Exception("Error while scanning directory %s", dirname);
188  }
189  }
190 
191  read_file();
192  opened = true;
193 }
194 
195 
196 void
197 FileLoader::start()
198 {
199  if (started) return;
200 
201  if (!opened) {
202  throw Exception("Trying to start closed file");
203  }
204 
205  started = true;
206 }
207 
208 void
209 FileLoader::stop()
210 {
211  started = false;
212 }
213 
214 
215 void
216 FileLoader::print_info()
217 {
218 }
219 
220 
221 void
222 FileLoader::capture()
223 {
224  if (0 != num_files) {
225  if (file_buffer) {
226  free(file_buffer);
227  }
228 
229  read_file();
230 
231  if (++cur_file == num_files) {
232  cur_file = 0;
233  }
234  }
235 }
236 
237 
238 unsigned char*
239 FileLoader::buffer()
240 {
241  return file_buffer;
242 }
243 
244 
245 unsigned int
246 FileLoader::buffer_size()
247 {
248  return _buffer_size;
249 }
250 
251 
252 void
253 FileLoader::close()
254 {
255  if (file_buffer != NULL) {
256  free(file_buffer);
257  file_buffer = NULL;
258  }
259  opened = false;
260 }
261 
262 
263 void
264 FileLoader::dispose_buffer()
265 {
266 }
267 
268 
269 void
270 FileLoader::flush()
271 {
272 }
273 
274 
275 bool
276 FileLoader::ready()
277 {
278  return started;
279 }
280 
281 
282 void
283 FileLoader::set_image_number(unsigned int n)
284 {
285 }
286 
287 
288 unsigned int
289 FileLoader::pixel_width()
290 {
291  return width;
292 }
293 
294 
295 unsigned int
296 FileLoader::pixel_height()
297 {
298  return height;
299 }
300 
301 
302 colorspace_t
303 FileLoader::colorspace()
304 {
305  return cspace;
306 }
307 
308 
309 /** Set the colorspace of the image.
310  * @param c colorspace
311  */
312 void
313 FileLoader::set_colorspace(colorspace_t c)
314 {
315  cspace = c;
316 }
317 
318 
319 /** Set width.
320  * @param w image width in pixels
321  */
322 void
323 FileLoader::set_pixel_width(unsigned int w)
324 {
325  width = w;
326 }
327 
328 
329 /** Set height.
330  * @param h image height in pixels
331  */
332 void
333 FileLoader::set_pixel_height(unsigned int h)
334 {
335  height = h;
336 }
337 
338 void
339 FileLoader::read_file()
340 {
341  char* fn;
342  if (0 != num_files) {
343  if (asprintf(&fn, "%s/%s", dirname, file_list[cur_file]->d_name) == -1) {
344  throw OutOfMemoryException("FileLoader::read_file(): asprintf() failed (2)");
345  }
346  } else {
347  fn = strdup(filename);
348  }
349 
350  std::string ft = fv_filetype_file( fn );
351 
352  if ( ft == "FvRaw" ) {
353  FvRawReader *fvrr = new FvRawReader( fn );
354  cspace = fvrr->colorspace();
355  width = fvrr->pixel_width();
356  height = fvrr->pixel_height();
357  _buffer_size = colorspace_buffer_size( cspace, width, height );
358  file_buffer = (unsigned char*)malloc(_buffer_size);
359  fvrr->set_buffer( file_buffer );
360  try {
361  fvrr->read();
362  } catch (Exception &e) {
363  delete fvrr;
364  e.append("FileLoader::open() failed");
365  throw;
366  }
367  delete fvrr;
368 
369 #ifdef HAVE_LIBJPEG
370  } else if ( ft.find( "JPEG" ) != std::string::npos ) {
371  JpegReader *jr = new JpegReader( fn );
372  cspace = jr->colorspace();
373  width = jr->pixel_width();
374  height = jr->pixel_height();
375  _buffer_size = colorspace_buffer_size( cspace, width, height );
376  file_buffer = (unsigned char*)malloc(_buffer_size);
377  jr->set_buffer( file_buffer );
378  try {
379  jr->read();
380  } catch (Exception &e) {
381  delete jr;
382  e.append("FileLoader::open() failed");
383  throw;
384  }
385  delete jr;
386 #endif
387 
388 #ifdef HAVE_LIBPNG
389  } else if ( ft.find( "PNG" ) != std::string::npos ) {
390  PNGReader *pr = new PNGReader( fn ); cspace = pr->colorspace();
391  width = pr->pixel_width();
392  height = pr->pixel_height();
393  _buffer_size = colorspace_buffer_size( cspace, width, height );
394  file_buffer = (unsigned char*)malloc(_buffer_size);
395  pr->set_buffer( file_buffer );
396  try {
397  pr->read();
398  } catch (Exception &e) {
399  delete pr;
400  e.append("FileLoader::open() failed for PNG");
401  throw;
402  }
403  delete pr;
404 #endif
405 
406  } else if ( ft == "FvColormap" ) {
407  ColormapFile cmf;
408  cmf.read(fn);
409 
410  Colormap *colormap = cmf.get_colormap();
411  cspace = YUV422_PLANAR;
412  width = colormap->width() * 2;
413  height = colormap->height() * 2;
414  _buffer_size = colorspace_buffer_size( cspace, width, height );
415  file_buffer = (unsigned char*)malloc(_buffer_size);
416  colormap->to_image(file_buffer);
417 
418  delete colormap;
419 
420  } else {
421  _buffer_size = colorspace_buffer_size( cspace, width, height );
422 
423  if (_buffer_size > 0) {
424  FILE *f;
425  f = fopen( fn, "rb" );
426  file_buffer = (unsigned char*)malloc(_buffer_size);
427  if (fread(file_buffer, _buffer_size, 1, f) != 1) {
428  // cout << "FileLoader: Could not read data." << endl;
429  fclose(f);
430  throw Exception("Could not read data");
431  }
432  fclose(f);
433  } else {
434  throw Exception("Invalid color space (buffer size is 0)");
435  }
436  }
437 
438  free(fn);
439 }
440 
441 } // end namespace firevision
std::string get(std::string s) const
Get the value of the given parameter.
Definition: camargp.cpp:164
Fawkes library namespace.
Camera argument parser.
Definition: camargp.h:38
Base class for exceptions in Fawkes.
Definition: exception.h:36
Expected parameter is missing.
Definition: software.h:76
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:341
bool has(std::string s) const
Check if an parameter was given.
Definition: camargp.cpp:152