Fawkes API  Fawkes Development Version
yuvcm.cpp
1 
2 /**************************************************************************
3  * colormap.cpp - colormap
4  *
5  * Created: Sat Mar 29 18:11:38 2008
6  * Copyright 2005-2008 Tim Niemueller [www.niemueller.de]
7  *
8  ***************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <fvutils/colormap/yuvcm.h>
25 
26 #include <fvutils/colormap/cmfile.h>
27 #include <fvutils/colormap/cmfile_yuvblock.h>
28 #include <fvutils/ipc/shm_lut.h>
29 #include <core/exceptions/software.h>
30 
31 #include <cstdlib>
32 #include <cstring>
33 
34 using namespace fawkes;
35 
36 namespace firevision {
37 #if 0 /* just to make Emacs auto-indent happy */
38 }
39 #endif
40 
41 /** @class YuvColormap <fvutils/colormap/colormap.h>
42  * YUV Colormap.
43  * This class is the implementation of a 3D YUV colormap. The U/V planes are always
44  * sampled in full. In general for colormaps we assume that in many cases the luminance
45  * can be ignored completely. This allows for small datasets with speedy access and
46  * sufficient discriminatory power. However, in some situations this is not enough.
47  * In that case you can give a depth for the Y value. The Y axis is then separated
48  * in the given number of ranges, each range is a stacked complete U/V plane.
49  * Note, only depth values where depth = 2^n, n from natural numbers holds will provide
50  * with equal ranges. Other values will lead to one bigger range, being the one with
51  * the highest Y values which will be filled with the whole rest.
52  *
53  * You can see such a colormap as a colormap that consists of UV planes that represent
54  * a certain Y range stacked on top of each other.
55  *
56  * @author Tim Niemueller
57  */
58 
59 /** Constructor.
60  * @param depth Y resolution depth
61  * @param width U depth
62  * @param height V depth
63  */
64 YuvColormap::YuvColormap(unsigned int depth, unsigned int width, unsigned int height)
65 {
66  constructor(depth, width, height);
67 }
68 
69 
70 /** Constructor.
71  * Creates a colormap in shared memory for the given LUT ID.
72  * @param shmem_lut_id shared memory LUT ID
73  * @param depth Y depth
74  * @param width U depth
75  * @param height V depth
76  */
77 YuvColormap::YuvColormap(const char *shmem_lut_id, unsigned int depth, unsigned int width, unsigned int height)
78 {
79  constructor(depth, width, height, shmem_lut_id);
80 }
81 
82 
83 /** Constructor.
84  * Creates a colormap in shared memory for the given LUT ID.
85  * @param shmem_lut_id shared memory LUT ID
86  * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment
87  * @param depth Y depth
88  * @param width U depth
89  * @param height V depth
90  */
91 YuvColormap::YuvColormap(const char *shmem_lut_id, bool destroy_on_free, unsigned int depth, unsigned int width, unsigned int height)
92 {
93  constructor(depth, width, height, shmem_lut_id, destroy_on_free);
94 }
95 
96 
97 /** Constructor.
98  * Creates a colormap in shared memory for the given LUT ID and copies the data of the
99  * given existing colormap.
100  * @param cm existing colormap to copy data from
101  * @param shmem_lut_id shared memory LUT ID
102  * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment
103  */
104 YuvColormap::YuvColormap(YuvColormap *cm, const char *shmem_lut_id, bool destroy_on_free)
105 {
106  constructor(cm->depth(), cm->width(), cm->height(), shmem_lut_id, destroy_on_free);
107  memcpy(__lut, cm->__lut, __lut_size);
108 }
109 
110 
111 /** Internal constructor.
112  * @param shmem_lut_id shared memory LUT ID
113  * @param destroy_on_free true to delete the shared memory segment to delete, false to keep the segment
114  * @param depth Y depth
115  * @param width U depth
116  * @param height V depth
117  */
118 void
119 YuvColormap::constructor(unsigned int depth, unsigned int width, unsigned int height,
120  const char *shmem_lut_id, bool destroy_on_free)
121 {
122  if ( depth > 256 ) {
123  throw OutOfBoundsException("YuvColormap depth out of bounds", depth, 1, 256);
124  }
125  if ( (depth != 1) && (depth != 2) && (depth != 4) && (depth != 8) && (depth != 16) &&
126  (depth != 32) && (depth != 64) && (depth != 128) && (depth != 256) ) {
127  throw IllegalArgumentException("Depth must be of the form d=2^n with n from [1,8]");
128  }
129 
130  if ( width > 256 ) {
131  throw OutOfBoundsException("YuvColormap width out of bounds", width, 1, 256);
132  }
133  if ( (width != 1) && (width != 2) && (width != 4) && (width != 8) && (width != 16) &&
134  (width != 32) && (width != 64) && (width != 128) && (width != 256) ) {
135  throw IllegalArgumentException("Width must be of the form d=2^n with n from [1,8]");
136  }
137 
138  if ( height > 256 ) {
139  throw OutOfBoundsException("YuvColormap height out of bounds", height, 1, 256);
140  }
141  if ( (height != 1) && (height != 2) && (height != 4) && (height != 8) && (height != 16) &&
142  (height != 32) && (height != 64) && (height != 128) && (height != 256) ) {
143  throw IllegalArgumentException("Height must be of the form d=2^n with n from [1,8]");
144  }
145 
146  __width = width;
147  __height = height;
148  __depth = depth;
149  __depth_div = 256 / __depth;
150  __width_div = 256 / __width;
151  __height_div = 256 / __height;
152  __plane_size = __width * __height;
153 
154  if ( shmem_lut_id != NULL ) {
155  __shm_lut = new SharedMemoryLookupTable(shmem_lut_id, __width, __height, __depth, /* bytes p. cell */ 1);
156  __shm_lut->set_destroy_on_delete( destroy_on_free );
157  __lut = __shm_lut->buffer();
158  __lut_size = __shm_lut->data_size();
159  } else {
160  __shm_lut = NULL;
161  __lut_size = __width * __height * __depth;
162  __lut = (unsigned char *)malloc( __lut_size );
163  }
164  memset(__lut, C_OTHER, __lut_size);
165 }
166 
167 
168 /** Destructor. */
169 YuvColormap::~YuvColormap()
170 {
171  if ( __shm_lut ) {
172  delete __shm_lut;
173  } else {
174  free(__lut);
175  }
176  __lut = NULL;
177  __lut_size = 0;
178 }
179 
180 
181 void
182 YuvColormap::set(unsigned int y, unsigned int u, unsigned int v, color_t c)
183 {
184  *(__lut + (y / __depth_div) * __plane_size + (v / __height_div) * __width + (u / __width_div)) = c;
185 }
186 
187 
188 void
189 YuvColormap::reset()
190 {
191  memset(__lut, C_OTHER, __lut_size);
192 }
193 
194 
195 void
196 YuvColormap::set(unsigned char *buffer)
197 {
198  memcpy(__lut, buffer, __lut_size);
199 }
200 
201 
202 size_t
203 YuvColormap::size()
204 {
205  return __lut_size;
206 }
207 
208 
209 std::list<ColormapFileBlock *>
210 YuvColormap::get_blocks()
211 {
212  std::list<ColormapFileBlock *> rv;
213 
214  for (unsigned int i = 0; i < __depth; ++i) {
215  ColormapFileYuvBlock *yuvb = new ColormapFileYuvBlock(this, i);
216  rv.push_back(yuvb);
217  }
218 
219  return rv;
220 }
221 
222 
223 unsigned char *
224 YuvColormap::get_buffer() const
225 {
226  return __lut;
227 }
228 
229 
230 /** Copy single U/V plane.
231  * This will copy the given U/V plane to the given level in this colormap.
232  * @param uvplane buffer of U/V plane to copy
233  * @param level level to copy the plane to
234  * @exception OutOfBoundsException thrown if level > depth()
235  */
236 void
237 YuvColormap::copy_uvplane(unsigned char *uvplane, unsigned int level)
238 {
239  if ( level > __depth ) {
240  throw OutOfBoundsException("YuvColormap::copy_uvplane(): Invalid level", level, 0, __depth);
241  }
242 
243  memcpy(__lut + level * __plane_size, uvplane, __plane_size);
244 }
245 
246 
247 /** Adds the given colormap to this colormap.
248  * This operator takes the given colormap and compares it to this colormap. If
249  * this colormap has C_OTHER or C_BACKGROUND the value is compied from the other
250  * LUT, otherwise the value is kept as is.
251  * @param cmlt other colormap to add
252  * @return reference to this
253  */
254 Colormap &
255 YuvColormap::operator+=(const Colormap & cmlt)
256 {
257  const YuvColormap *tc = dynamic_cast<const YuvColormap *>(&cmlt);
258  if ( tc == NULL ) {
259  throw TypeMismatchException("Only YUV colormaps can be added to a YUV colormap");
260  }
261 
262  if ( (__width != tc->__width) || (__height != tc->__height) || (__depth != tc->__depth) ) {
263  throw TypeMismatchException("YuvColormaps are of different sizes");
264  }
265 
266  unsigned char *this_lut = __lut;
267  unsigned char *other_lut = tc->__lut;
268 
269  for (unsigned int i = 0; i < __plane_size * __depth; ++i) {
270  if ( (*this_lut == C_OTHER) || (*this_lut == C_BACKGROUND) ) {
271  // can be overridden
272  if ( (*other_lut != C_OTHER) && (*other_lut != C_BACKGROUND) ) {
273  // there is something that is worth overriding this value
274  *this_lut = *other_lut;
275  }
276  }
277  ++this_lut;
278  ++other_lut;
279  }
280 
281  return *this;
282 }
283 
284 
285 /** Assign operation.
286  * Copies all values from the given colormap.
287  * @param yuvcm colormap which's data to copy to this instance
288  * @exception TypeMismatchException thrown if depth of colormaps does not match.
289  * @return reference to this
290  */
291 Colormap &
292 YuvColormap::operator=(const YuvColormap & yuvcm)
293 {
294  if ( __lut_size != yuvcm.__lut_size ) {
295  throw TypeMismatchException("Size of colormaps does not match");
296  }
297 
298  memcpy(__lut, yuvcm.__lut, __lut_size);
299 
300  return *this;
301 }
302 
303 
304 Colormap &
305 YuvColormap::operator+=(const char *filename)
306 {
307  ColormapFile cmf;
308  cmf.read(filename);
309  Colormap *tcm = cmf.get_colormap();
310  YuvColormap *tycm = dynamic_cast<YuvColormap *>(tcm);
311  if ( ! tycm ) {
312  delete tcm;
313  throw TypeMismatchException("File does not contain a YUV colormap");
314  }
315  *this += *tycm;
316  delete tcm;
317  return *this;
318 }
319 
320 
321 unsigned int
322 YuvColormap::width() const
323 {
324  return __width;
325 }
326 
327 
328 unsigned int
329 YuvColormap::height() const
330 {
331  return __height;
332 }
333 
334 
335 unsigned int
336 YuvColormap::depth() const
337 {
338  return __depth;
339 }
340 
341 
342 unsigned int
343 YuvColormap::deepness() const
344 {
345  return 256;
346 }
347 
348 
349 /** Get U/V plane size.
350  * @return size of a single U/V plane
351  */
352 unsigned int
353 YuvColormap::plane_size() const
354 {
355  return __plane_size;
356 }
357 
358 
359 /** Replace a given color with another one.
360  * @param from color to replace
361  * @param to color to replace @p from with
362  */
363 void
364 YuvColormap::replace_color(color_t from, color_t to)
365 {
366  unsigned char *this_lut = __lut;
367 
368  for (unsigned int i = 0; i < __plane_size * __depth; ++i, ++this_lut) {
369  if (*this_lut == from) *this_lut = to;
370  }
371 }
372 
373 } // end namespace firevision
virtual unsigned int width() const
Get width of colormap.
Definition: yuvcm.cpp:322
Fawkes library namespace.
Colormap interface.
Definition: colormap.h:38
YUV block for colormap file.
Colormap * get_colormap()
Get a freshly generated colormap based on current file content.
Definition: cmfile.cpp:169
YUV Colormap.
Definition: yuvcm.h:39
virtual void read(const char *file_name)
Read file.
Definition: fvfile.cpp:308
Colormap file.
Definition: cmfile.h:55
virtual unsigned int depth() const
Get depth of colormap.
Definition: yuvcm.cpp:336
Index out of bounds.
Definition: software.h:88
Expected parameter is missing.
Definition: software.h:82
virtual unsigned int height() const
Get height of colormap.
Definition: yuvcm.cpp:329
Shared memory lookup table.
Definition: shm_lut.h:113