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 /** @class ColormapFile::ColormapBlockVector <fvutils/colormap/cmfile.h>
00037  * Vector of colormap blocks.
00038  * @author Tim Niemueller
00039  */
00040 
00041 /** Destructor.
00042  * Deletes all hold colormap blocks.
00043  */
00044 ColormapFile::ColormapBlockVector::~ColormapBlockVector()
00045 {
00046   for (iterator i = begin(); i != end(); ++i) {
00047     delete *i;
00048   }
00049 }
00050
00051 
00052 /** @class ColormapFile <fvutils/colormap/cmfile.h>
00053  * Colormap file.
00054  * This class implements a FireVision data file format for colormaps.
00055  * @author Tim Niemueller
00056  */
00057 
00058 /** Constructor.
00059  * Creates a plain empty colormap file with given dimensions.
00060  * @param depth depth of colormap
00061  * @param width width of colormap
00062  * @param height height of colormap
00063  */
00064 ColormapFile::ColormapFile(uint16_t depth, uint16_t width, uint16_t height)
00065   : FireVisionDataFile(CMFILE_MAGIC_TOKEN, CMFILE_CUR_VERSION)
00066 {
00067   _spec_header      = calloc(1, sizeof(cmfile_header_t));
00068   _spec_header_size = sizeof(cmfile_header_t);
00069   __header = (cmfile_header_t *)_spec_header;
00070   __header->depth  = depth;
00071   __header->width  = width;
00072   __header->height = height;
00073 }
00074 
00075 /** Constructor.
00076  * Creates a plain empty colormap file.
00077  */
00078 ColormapFile::ColormapFile()
00079   : FireVisionDataFile(CMFILE_MAGIC_TOKEN, CMFILE_CUR_VERSION)
00080 {
00081   __header = NULL;
00082 }
00083
00084 
00085 /** Add colormap.
00086  * This will add the given colormap to this file. It will query the colormap for
00087  * a number of blocks that shall be added to the file.
00088  * Note that for now only a single colormap per file is supported, though not
00089  * enforced.
00090  * @param colormap colormap to add
00091  */
00092 void
00093 ColormapFile::add_colormap(Colormap *colormap)
00094 {
00095   if (! __header) {
00096     if ( _spec_header) {
00097       __header = (cmfile_header_t *)_spec_header;
00098     } else {
00099       _spec_header      = calloc(1, sizeof(cmfile_header_t));
00100       _spec_header_size = sizeof(cmfile_header_t);
00101       __header = (cmfile_header_t *)_spec_header;
00102       __header->depth  = colormap->depth();
00103       __header->width  = colormap->width();
00104       __header->height = colormap->height();
00105     }
00106   }
00107
00108   if ( (colormap->depth()  != __header->depth) ||
00109        (colormap->width()  != __header->width) ||
00110        (colormap->height() != __header->height) ) {
00111     throw fawkes::Exception("Colormap dimensions %dx%dx%d do not match expected dimensions %dx%dx%d",
00112                             colormap->depth(), colormap->width(), colormap->height(),
00113                             __header->depth, __header->width, __header->height);
00114   }
00115
00116   printf("Adding colormap with dimensions %dx%dx%d\n", colormap->width(), colormap->height(), colormap->depth());
00117
00118   std::list<ColormapFileBlock *> blocks = colormap->get_blocks();
00119   for (std::list<ColormapFileBlock *>::iterator i = blocks.begin(); i != blocks.end(); ++i) {
00120     add_block(*i);
00121   }
00122 }
00123
00124 
00125 /** Get colormap blocks.
00126  * @return vector of colormap blocks
00127  */
00128 ColormapFile::ColormapBlockVector *
00129 ColormapFile::colormap_blocks()
00130 {
00131   FireVisionDataFile::BlockList &b = blocks();
00132   ColormapBlockVector *rv = new ColormapBlockVector();
00133   for (std::list<FireVisionDataFileBlock *>::iterator i = b.begin(); i != b.end(); ++i) {
00134     if ((*i)->type() == CMFILE_TYPE_YUV ) {
00135       ColormapFileYuvBlock *yuvb = new ColormapFileYuvBlock(*i);
00136       rv->push_back(yuvb);
00137     }
00138   }
00139
00140   return rv;
00141 }
00142
00143
00144 void
00145 ColormapFile::assert_header()
00146 {
00147   if ( ! __header ) {
00148     if (! _spec_header) {
00149       throw fawkes::Exception("Cannot get header information, invalid ctor used or file not read?");
00150     }
00151     __header = (cmfile_header_t *)_spec_header;
00152   }
00153
00154 }
00155 
00156 /** Get a freshly generated colormap based on current file content.
00157  * This returns an instance of a colormap that uses all current blocks of this instance.
00158  * Currently it only supports file which contain a valid YuvColormap. This means that it
00159  * has d blocks of YUV type. d is the depth and must fulfill d=2^n with n from [1,8].
00160  * It can throw any exception that the YuvColormap ctor can throw.
00161  * @return instance of colormap. You must delete it after you are done with it.
00162  */
00163 Colormap *
00164 ColormapFile::get_colormap()
00165 {
00166   // Make sure we only have YUV blocks
00167   BlockList &bl = blocks();
00168   YuvColormap *cm = NULL;
00169
00170   for (BlockList::iterator b = bl.begin(); b != bl.end(); ++b) {
00171     if ( (*b)->type() != CMFILE_TYPE_YUV ) {
00172       throw fawkes::Exception("Colormap file contains block of unknown type");
00173     }
00174   }
00175
00176   assert_header();
00177
00178   // create colormap, throws an exception is depth/num_blocks is invalid
00179   printf("File header dimensions: %dx%dx%d\n", __header->depth, __header->width, __header->height);
00180   cm = new YuvColormap(__header->depth, __header->width, __header->height);
00181
00182   unsigned int level = 0;
00183   for (BlockList::iterator b = bl.begin(); b != bl.end(); ++b) {
00184     if ( (*b)->data_size() != cm->plane_size() ) {
00185       // invalid size, for a YUV colormap we must have this for one plane!
00186       delete cm;
00187       throw fawkes::Exception("Invalid data size for a YUV block");
00188     }
00189
00190     cm->copy_uvplane((unsigned char *)(*b)->data_ptr(), level++);
00191   }
00192
00193   return cm;
00194 }
00195
00196 
00197 /** Check if given file is a colormap file.
00198  * @param filename name of file to check
00199  */
00200 bool
00201 ColormapFile::is_colormap_file(const char *filename)
00202 {
00203   return FireVisionDataFile::has_magic_token(filename, CMFILE_MAGIC_TOKEN);
00204 }
00205
00206 
00207 /** Compose filename.
00208  * In the format %g is replaced with the hostname.
00209  * @param format format for the filename
00210  */
00211 std::string
00212 ColormapFile::compose_filename(const std::string format)
00213 {
00214   std::string rv = format;
00215
00216   struct utsname uname_info;
00217   uname( &uname_info );
00218
00219   size_t loc = rv.find( "%h" );
00220   while (loc != std::string::npos) {
00221     rv.replace( loc, 2, uname_info.nodename );
00222     loc = rv.find( "%h" );
00223   }
00224
00225   return rv;
00226 }
00227
00228
00229 void
00230 ColormapFile::clear()
00231 {
00232   FireVisionDataFile::clear();
00233   __header = NULL;
00234 }
00235
00236 
00237 /** Get depth of colormap.
00238  * @return depth
00239  */
00240 uint16_t
00241 ColormapFile::get_depth()
00242 {
00243   assert_header();
00244   return __header->depth;
00245 }
00246 
00247 /** Get width of colormap.
00248  * @return width
00249  */
00250 uint16_t
00251 ColormapFile::get_width()
00252 {
00253   assert_header();
00254   return __header->width;
00255 }
00256 
00257 /** Get height of colormap.
00258  * @return height
00259  */
00260 uint16_t
00261 ColormapFile::get_height()
00262 {
00263   assert_header();
00264   return __header->height;
00265 }