cmfile.cpp

00001 
00002 /**************************************************************************
00003  *  cmfile.cpp - FVFF Colormap File Format
00004  *
00005  *  Created: Mon Mar 31 14:11:01 2008
00006  *  Copyright  2005-2008  Tim Niemueller  [www.niemueller.de]
00007  *
00008  ***************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <fvutils/colormap/cmfile.h>
00025 
00026 #include <fvutils/colormap/colormap.h>
00027 #include <fvutils/colormap/cmfile_yuvblock.h>
00028 
00029 #include <fvutils/colormap/yuvcm.h>
00030 #include <core/exception.h>
00031 
00032 #include <sys/utsname.h>
00033 
00034 #include <cstdio>
00035 
00036 namespace firevision {
00037 #if 0 /* just to make Emacs auto-indent happy */
00038 }
00039 #endif
00040 
00041 /** @class ColormapFile::ColormapBlockVector <fvutils/colormap/cmfile.h>
00042  * Vector of colormap blocks.
00043  * @author Tim Niemueller
00044  */
00045 
00046 /** Destructor.
00047  * Deletes all hold colormap blocks.
00048  */
00049 ColormapFile::ColormapBlockVector::~ColormapBlockVector()
00050 {
00051   for (iterator i = begin(); i != end(); ++i) {
00052     delete *i;
00053   }
00054 }
00055 
00056 
00057 /** @class ColormapFile <fvutils/colormap/cmfile.h>
00058  * Colormap file.
00059  * This class implements a FireVision data file format for colormaps.
00060  * @author Tim Niemueller
00061  */
00062 
00063 /** Constructor.
00064  * Creates a plain empty colormap file with given dimensions.
00065  * @param depth depth of colormap
00066  * @param width width of colormap
00067  * @param height height of colormap
00068  */
00069 ColormapFile::ColormapFile(uint16_t depth, uint16_t width, uint16_t height)
00070   : FireVisionDataFile(CMFILE_MAGIC_TOKEN, CMFILE_CUR_VERSION)
00071 {
00072   _spec_header      = calloc(1, sizeof(cmfile_header_t));
00073   _spec_header_size = sizeof(cmfile_header_t);
00074   __header = (cmfile_header_t *)_spec_header;
00075   __header->depth  = depth;
00076   __header->width  = width;
00077   __header->height = height;
00078 }
00079 
00080 /** Constructor.
00081  * Creates a plain empty colormap file.
00082  */
00083 ColormapFile::ColormapFile()
00084   : FireVisionDataFile(CMFILE_MAGIC_TOKEN, CMFILE_CUR_VERSION)
00085 {
00086   __header = NULL;
00087 }
00088 
00089 
00090 /** Add colormap.
00091  * This will add the given colormap to this file. It will query the colormap for
00092  * a number of blocks that shall be added to the file.
00093  * Note that for now only a single colormap per file is supported, though not
00094  * enforced.
00095  * @param colormap colormap to add
00096  */
00097 void
00098 ColormapFile::add_colormap(Colormap *colormap)
00099 {
00100   if (! __header) {
00101     if ( _spec_header) {
00102       __header = (cmfile_header_t *)_spec_header;
00103     } else {
00104       _spec_header      = calloc(1, sizeof(cmfile_header_t));
00105       _spec_header_size = sizeof(cmfile_header_t);
00106       __header = (cmfile_header_t *)_spec_header;
00107       __header->depth  = colormap->depth();
00108       __header->width  = colormap->width();
00109       __header->height = colormap->height();
00110     }
00111   }
00112 
00113   if ( (colormap->depth()  != __header->depth) ||
00114        (colormap->width()  != __header->width) ||
00115        (colormap->height() != __header->height) ) {
00116     throw fawkes::Exception("Colormap dimensions %dx%dx%d do not match expected dimensions %dx%dx%d",
00117                             colormap->depth(), colormap->width(), colormap->height(),
00118                             __header->depth, __header->width, __header->height);
00119   }
00120 
00121   printf("Adding colormap with dimensions %dx%dx%d\n", colormap->width(), colormap->height(), colormap->depth());
00122 
00123   std::list<ColormapFileBlock *> blocks = colormap->get_blocks();
00124   for (std::list<ColormapFileBlock *>::iterator i = blocks.begin(); i != blocks.end(); ++i) {
00125     add_block(*i);
00126   }
00127 }
00128 
00129 
00130 /** Get colormap blocks.
00131  * @return vector of colormap blocks
00132  */
00133 ColormapFile::ColormapBlockVector *
00134 ColormapFile::colormap_blocks()
00135 {
00136   FireVisionDataFile::BlockList &b = blocks();
00137   ColormapBlockVector *rv = new ColormapBlockVector();
00138   for (std::list<FireVisionDataFileBlock *>::iterator i = b.begin(); i != b.end(); ++i) {
00139     if ((*i)->type() == CMFILE_TYPE_YUV ) {
00140       ColormapFileYuvBlock *yuvb = new ColormapFileYuvBlock(*i);
00141       rv->push_back(yuvb);
00142     }
00143   }
00144 
00145   return rv;
00146 }
00147 
00148 
00149 void
00150 ColormapFile::assert_header()
00151 {
00152   if ( ! __header ) {
00153     if (! _spec_header) {
00154       throw fawkes::Exception("Cannot get header information, invalid ctor used or file not read?");
00155     }
00156     __header = (cmfile_header_t *)_spec_header;
00157   }
00158 
00159 }
00160 
00161 /** Get a freshly generated colormap based on current file content.
00162  * This returns an instance of a colormap that uses all current blocks of this instance.
00163  * Currently it only supports file which contain a valid YuvColormap. This means that it
00164  * has d blocks of YUV type. d is the depth and must fulfill d=2^n with n from [1,8].
00165  * It can throw any exception that the YuvColormap ctor can throw.
00166  * @return instance of colormap. You must delete it after you are done with it.
00167  */
00168 Colormap *
00169 ColormapFile::get_colormap()
00170 {
00171   // Make sure we only have YUV blocks
00172   BlockList &bl = blocks();
00173   YuvColormap *cm = NULL;
00174 
00175   for (BlockList::iterator b = bl.begin(); b != bl.end(); ++b) {
00176     if ( (*b)->type() != CMFILE_TYPE_YUV ) {
00177       throw fawkes::Exception("Colormap file contains block of unknown type");
00178     }
00179   }
00180 
00181   assert_header();
00182 
00183   // create colormap, throws an exception is depth/num_blocks is invalid
00184   printf("File header dimensions: %dx%dx%d\n", __header->depth, __header->width, __header->height);
00185   cm = new YuvColormap(__header->depth, __header->width, __header->height);
00186 
00187   unsigned int level = 0;
00188   for (BlockList::iterator b = bl.begin(); b != bl.end(); ++b) {
00189     if ( (*b)->data_size() != cm->plane_size() ) {
00190       // invalid size, for a YUV colormap we must have this for one plane!
00191       delete cm;
00192       throw fawkes::Exception("Invalid data size for a YUV block");
00193     }
00194 
00195     cm->copy_uvplane((unsigned char *)(*b)->data_ptr(), level++);
00196   }
00197 
00198   return cm;
00199 }
00200 
00201 
00202 /** Check if given file is a colormap file.
00203  * @param filename name of file to check
00204  * @return true if file is a colormap file, false otherwise
00205  */
00206 bool
00207 ColormapFile::is_colormap_file(const char *filename)
00208 {
00209   return FireVisionDataFile::has_magic_token(filename, CMFILE_MAGIC_TOKEN);
00210 }
00211 
00212 
00213 /** Compose filename.
00214  * In the format %g is replaced with the hostname.
00215  * @param format format for the filename
00216  * @return filename
00217  */
00218 std::string
00219 ColormapFile::compose_filename(const std::string format)
00220 {
00221   std::string rv = format;
00222 
00223   struct utsname uname_info;
00224   uname( &uname_info );
00225 
00226   size_t loc = rv.find( "%h" );
00227   while (loc != std::string::npos) {
00228     rv.replace( loc, 2, uname_info.nodename );
00229     loc = rv.find( "%h" );
00230   }
00231 
00232   return rv;
00233 }
00234 
00235 
00236 void
00237 ColormapFile::clear()
00238 {
00239   FireVisionDataFile::clear();
00240   __header = NULL;
00241 }
00242 
00243 
00244 /** Get depth of colormap.
00245  * @return depth
00246  */
00247 uint16_t
00248 ColormapFile::get_depth()
00249 {
00250   assert_header();
00251   return __header->depth;
00252 }
00253 
00254 /** Get width of colormap.
00255  * @return width
00256  */
00257 uint16_t
00258 ColormapFile::get_width()
00259 {
00260   assert_header();
00261   return __header->width;
00262 }
00263 
00264 /** Get height of colormap.
00265  * @return height
00266  */
00267 uint16_t
00268 ColormapFile::get_height()
00269 {
00270   assert_header();
00271   return __header->height;
00272 }
00273 
00274 } // end namespace firevision

Generated on 1 Mar 2011 for Fawkes API by  doxygen 1.6.1