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/colormap/cmfile.h>
31 #include <fvutils/colormap/colormap.h>
32 #include <fvutils/readers/fvraw.h>
33 #include <fvutils/system/camargp.h>
34 #include <fvutils/system/filetype.h>
35 #include <fvutils/writers/fvraw.h>
36 #ifdef HAVE_LIBJPEG
37 # include <fvutils/readers/jpeg.h>
38 #endif
39 #ifdef HAVE_LIBPNG
40 # include <fvutils/readers/png.h>
41 #endif
42 
43 #include <sys/types.h>
44 
45 #include <cstdio>
46 #include <cstdlib>
47 #include <cstring>
48 
49 using namespace fawkes;
50 
51 namespace firevision {
52 
53 /** @class FileLoader <fvcams/fileloader.h>
54  * Load images from files.
55  * The file loader tries to determine the image format of the given image using
56  * the the file type utility. Currently it recognizes JPEG and FvRaw image files.
57  *
58  * @author Tim Niemueller
59  * @author Daniel Beck
60  */
61 
62 char *FileLoader::extension = NULL;
63 
64 #if defined(__GLIBC__) || defined(__FreeBSD__)
65 int
66 file_select(const struct dirent *ent)
67 #else
68 int
69 file_select(struct dirent *ent)
70 #endif
71 {
72  if (!FileLoader::extension) {
73  return 1;
74  }
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 /** Constructor.
103  * Initialize with the parameters from the given camera argument parser. The following
104  * parameters are supported:
105  * - file=FILENAME: open the given file
106  * - dir=DIRECTORY: sequentially open files in this directory
107  * - ext=EXTENSION: only open files with this extension
108  * - width=W: width in pixels of image
109  * - height=H: height in pixels of image
110  * - colorspace=C: colorspace of image
111  *
112  * Width, height, and colorspace are used for raw images without an header, e.g if
113  * captured by v4l2-ctl.
114  *
115  * @param cap camera argument parser
116  */
117 FileLoader::FileLoader(const CameraArgumentParser *cap)
118 {
119  filename = NULL;
120  dirname = NULL;
121 
122  file_list = NULL;
123  num_files = 0;
124  cur_file = 0;
125  width = height = 0;
126  file_buffer = NULL;
127  this->cspace = CS_UNKNOWN;
128  opened = started = false;
129 
130  if (cap->has("file")) {
131  this->filename = strdup(cap->get("file").c_str());
132  if (cap->has("width")) {
133  width = cap->get_int("width");
134  }
135  if (cap->has("height")) {
136  height = cap->get_int("height");
137  }
138  if (cap->has("colorspace")) {
139  cspace = colorspace_by_name(cap->get("colorspace").c_str());
140  }
141  } else if (cap->has("dir")) {
142  this->dirname = strdup(cap->get("dir").c_str());
143  if (cap->has("ext")) {
144  this->extension = strdup(cap->get("ext").c_str());
145  }
146  } else {
147  throw MissingParameterException("Neither parameter file nor parameter directory are present");
148  }
149 }
150 
151 /** Legacy constructor.
152  * Before FvRaw FireVision had the ability to store the pure buffer of an image
153  * without any header. Because of this additional information like colorspace,
154  * width and height of the image had to be supplied. The number of bytes that
155  * has to be read for the image is calculated from the given parameters.
156  * @param cspace color space of image
157  * @param filename filename to open
158  * @param width width of image
159  * @param height height of image
160  */
161 FileLoader::FileLoader(colorspace_t cspace,
162  const char * filename,
163  unsigned int width,
164  unsigned int height)
165 {
166  started = opened = false;
167  this->cspace = cspace;
168  this->width = width;
169  this->height = height;
170  this->filename = strdup(filename);
171  this->dirname = NULL;
172  this->extension = NULL;
173  this->file_list = NULL;
174  num_files = 0;
175  cur_file = 0;
176  file_buffer = NULL;
177 }
178 
179 /** Destructor. */
180 FileLoader::~FileLoader()
181 {
182  for (int i = 0; i < num_files; ++i) {
183  free(file_list[i]);
184  }
185  free(file_list);
186  free(dirname);
187  free(extension);
188  free(filename);
189 }
190 
191 void
192 FileLoader::open()
193 {
194  if (opened)
195  return;
196 
197  if (dirname) {
198  num_files = scandir(dirname, &file_list, file_select, alphasort);
199 
200  if (-1 == num_files) {
201  throw Exception("Error while scanning directory %s", dirname);
202  }
203  }
204 
205  read_file();
206  opened = true;
207 }
208 
209 void
210 FileLoader::start()
211 {
212  if (started)
213  return;
214 
215  if (!opened) {
216  throw Exception("Trying to start closed file");
217  }
218 
219  started = true;
220 }
221 
222 void
223 FileLoader::stop()
224 {
225  started = false;
226 }
227 
228 void
229 FileLoader::print_info()
230 {
231 }
232 
233 void
234 FileLoader::capture()
235 {
236  if (0 != num_files) {
237  if (file_buffer) {
238  free(file_buffer);
239  }
240 
241  read_file();
242 
243  if (++cur_file == num_files) {
244  cur_file = 0;
245  }
246  }
247 }
248 
249 unsigned char *
250 FileLoader::buffer()
251 {
252  return file_buffer;
253 }
254 
255 unsigned int
256 FileLoader::buffer_size()
257 {
258  return _buffer_size;
259 }
260 
261 void
262 FileLoader::close()
263 {
264  if (file_buffer != NULL) {
265  free(file_buffer);
266  file_buffer = NULL;
267  }
268  opened = false;
269 }
270 
271 void
272 FileLoader::dispose_buffer()
273 {
274 }
275 
276 void
277 FileLoader::flush()
278 {
279 }
280 
281 bool
282 FileLoader::ready()
283 {
284  return started;
285 }
286 
287 void
288 FileLoader::set_image_number(unsigned int n)
289 {
290 }
291 
292 unsigned int
293 FileLoader::pixel_width()
294 {
295  return width;
296 }
297 
298 unsigned int
299 FileLoader::pixel_height()
300 {
301  return height;
302 }
303 
304 colorspace_t
305 FileLoader::colorspace()
306 {
307  return cspace;
308 }
309 
310 /** Set the colorspace of the image.
311  * @param c colorspace
312  */
313 void
314 FileLoader::set_colorspace(colorspace_t c)
315 {
316  cspace = c;
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 /** Set height.
329  * @param h image height in pixels
330  */
331 void
332 FileLoader::set_pixel_height(unsigned int h)
333 {
334  height = h;
335 }
336 
337 void
338 FileLoader::read_file()
339 {
340  char *fn;
341  if (0 != num_files) {
342  if (asprintf(&fn, "%s/%s", dirname, file_list[cur_file]->d_name) == -1) {
343  throw OutOfMemoryException("FileLoader::read_file(): asprintf() failed (2)");
344  }
345  } else {
346  fn = strdup(filename);
347  }
348 
349  std::string ft = fv_filetype_file(fn);
350 
351  if (ft == "FvRaw") {
352  FvRawReader *fvrr = new FvRawReader(fn);
353  cspace = fvrr->colorspace();
354  width = fvrr->pixel_width();
355  height = fvrr->pixel_height();
356  _buffer_size = colorspace_buffer_size(cspace, width, height);
357  file_buffer = (unsigned char *)malloc(_buffer_size);
358  fvrr->set_buffer(file_buffer);
359  try {
360  fvrr->read();
361  } catch (Exception &e) {
362  delete fvrr;
363  e.append("FileLoader::open() failed");
364  throw;
365  }
366  delete fvrr;
367 
368 #ifdef HAVE_LIBJPEG
369  } else if (ft.find("JPEG") != std::string::npos) {
370  JpegReader *jr = new JpegReader(fn);
371  cspace = jr->colorspace();
372  width = jr->pixel_width();
373  height = jr->pixel_height();
374  _buffer_size = colorspace_buffer_size(cspace, width, height);
375  file_buffer = (unsigned char *)malloc(_buffer_size);
376  jr->set_buffer(file_buffer);
377  try {
378  jr->read();
379  } catch (Exception &e) {
380  delete jr;
381  e.append("FileLoader::open() failed");
382  throw;
383  }
384  delete jr;
385 #endif
386 
387 #ifdef HAVE_LIBPNG
388  } else if (ft.find("PNG") != std::string::npos) {
389  PNGReader *pr = new PNGReader(fn);
390  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
fawkes::Exception::append
void append(const char *format,...)
Append messages to the message list.
Definition: exception.cpp:333
fawkes
Fawkes library namespace.
firevision::CameraArgumentParser::has
bool has(std::string s) const
Check if an parameter was given.
Definition: camargp.cpp:145
fawkes::MissingParameterException
Expected parameter is missing.
Definition: software.h:74
firevision::CameraArgumentParser
Camera argument parser.
Definition: camargp.h:36
firevision::CameraArgumentParser::get_int
long int get_int(std::string s) const
Get the value of the given parameter as integer.
Definition: camargp.cpp:175
firevision::CameraArgumentParser::get
std::string get(std::string s) const
Get the value of the given parameter.
Definition: camargp.cpp:156
fawkes::OutOfMemoryException
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
fawkes::Exception
Base class for exceptions in Fawkes.
Definition: exception.h:36