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  * - width=W: width in pixels of image
110  * - height=H: height in pixels of image
111  * - colorspace=C: colorspace of image
112  *
113  * Width, height, and colorspace are used for raw images without an header, e.g if
114  * captured by v4l2-ctl.
115  *
116  * @param cap camera argument parser
117  */
118 FileLoader::FileLoader(const CameraArgumentParser *cap)
119 {
120  filename = NULL;
121  dirname = NULL;
122 
123  file_list = NULL;
124  num_files = 0;
125  cur_file = 0;
126  width = height = 0;
127  file_buffer = NULL;
128  this->cspace = CS_UNKNOWN;
129  opened = started = false;
130 
131  if ( cap->has("file") ) {
132  this->filename = strdup(cap->get("file").c_str());
133  if (cap->has("width")) {
134  width = cap->get_int("width");
135  }
136  if (cap->has("height")) {
137  height = cap->get_int("height");
138  }
139  if (cap->has("colorspace")) {
140  cspace = colorspace_by_name(cap->get("colorspace").c_str());
141  }
142  } else if ( cap->has("dir") ) {
143  this->dirname = strdup( cap->get("dir").c_str() );
144  if ( cap->has("ext") ) {
145  this->extension = strdup( cap->get("ext").c_str() );
146  }
147  } else {
148  throw MissingParameterException("Neither parameter file nor parameter directory are present");
149  }
150 
151 }
152 
153 
154 /** Legacy constructor.
155  * Before FvRaw FireVision had the ability to store the pure buffer of an image
156  * without any header. Because of this additional information like colorspace,
157  * width and height of the image had to be supplied. The number of bytes that
158  * has to be read for the image is calculated from the given parameters.
159  * @param cspace color space of image
160  * @param filename filename to open
161  * @param width width of image
162  * @param height height of image
163  */
164 FileLoader::FileLoader(colorspace_t cspace, const char *filename,
165  unsigned int width, unsigned int height)
166 {
167  started = opened = false;
168  this->cspace = cspace;
169  this->width = width;
170  this->height = height;
171  this->filename = strdup(filename);
172  this->dirname = NULL;
173  this->extension = NULL;
174  this->file_list = NULL;
175  num_files = 0;
176  cur_file = 0;
177  file_buffer = NULL;
178 }
179 
180 
181 /** Destructor. */
182 FileLoader::~FileLoader()
183 {
184  for (int i = 0; i < num_files; ++i) {
185  free(file_list[i]);
186  }
187  free(file_list);
188  free(dirname);
189  free(extension);
190  free(filename);
191 }
192 
193 
194 void
195 FileLoader::open()
196 {
197  if (opened) return;
198 
199  if (dirname) {
200  num_files = scandir(dirname, &file_list, file_select, alphasort);
201 
202  if ( -1 == num_files ) {
203  throw Exception("Error while scanning directory %s", dirname);
204  }
205  }
206 
207  read_file();
208  opened = true;
209 }
210 
211 
212 void
213 FileLoader::start()
214 {
215  if (started) return;
216 
217  if (!opened) {
218  throw Exception("Trying to start closed file");
219  }
220 
221  started = true;
222 }
223 
224 void
225 FileLoader::stop()
226 {
227  started = false;
228 }
229 
230 
231 void
232 FileLoader::print_info()
233 {
234 }
235 
236 
237 void
238 FileLoader::capture()
239 {
240  if (0 != num_files) {
241  if (file_buffer) {
242  free(file_buffer);
243  }
244 
245  read_file();
246 
247  if (++cur_file == num_files) {
248  cur_file = 0;
249  }
250  }
251 }
252 
253 
254 unsigned char*
255 FileLoader::buffer()
256 {
257  return file_buffer;
258 }
259 
260 
261 unsigned int
262 FileLoader::buffer_size()
263 {
264  return _buffer_size;
265 }
266 
267 
268 void
269 FileLoader::close()
270 {
271  if (file_buffer != NULL) {
272  free(file_buffer);
273  file_buffer = NULL;
274  }
275  opened = false;
276 }
277 
278 
279 void
280 FileLoader::dispose_buffer()
281 {
282 }
283 
284 
285 void
286 FileLoader::flush()
287 {
288 }
289 
290 
291 bool
292 FileLoader::ready()
293 {
294  return started;
295 }
296 
297 
298 void
299 FileLoader::set_image_number(unsigned int n)
300 {
301 }
302 
303 
304 unsigned int
305 FileLoader::pixel_width()
306 {
307  return width;
308 }
309 
310 
311 unsigned int
312 FileLoader::pixel_height()
313 {
314  return height;
315 }
316 
317 
318 colorspace_t
319 FileLoader::colorspace()
320 {
321  return cspace;
322 }
323 
324 
325 /** Set the colorspace of the image.
326  * @param c colorspace
327  */
328 void
329 FileLoader::set_colorspace(colorspace_t c)
330 {
331  cspace = c;
332 }
333 
334 
335 /** Set width.
336  * @param w image width in pixels
337  */
338 void
339 FileLoader::set_pixel_width(unsigned int w)
340 {
341  width = w;
342 }
343 
344 
345 /** Set height.
346  * @param h image height in pixels
347  */
348 void
349 FileLoader::set_pixel_height(unsigned int h)
350 {
351  height = h;
352 }
353 
354 void
355 FileLoader::read_file()
356 {
357  char* fn;
358  if (0 != num_files) {
359  if (asprintf(&fn, "%s/%s", dirname, file_list[cur_file]->d_name) == -1) {
360  throw OutOfMemoryException("FileLoader::read_file(): asprintf() failed (2)");
361  }
362  } else {
363  fn = strdup(filename);
364  }
365 
366  std::string ft = fv_filetype_file( fn );
367 
368  if ( ft == "FvRaw" ) {
369  FvRawReader *fvrr = new FvRawReader( fn );
370  cspace = fvrr->colorspace();
371  width = fvrr->pixel_width();
372  height = fvrr->pixel_height();
373  _buffer_size = colorspace_buffer_size( cspace, width, height );
374  file_buffer = (unsigned char*)malloc(_buffer_size);
375  fvrr->set_buffer( file_buffer );
376  try {
377  fvrr->read();
378  } catch (Exception &e) {
379  delete fvrr;
380  e.append("FileLoader::open() failed");
381  throw;
382  }
383  delete fvrr;
384 
385 #ifdef HAVE_LIBJPEG
386  } else if ( ft.find( "JPEG" ) != std::string::npos ) {
387  JpegReader *jr = new JpegReader( fn );
388  cspace = jr->colorspace();
389  width = jr->pixel_width();
390  height = jr->pixel_height();
391  _buffer_size = colorspace_buffer_size( cspace, width, height );
392  file_buffer = (unsigned char*)malloc(_buffer_size);
393  jr->set_buffer( file_buffer );
394  try {
395  jr->read();
396  } catch (Exception &e) {
397  delete jr;
398  e.append("FileLoader::open() failed");
399  throw;
400  }
401  delete jr;
402 #endif
403 
404 #ifdef HAVE_LIBPNG
405  } else if ( ft.find( "PNG" ) != std::string::npos ) {
406  PNGReader *pr = new PNGReader( fn ); cspace = pr->colorspace();
407  width = pr->pixel_width();
408  height = pr->pixel_height();
409  _buffer_size = colorspace_buffer_size( cspace, width, height );
410  file_buffer = (unsigned char*)malloc(_buffer_size);
411  pr->set_buffer( file_buffer );
412  try {
413  pr->read();
414  } catch (Exception &e) {
415  delete pr;
416  e.append("FileLoader::open() failed for PNG");
417  throw;
418  }
419  delete pr;
420 #endif
421 
422  } else if ( ft == "FvColormap" ) {
423  ColormapFile cmf;
424  cmf.read(fn);
425 
426  Colormap *colormap = cmf.get_colormap();
427  cspace = YUV422_PLANAR;
428  width = colormap->width() * 2;
429  height = colormap->height() * 2;
430  _buffer_size = colorspace_buffer_size( cspace, width, height );
431  file_buffer = (unsigned char*)malloc(_buffer_size);
432  colormap->to_image(file_buffer);
433 
434  delete colormap;
435 
436  } else {
437  _buffer_size = colorspace_buffer_size( cspace, width, height );
438 
439  if (_buffer_size > 0) {
440  FILE *f;
441  f = fopen( fn, "rb" );
442  file_buffer = (unsigned char*)malloc(_buffer_size);
443  if (fread(file_buffer, _buffer_size, 1, f) != 1) {
444  // cout << "FileLoader: Could not read data." << endl;
445  fclose(f);
446  throw Exception("Could not read data");
447  }
448  fclose(f);
449  } else {
450  throw Exception("Invalid color space (buffer size is 0)");
451  }
452  }
453 
454  free(fn);
455 }
456 
457 } // end namespace firevision
virtual unsigned int pixel_height()
Get height of read image in pixels.
Definition: png.cpp:207
virtual void to_image(unsigned char *yuv422_planar_buffer, unsigned int level=0)
Create image from LUT.
Definition: colormap.cpp:129
virtual void set_buffer(unsigned char *yuv422planar_buffer)
Set buffer that the read image should be written to.
Definition: fvraw.cpp:81
Fawkes library namespace.
virtual unsigned int pixel_width()
Get width of read image in pixels.
Definition: png.cpp:196
virtual void read()
Read data from file.
Definition: png.cpp:218
virtual void set_buffer(unsigned char *yuv422planar_buffer)
Set buffer that the read image should be written to.
Definition: png.cpp:182
virtual void read()
Read data from file.
Definition: fvraw.cpp:121
Camera argument parser.
Definition: camargp.h:38
Colormap interface.
Definition: colormap.h:38
virtual unsigned int height() const =0
Get height of colormap.
JPEG file reader.
Definition: jpeg.h:39
Colormap * get_colormap()
Get a freshly generated colormap based on current file content.
Definition: cmfile.cpp:169
virtual unsigned int pixel_width()
Get width of read image in pixels.
Definition: jpeg.cpp:96
PNG file reader.
Definition: png.h:36
virtual void read(const char *file_name)
Read file.
Definition: fvfile.cpp:308
Colormap file.
Definition: cmfile.h:55
bool has(std::string s) const
Check if an parameter was given.
Definition: camargp.cpp:152
Base class for exceptions in Fawkes.
Definition: exception.h:36
virtual unsigned int pixel_height()
Get height of read image in pixels.
Definition: jpeg.cpp:107
virtual unsigned int pixel_width()
Get width of read image in pixels.
Definition: fvraw.cpp:99
virtual unsigned int width() const =0
Get width of colormap.
virtual colorspace_t colorspace()
Get colorspace from the just read image.
Definition: fvraw.cpp:88
virtual colorspace_t colorspace()
Get colorspace from the just read image.
Definition: jpeg.cpp:89
virtual unsigned int pixel_height()
Get height of read image in pixels.
Definition: fvraw.cpp:110
long int get_int(std::string s) const
Get the value of the given parameter as integer.
Definition: camargp.cpp:184
virtual void set_buffer(unsigned char *yuv422planar_buffer)
Set buffer that the read image should be written to.
Definition: jpeg.cpp:82
std::string get(std::string s) const
Get the value of the given parameter.
Definition: camargp.cpp:164
FvRaw image reader implementation.
Definition: fvraw.h:37
virtual colorspace_t colorspace()
Get colorspace from the just read image.
Definition: png.cpp:189
Expected parameter is missing.
Definition: software.h:76
virtual void read()
Read data from file.
Definition: jpeg.cpp:118
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