MVE - Multi-View Environment mve-devel
Loading...
Searching...
No Matches
image_color.h
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015, Simon Fuhrmann
3 * TU Darmstadt - Graphics, Capture and Massively Parallel Computing
4 * All rights reserved.
5 *
6 * This software may be modified and distributed under the terms
7 * of the BSD 3-Clause license. See the LICENSE.txt file for details.
8 */
9
10#ifndef MVE_IMAGE_COLOR_HEADER
11#define MVE_IMAGE_COLOR_HEADER
12
13#include <algorithm>
14
15#include "math/functions.h"
16#include "mve/image.h"
17#include "mve/defines.h"
18
21
37template <typename T, typename FUNCTOR>
38void
39color_convert (typename Image<T>::Ptr image, FUNCTOR& converter);
40
41/* ---------------------------- Functors -------------------------- */
42
53template <typename T>
54void
55color_srgb_to_xyz (T* values);
56
67template <typename T>
68void
69color_xyz_to_srgb (T* values);
70
82template <typename T>
83void
84color_xyy_to_xyz (T* values);
85
97template <typename T>
98void
99color_xyz_to_xyy (T* values);
100
111template <typename T>
112void
113color_rgb_to_ycbcr (T* values);
114
125template <typename T>
126void
127color_ycbcr_to_rgb (T* values);
128
129/* ------------------------- Implementation ----------------------- */
130
131template <typename T, typename FUNCTOR>
132void
133color_convert (typename Image<T>::Ptr image, FUNCTOR& converter)
134{
135 int64_t const channels = image->channels();
136 if (channels != 3)
137 throw std::invalid_argument("Only 3-channel images supported");
138
139 for (T* ptr = image->begin(); ptr != image->end(); ptr += channels)
140 converter(ptr);
141}
142
143template <typename T>
144void
146{
147 T out[3];
148 out[0] = v[0] * T(0.4124) + v[1] * T(0.3576) + v[2] * T(0.1805);
149 out[1] = v[0] * T(0.2126) + v[1] * T(0.7152) + v[2] * T(0.0722);
150 out[2] = v[0] * T(0.0193) + v[1] * T(0.1192) + v[2] * T(0.9505);
151 std::copy_n(out, 3, v);
152}
153
154template <>
155inline void
156color_srgb_to_xyz<uint8_t> (uint8_t* v)
157{
158 double out[3];
159 out[0] = v[0] * 0.4124 + v[1] * 0.3576 + v[2] * 0.1805;
160 out[1] = v[0] * 0.2126 + v[1] * 0.7152 + v[2] * 0.0722;
161 out[2] = v[0] * 0.0193 + v[1] * 0.1192 + v[2] * 0.9505;
162 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
163 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
164 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
165}
166
167template <typename T>
168void
170{
171 T out[3];
172 out[0] = v[0] * T( 3.2410) + v[1] * T(-1.5374) + v[2] * T(-0.4986);
173 out[1] = v[0] * T(-0.9692) + v[1] * T( 1.8760) + v[2] * T( 0.0416);
174 out[2] = v[0] * T( 0.0556) + v[1] * T(-0.2040) + v[2] * T( 1.0570);
175 std::copy_n(out, 3, v);
176}
177
178template <>
179inline void
180color_xyz_to_srgb<uint8_t> (uint8_t* v)
181{
182 double out[3];
183 out[0] = v[0] * 3.2410 + v[1] * -1.5374 + v[2] * -0.4986;
184 out[1] = v[0] * -0.9692 + v[1] * 1.8760 + v[2] * 0.0416;
185 out[2] = v[0] * 0.0556 + v[1] * -0.2040 + v[2] * 1.0570;
186 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
187 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
188 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
189}
190
191template <typename T>
192void
194{
195 if (v[1] == T(0))
196 {
197 v[0] = T(0);
198 v[1] = T(0);
199 v[2] = T(0);
200 }
201 else
202 {
203 T const ratio = v[2] / v[1];
204 T out[3];
205 out[0] = v[0] * ratio;
206 out[1] = v[2];
207 out[2] = (T(1) - v[0] - v[1]) * ratio;
208 std::copy_n(out, 3, v);
209 }
210}
211
212template <>
213inline void
214color_xyy_to_xyz<uint8_t> (uint8_t* v)
215{
216 if (v[1] == 0)
217 {
218 v[0] = 0;
219 v[1] = 0;
220 v[2] = 0;
221 }
222 else
223 {
224 double const ratio = v[2] / static_cast<double>(v[1]);
225 double out[3];
226 out[0] = v[0] * ratio;
227 out[1] = v[2];
228 out[2] = (255 - v[0] - v[1]) * ratio;
229 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
230 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
231 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
232 }
233}
234
235template <typename T>
236void
238{
239 T const sum = v[0] + v[1] + v[2];
240 if (sum == T(0))
241 {
242 v[0] = T(0);
243 v[1] = T(0);
244 v[2] = T(0);
245 }
246 else
247 {
248 T out[3];
249 out[0] = v[0] / sum;
250 out[1] = v[1] / sum;
251 out[2] = v[1];
252 std::copy_n(out, 3, v);
253 }
254}
255
256template <>
257inline void
258color_xyz_to_xyy<uint8_t> (uint8_t* v)
259{
260 if (v[0] == 0 && v[1] == 0 && v[2] == 0)
261 {
262 v[0] = 0;
263 v[1] = 0;
264 v[2] = 0;
265 }
266 else
267 {
268 double const sum = v[0] + v[1] + v[2];
269 double out[3];
270 out[0] = 255.0 * v[0] / sum;
271 out[1] = 255.0 * v[1] / sum;
272 out[2] = static_cast<double>(v[1]);
273 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
274 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
275 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
276 }
277}
278
279template <typename T>
280void
282{
283 T out[3];
284 out[0] = v[0] * T(0.299) + v[1] * T(0.587) + v[2] * T(0.114);
285 out[1] = v[0] * T(-0.168736) + v[1] * T(-0.331264) + v[2] * T(0.5) + T(0.5);
286 out[2] = v[0] * T(0.5) + v[1] * T(-0.418688) + v[2] * T(-0.081312) + T(0.5);
287 std::copy_n(out, 3, v);
288}
289
290template <>
291inline void
292color_rgb_to_ycbcr<uint8_t> (uint8_t* v)
293{
294 double out[3];
295 out[0] = v[0] * 0.299 + v[1] * 0.587 + v[2] * 0.114 + 0.0;
296 out[1] = v[0] * -0.168736 + v[1] * -0.331264 + v[2] * 0.5 + 128.0;
297 out[2] = v[0] * 0.5 + v[1] * -0.418688 + v[2] * -0.081312 + 128.0;
298 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
299 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
300 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
301}
302
303template <typename T>
304void
306{
307 v[1] = v[1] - T(0.5);
308 v[2] = v[2] - T(0.5);
309
310 T out[3];
311 out[0] = v[0] * T(1) + v[1] * T(0) + v[2] * T(1.402);
312 out[1] = v[0] * T(1) + v[1] * T(-0.34414) + v[2] * T(-0.71414);
313 out[2] = v[0] * T(1) + v[1] * T(1.772) + v[2] * T(0);
314 std::copy_n(out, 3, v);
315}
316
317template <>
318inline void
319color_ycbcr_to_rgb<uint8_t> (uint8_t* v)
320{
321 double out[3];
322 out[0] = v[0] + 1.402 * (v[2] - 128.0);
323 out[1] = v[0] - 0.34414 * (v[1] - 128.0) - 0.71414 * (v[2] - 128.0);
324 out[2] = v[0] + 1.772 * (v[1] - 128.0);
325 v[0] = std::max(0.0, std::min(255.0, math::round(out[0])));
326 v[1] = std::max(0.0, std::min(255.0, math::round(out[1])));
327 v[2] = std::max(0.0, std::min(255.0, math::round(out[2])));
328}
329
332
333#endif /* MVE_IMAGE_COLOR_HEADER */
int64_t channels(void) const
Returns the amount of channels in the image.
Definition image_base.h:213
std::shared_ptr< Image< T > > Ptr
Definition image.h:42
T * begin(void)
Returns data pointer to beginning.
Definition image_base.h:472
T * end(void)
Returns data pointer to end.
Definition image_base.h:486
#define MVE_IMAGE_NAMESPACE_END
Definition defines.h:17
#define MVE_NAMESPACE_BEGIN
Definition defines.h:13
#define MVE_IMAGE_NAMESPACE_BEGIN
Definition defines.h:16
#define MVE_NAMESPACE_END
Definition defines.h:14
T round(T const &x)
Removes the fractional part of the value to the closest integer.
Definition functions.h:70
void color_srgb_to_xyz(T *values)
Converts linear sRGB values RGB into XYZ (CIE 1931) according to http://www.w3.org/Graphics/Color/sRG...
void color_xyy_to_xyz(T *values)
Converts xyY colors to XYZ (CIE 1931) coordinates according to http://www.brucelindbloom....
void color_rgb_to_ycbcr(T *values)
Converts an image from RGB to YCbCr color space according to http://en.wikipedia.org/wiki/YCbCr.
void color_xyz_to_xyy(T *values)
Converts XYZ colors to xyY coordinates according to http://www.brucelindbloom.com/index....
void color_ycbcr_to_rgb(T *values)
Converts an image from YCbCr to RGB color space according to http://en.wikipedia.org/wiki/YCbCr.
void color_xyz_to_srgb(T *values)
Converts XYZ into linear sRGB values RGB according to http://www.w3.org/Graphics/Color/sRGB.
void color_convert(typename Image< T >::Ptr image, FUNCTOR &converter)
Applies an in-place color conversion to the given image.