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 
00050 using namespace fawkes;
00051 
00052 namespace firevision {
00053 #if 0 /* just to make Emacs auto-indent happy */
00054 }
00055 #endif
00056 
00057 /** @class FileLoader <cams/fileloader.h>
00058  * Load images from files.
00059  * The file loader tries to determine the image format of the given image using
00060  * the the file type utility. Currently it recognizes JPEG and FvRaw image files.
00061  *
00062  * @author Tim Niemueller
00063  * @author Daniel Beck
00064  */
00065 
00066 char* FileLoader::extension = NULL;
00067 
00068 #if defined(__GLIBC__) || defined(__FreeBSD__)
00069 int file_select(const struct dirent* ent)
00070 #else
00071 int file_select(struct dirent *ent)
00072 #endif
00073 {
00074   if ( !FileLoader::extension ) { return 1; }
00075 
00076   // NOTE: this only checks whether the filename contains the
00077   // extension and not whether it ends with it.
00078   if ( NULL != strstr(ent->d_name, FileLoader::extension) ) {
00079     return 1; 
00080   }
00081 
00082   return 0;
00083 }
00084 
00085 /** Constructor.
00086  * @param filename name of file to open, full path or relative to working directory
00087  */
00088 FileLoader::FileLoader(const char *filename)
00089 {
00090   this->filename = strdup(filename);
00091   this->dirname = NULL;
00092   this->extension = NULL;
00093   this->file_list = NULL;
00094   num_files = 0;
00095   cur_file = 0;
00096   opened = started = false;
00097   width = height = 0;
00098   file_buffer = NULL;
00099   this->cspace = CS_UNKNOWN;
00100 }
00101 
00102 
00103 /** Constructor.
00104  * Initialize with the parameters from the given camera argument parser. The following
00105  * parameters are supported:
00106  * - file=FILENAME: open the given file
00107  * - dir=DIRECTORY: sequentially open files in this directory
00108  * - ext=EXTENSION: only open files with this extension
00109  *
00110  * @param cap camera argument parser
00111  */
00112 FileLoader::FileLoader(const CameraArgumentParser *cap)
00113 {
00114   filename = NULL;
00115   dirname = NULL;
00116 
00117   if ( cap->has("file") ) {
00118     this->filename = strdup(cap->get("file").c_str());
00119   } else if ( cap->has("dir") ) {
00120     this->dirname = strdup( cap->get("dir").c_str() );
00121     if ( cap->has("ext") ) {
00122       this->extension = strdup( cap->get("ext").c_str() );
00123     }
00124   } else {
00125     throw MissingParameterException("Neither parameter file nor parameter directory are present");
00126   }
00127 
00128   file_list = NULL;
00129   num_files = 0;
00130   cur_file = 0;
00131   width = height = 0;
00132   file_buffer = NULL;
00133   this->cspace = CS_UNKNOWN;
00134   opened = started = false;
00135 }
00136 
00137 
00138 /** Legacy constructor.
00139  * Before FvRaw FireVision had the ability to store the pure buffer of an image
00140  * without any header. Because of this additional information like colorspace,
00141  * width and height of the image had to be supplied. The number of bytes that
00142  * has to be read for the image is calculated from the given parameters.
00143  * @param cspace color space of image
00144  * @param filename filename to open
00145  * @param width width of image
00146  * @param height height of image
00147  */
00148 FileLoader::FileLoader(colorspace_t cspace, const char *filename,
00149                        unsigned int width, unsigned int height)
00150 {
00151   started = opened = false;
00152   this->cspace = cspace;
00153   this->width = width;
00154   this->height = height;
00155   this->filename = strdup(filename);
00156   this->dirname = NULL;
00157   this->extension = NULL;
00158   this->file_list = NULL;
00159   num_files = 0;
00160   cur_file = 0;
00161   file_buffer = NULL;
00162 }
00163 
00164 
00165 /** Destructor. */
00166 FileLoader::~FileLoader()
00167 {
00168   for (int i = 0; i < num_files; ++i) {
00169     free(file_list[i]);
00170   }
00171   free(file_list);
00172   free(dirname);
00173   free(extension);
00174   free(filename);
00175 }
00176 
00177 
00178 void
00179 FileLoader::open()
00180 {
00181   if (opened) return;
00182 
00183   if (dirname) {
00184     num_files = scandir(dirname, &file_list, file_select, alphasort);
00185     
00186     if ( -1 == num_files ) {
00187       throw Exception("Error while scanning directory %s", dirname);
00188     }
00189   }
00190 
00191   read_file();
00192   opened = true;
00193 }
00194 
00195 
00196 void
00197 FileLoader::start()
00198 {
00199   if (started) return;
00200 
00201   if (!opened) {
00202     throw Exception("Trying to start closed file");
00203   }
00204 
00205   started = true;
00206 }
00207 
00208 void
00209 FileLoader::stop()
00210 {
00211   started = false;
00212 }
00213 
00214 
00215 void
00216 FileLoader::print_info()
00217 {
00218 }
00219 
00220 
00221 void
00222 FileLoader::capture()
00223 {
00224   if (0 != num_files) {
00225     if (file_buffer) {
00226       free(file_buffer);
00227     }
00228 
00229     read_file();
00230 
00231     if (++cur_file == num_files) {
00232       cur_file = 0;
00233     }
00234   }
00235 }
00236 
00237 
00238 unsigned char*
00239 FileLoader::buffer()
00240 {
00241   return file_buffer;
00242 }
00243 
00244 
00245 unsigned int
00246 FileLoader::buffer_size()
00247 {
00248   return _buffer_size;
00249 }
00250 
00251 
00252 void
00253 FileLoader::close()
00254 {
00255   if (file_buffer != NULL) {
00256     free(file_buffer);
00257     file_buffer = NULL;
00258   }
00259   opened = false;
00260 }
00261 
00262 
00263 void
00264 FileLoader::dispose_buffer()
00265 {
00266 }
00267 
00268 
00269 void
00270 FileLoader::flush()
00271 {
00272 }
00273 
00274 
00275 bool
00276 FileLoader::ready()
00277 {
00278   return started;
00279 }
00280 
00281 
00282 void
00283 FileLoader::set_image_number(unsigned int n)
00284 {
00285 }
00286 
00287 
00288 unsigned int
00289 FileLoader::pixel_width()
00290 {
00291   return width;
00292 }
00293 
00294 
00295 unsigned int
00296 FileLoader::pixel_height()
00297 {
00298   return height;
00299 }
00300 
00301 
00302 colorspace_t
00303 FileLoader::colorspace()
00304 {
00305   return cspace;
00306 }
00307 
00308 
00309 /** Set the colorspace of the image.
00310  * @param c colorspace
00311  */
00312 void
00313 FileLoader::set_colorspace(colorspace_t c)
00314 {
00315   cspace = c;
00316 }
00317 
00318 
00319 /** Set width.
00320  * @param w image width in pixels
00321  */
00322 void
00323 FileLoader::set_pixel_width(unsigned int w)
00324 {
00325   width = w;
00326 }
00327 
00328 
00329 /** Set height.
00330  * @param h image height in pixels
00331  */
00332 void
00333 FileLoader::set_pixel_height(unsigned int h)
00334 {
00335   height = h;
00336 }
00337 
00338 void
00339 FileLoader::read_file()
00340 {
00341   char* fn;
00342   if (0 != num_files) {
00343     if (asprintf(&fn, "%s/%s", dirname, file_list[cur_file]->d_name) == -1) {
00344       throw OutOfMemoryException("FileLoader::read_file(): asprintf() failed (2)");
00345     }
00346   } else {
00347     fn = strdup(filename);
00348   }
00349 
00350   std::string ft = fv_filetype_file( fn );
00351 
00352   if ( ft == "FvRaw" ) {
00353     FvRawReader *fvrr = new FvRawReader( fn );
00354     cspace = fvrr->colorspace();
00355     width  = fvrr->pixel_width();
00356     height = fvrr->pixel_height();
00357     _buffer_size = colorspace_buffer_size( cspace, width, height );
00358     file_buffer = (unsigned char*)malloc(_buffer_size);
00359     fvrr->set_buffer( file_buffer );
00360     try {
00361       fvrr->read();
00362     } catch (Exception &e) {
00363       delete fvrr;
00364       e.append("FileLoader::open() failed");
00365       throw;
00366     }
00367     delete fvrr;
00368 
00369 #ifdef HAVE_LIBJPEG
00370   } else if ( ft.find( "JPEG" ) != std::string::npos ) {
00371     JpegReader *jr = new JpegReader( fn );
00372     cspace = jr->colorspace();
00373     width  = jr->pixel_width();
00374     height = jr->pixel_height();
00375     _buffer_size = colorspace_buffer_size( cspace, width, height );
00376     file_buffer = (unsigned char*)malloc(_buffer_size);
00377     jr->set_buffer( file_buffer );
00378     try {
00379       jr->read();
00380     } catch (Exception &e) {
00381       delete jr;
00382       e.append("FileLoader::open() failed");
00383       throw;
00384     }
00385     delete jr;
00386 #endif
00387 
00388 #ifdef HAVE_LIBPNG
00389   } else if ( ft.find( "PNG" ) != std::string::npos ) {
00390     PNGReader *pr = new PNGReader( fn );    cspace = pr->colorspace();
00391     width  = pr->pixel_width();
00392     height = pr->pixel_height();
00393     _buffer_size = colorspace_buffer_size( cspace, width, height );
00394     file_buffer = (unsigned char*)malloc(_buffer_size);
00395     pr->set_buffer( file_buffer );
00396     try {
00397       pr->read();
00398     } catch (Exception &e) {
00399       delete pr;
00400       e.append("FileLoader::open() failed for PNG");
00401       throw;
00402     }
00403     delete pr;
00404 #endif
00405 
00406   } else if ( ft == "FvColormap" ) {
00407     ColormapFile cmf;
00408     cmf.read(fn);
00409 
00410     Colormap *colormap = cmf.get_colormap();
00411     cspace = YUV422_PLANAR;
00412     width  = colormap->width() * 2;
00413     height = colormap->height() * 2;
00414     _buffer_size = colorspace_buffer_size( cspace, width, height );
00415     file_buffer = (unsigned char*)malloc(_buffer_size);
00416     colormap->to_image(file_buffer);
00417 
00418     delete colormap;
00419 
00420   } else {
00421     _buffer_size = colorspace_buffer_size( cspace, width, height );
00422 
00423     if (_buffer_size > 0) {
00424       FILE *f;
00425       f = fopen( fn, "rb" );
00426       file_buffer = (unsigned char*)malloc(_buffer_size);
00427       if (fread(file_buffer, _buffer_size, 1, f) != 1) {
00428         // cout << "FileLoader: Could not read data." << endl;
00429         fclose(f);
00430         throw Exception("Could not read data");
00431       }
00432       fclose(f);
00433     } else {
00434       throw Exception("Invalid color space (buffer size is 0)");
00435     }
00436   }
00437 
00438   free(fn);
00439 }
00440 
00441 } // end namespace firevision