fileloader.cpp

00001
00002 /***************************************************************************
00003  *  fileloader.cpp - A camera which obtains its images from a single image
00004  *                   file or from several image files in a directory
00005  *
00006  *  Generated: Tue Feb 22 13:28:08 2005
00007  *  Copyright  2005-2007  Tim Niemueller [www.niemueller.de]
00008  *             2008       Daniel Beck
00009  *
00010  ****************************************************************************/
00011
00012 /*  This program is free software; you can redistribute it and/or modify
00013  *  it under the terms of the GNU General Public License as published by
00014  *  the Free Software Foundation; either version 2 of the License, or
00015  *  (at your option) any later version. A runtime exception applies to
00016  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00017  *
00018  *  This program is distributed in the hope that it will be useful,
00019  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00020  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00021  *  GNU Library General Public License for more details.
00022  *
00023  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00024  */
00025
00026 #include <core/exception.h>
00027 #include <core/exceptions/software.h>
00028 #include <core/exceptions/system.h>
00029 #include <cams/fileloader.h>
00030 #include <fvutils/writers/fvraw.h>
00031 #include <fvutils/system/filetype.h>
00032 #include <fvutils/system/camargp.h>
00033 #include <fvutils/colormap/cmfile.h>
00034 #include <fvutils/colormap/colormap.h>
00035
00036 #include <fvutils/readers/fvraw.h>
00037 #ifdef HAVE_LIBJPEG
00038 #include <fvutils/readers/jpeg.h>
00039 #endif
00040 #ifdef HAVE_LIBPNG
00041 #include <fvutils/readers/png.h>
00042 #endif
00043 
00044 #include <cstring>
00045 #include <cstdlib>
00046 #include <cstdio>
00047
00048 #include <sys/types.h>
00049 #include <dirent.h>
00050
00051 using namespace fawkes;
00052 
00053 /** @class FileLoader <cams/fileloader.h>
00054  * Load images from files.
00055  * The file loader tries to determine the image format of the given image using
00056  * the the file type utility. Currently it recognizes JPEG and FvRaw image files.
00057  *
00058  * @author Tim Niemueller
00059  * @author Daniel Beck
00060  */
00061
00062 char* FileLoader::extension = NULL;
00063
00064 #if defined(__GLIBC__)
00065 int file_select(const struct dirent* ent)
00066 #else
00067 int file_select(struct dirent *ent)
00068 #endif
00069 {
00070   if ( !FileLoader::extension ) { return 1; }
00071
00072   // NOTE: this only checks whether the filename contains the
00073   // extension and not whether it ends with it.
00074   if ( NULL != strstr(ent->d_name, FileLoader::extension) ) {
00075     return 1;
00076   }
00077
00078   return 0;
00079 }
00080 
00081 /** Constructor.
00082  * @param filename name of file to open, full path or relative to working directory
00083  */
00084 FileLoader::FileLoader(const char *filename)
00085 {
00086   this->filename = strdup(filename);
00087   this->dirname = NULL;
00088   this->extension = NULL;
00089   this->file_list = NULL;
00090   num_files = 0;
00091   cur_file = 0;
00092   opened = started = false;
00093   width = height = 0;
00094   file_buffer = NULL;
00095   this->cspace = CS_UNKNOWN;
00096 }
00097
00098 
00099 /** Constructor.
00100  * Initialize with the parameters from the given camera argument parser. The following
00101  * parameters are supported:
00102  * - file=FILENAME: open the given file
00103  * - dir=DIRECTORY: sequentially open files in this directory
00104  * - ext=EXTENSION: only open files with this extension
00105  *
00106  * @param cap camera argument parser
00107  */
00108 FileLoader::FileLoader(const CameraArgumentParser *cap)
00109 {
00110   filename = NULL;
00111   dirname = NULL;
00112
00113   if ( cap->has("file") ) {
00114     this->filename = strdup(cap->get("file").c_str());
00115   } else if ( cap->has("dir") ) {
00116     this->dirname = strdup( cap->get("dir").c_str() );
00117     if ( cap->has("ext") ) {
00118       this->extension = strdup( cap->get("ext").c_str() );
00119     }
00120   } else {
00121     throw MissingParameterException("Neither parameter file nor parameter directory are present");
00122   }
00123
00124   file_list = NULL;
00125   num_files = 0;
00126   cur_file = 0;
00127   width = height = 0;
00128   file_buffer = NULL;
00129   this->cspace = CS_UNKNOWN;
00130   opened = started = false;
00131 }
00132
00133 
00134 /** Legacy constructor.
00135  * Before FvRaw FireVision had the ability to store the pure buffer of an image
00136  * without any header. Because of this additional information like colorspace,
00137  * width and height of the image had to be supplied. The number of bytes that
00138  * has to be read for the image is calculated from the given parameters.
00139  * @param cspace color space of image
00140  * @param filename filename to open
00141  * @param width width of image
00142  * @param height height of image
00143  */
00144 FileLoader::FileLoader(colorspace_t cspace, const char *filename,
00145                        unsigned int width, unsigned int height)
00146 {
00147   started = opened = false;
00148   this->cspace = cspace;
00149   this->width = width;
00150   this->height = height;
00151   this->filename = strdup(filename);
00152   this->dirname = NULL;
00153   this->extension = NULL;
00154   this->file_list = NULL;
00155   num_files = 0;
00156   cur_file = 0;
00157   file_buffer = NULL;
00158 }
00159
00160 
00161 /** Destructor. */
00162 FileLoader::~FileLoader()
00163 {
00164   for (int i = 0; i < num_files; ++i) {
00165     free(file_list[i]);
00166   }
00167   free(file_list);
00168   free(dirname);
00169   free(extension);
00170   free(filename);
00171 }
00172
00173
00174 void
00175 FileLoader::open()
00176 {
00177   if (opened) return;
00178
00179   if (dirname) {
00180     num_files = scandir(dirname, &file_list, file_select, alphasort);
00181
00182     if ( -1 == num_files ) {
00183       throw Exception("Error while scanning directory %s", dirname);
00184     }
00185   }
00186
00187   read_file();
00188   opened = true;
00189 }
00190
00191
00192 void
00193 FileLoader::start()
00194 {
00195   if (started) return;
00196
00197   if (!opened) {
00198     throw Exception("Trying to start closed file");
00199   }
00200
00201   started = true;
00202 }
00203
00204 void
00205 FileLoader::stop()
00206 {
00207   started = false;
00208 }
00209
00210
00211 void
00212 FileLoader::print_info()
00213 {
00214 }
00215
00216
00217 void
00218 FileLoader::capture()
00219 {
00220   if (0 != num_files) {
00221     if (file_buffer) {
00222       free(file_buffer);
00223     }
00224
00225     read_file();
00226
00227     if (++cur_file == num_files) {
00228       cur_file = 0;
00229     }
00230   }
00231 }
00232
00233
00234 unsigned char*
00235 FileLoader::buffer()
00236 {
00237   return file_buffer;
00238 }
00239
00240
00241 unsigned int
00242 FileLoader::buffer_size()
00243 {
00244   return _buffer_size;
00245 }
00246
00247
00248 void
00249 FileLoader::close()
00250 {
00251   if (file_buffer != NULL) {
00252     free(file_buffer);
00253     file_buffer = NULL;
00254   }
00255   opened = false;
00256 }
00257
00258
00259 void
00260 FileLoader::dispose_buffer()
00261 {
00262 }
00263
00264
00265 void
00266 FileLoader::flush()
00267 {
00268 }
00269
00270
00271 bool
00272 FileLoader::ready()
00273 {
00274   return started;
00275 }
00276
00277
00278 void
00279 FileLoader::set_image_number(unsigned int n)
00280 {
00281 }
00282
00283
00284 unsigned int
00285 FileLoader::pixel_width()
00286 {
00287   return width;
00288 }
00289
00290
00291 unsigned int
00292 FileLoader::pixel_height()
00293 {
00294   return height;
00295 }
00296
00297
00298 colorspace_t
00299 FileLoader::colorspace()
00300 {
00301   return cspace;
00302 }
00303
00304 
00305 /** Set the colorspace of the image.
00306  * @param c colorspace
00307  */
00308 void
00309 FileLoader::set_colorspace(colorspace_t c)
00310 {
00311   cspace = c;
00312 }
00313
00314 
00315 /** Set width.
00316  * @param w image width in pixels
00317  */
00318 void
00319 FileLoader::set_pixel_width(unsigned int w)
00320 {
00321   width = w;
00322 }
00323
00324 
00325 /** Set height.
00326  * @param h image height in pixels
00327  */
00328 void
00329 FileLoader::set_pixel_height(unsigned int h)
00330 {
00331   height = h;
00332 }
00333
00334 void
00335 FileLoader::read_file()
00336 {
00337   char* fn;
00338   if (0 != num_files) {
00339     if (asprintf(&fn, "%s/%s", dirname, file_list[cur_file]->d_name) == -1) {
00340       throw OutOfMemoryException("FileLoader::read_file(): asprintf() failed (2)");
00341     }
00342   } else {
00343     fn = strdup(filename);
00344   }
00345
00346   std::string ft = fv_filetype_file( fn );
00347
00348   if ( ft == "FvRaw" ) {
00349     FvRawReader *fvrr = new FvRawReader( fn );
00350     cspace = fvrr->colorspace();
00351     width  = fvrr->pixel_width();
00352     height = fvrr->pixel_height();
00353     _buffer_size = colorspace_buffer_size( cspace, width, height );
00354     file_buffer = (unsigned char*)malloc(_buffer_size);
00355     fvrr->set_buffer( file_buffer );
00356     try {
00357       fvrr->read();
00358     } catch (Exception &e) {
00359       delete fvrr;
00360       e.append("FileLoader::open() failed");
00361       throw;
00362     }
00363     delete fvrr;
00364
00365 #ifdef HAVE_LIBJPEG
00366   } else if ( ft.find( "JPEG" ) != std::string::npos ) {
00367     JpegReader *jr = new JpegReader( fn );
00368     cspace = jr->colorspace();
00369     width  = jr->pixel_width();
00370     height = jr->pixel_height();
00371     _buffer_size = colorspace_buffer_size( cspace, width, height );
00372     file_buffer = (unsigned char*)malloc(_buffer_size);
00373     jr->set_buffer( file_buffer );
00374     try {
00375       jr->read();
00376     } catch (Exception &e) {
00377       delete jr;
00378       e.append("FileLoader::open() failed");
00379       throw;
00380     }
00381     delete jr;
00382 #endif
00383 
00384 #ifdef HAVE_LIBPNG
00385   } else if ( ft.find( "PNG" ) != std::string::npos ) {
00386     PNGReader *pr = new PNGReader( fn );    cspace = pr->colorspace();
00387     width  = pr->pixel_width();
00388     height = pr->pixel_height();
00389     _buffer_size = colorspace_buffer_size( cspace, width, height );
00390     file_buffer = (unsigned char*)malloc(_buffer_size);
00391     pr->set_buffer( file_buffer );
00392     try {
00393       pr->read();
00394     } catch (Exception &e) {
00395       delete pr;
00396       e.append("FileLoader::open() failed for PNG");
00397       throw;
00398     }
00399     delete pr;
00400 #endif
00401 
00402   } else if ( ft == "FvColormap" ) {
00403     ColormapFile cmf;
00404     cmf.read(fn);
00405
00406     Colormap *colormap = cmf.get_colormap();
00407     cspace = YUV422_PLANAR;
00408     width  = colormap->width() * 2;
00409     height = colormap->height() * 2;
00410     _buffer_size = colorspace_buffer_size( cspace, width, height );
00411     file_buffer = (unsigned char*)malloc(_buffer_size);
00412     colormap->to_image(file_buffer);
00413
00414     delete colormap;
00415
00416   } else {
00417     _buffer_size = colorspace_buffer_size( cspace, width, height );
00418
00419     if (_buffer_size > 0) {
00420       FILE *f;
00421       f = fopen( fn, "rb" );
00422       file_buffer = (unsigned char*)malloc(_buffer_size);
00423       if (fread(file_buffer, _buffer_size, 1, f) != 1) {
00424         // cout << "FileLoader: Could not read data." << endl;
00425         fclose(f);
00426         throw Exception("Could not read data");
00427       }
00428       fclose(f);
00429     } else {
00430       throw Exception("Invalid color space (buffer size is 0)");
00431     }
00432   }
00433
00434   free(fn);
00435 }
00436