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
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 YuvColormap::YuvColormap(unsigned int depth, unsigned int width, unsigned int height)
00060 {
00061 constructor(depth, width, height);
00062 }
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 YuvColormap::YuvColormap(const char *shmem_lut_id, unsigned int depth, unsigned int width, unsigned int height)
00073 {
00074 constructor(depth, width, height, shmem_lut_id);
00075 }
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086 YuvColormap::YuvColormap(const char *shmem_lut_id, bool destroy_on_free, unsigned int depth, unsigned int width, unsigned int height)
00087 {
00088 constructor(depth, width, height, shmem_lut_id, destroy_on_free);
00089 }
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099 YuvColormap::YuvColormap(YuvColormap *cm, const char *shmem_lut_id, bool destroy_on_free)
00100 {
00101 constructor(cm->depth(), cm->width(), cm->height(), shmem_lut_id, destroy_on_free);
00102 memcpy(__lut, cm->__lut, __lut_size);
00103 }
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113 void
00114 YuvColormap::constructor(unsigned int depth, unsigned int width, unsigned int height,
00115 const char *shmem_lut_id, bool destroy_on_free)
00116 {
00117 if ( depth > 256 ) {
00118 throw OutOfBoundsException("YuvColormap depth out of bounds", depth, 1, 256);
00119 }
00120 if ( (depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) && (depth != 16) &&
00121 (depth != 32) && (depth != 64) && (depth != 128) && (depth != 256) ) {
00122 throw IllegalArgumentException("Depth must be of the form d=2^n with n from [1,8]");
00123 }
00124
00125 if ( width > 256 ) {
00126 throw OutOfBoundsException("YuvColormap width out of bounds", width, 1, 256);
00127 }
00128 if ( (width != 1) && (width != 2) && (width != 4) && (width != 8) && (width != 16) &&
00129 (width != 32) && (width != 64) && (width != 128) && (width != 256) ) {
00130 throw IllegalArgumentException("Width must be of the form d=2^n with n from [1,8]");
00131 }
00132
00133 if ( height > 256 ) {
00134 throw OutOfBoundsException("YuvColormap height out of bounds", height, 1, 256);
00135 }
00136 if ( (height != 1) && (height != 2) && (height != 4) && (height != 8) && (height != 16) &&
00137 (height != 32) && (height != 64) && (height != 128) && (height != 256) ) {
00138 throw IllegalArgumentException("Height must be of the form d=2^n with n from [1,8]");
00139 }
00140
00141 __width = width;
00142 __height = height;
00143 __depth = depth;
00144 __depth_div = 256 / __depth;
00145 __width_div = 256 / __width;
00146 __height_div = 256 / __height;
00147 __plane_size = __width * __height;
00148
00149 if ( shmem_lut_id != NULL ) {
00150 __shm_lut = new SharedMemoryLookupTable(shmem_lut_id, __width, __height, __depth, 1);
00151 __shm_lut->set_destroy_on_delete( destroy_on_free );
00152 __lut = __shm_lut->buffer();
00153 __lut_size = __shm_lut->data_size();
00154 } else {
00155 __shm_lut = NULL;
00156 __lut_size = __width * __height * __depth;
00157 __lut = (unsigned char *)malloc( __lut_size );
00158 }
00159 memset(__lut, C_OTHER, __lut_size);
00160 }
00161
00162
00163
00164 YuvColormap::~YuvColormap()
00165 {
00166 if ( __shm_lut ) {
00167 delete __shm_lut;
00168 } else {
00169 free(__lut);
00170 }
00171 __lut = NULL;
00172 __lut_size = 0;
00173 }
00174
00175
00176 void
00177 YuvColormap::set(unsigned int y, unsigned int u, unsigned int v, color_t c)
00178 {
00179 *(__lut + (y / __depth_div) * __plane_size + (v / __height_div) * __width + (u / __width_div)) = c;
00180 }
00181
00182
00183 void
00184 YuvColormap::reset()
00185 {
00186 memset(__lut, C_OTHER, __lut_size);
00187 }
00188
00189
00190 void
00191 YuvColormap::set(unsigned char *buffer)
00192 {
00193 memcpy(__lut, buffer, __lut_size);
00194 }
00195
00196
00197 size_t
00198 YuvColormap::size()
00199 {
00200 return __lut_size;
00201 }
00202
00203
00204 std::list<ColormapFileBlock *>
00205 YuvColormap::get_blocks()
00206 {
00207 std::list<ColormapFileBlock *> rv;
00208
00209 for (unsigned int i = 0; i < __depth; ++i) {
00210 ColormapFileYuvBlock *yuvb = new ColormapFileYuvBlock(this, i);
00211 rv.push_back(yuvb);
00212 }
00213
00214 return rv;
00215 }
00216
00217
00218 unsigned char *
00219 YuvColormap::get_buffer() const
00220 {
00221 return __lut;
00222 }
00223
00224
00225
00226
00227
00228
00229
00230
00231 void
00232 YuvColormap::copy_uvplane(unsigned char *uvplane, unsigned int level)
00233 {
00234 if ( level > __depth ) {
00235 throw OutOfBoundsException("YuvColormap::copy_uvplane(): Invalid level", level, 0, __depth);
00236 }
00237
00238 memcpy(__lut + level * __plane_size, uvplane, __plane_size);
00239 }
00240
00241
00242 Colormap &
00243 YuvColormap::operator+=(const Colormap & cmlt)
00244 {
00245 const YuvColormap *tc = dynamic_cast<const YuvColormap *>(&cmlt);
00246 if ( tc == NULL ) {
00247 throw TypeMismatchException("Only YUV colormaps can be added to a YUV colormap");
00248 }
00249
00250 if ( (__width != tc->__width) || (__height != tc->__height) || (__depth != tc->__depth) ) {
00251 throw TypeMismatchException("YuvColormaps are of different sizes");
00252 }
00253
00254 unsigned char *this_lut = __lut;
00255 unsigned char *other_lut = tc->__lut;
00256
00257 for (unsigned int i = 0; i < __plane_size * __depth; ++i) {
00258 if ( (*this_lut == C_OTHER) || (*this_lut == C_BACKGROUND) ) {
00259
00260 if ( (*other_lut != C_OTHER) && (*other_lut != C_BACKGROUND) ) {
00261
00262 *this_lut = *other_lut;
00263 }
00264 }
00265 ++this_lut;
00266 ++other_lut;
00267 }
00268
00269 return *this;
00270 }
00271
00272
00273
00274
00275
00276
00277
00278
00279 Colormap &
00280 YuvColormap::operator=(const YuvColormap & yuvcm)
00281 {
00282 if ( __depth != yuvcm.__depth ) {
00283 throw TypeMismatchException("Depth of colormaps does not match");
00284 }
00285
00286 memcpy(__lut, yuvcm.__lut, __lut_size);
00287
00288 return *this;
00289 }
00290
00291
00292 Colormap &
00293 YuvColormap::operator+=(const char *filename)
00294 {
00295 ColormapFile cmf;
00296 cmf.read(filename);
00297 Colormap *tcm = cmf.get_colormap();
00298 YuvColormap *tycm = dynamic_cast<YuvColormap *>(tcm);
00299 if ( ! tycm ) {
00300 delete tcm;
00301 throw TypeMismatchException("File does not contain a YUV colormap");
00302 }
00303 *this += *tycm;
00304 delete tcm;
00305 return *this;
00306 }
00307
00308
00309 unsigned int
00310 YuvColormap::width() const
00311 {
00312 return __width;
00313 }
00314
00315
00316 unsigned int
00317 YuvColormap::height() const
00318 {
00319 return __height;
00320 }
00321
00322
00323 unsigned int
00324 YuvColormap::depth() const
00325 {
00326 return __depth;
00327 }
00328
00329
00330 unsigned int
00331 YuvColormap::deepness() const
00332 {
00333 return 256;
00334 }
00335
00336
00337
00338
00339
00340 unsigned int
00341 YuvColormap::plane_size() const
00342 {
00343 return __plane_size;
00344 }