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
33using namespace fawkes;
34
35namespace 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 */
60YuvColormap::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 */
72YuvColormap::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 */
88YuvColormap::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 */
104YuvColormap::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 */
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 */
128void
129YuvColormap::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. */
183{
184 if (shm_lut_) {
185 delete shm_lut_;
186 } else {
187 free(lut_);
188 }
189 lut_ = NULL;
190 lut_size_ = 0;
191}
192
193void
194YuvColormap::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
199void
201{
202 memset(lut_, C_OTHER, lut_size_);
203}
204
205void
206YuvColormap::set(unsigned char *buffer)
207{
208 memcpy(lut_, buffer, lut_size_);
209}
210
211size_t
213{
214 return lut_size_;
215}
216
217std::list<ColormapFileBlock *>
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
230unsigned char *
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 */
242void
243YuvColormap::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 */
259Colormap &
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 */
295Colormap &
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
307Colormap &
308YuvColormap::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
323unsigned int
325{
326 return width_;
327}
328
329unsigned int
331{
332 return height_;
333}
334
335unsigned int
337{
338 return depth_;
339}
340
341unsigned int
343{
344 return 256;
345}
346
347/** Get U/V plane size.
348 * @return size of a single U/V plane
349 */
350unsigned int
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 */
360void
361YuvColormap::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
size_t data_size() const
Get the size of the data-segment.
Definition: shm.cpp:745
void set_destroy_on_delete(bool destroy)
Set deletion behaviour.
Definition: shm.cpp:839
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
unsigned char * buffer() const
Get LUT buffer.
Definition: shm_lut.cpp:141
YUV Colormap.
Definition: yuvcm.h:36
virtual Colormap & operator=(const YuvColormap &yuvcm)
Assign operation.
Definition: yuvcm.cpp:296
void copy_uvplane(unsigned char *uvplane, unsigned int level)
Copy single U/V plane.
Definition: yuvcm.cpp:243
virtual Colormap & operator+=(const Colormap &cmlt)
Adds the given colormap to this colormap.
Definition: yuvcm.cpp:260
virtual unsigned char * get_buffer() const
Get the raw buffer of this colormap.
Definition: yuvcm.cpp:231
virtual size_t size()
Size in bytes of buffer returned by get_buffer().
Definition: yuvcm.cpp:212
void replace_color(color_t from, color_t to)
Replace a given color with another one.
Definition: yuvcm.cpp:361
YuvColormap(unsigned int depth=1, unsigned int width=256, unsigned int height=256)
Constructor.
Definition: yuvcm.cpp:60
virtual unsigned int height() const
Get height of colormap.
Definition: yuvcm.cpp:330
virtual void reset()
Reset colormap.
Definition: yuvcm.cpp:200
virtual std::list< ColormapFileBlock * > get_blocks()
Get file blocks for this colormap.
Definition: yuvcm.cpp:218
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
virtual ~YuvColormap()
Destructor.
Definition: yuvcm.cpp:182
virtual void set(unsigned int y, unsigned int u, unsigned int v, color_t c)
Set color class for given YUV value.
Definition: yuvcm.cpp:194
unsigned int plane_size() const
Get U/V plane size.
Definition: yuvcm.cpp:351
virtual unsigned int deepness() const
Get deepness of colormap.
Definition: yuvcm.cpp:342
Fawkes library namespace.