Fawkes API
Fawkes Development Version
|
00001 00002 /************************************************************************** 00003 * colormap.cpp - colormap 00004 * 00005 * Created: Sat Mar 29 18:11:38 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/yuvcm.h> 00025 00026 #include <fvutils/colormap/cmfile.h> 00027 #include <fvutils/colormap/cmfile_yuvblock.h> 00028 #include <fvutils/ipc/shm_lut.h> 00029 #include <core/exceptions/software.h> 00030 00031 #include <cstdlib> 00032 #include <cstring> 00033 00034 using namespace fawkes; 00035 00036 namespace firevision { 00037 #if 0 /* just to make Emacs auto-indent happy */ 00038 } 00039 #endif 00040 00041 /** @class YuvColormap <fvutils/colormap/colormap.h> 00042 * YUV Colormap. 00043 * This class is the implementation of a 3D YUV colormap. The U/V planes are always 00044 * sampled in full. In general for colormaps we assume that in many cases the luminance 00045 * can be ignored completely. This allows for small datasets with speedy access and 00046 * sufficient discriminatory power. However, in some situations this is not enough. 00047 * In that case you can give a depth for the Y value. The Y axis is then separated 00048 * in the given number of ranges, each range is a stacked complete U/V plane. 00049 * Note, only depth values where depth = 2^n, n from natural numbers holds will provide 00050 * with equal ranges. Other values will lead to one bigger range, being the one with 00051 * the highest Y values which will be filled with the whole rest. 00052 * 00053 * You can see such a colormap as a colormap that consists of UV planes that represent 00054 * a certain Y range stacked on top of each other. 00055 * 00056 * @author Tim Niemueller 00057 */ 00058 00059 /** Constructor. 00060 * @param depth Y resolution depth 00061 * @param width U depth 00062 * @param height V depth 00063 */ 00064 YuvColormap::YuvColormap(unsigned int depth, unsigned int width, unsigned int height) 00065 { 00066 constructor(depth, width, height); 00067 } 00068 00069 00070 /** Constructor. 00071 * Creates a colormap in shared memory for the given LUT ID. 00072 * @param shmem_lut_id shared memory LUT ID 00073 * @param depth Y depth 00074 * @param width U depth 00075 * @param height V depth 00076 */ 00077 YuvColormap::YuvColormap(const char *shmem_lut_id, unsigned int depth, unsigned int width, unsigned int height) 00078 { 00079 constructor(depth, width, height, shmem_lut_id); 00080 } 00081 00082 00083 /** Constructor. 00084 * Creates a colormap in shared memory for the given LUT ID. 00085 * @param shmem_lut_id shared memory LUT ID 00086 * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment 00087 * @param depth Y depth 00088 * @param width U depth 00089 * @param height V depth 00090 */ 00091 YuvColormap::YuvColormap(const char *shmem_lut_id, bool destroy_on_free, unsigned int depth, unsigned int width, unsigned int height) 00092 { 00093 constructor(depth, width, height, shmem_lut_id, destroy_on_free); 00094 } 00095 00096 00097 /** Constructor. 00098 * Creates a colormap in shared memory for the given LUT ID and copies the data of the 00099 * given existing colormap. 00100 * @param cm existing colormap to copy data from 00101 * @param shmem_lut_id shared memory LUT ID 00102 * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment 00103 */ 00104 YuvColormap::YuvColormap(YuvColormap *cm, const char *shmem_lut_id, bool destroy_on_free) 00105 { 00106 constructor(cm->depth(), cm->width(), cm->height(), shmem_lut_id, destroy_on_free); 00107 memcpy(__lut, cm->__lut, __lut_size); 00108 } 00109 00110 00111 /** Internal constructor. 00112 * @param shmem_lut_id shared memory LUT ID 00113 * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment 00114 * @param depth Y depth 00115 * @param width U depth 00116 * @param height V depth 00117 */ 00118 void 00119 YuvColormap::constructor(unsigned int depth, unsigned int width, unsigned int height, 00120 const char *shmem_lut_id, bool destroy_on_free) 00121 { 00122 if ( depth > 256 ) { 00123 throw OutOfBoundsException("YuvColormap depth out of bounds", depth, 1, 256); 00124 } 00125 if ( (depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) && (depth != 16) && 00126 (depth != 32) && (depth != 64) && (depth != 128) && (depth != 256) ) { 00127 throw IllegalArgumentException("Depth must be of the form d=2^n with n from [1,8]"); 00128 } 00129 00130 if ( width > 256 ) { 00131 throw OutOfBoundsException("YuvColormap width out of bounds", width, 1, 256); 00132 } 00133 if ( (width != 1) && (width != 2) && (width != 4) && (width != 8) && (width != 16) && 00134 (width != 32) && (width != 64) && (width != 128) && (width != 256) ) { 00135 throw IllegalArgumentException("Width must be of the form d=2^n with n from [1,8]"); 00136 } 00137 00138 if ( height > 256 ) { 00139 throw OutOfBoundsException("YuvColormap height out of bounds", height, 1, 256); 00140 } 00141 if ( (height != 1) && (height != 2) && (height != 4) && (height != 8) && (height != 16) && 00142 (height != 32) && (height != 64) && (height != 128) && (height != 256) ) { 00143 throw IllegalArgumentException("Height must be of the form d=2^n with n from [1,8]"); 00144 } 00145 00146 __width = width; 00147 __height = height; 00148 __depth = depth; 00149 __depth_div = 256 / __depth; 00150 __width_div = 256 / __width; 00151 __height_div = 256 / __height; 00152 __plane_size = __width * __height; 00153 00154 if ( shmem_lut_id != NULL ) { 00155 __shm_lut = new SharedMemoryLookupTable(shmem_lut_id, __width, __height, __depth, /* bytes p. cell */ 1); 00156 __shm_lut->set_destroy_on_delete( destroy_on_free ); 00157 __lut = __shm_lut->buffer(); 00158 __lut_size = __shm_lut->data_size(); 00159 } else { 00160 __shm_lut = NULL; 00161 __lut_size = __width * __height * __depth; 00162 __lut = (unsigned char *)malloc( __lut_size ); 00163 } 00164 memset(__lut, C_OTHER, __lut_size); 00165 } 00166 00167 00168 /** Destructor. */ 00169 YuvColormap::~YuvColormap() 00170 { 00171 if ( __shm_lut ) { 00172 delete __shm_lut; 00173 } else { 00174 free(__lut); 00175 } 00176 __lut = NULL; 00177 __lut_size = 0; 00178 } 00179 00180 00181 void 00182 YuvColormap::set(unsigned int y, unsigned int u, unsigned int v, color_t c) 00183 { 00184 *(__lut + (y / __depth_div) * __plane_size + (v / __height_div) * __width + (u / __width_div)) = c; 00185 } 00186 00187 00188 void 00189 YuvColormap::reset() 00190 { 00191 memset(__lut, C_OTHER, __lut_size); 00192 } 00193 00194 00195 void 00196 YuvColormap::set(unsigned char *buffer) 00197 { 00198 memcpy(__lut, buffer, __lut_size); 00199 } 00200 00201 00202 size_t 00203 YuvColormap::size() 00204 { 00205 return __lut_size; 00206 } 00207 00208 00209 std::list<ColormapFileBlock *> 00210 YuvColormap::get_blocks() 00211 { 00212 std::list<ColormapFileBlock *> rv; 00213 00214 for (unsigned int i = 0; i < __depth; ++i) { 00215 ColormapFileYuvBlock *yuvb = new ColormapFileYuvBlock(this, i); 00216 rv.push_back(yuvb); 00217 } 00218 00219 return rv; 00220 } 00221 00222 00223 unsigned char * 00224 YuvColormap::get_buffer() const 00225 { 00226 return __lut; 00227 } 00228 00229 00230 /** Copy single U/V plane. 00231 * This will copy the given U/V plane to the given level in this colormap. 00232 * @param uvplane buffer of U/V plane to copy 00233 * @param level level to copy the plane to 00234 * @exception OutOfBoundsException thrown if level > depth() 00235 */ 00236 void 00237 YuvColormap::copy_uvplane(unsigned char *uvplane, unsigned int level) 00238 { 00239 if ( level > __depth ) { 00240 throw OutOfBoundsException("YuvColormap::copy_uvplane(): Invalid level", level, 0, __depth); 00241 } 00242 00243 memcpy(__lut + level * __plane_size, uvplane, __plane_size); 00244 } 00245 00246 00247 /** Adds the given colormap to this colormap. 00248 * This operator takes the given colormap and compares it to this colormap. If 00249 * this colormap has C_OTHER or C_BACKGROUND the value is compied from the other 00250 * LUT, otherwise the value is kept as is. 00251 * @param cmlt other colormap to add 00252 * @return reference to this 00253 */ 00254 Colormap & 00255 YuvColormap::operator+=(const Colormap & cmlt) 00256 { 00257 const YuvColormap *tc = dynamic_cast<const YuvColormap *>(&cmlt); 00258 if ( tc == NULL ) { 00259 throw TypeMismatchException("Only YUV colormaps can be added to a YUV colormap"); 00260 } 00261 00262 if ( (__width != tc->__width) || (__height != tc->__height) || (__depth != tc->__depth) ) { 00263 throw TypeMismatchException("YuvColormaps are of different sizes"); 00264 } 00265 00266 unsigned char *this_lut = __lut; 00267 unsigned char *other_lut = tc->__lut; 00268 00269 for (unsigned int i = 0; i < __plane_size * __depth; ++i) { 00270 if ( (*this_lut == C_OTHER) || (*this_lut == C_BACKGROUND) ) { 00271 // can be overridden 00272 if ( (*other_lut != C_OTHER) && (*other_lut != C_BACKGROUND) ) { 00273 // there is something that is worth overriding this value 00274 *this_lut = *other_lut; 00275 } 00276 } 00277 ++this_lut; 00278 ++other_lut; 00279 } 00280 00281 return *this; 00282 } 00283 00284 00285 /** Assign operation. 00286 * Copies all values from the given colormap. 00287 * @param yuvcm colormap which's data to copy to this instance 00288 * @exception TypeMismatchException thrown if depth of colormaps does not match. 00289 * @return reference to this 00290 */ 00291 Colormap & 00292 YuvColormap::operator=(const YuvColormap & yuvcm) 00293 { 00294 if ( __lut_size != yuvcm.__lut_size ) { 00295 throw TypeMismatchException("Size of colormaps does not match"); 00296 } 00297 00298 memcpy(__lut, yuvcm.__lut, __lut_size); 00299 00300 return *this; 00301 } 00302 00303 00304 Colormap & 00305 YuvColormap::operator+=(const char *filename) 00306 { 00307 ColormapFile cmf; 00308 cmf.read(filename); 00309 Colormap *tcm = cmf.get_colormap(); 00310 YuvColormap *tycm = dynamic_cast<YuvColormap *>(tcm); 00311 if ( ! tycm ) { 00312 delete tcm; 00313 throw TypeMismatchException("File does not contain a YUV colormap"); 00314 } 00315 *this += *tycm; 00316 delete tcm; 00317 return *this; 00318 } 00319 00320 00321 unsigned int 00322 YuvColormap::width() const 00323 { 00324 return __width; 00325 } 00326 00327 00328 unsigned int 00329 YuvColormap::height() const 00330 { 00331 return __height; 00332 } 00333 00334 00335 unsigned int 00336 YuvColormap::depth() const 00337 { 00338 return __depth; 00339 } 00340 00341 00342 unsigned int 00343 YuvColormap::deepness() const 00344 { 00345 return 256; 00346 } 00347 00348 00349 /** Get U/V plane size. 00350 * @return size of a single U/V plane 00351 */ 00352 unsigned int 00353 YuvColormap::plane_size() const 00354 { 00355 return __plane_size; 00356 } 00357 00358 00359 /** Replace a given color with another one. 00360 * @param from color to replace 00361 * @param to color to replace @p from with 00362 */ 00363 void 00364 YuvColormap::replace_color(color_t from, color_t to) 00365 { 00366 unsigned char *this_lut = __lut; 00367 00368 for (unsigned int i = 0; i < __plane_size * __depth; ++i, ++this_lut) { 00369 if (*this_lut == from) *this_lut = to; 00370 } 00371 } 00372 00373 } // end namespace firevision