]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/gil/include/boost/gil/channel_algorithm.hpp
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / gil / include / boost / gil / channel_algorithm.hpp
1 /*
2 Copyright 2005-2007 Adobe Systems Incorporated
3
4 Use, modification and distribution are subject to the Boost Software License,
5 Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6 http://www.boost.org/LICENSE_1_0.txt).
7
8 See http://opensource.adobe.com/gil for most recent version including documentation.
9 */
10 /*************************************************************************************************/
11
12 #ifndef GIL_CHANNEL_ALGORITHM_HPP
13 #define GIL_CHANNEL_ALGORITHM_HPP
14
15 ////////////////////////////////////////////////////////////////////////////////////////
16 /// \file
17 /// \brief Channel algorithms
18 /// \author Lubomir Bourdev and Hailin Jin \n
19 /// Adobe Systems Incorporated
20 /// \date 2005-2007 \n Last updated on May 6, 2007
21 ///
22 /// Definitions of standard GIL 8-bit, 16-bit, 32-bit channels
23 ///
24 ////////////////////////////////////////////////////////////////////////////////////////
25
26 #include "gil_config.hpp"
27 #include "channel.hpp"
28 #include <boost/mpl/less.hpp>
29 #include <boost/mpl/integral_c.hpp>
30 #include <boost/mpl/greater.hpp>
31 #include <boost/type_traits.hpp>
32
33 namespace boost { namespace gil {
34
35 //#ifdef _MSC_VER
36 //#pragma warning(push)
37 //#pragma warning(disable: 4309) // disable truncation of constant value warning (using -1 to get the max value of an integral)
38 //#endif
39
40 namespace detail {
41
42 // some forward declarations
43 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral> struct channel_converter_unsigned_impl;
44 template <typename SrcChannelV, typename DstChannelV, bool SrcIsGreater> struct channel_converter_unsigned_integral;
45 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool SrcDivisible> struct channel_converter_unsigned_integral_impl;
46 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst, bool CannotFitInInteger> struct channel_converter_unsigned_integral_nondivisible;
47
48 //////////////////////////////////////
49 //// unsigned_integral_max_value - given an unsigned integral channel type, returns its maximum value as an MPL integral constant
50 //////////////////////////////////////
51
52
53 template <typename UnsignedIntegralChannel>
54 struct unsigned_integral_max_value : public mpl::integral_c<UnsignedIntegralChannel,-1> {};
55
56 template <>
57 struct unsigned_integral_max_value<uint8_t> : public mpl::integral_c<uint32_t,0xFF> {};
58 template <>
59 struct unsigned_integral_max_value<uint16_t> : public mpl::integral_c<uint32_t,0xFFFF> {};
60 template <>
61 struct unsigned_integral_max_value<uint32_t> : public mpl::integral_c<uintmax_t,0xFFFFFFFF> {};
62
63
64 template <int K>
65 struct unsigned_integral_max_value<packed_channel_value<K> >
66 : public mpl::integral_c<typename packed_channel_value<K>::integer_t, (1<<K)-1> {};
67
68 //////////////////////////////////////
69 //// unsigned_integral_num_bits - given an unsigned integral channel type, returns the minimum number of bits needed to represent it
70 //////////////////////////////////////
71
72 template <typename UnsignedIntegralChannel>
73 struct unsigned_integral_num_bits : public mpl::int_<sizeof(UnsignedIntegralChannel)*8> {};
74
75 template <int K>
76 struct unsigned_integral_num_bits<packed_channel_value<K> >
77 : public mpl::int_<K> {};
78
79 } // namespace detail
80
81 /**
82 \defgroup ChannelConvertAlgorithm channel_convert
83 \brief Converting from one channel type to another
84 \ingroup ChannelAlgorithm
85
86 Conversion is done as a simple linear mapping of one channel range to the other,
87 such that the minimum/maximum value of the source maps to the minimum/maximum value of the destination.
88 One implication of this is that the value 0 of signed channels may not be preserved!
89
90 When creating new channel models, it is often a good idea to provide specializations for the channel conversion algorithms, for
91 example, for performance optimizations. If the new model is an integral type that can be signed, it is easier to define the conversion
92 only for the unsigned type (\p channel_converter_unsigned) and provide specializations of \p detail::channel_convert_to_unsigned
93 and \p detail::channel_convert_from_unsigned to convert between the signed and unsigned type.
94
95 Example:
96 \code
97 // bits32f is a floating point channel with range [0.0f ... 1.0f]
98 bits32f src_channel = channel_traits<bits32f>::max_value();
99 assert(src_channel == 1);
100
101 // bits8 is 8-bit unsigned integral channel (typedef-ed from unsigned char)
102 bits8 dst_channel = channel_convert<bits8>(src_channel);
103 assert(dst_channel == 255); // max value goes to max value
104 \endcode
105 */
106
107 /**
108 \defgroup ChannelConvertUnsignedAlgorithm channel_converter_unsigned
109 \ingroup ChannelConvertAlgorithm
110 \brief Convert one unsigned/floating point channel to another. Converts both the channel type and range
111 @{
112 */
113
114 //////////////////////////////////////
115 //// channel_converter_unsigned
116 //////////////////////////////////////
117
118 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
119 struct channel_converter_unsigned
120 : public detail::channel_converter_unsigned_impl<SrcChannelV,DstChannelV,is_integral<SrcChannelV>::value,is_integral<DstChannelV>::value> {};
121
122
123 /// \brief Converting a channel to itself - identity operation
124 template <typename T> struct channel_converter_unsigned<T,T> : public detail::identity<T> {};
125
126
127 namespace detail {
128
129 //////////////////////////////////////
130 //// channel_converter_unsigned_impl
131 //////////////////////////////////////
132
133 /// \brief This is the default implementation. Performance specializatons are provided
134 template <typename SrcChannelV, typename DstChannelV, bool SrcIsIntegral, bool DstIsIntegral>
135 struct channel_converter_unsigned_impl : public std::unary_function<DstChannelV,SrcChannelV> {
136 DstChannelV operator()(SrcChannelV src) const {
137 return DstChannelV(channel_traits<DstChannelV>::min_value() +
138 (src - channel_traits<SrcChannelV>::min_value()) / channel_range<SrcChannelV>() * channel_range<DstChannelV>());
139 }
140 private:
141 template <typename C>
142 static double channel_range() {
143 return double(channel_traits<C>::max_value()) - double(channel_traits<C>::min_value());
144 }
145 };
146
147 // When both the source and the destination are integral channels, perform a faster conversion
148 template <typename SrcChannelV, typename DstChannelV>
149 struct channel_converter_unsigned_impl<SrcChannelV,DstChannelV,true,true>
150 : public channel_converter_unsigned_integral<SrcChannelV,DstChannelV,
151 mpl::less<unsigned_integral_max_value<SrcChannelV>,unsigned_integral_max_value<DstChannelV> >::value > {};
152
153
154 //////////////////////////////////////
155 //// channel_converter_unsigned_integral
156 //////////////////////////////////////
157
158 template <typename SrcChannelV, typename DstChannelV>
159 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,true>
160 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,
161 !(unsigned_integral_max_value<DstChannelV>::value % unsigned_integral_max_value<SrcChannelV>::value) > {};
162
163 template <typename SrcChannelV, typename DstChannelV>
164 struct channel_converter_unsigned_integral<SrcChannelV,DstChannelV,false>
165 : public channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,
166 !(unsigned_integral_max_value<SrcChannelV>::value % unsigned_integral_max_value<DstChannelV>::value) > {};
167
168
169 //////////////////////////////////////
170 //// channel_converter_unsigned_integral_impl
171 //////////////////////////////////////
172
173 // Both source and destination are unsigned integral channels,
174 // the src max value is less than the dst max value,
175 // and the dst max value is divisible by the src max value
176 template <typename SrcChannelV, typename DstChannelV>
177 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,true,true> {
178 DstChannelV operator()(SrcChannelV src) const {
179 typedef typename unsigned_integral_max_value<DstChannelV>::value_type integer_t;
180 static const integer_t mul = unsigned_integral_max_value<DstChannelV>::value / unsigned_integral_max_value<SrcChannelV>::value;
181 return DstChannelV(src * mul);
182 }
183 };
184
185 // Both source and destination are unsigned integral channels,
186 // the dst max value is less than (or equal to) the src max value,
187 // and the src max value is divisible by the dst max value
188 template <typename SrcChannelV, typename DstChannelV>
189 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,false,true> {
190 DstChannelV operator()(SrcChannelV src) const {
191 typedef typename unsigned_integral_max_value<SrcChannelV>::value_type integer_t;
192 static const integer_t div = unsigned_integral_max_value<SrcChannelV>::value / unsigned_integral_max_value<DstChannelV>::value;
193 static const integer_t div2 = div/2;
194 return DstChannelV((src + div2) / div);
195 }
196 };
197
198 // Prevent overflow for the largest integral type
199 template <typename DstChannelV>
200 struct channel_converter_unsigned_integral_impl<uintmax_t,DstChannelV,false,true> {
201 DstChannelV operator()(uintmax_t src) const {
202 static const uintmax_t div = unsigned_integral_max_value<bits32>::value / unsigned_integral_max_value<DstChannelV>::value;
203 static const uintmax_t div2 = div/2;
204 if (src > unsigned_integral_max_value<uintmax_t>::value - div2)
205 return unsigned_integral_max_value<DstChannelV>::value;
206 return DstChannelV((src + div2) / div);
207 }
208 };
209
210 // Both source and destination are unsigned integral channels,
211 // and the dst max value is not divisible by the src max value
212 // See if you can represent the expression (src * dst_max) / src_max in integral form
213 template <typename SrcChannelV, typename DstChannelV, bool SrcLessThanDst>
214 struct channel_converter_unsigned_integral_impl<SrcChannelV,DstChannelV,SrcLessThanDst,false>
215 : public channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,SrcLessThanDst,
216 mpl::greater<
217 mpl::plus<unsigned_integral_num_bits<SrcChannelV>,unsigned_integral_num_bits<DstChannelV> >,
218 unsigned_integral_num_bits<uintmax_t>
219 >::value> {};
220
221
222 // Both source and destination are unsigned integral channels,
223 // the src max value is less than the dst max value,
224 // and the dst max value is not divisible by the src max value
225 // The expression (src * dst_max) / src_max fits in an integer
226 template <typename SrcChannelV, typename DstChannelV>
227 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,false> {
228 DstChannelV operator()(SrcChannelV src) const {
229 typedef typename detail::min_fast_uint<unsigned_integral_num_bits<SrcChannelV>::value+unsigned_integral_num_bits<DstChannelV>::value>::type integer_t;
230 return DstChannelV(integer_t(src * unsigned_integral_max_value<DstChannelV>::value) / unsigned_integral_max_value<SrcChannelV>::value);
231 }
232 };
233
234 // Both source and destination are unsigned integral channels,
235 // the src max value is less than the dst max value,
236 // and the dst max value is not divisible by the src max value
237 // The expression (src * dst_max) / src_max cannot fit in an integer (overflows). Use a double
238 template <typename SrcChannelV, typename DstChannelV>
239 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,true,true> {
240 DstChannelV operator()(SrcChannelV src) const {
241 static const double mul = unsigned_integral_max_value<DstChannelV>::value / double(unsigned_integral_max_value<SrcChannelV>::value);
242 return DstChannelV(src * mul);
243 }
244 };
245
246 // Both source and destination are unsigned integral channels,
247 // the dst max value is less than (or equal to) the src max value,
248 // and the src max value is not divisible by the dst max value
249 template <typename SrcChannelV, typename DstChannelV, bool CannotFit>
250 struct channel_converter_unsigned_integral_nondivisible<SrcChannelV,DstChannelV,false,CannotFit> {
251 DstChannelV operator()(SrcChannelV src) const {
252
253 typedef typename detail::unsigned_integral_max_value< SrcChannelV >::value_type src_integer_t;
254 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
255
256 static const double div = unsigned_integral_max_value<SrcChannelV>::value
257 / static_cast< double >( unsigned_integral_max_value<DstChannelV>::value );
258
259 static const src_integer_t div2 = static_cast< src_integer_t >( div / 2.0 );
260
261 return DstChannelV( static_cast< dst_integer_t >(( static_cast< double >( src + div2 ) / div )));
262 }
263 };
264
265 } // namespace detail
266
267 /////////////////////////////////////////////////////
268 /// bits32f conversion
269 /////////////////////////////////////////////////////
270
271 template <typename DstChannelV> struct channel_converter_unsigned<bits32f,DstChannelV> : public std::unary_function<bits32f,DstChannelV> {
272 DstChannelV operator()(bits32f x) const
273 {
274 typedef typename detail::unsigned_integral_max_value< DstChannelV >::value_type dst_integer_t;
275 return DstChannelV( static_cast< dst_integer_t >(x*channel_traits<DstChannelV>::max_value()+0.5f ));
276 }
277 };
278
279 template <typename SrcChannelV> struct channel_converter_unsigned<SrcChannelV,bits32f> : public std::unary_function<SrcChannelV,bits32f> {
280 bits32f operator()(SrcChannelV x) const { return bits32f(x/float(channel_traits<SrcChannelV>::max_value())); }
281 };
282
283 template <> struct channel_converter_unsigned<bits32f,bits32f> : public std::unary_function<bits32f,bits32f> {
284 bits32f operator()(bits32f x) const { return x; }
285 };
286
287
288 /// \brief 32 bit <-> float channel conversion
289 template <> struct channel_converter_unsigned<bits32,bits32f> : public std::unary_function<bits32,bits32f> {
290 bits32f operator()(bits32 x) const {
291 // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f
292 if (x>=channel_traits<bits32>::max_value()) return channel_traits<bits32f>::max_value();
293 return float(x) / float(channel_traits<bits32>::max_value());
294 }
295 };
296 /// \brief 32 bit <-> float channel conversion
297 template <> struct channel_converter_unsigned<bits32f,bits32> : public std::unary_function<bits32f,bits32> {
298 bits32 operator()(bits32f x) const {
299 // unfortunately without an explicit check it is possible to get a round-off error. We must ensure that max_value of bits32 matches max_value of bits32f
300 if (x>=channel_traits<bits32f>::max_value()) return channel_traits<bits32>::max_value();
301 return bits32(x * channel_traits<bits32>::max_value() + 0.5f);
302 }
303 };
304
305 /// @}
306
307 namespace detail {
308 // Converting from signed to unsigned integral channel.
309 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
310 template <typename ChannelValue> // Model ChannelValueConcept
311 struct channel_convert_to_unsigned : public detail::identity<ChannelValue> {
312 typedef ChannelValue type;
313 };
314
315 template <> struct channel_convert_to_unsigned<bits8s> : public std::unary_function<bits8s,bits8> {
316 typedef bits8 type;
317 type operator()(bits8s val) const { return val+128; }
318 };
319
320 template <> struct channel_convert_to_unsigned<bits16s> : public std::unary_function<bits16s,bits16> {
321 typedef bits16 type;
322 type operator()(bits16s val) const { return val+32768; }
323 };
324
325 template <> struct channel_convert_to_unsigned<bits32s> : public std::unary_function<bits32s,bits32> {
326 typedef bits32 type;
327 type operator()(bits32s x) const { return static_cast<bits32>(x+(1<<31)); }
328 };
329
330
331 // Converting from unsigned to signed integral channel
332 // It is both a unary function, and a metafunction (thus requires the 'type' nested typedef, which equals result_type)
333 template <typename ChannelValue> // Model ChannelValueConcept
334 struct channel_convert_from_unsigned : public detail::identity<ChannelValue> {
335 typedef ChannelValue type;
336 };
337
338 template <> struct channel_convert_from_unsigned<bits8s> : public std::unary_function<bits8,bits8s> {
339 typedef bits8s type;
340 type operator()(bits8 val) const { return val-128; }
341 };
342
343 template <> struct channel_convert_from_unsigned<bits16s> : public std::unary_function<bits16,bits16s> {
344 typedef bits16s type;
345 type operator()(bits16 val) const { return val-32768; }
346 };
347
348 template <> struct channel_convert_from_unsigned<bits32s> : public std::unary_function<bits32,bits32s> {
349 typedef bits32s type;
350 type operator()(bits32 x) const { return static_cast<bits32s>(x-(1<<31)); }
351 };
352
353 } // namespace detail
354
355 /// \ingroup ChannelConvertAlgorithm
356 /// \brief A unary function object converting between channel types
357 template <typename SrcChannelV, typename DstChannelV> // Model ChannelValueConcept
358 struct channel_converter : public std::unary_function<SrcChannelV,DstChannelV> {
359 DstChannelV operator()(const SrcChannelV& src) const {
360 typedef detail::channel_convert_to_unsigned<SrcChannelV> to_unsigned;
361 typedef detail::channel_convert_from_unsigned<DstChannelV> from_unsigned;
362 typedef channel_converter_unsigned<typename to_unsigned::result_type, typename from_unsigned::argument_type> converter_unsigned;
363 return from_unsigned()(converter_unsigned()(to_unsigned()(src)));
364 }
365 };
366
367 /// \ingroup ChannelConvertAlgorithm
368 /// \brief Converting from one channel type to another.
369 template <typename DstChannel, typename SrcChannel> // Model ChannelConcept (could be channel references)
370 inline typename channel_traits<DstChannel>::value_type channel_convert(const SrcChannel& src) {
371 return channel_converter<typename channel_traits<SrcChannel>::value_type,
372 typename channel_traits<DstChannel>::value_type>()(src);
373 }
374
375 /// \ingroup ChannelConvertAlgorithm
376 /// \brief Same as channel_converter, except it takes the destination channel by reference, which allows
377 /// us to move the templates from the class level to the method level. This is important when invoking it
378 /// on heterogeneous pixels.
379 struct default_channel_converter {
380 template <typename Ch1, typename Ch2>
381 void operator()(const Ch1& src, Ch2& dst) const {
382 dst=channel_convert<Ch2>(src);
383 }
384 };
385
386 namespace detail {
387 // fast integer division by 255
388 inline uint32_t div255(uint32_t in) { uint32_t tmp=in+128; return (tmp + (tmp>>8))>>8; }
389
390 // fast integer divison by 32768
391 inline uint32_t div32768(uint32_t in) { return (in+16384)>>15; }
392 }
393
394 /**
395 \defgroup ChannelMultiplyAlgorithm channel_multiply
396 \ingroup ChannelAlgorithm
397 \brief Multiplying unsigned channel values of the same type. Performs scaled multiplication result = a * b / max_value
398
399 Example:
400 \code
401 bits8 x=128;
402 bits8 y=128;
403 bits8 mul = channel_multiply(x,y);
404 assert(mul == 64); // 64 = 128 * 128 / 255
405 \endcode
406 */
407 /// @{
408
409 /// \brief This is the default implementation. Performance specializatons are provided
410 template <typename ChannelValue>
411 struct channel_multiplier_unsigned : public std::binary_function<ChannelValue,ChannelValue,ChannelValue> {
412 ChannelValue operator()(ChannelValue a, ChannelValue b) const {
413 return ChannelValue(a / double(channel_traits<ChannelValue>::max_value()) * b);
414 }
415 };
416
417 /// \brief Specialization of channel_multiply for 8-bit unsigned channels
418 template<> struct channel_multiplier_unsigned<bits8> : public std::binary_function<bits8,bits8,bits8> {
419 bits8 operator()(bits8 a, bits8 b) const { return bits8(detail::div255(uint32_t(a) * uint32_t(b))); }
420 };
421
422 /// \brief Specialization of channel_multiply for 16-bit unsigned channels
423 template<> struct channel_multiplier_unsigned<bits16> : public std::binary_function<bits16,bits16,bits16> {
424 bits16 operator()(bits16 a, bits16 b) const { return bits16((uint32_t(a) * uint32_t(b))/65535); }
425 };
426
427 /// \brief Specialization of channel_multiply for float 0..1 channels
428 template<> struct channel_multiplier_unsigned<bits32f> : public std::binary_function<bits32f,bits32f,bits32f> {
429 bits32f operator()(bits32f a, bits32f b) const { return a*b; }
430 };
431
432 /// \brief A function object to multiply two channels. result = a * b / max_value
433 template <typename ChannelValue>
434 struct channel_multiplier : public std::binary_function<ChannelValue, ChannelValue, ChannelValue> {
435 ChannelValue operator()(ChannelValue a, ChannelValue b) const {
436 typedef detail::channel_convert_to_unsigned<ChannelValue> to_unsigned;
437 typedef detail::channel_convert_from_unsigned<ChannelValue> from_unsigned;
438 typedef channel_multiplier_unsigned<typename to_unsigned::result_type> multiplier_unsigned;
439 return from_unsigned()(multiplier_unsigned()(to_unsigned()(a), to_unsigned()(b)));
440 }
441 };
442
443 /// \brief A function multiplying two channels. result = a * b / max_value
444 template <typename Channel> // Models ChannelConcept (could be a channel reference)
445 inline typename channel_traits<Channel>::value_type channel_multiply(Channel a, Channel b) {
446 return channel_multiplier<typename channel_traits<Channel>::value_type>()(a,b);
447 }
448 /// @}
449
450 /**
451 \defgroup ChannelInvertAlgorithm channel_invert
452 \ingroup ChannelAlgorithm
453 \brief Returns the inverse of a channel. result = max_value - x + min_value
454
455 Example:
456 \code
457 // bits8 == uint8_t == unsigned char
458 bits8 x=255;
459 bits8 inv = channel_invert(x);
460 assert(inv == 0);
461 \endcode
462 */
463
464 /// \brief Default implementation. Provide overloads for performance
465 /// \ingroup ChannelInvertAlgorithm channel_invert
466 template <typename Channel> // Models ChannelConcept (could be a channel reference)
467 inline typename channel_traits<Channel>::value_type channel_invert(Channel x) {
468 return channel_traits<Channel>::max_value()-x + channel_traits<Channel>::min_value();
469 }
470
471 //#ifdef _MSC_VER
472 //#pragma warning(pop)
473 //#endif
474
475 } } // namespace boost::gil
476
477 #endif