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