00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
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
00038 }
00039 #endif
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 YuvColormap::YuvColormap(unsigned int depth, unsigned int width, unsigned int height)
00065 {
00066 constructor(depth, width, height);
00067 }
00068
00069
00070
00071
00072
00073
00074
00075
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
00084
00085
00086
00087
00088
00089
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
00098
00099
00100
00101
00102
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
00112
00113
00114
00115
00116
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, 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
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
00231
00232
00233
00234
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
00248
00249
00250
00251
00252
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
00272 if ( (*other_lut != C_OTHER) && (*other_lut != C_BACKGROUND) ) {
00273
00274 *this_lut = *other_lut;
00275 }
00276 }
00277 ++this_lut;
00278 ++other_lut;
00279 }
00280
00281 return *this;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291 Colormap &
00292 YuvColormap::operator=(const YuvColormap & yuvcm)
00293 {
00294 if ( __depth != yuvcm.__depth ) {
00295 throw TypeMismatchException("Depth 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
00350
00351
00352 unsigned int
00353 YuvColormap::plane_size() const
00354 {
00355 return __plane_size;
00356 }
00357
00358 }