Fawkes API Fawkes Development Version
|
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