iLab Neuromorphic Robotics Toolkit  0.1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PixelOperatorsImpl.H
Go to the documentation of this file.
1 ///*! @file
2 // @author Randolph Voorhies
3 // @copyright GNU Public License (GPL v3)
4 // @section License
5 // @verbatim
6 // // ////////////////////////////////////////////////////////////////////////
7 // // The iLab Neuromorphic Robotics Toolkit (NRT) //
8 // // Copyright 2010-2012 by the University of Southern California (USC) //
9 // // and the iLab at USC. //
10 // // //
11 // // iLab - University of Southern California //
12 // // Hedco Neurociences Building, Room HNB-10 //
13 // // Los Angeles, Ca 90089-2520 - USA //
14 // // //
15 // // See http://ilab.usc.edu for information about this project. //
16 // // ////////////////////////////////////////////////////////////////////////
17 // // This file is part of The iLab Neuromorphic Robotics Toolkit. //
18 // // //
19 // // The iLab Neuromorphic Robotics Toolkit is free software: you can //
20 // // redistribute it and/or modify it under the terms of the GNU General //
21 // // Public License as published by the Free Software Foundation, either //
22 // // version 3 of the License, or (at your option) any later version. //
23 // // //
24 // // The iLab Neuromorphic Robotics Toolkit is distributed in the hope //
25 // // that it will be useful, but WITHOUT ANY WARRANTY; without even the //
26 // // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR //
27 // // PURPOSE. See the GNU General Public License for more details. //
28 // // //
29 // // You should have received a copy of the GNU General Public License //
30 // // along with The iLab Neuromorphic Robotics Toolkit. If not, see //
31 // // <http://www.gnu.org/licenses/>. //
32 // // ////////////////////////////////////////////////////////////////////////
33 // @endverbatim */
34 //
35 //
36 // ######################################################################
37 // we could use our implicit conversion operators but that is not efficient so we
38 // will spell out all the cases for the pixel class only.
39 // ######################################################################
40 
41 template<class T, class U>
42 inline typename std::enable_if<pixel_traits<T>::has_extra_data &&
43  pixel_traits<U>::has_extra_data>::type
44 copy_extra_data(T const & from, U & to)
45 { static_cast<typename U::ExtraType&>(to) = static_cast<typename U::ExtraType>(static_cast<typename T::ExtraType>(from)); }
46 
47 template<class T, class U>
48 inline typename std::enable_if<!(pixel_traits<T>::has_extra_data &&
49  pixel_traits<U>::has_extra_data)>::type
50 copy_extra_data(T const & from, U & to)
51 { }
52 
53 
54 template<template<typename> class OpType, class T1, class T2, class RetType>
55 inline typename std::enable_if<!pixel_traits<RetType>::has_extra_data>::type
56 apply_extra_data_op(T1 const & lhs, T2 const & rhs, RetType & ret)
57 { }
58 
59 template<template<typename> class OpType, class T1, class T2, class RetType>
60  inline typename std::enable_if<pixel_traits<RetType>::has_extra_data &&
61  pixel_traits<T1>::has_extra_data &&
62  pixel_traits<T2>::has_extra_data>::type
63 apply_extra_data_op(T1 const & lhs, T2 const & rhs, RetType & ret)
64 {
65  typedef typename RetType::ExtraType RetExtraType;
66 
67  OpType<RetExtraType> op;
68 
69  RetExtraType lhs_cast = static_cast<RetExtraType>(static_cast<typename T1::ExtraType>(lhs));
70  RetExtraType rhs_cast = static_cast<RetExtraType>(static_cast<typename T2::ExtraType>(rhs));
71 
72  static_cast<typename RetType::ExtraType&>(ret) = op(lhs_cast, rhs_cast);
73 }
74 
75 template<template<typename> class OpType, class T1, class T2, class RetType>
76  inline typename std::enable_if<pixel_traits<RetType>::has_extra_data &&
77  pixel_traits<T1>::has_extra_data &&
78  !pixel_traits<T2>::has_extra_data>::type
79 apply_extra_data_op(T1 const & lhs, T2 const & rhs, RetType & ret)
80 {
81  copy_extra_data(lhs, ret);
82 }
83 
84 template<template<typename> class OpType, class T1, class T2, class RetType>
85  inline typename std::enable_if<pixel_traits<RetType>::has_extra_data &&
86  !pixel_traits<T1>::has_extra_data &&
87  pixel_traits<T2>::has_extra_data>::type
88 apply_extra_data_op(T1 const & lhs, T2 const & rhs, RetType & ret)
89 {
90  copy_extra_data(rhs, ret);
91 }
92 
93 // ######################################################################
94 //plus
95 // ######################################################################
96 template<class P1, class P2> inline
97 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value, P1>::type &
98 operator+=(P1 & lhs, P2 const & rhs)
99 {
100  typedef typename P1::PODType T1;
101  typedef typename P2::PODType T2;
102 
103  std::transform(lhs.channels.begin(), lhs.channels.end(),
104  rhs.channels.begin(), lhs.channels.begin(),
105  [](T1 const & l, T2 const& r){ return clamped_convert<T1>(l+r); });
106 
107  apply_extra_data_op<std::plus>(lhs, rhs, lhs);
108 
109  return lhs;
110 }
111 
112 // ######################################################################
113 template<class P1, class P2> inline
114 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
115  pixel_traits<P2>::is_single_channel, P1>::type &
116 operator+=(P1 & lhs, P2 const & rhs)
117 {
118  typedef typename P1::PODType T1;
119  typedef typename P2::PODType T2;
120 
121  T2 const val = rhs.channels[0];
122  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
123  [val](T1 const & l){ return clamped_convert<T1>(l+val); });
124 
125  apply_extra_data_op<std::plus>(lhs, rhs, lhs);
126 
127  return lhs;
128 }
129 
130 // ######################################################################
131 template<class P1, typename T2> inline
132 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
133  pixel_helper::is_pixel<P1>::value &&
134  std::is_arithmetic<T2>::value, P1>::type &
135 operator+=(P1 & lhs, T2 const rhs)
136 {
137  typedef typename P1::PODType T1;
138 
139  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
140  [rhs](T1 const & l){ return clamped_convert<T1>(l+rhs); });
141  return lhs;
142 }
143 
144 // ######################################################################
145 template<class P1, typename T2> inline
146 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
147  std::is_arithmetic<T2>::value, P1>::type &
148 operator+=(P1 & lhs, T2 const rhs)
149 {
150  static_cast<typename P1::BaseType&>(lhs) += rhs;
151  static_cast<typename P1::ExtraType&>(lhs) += rhs;
152  return lhs;
153 }
154 
155 // ######################################################################
156 template<class P1, class P2> inline
157 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value,
158  typename pixel_helper::are_comparable<P1,P2>::type>::type
159 operator+(P1 const & lhs, P2 const & rhs)
160 {
161  typedef typename pixel_helper::are_comparable<P1,P2>::type RetType;
162  typedef typename RetType::PODType chan_promo;
163 
164  RetType ret;
165 
166  std::transform(lhs.channels.begin(), lhs.channels.end(),
167  rhs.channels.begin(), ret.channels.begin(), std::plus<chan_promo>());
168 
169  apply_extra_data_op<std::plus>(lhs, rhs, ret);
170 
171  return ret;
172 }
173 
174 // ######################################################################
175 template<class P1, class P2> inline
176 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
177  pixel_traits<P2>::is_single_channel,
178  typename P1::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
179  operator+(P1 const & lhs, P2 const & rhs)
180 {
181  typedef typename P1::PODType T1;
182  typedef typename P2::PODType T2;
183  typedef typename promote<T1,T2>::type chan_promo;
184  typedef typename P1::template rebind<chan_promo>::type RetType;
185 
186  RetType ret;
187  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
188  std::bind2nd(std::plus<chan_promo>(), chan_promo(rhs.channels[0])));
189 
190  apply_extra_data_op<std::plus>(lhs, rhs, ret);
191 
192  return ret;
193 }
194 
195 // ######################################################################
196 template<class P1, class P2> inline
197 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
198  pixel_traits<P2>::is_multi_channel,
199  typename P2::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
200 operator+(P1 const & lhs, P2 const & rhs)
201 {
202  typedef typename P1::PODType T1;
203  typedef typename P2::PODType T2;
204  typedef typename promote<T1,T2>::type chan_promo;
205  typedef typename P2::template rebind<chan_promo>::type RetType;
206 
207  RetType ret;
208  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
209  std::bind1st(std::plus<chan_promo>(), chan_promo(lhs.channels[0])));
210 
211  apply_extra_data_op<std::plus>(lhs, rhs, ret);
212 
213  return ret;
214 }
215 
216 // ######################################################################
217 template<class P1, typename T2> inline
218 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
219  pixel_helper::is_pixel<P1>::value &&
220  std::is_arithmetic<T2>::value,
221  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
222 operator+(P1 const & lhs, T2 const rhs)
223 {
224 
225  typedef typename P1::PODType T1;
226  typedef typename promote<T1,T2>::type chan_promo;
227  typedef typename P1::template rebind<chan_promo>::type RetType;
228 
229  RetType ret;
230  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
231  std::bind2nd(std::plus<chan_promo>(), chan_promo(rhs)));
232  return ret;
233 }
234 
235 // ######################################################################
236 template<class P1, typename T2> inline
237 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
238  pixel_helper::is_pixel<P1>::value &&
239  std::is_arithmetic<T2>::value,
240  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
241 operator+(P1 const & lhs, T2 const rhs)
242 {
243  typedef typename P1::PODType T1;
244  typedef typename promote<T1,T2>::type chan_promo;
245  typedef typename P1::template rebind<chan_promo>::type RetType;
246 
247  RetType ret;
248 
249  static_cast<typename RetType::BaseType&>(ret) = static_cast<typename P1::BaseType>(lhs) + rhs;
250  static_cast<typename RetType::ExtraType&>(ret) = static_cast<typename P1::ExtraType>(lhs) + rhs;
251 
252  return ret;
253 }
254 
255 // ######################################################################
256 template<class P2, typename T1> inline
257 typename std::enable_if<!pixel_traits<P2>::has_extra_data &&
258  pixel_helper::is_pixel<P2>::value &&
259  std::is_arithmetic<T1>::value,
260  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
261 operator+(T1 const lhs, P2 const & rhs)
262 {
263 
264  typedef typename P2::PODType T2;
265  typedef typename promote<T1,T2>::type chan_promo;
266  typedef typename P2::template rebind<chan_promo>::type RetType;
267 
268  RetType ret;
269  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
270  std::bind1st(std::plus<chan_promo>(), chan_promo(lhs)));
271  return ret;
272 }
273 
274 // ######################################################################
275 template<class P2, typename T1> inline
276 typename std::enable_if<pixel_traits<P2>::has_extra_data &&
277  pixel_helper::is_pixel<P2>::value &&
278  std::is_arithmetic<T1>::value,
279  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
280 operator+(T1 const lhs, P2 const & rhs)
281 {
282 
283  typedef typename P2::PODType T2;
284  typedef typename promote<T1,T2>::type chan_promo;
285  typedef typename P2::template rebind<chan_promo>::type RetType;
286 
287  RetType ret;
288  static_cast<typename RetType::BaseType&>(ret) = lhs - static_cast<typename P2::BaseType>(rhs);
289  static_cast<typename RetType::ExtraType&>(ret) = lhs - static_cast<typename P2::ExtraType>(rhs);
290 
291  return ret;
292 }
293 
294 
295 
296 // ######################################################################
297 //minus
298 // ######################################################################
299 template<class P1, class P2> inline
300 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value, P1>::type &
301 operator-=(P1 & lhs, P2 const & rhs)
302 {
303  typedef typename P1::PODType T1;
304  typedef typename P2::PODType T2;
305 
306  std::transform(lhs.channels.begin(), lhs.channels.end(),
307  rhs.channels.begin(), lhs.channels.begin(),
308  [](T1 const & l, T2 const& r){ return clamped_convert<T1>(l-r); });
309 
310  apply_extra_data_op<std::minus>(lhs, rhs, lhs);
311 
312  return lhs;
313 }
314 
315 // ######################################################################
316 template<class P1, class P2> inline
317 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
318  pixel_traits<P2>::is_single_channel, P1>::type &
319 operator-=(P1 & lhs, P2 const & rhs)
320 {
321  typedef typename P1::PODType T1;
322  typedef typename P2::PODType T2;
323 
324  T2 const val = rhs.channels[0];
325  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
326  [val](T1 const & l){ return clamped_convert<T1>(l-val); });
327 
328  apply_extra_data_op<std::minus>(lhs, rhs, lhs);
329 
330  return lhs;
331 }
332 
333 // ######################################################################
334 template<class P1, typename T2> inline
335 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
336  pixel_helper::is_pixel<P1>::value &&
337  std::is_arithmetic<T2>::value, P1>::type &
338 operator-=(P1 & lhs, T2 const rhs)
339 {
340  typedef typename P1::PODType T1;
341 
342  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
343  [rhs](T1 const & l){ return clamped_convert<T1>(l-rhs); });
344  return lhs;
345 }
346 
347 // ######################################################################
348 template<class P1, typename T2> inline
349 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
350  std::is_arithmetic<T2>::value, P1>::type &
351 operator-=(P1 & lhs, T2 const rhs)
352 {
353  static_cast<typename P1::BaseType&>(lhs) -= rhs;
354  static_cast<typename P1::ExtraType&>(lhs) -= rhs;
355  return lhs;
356 }
357 
358 // ######################################################################
359 template<class P1, class P2> inline
360 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value,
361  typename pixel_helper::are_comparable<P1,P2>::type>::type
362 operator-(P1 const & lhs, P2 const & rhs)
363 {
364  typedef typename pixel_helper::are_comparable<P1,P2>::type RetType;
365  typedef typename RetType::PODType chan_promo;
366 
367  RetType ret;
368 
369  std::transform(lhs.channels.begin(), lhs.channels.end(),
370  rhs.channels.begin(), ret.channels.begin(), std::minus<chan_promo>());
371 
372  apply_extra_data_op<std::minus>(lhs, rhs, ret);
373 
374  return ret;
375 }
376 
377 // ######################################################################
378 template<class P1, class P2> inline
379 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
380  pixel_traits<P2>::is_single_channel,
381  typename P1::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
382  operator-(P1 const & lhs, P2 const & rhs)
383 {
384  typedef typename P1::PODType T1;
385  typedef typename P2::PODType T2;
386  typedef typename promote<T1,T2>::type chan_promo;
387  typedef typename P1::template rebind<chan_promo>::type RetType;
388 
389  RetType ret;
390  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
391  std::bind2nd(std::minus<chan_promo>(), chan_promo(rhs.channels[0])));
392 
393  apply_extra_data_op<std::minus>(lhs, rhs, ret);
394 
395  return ret;
396 }
397 
398 // ######################################################################
399 template<class P1, class P2> inline
400 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
401  pixel_traits<P2>::is_multi_channel,
402  typename P2::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
403 operator-(P1 const & lhs, P2 const & rhs)
404 {
405  typedef typename P1::PODType T1;
406  typedef typename P2::PODType T2;
407  typedef typename promote<T1,T2>::type chan_promo;
408  typedef typename P2::template rebind<chan_promo>::type RetType;
409 
410  RetType ret;
411  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
412  std::bind1st(std::minus<chan_promo>(), chan_promo(lhs.channels[0])));
413 
414  apply_extra_data_op<std::minus>(lhs, rhs, ret);
415 
416  return ret;
417 }
418 
419 // ######################################################################
420 template<class P1, typename T2> inline
421 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
422  pixel_helper::is_pixel<P1>::value &&
423  std::is_arithmetic<T2>::value,
424  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
425 operator-(P1 const & lhs, T2 const rhs)
426 {
427 
428  typedef typename P1::PODType T1;
429  typedef typename promote<T1,T2>::type chan_promo;
430  typedef typename P1::template rebind<chan_promo>::type RetType;
431 
432  RetType ret;
433  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
434  std::bind2nd(std::minus<chan_promo>(), chan_promo(rhs)));
435  return ret;
436 }
437 
438 // ######################################################################
439 template<class P1, typename T2> inline
440 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
441  pixel_helper::is_pixel<P1>::value &&
442  std::is_arithmetic<T2>::value,
443  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
444 operator-(P1 const & lhs, T2 const rhs)
445 {
446  typedef typename P1::PODType T1;
447  typedef typename promote<T1,T2>::type chan_promo;
448  typedef typename P1::template rebind<chan_promo>::type RetType;
449 
450  RetType ret;
451 
452  static_cast<typename RetType::BaseType&>(ret) = static_cast<typename P1::BaseType>(lhs) - rhs;
453  static_cast<typename RetType::ExtraType&>(ret) = static_cast<typename P1::ExtraType>(lhs) - rhs;
454 
455  return ret;
456 }
457 
458 // ######################################################################
459 template<class P2, typename T1> inline
460 typename std::enable_if<!pixel_traits<P2>::has_extra_data &&
461  pixel_helper::is_pixel<P2>::value &&
462  std::is_arithmetic<T1>::value,
463  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
464 operator-(T1 const lhs, P2 const & rhs)
465 {
466 
467  typedef typename P2::PODType T2;
468  typedef typename promote<T1,T2>::type chan_promo;
469  typedef typename P2::template rebind<chan_promo>::type RetType;
470 
471  RetType ret;
472  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
473  std::bind1st(std::minus<chan_promo>(), chan_promo(lhs)));
474  return ret;
475 }
476 
477 // ######################################################################
478 template<class P2, typename T1> inline
479 typename std::enable_if<pixel_traits<P2>::has_extra_data &&
480  pixel_helper::is_pixel<P2>::value &&
481  std::is_arithmetic<T1>::value,
482  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
483 operator-(T1 const lhs, P2 const & rhs)
484 {
485 
486  typedef typename P2::PODType T2;
487  typedef typename promote<T1,T2>::type chan_promo;
488  typedef typename P2::template rebind<chan_promo>::type RetType;
489 
490  RetType ret;
491  static_cast<typename RetType::BaseType&>(ret) = lhs - static_cast<typename P2::BaseType>(rhs);
492  static_cast<typename RetType::ExtraType&>(ret) = lhs - static_cast<typename P2::ExtraType>(rhs);
493 
494  return ret;
495 }
496 
497 
498 // ######################################################################
499 // multiplies
500 // ######################################################################
501 template<class P1, class P2> inline
502 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value, P1>::type &
503 operator*=(P1 & lhs, P2 const & rhs)
504 {
505  typedef typename P1::PODType T1;
506  typedef typename P2::PODType T2;
507 
508  std::transform(lhs.channels.begin(), lhs.channels.end(),
509  rhs.channels.begin(), lhs.channels.begin(),
510  [](T1 const & l, T2 const& r){ return clamped_convert<T1>(l*r); });
511 
512  apply_extra_data_op<std::multiplies>(lhs, rhs, lhs);
513 
514  return lhs;
515 }
516 
517 // ######################################################################
518 template<class P1, class P2> inline
519 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
520  pixel_traits<P2>::is_single_channel, P1>::type &
521 operator*=(P1 & lhs, P2 const & rhs)
522 {
523  typedef typename P1::PODType T1;
524  typedef typename P2::PODType T2;
525 
526  T2 const val = rhs.channels[0];
527  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
528  [val](T1 const & l){ return clamped_convert<T1>(l*val); });
529 
530  apply_extra_data_op<std::multiplies>(lhs, rhs, lhs);
531 
532  return lhs;
533 }
534 
535 // ######################################################################
536 template<class P1, typename T2> inline
537 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
538  pixel_helper::is_pixel<P1>::value &&
539  std::is_arithmetic<T2>::value, P1>::type &
540 operator*=(P1 & lhs, T2 const rhs)
541 {
542  typedef typename P1::PODType T1;
543 
544  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
545  [rhs](T1 const & l){ return clamped_convert<T1>(l*rhs); });
546  return lhs;
547 }
548 
549 // ######################################################################
550 template<class P1, typename T2> inline
551 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
552  std::is_arithmetic<T2>::value, P1>::type &
553 operator*=(P1 & lhs, T2 const rhs)
554 {
555  static_cast<typename P1::BaseType&>(lhs) *= rhs;
556  static_cast<typename P1::ExtraType&>(lhs) *= rhs;
557  return lhs;
558 }
559 
560 // ######################################################################
561 template<class P1, class P2> inline
562 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value,
563  typename pixel_helper::are_comparable<P1,P2>::type>::type
564 operator*(P1 const & lhs, P2 const & rhs)
565 {
566  typedef typename pixel_helper::are_comparable<P1,P2>::type RetType;
567  typedef typename RetType::PODType chan_promo;
568 
569  RetType ret;
570 
571  std::transform(lhs.channels.begin(), lhs.channels.end(),
572  rhs.channels.begin(), ret.channels.begin(), std::multiplies<chan_promo>());
573 
574  apply_extra_data_op<std::multiplies>(lhs, rhs, ret);
575 
576  return ret;
577 }
578 
579 // ######################################################################
580 template<class P1, class P2> inline
581 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
582  pixel_traits<P2>::is_single_channel,
583  typename P1::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
584  operator*(P1 const & lhs, P2 const & rhs)
585 {
586  typedef typename P1::PODType T1;
587  typedef typename P2::PODType T2;
588  typedef typename promote<T1,T2>::type chan_promo;
589  typedef typename P1::template rebind<chan_promo>::type RetType;
590 
591  RetType ret;
592  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
593  std::bind2nd(std::multiplies<chan_promo>(), chan_promo(rhs.channels[0])));
594 
595  apply_extra_data_op<std::multiplies>(lhs, rhs, ret);
596 
597  return ret;
598 }
599 
600 // ######################################################################
601 template<class P1, class P2> inline
602 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
603  pixel_traits<P2>::is_multi_channel,
604  typename P2::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
605 operator*(P1 const & lhs, P2 const & rhs)
606 {
607  typedef typename P1::PODType T1;
608  typedef typename P2::PODType T2;
609  typedef typename promote<T1,T2>::type chan_promo;
610  typedef typename P2::template rebind<chan_promo>::type RetType;
611 
612  RetType ret;
613  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
614  std::bind1st(std::multiplies<chan_promo>(), chan_promo(lhs.channels[0])));
615 
616  apply_extra_data_op<std::multiplies>(lhs, rhs, ret);
617 
618  return ret;
619 }
620 
621 // ######################################################################
622 template<class P1, typename T2> inline
623 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
624  pixel_helper::is_pixel<P1>::value &&
625  std::is_arithmetic<T2>::value,
626  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
627 operator*(P1 const & lhs, T2 const rhs)
628 {
629 
630  typedef typename P1::PODType T1;
631  typedef typename promote<T1,T2>::type chan_promo;
632  typedef typename P1::template rebind<chan_promo>::type RetType;
633 
634  RetType ret;
635  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
636  std::bind2nd(std::multiplies<chan_promo>(), chan_promo(rhs)));
637  return ret;
638 }
639 
640 // ######################################################################
641 template<class P1, typename T2> inline
642 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
643  pixel_helper::is_pixel<P1>::value &&
644  std::is_arithmetic<T2>::value,
645  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
646 operator*(P1 const & lhs, T2 const rhs)
647 {
648  typedef typename P1::PODType T1;
649  typedef typename promote<T1,T2>::type chan_promo;
650  typedef typename P1::template rebind<chan_promo>::type RetType;
651 
652  RetType ret;
653 
654  static_cast<typename RetType::BaseType&>(ret) = static_cast<typename P1::BaseType>(lhs) * rhs;
655  static_cast<typename RetType::ExtraType&>(ret) = static_cast<typename P1::ExtraType>(lhs) * rhs;
656 
657  return ret;
658 }
659 
660 // ######################################################################
661 template<class P2, typename T1> inline
662 typename std::enable_if<!pixel_traits<P2>::has_extra_data &&
663  pixel_helper::is_pixel<P2>::value &&
664  std::is_arithmetic<T1>::value,
665  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
666 operator*(T1 const lhs, P2 const & rhs)
667 {
668 
669  typedef typename P2::PODType T2;
670  typedef typename promote<T1,T2>::type chan_promo;
671  typedef typename P2::template rebind<chan_promo>::type RetType;
672 
673  RetType ret;
674  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
675  std::bind1st(std::multiplies<chan_promo>(), chan_promo(lhs)));
676  return ret;
677 }
678 
679 // ######################################################################
680 template<class P2, typename T1> inline
681 typename std::enable_if<pixel_traits<P2>::has_extra_data &&
682  pixel_helper::is_pixel<P2>::value &&
683  std::is_arithmetic<T1>::value,
684  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
685 operator*(T1 const lhs, P2 const & rhs)
686 {
687 
688  typedef typename P2::PODType T2;
689  typedef typename promote<T1,T2>::type chan_promo;
690  typedef typename P2::template rebind<chan_promo>::type RetType;
691 
692  RetType ret;
693  static_cast<typename RetType::BaseType&>(ret) = lhs - static_cast<typename P2::BaseType>(rhs);
694  static_cast<typename RetType::ExtraType&>(ret) = lhs - static_cast<typename P2::ExtraType>(rhs);
695 
696  return ret;
697 }
698 
699 // ######################################################################
700 // divides
701 // ######################################################################
702 template<class P1, class P2> inline
703 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value, P1>::type &
704 operator/=(P1 & lhs, P2 const & rhs)
705 {
706  typedef typename P1::PODType T1;
707  typedef typename P2::PODType T2;
708 
709  std::transform(lhs.channels.begin(), lhs.channels.end(),
710  rhs.channels.begin(), lhs.channels.begin(),
711  [](T1 const & l, T2 const& r){ return clamped_convert<T1>(l/r); });
712 
713  apply_extra_data_op<std::divides>(lhs, rhs, lhs);
714 
715  return lhs;
716 }
717 
718 // ######################################################################
719 template<class P1, class P2> inline
720 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
721  pixel_traits<P2>::is_single_channel, P1>::type &
722 operator/=(P1 & lhs, P2 const & rhs)
723 {
724  typedef typename P1::PODType T1;
725  typedef typename P2::PODType T2;
726 
727  T2 const val = rhs.channels[0];
728  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
729  [val](T1 const & l){ return clamped_convert<T1>(l/val); });
730 
731  apply_extra_data_op<std::divides>(lhs, rhs, lhs);
732 
733  return lhs;
734 }
735 
736 // ######################################################################
737 template<class P1, typename T2> inline
738 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
739  pixel_helper::is_pixel<P1>::value &&
740  std::is_arithmetic<T2>::value, P1>::type &
741 operator/=(P1 & lhs, T2 const rhs)
742 {
743  typedef typename P1::PODType T1;
744 
745  std::transform(lhs.channels.begin(), lhs.channels.end(), lhs.channels.begin(),
746  [rhs](T1 const & l){ return clamped_convert<T1>(l/rhs); });
747  return lhs;
748 }
749 
750 // ######################################################################
751 template<class P1, typename T2> inline
752 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
753  std::is_arithmetic<T2>::value, P1>::type &
754 operator/=(P1 & lhs, T2 const rhs)
755 {
756  static_cast<typename P1::BaseType&>(lhs) /= rhs;
757  static_cast<typename P1::ExtraType&>(lhs) /= rhs;
758  return lhs;
759 }
760 
761 // ######################################################################
762 template<class P1, class P2> inline
763 typename std::enable_if<pixel_helper::are_comparable<P1,P2>::value,
764  typename pixel_helper::are_comparable<P1,P2>::type>::type
765 operator/(P1 const & lhs, P2 const & rhs)
766 {
767  typedef typename pixel_helper::are_comparable<P1,P2>::type RetType;
768  typedef typename RetType::PODType chan_promo;
769 
770  RetType ret;
771 
772  std::transform(lhs.channels.begin(), lhs.channels.end(),
773  rhs.channels.begin(), ret.channels.begin(), std::divides<chan_promo>());
774 
775  apply_extra_data_op<std::divides>(lhs, rhs, ret);
776 
777  return ret;
778 }
779 
780 // ######################################################################
781 template<class P1, class P2> inline
782 typename std::enable_if<pixel_traits<P1>::is_multi_channel &&
783  pixel_traits<P2>::is_single_channel,
784  typename P1::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
785  operator/(P1 const & lhs, P2 const & rhs)
786 {
787  typedef typename P1::PODType T1;
788  typedef typename P2::PODType T2;
789  typedef typename promote<T1,T2>::type chan_promo;
790  typedef typename P1::template rebind<chan_promo>::type RetType;
791 
792  RetType ret;
793  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
794  std::bind2nd(std::divides<chan_promo>(), chan_promo(rhs.channels[0])));
795 
796  apply_extra_data_op<std::divides>(lhs, rhs, ret);
797 
798  return ret;
799 }
800 
801 // ######################################################################
802 template<class P1, class P2> inline
803 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
804  pixel_traits<P2>::is_multi_channel,
805  typename P2::template rebind<typename promote<typename P1::PODType, typename P2::PODType>::type>::type>::type
806 operator/(P1 const & lhs, P2 const & rhs)
807 {
808  typedef typename P1::PODType T1;
809  typedef typename P2::PODType T2;
810  typedef typename promote<T1,T2>::type chan_promo;
811  typedef typename P2::template rebind<chan_promo>::type RetType;
812 
813  RetType ret;
814  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
815  std::bind1st(std::divides<chan_promo>(), chan_promo(lhs.channels[0])));
816 
817  apply_extra_data_op<std::divides>(lhs, rhs, ret);
818 
819  return ret;
820 }
821 
822 // ######################################################################
823 template<class P1, typename T2> inline
824 typename std::enable_if<!pixel_traits<P1>::has_extra_data &&
825  pixel_helper::is_pixel<P1>::value &&
826  std::is_arithmetic<T2>::value,
827  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
828 operator/(P1 const & lhs, T2 const rhs)
829 {
830 
831  typedef typename P1::PODType T1;
832  typedef typename promote<T1,T2>::type chan_promo;
833  typedef typename P1::template rebind<chan_promo>::type RetType;
834 
835  RetType ret;
836  std::transform(lhs.channels.begin(), lhs.channels.end(), ret.channels.begin(),
837  std::bind2nd(std::divides<chan_promo>(), chan_promo(rhs)));
838  return ret;
839 }
840 
841 // ######################################################################
842 template<class P1, typename T2> inline
843 typename std::enable_if<pixel_traits<P1>::has_extra_data &&
844  pixel_helper::is_pixel<P1>::value &&
845  std::is_arithmetic<T2>::value,
846  typename P1::template rebind<typename nrt::promote<typename P1::PODType,T2>::type>::type>::type
847 operator/(P1 const & lhs, T2 const rhs)
848 {
849  typedef typename P1::PODType T1;
850  typedef typename promote<T1,T2>::type chan_promo;
851  typedef typename P1::template rebind<chan_promo>::type RetType;
852 
853  RetType ret;
854 
855  static_cast<typename RetType::BaseType&>(ret) = static_cast<typename P1::BaseType>(lhs) / rhs;
856  static_cast<typename RetType::ExtraType&>(ret) = static_cast<typename P1::ExtraType>(lhs) / rhs;
857 
858  return ret;
859 }
860 
861 // ######################################################################
862 template<class P2, typename T1> inline
863 typename std::enable_if<!pixel_traits<P2>::has_extra_data &&
864  pixel_helper::is_pixel<P2>::value &&
865  std::is_arithmetic<T1>::value,
866  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
867 operator/(T1 const lhs, P2 const & rhs)
868 {
869 
870  typedef typename P2::PODType T2;
871  typedef typename promote<T1,T2>::type chan_promo;
872  typedef typename P2::template rebind<chan_promo>::type RetType;
873 
874  RetType ret;
875  std::transform(rhs.channels.begin(), rhs.channels.end(), ret.channels.begin(),
876  std::bind1st(std::divides<chan_promo>(), chan_promo(lhs)));
877  return ret;
878 }
879 
880 // ######################################################################
881 template<class P2, typename T1> inline
882 typename std::enable_if<pixel_traits<P2>::has_extra_data &&
883  pixel_helper::is_pixel<P2>::value &&
884  std::is_arithmetic<T1>::value,
885  typename P2::template rebind<typename promote<T1,typename P2::PODType>::type>::type>::type
886 operator/(T1 const lhs, P2 const & rhs)
887 {
888 
889  typedef typename P2::PODType T2;
890  typedef typename promote<T1,T2>::type chan_promo;
891  typedef typename P2::template rebind<chan_promo>::type RetType;
892 
893  RetType ret;
894  static_cast<typename RetType::BaseType&>(ret) = lhs - static_cast<typename P2::BaseType>(rhs);
895  static_cast<typename RetType::ExtraType&>(ret) = lhs - static_cast<typename P2::ExtraType>(rhs);
896 
897  return ret;
898 }
899 
900 // ######################################################################
901 // ######################################################################
902 // ######################################################################
903 template <class P1, class P2> inline
904 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
905  pixel_traits<P2>::is_single_channel, bool>::type
906 operator==(P1 const & lhs, P2 const & rhs)
907 { return (lhs.channels[0] == rhs.channels[0]); }
908 
909 template <class P1, class P2> inline
910 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
911  pixel_traits<P2>::is_single_channel, bool>::type
912 operator!=(P1 const & lhs, P2 const & rhs)
913 { return (lhs.channels[0] != rhs.channels[0]); }
914 
915 template <class P1, class P2> inline
916 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
917  pixel_traits<P2>::is_single_channel, bool>::type
918 operator<(P1 const & lhs, P2 const & rhs)
919 { return (lhs.channels[0] < rhs.channels[0]); }
920 
921 template <class P1, class P2> inline
922 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
923  pixel_traits<P2>::is_single_channel, bool>::type
924 operator<=(P1 const & lhs, P2 const & rhs)
925 { return (lhs.channels[0] <= rhs.channels[0]); }
926 
927 template <class P1, class P2> inline
928 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
929  pixel_traits<P2>::is_single_channel, bool>::type
930 operator>(P1 const & lhs, P2 const & rhs)
931 { return (lhs.channels[0] > rhs.channels[0]); }
932 
933 template <class P1, class P2> inline
934 typename std::enable_if<pixel_traits<P1>::is_single_channel &&
935  pixel_traits<P2>::is_single_channel, bool>::type
936 operator>=(P1 const & lhs, P2 const & rhs)
937 { return (lhs.channels[0] >= rhs.channels[0]); }
938 
939 // ######################################################################
940 // ######################################################################
941 // ######################################################################
942 template<class P1, class P2> inline
943 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
944  (pixel_traits<P1>::num_channels ==
945  pixel_traits<P2>::num_channels), bool>::type
946 operator==(P1 const & lhs, P2 const & rhs)
947 {
948  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
949  [](double const result, double const val){ return result + val*val; });
950  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
951  [](double const result, double const val){ return result + val*val; });
952  return sumsqr1 == sumsqr2;
953 }
954 
955 template<class P1, class P2> inline
956 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
957  (pixel_traits<P1>::num_channels ==
958  pixel_traits<P2>::num_channels), bool>::type
959 operator!=(P1 const & lhs, P2 const & rhs)
960 {
961  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
962  [](double const result, double const val){ return result + val*val; });
963  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
964  [](double const result, double const val){ return result + val*val; });
965  return sumsqr1 != sumsqr2;
966 }
967 
968 template<class P1, class P2> inline
969 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
970  (pixel_traits<P1>::num_channels ==
971  pixel_traits<P2>::num_channels), bool>::type
972 operator<(P1 const & lhs, P2 const & rhs)
973 {
974  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
975  [](double const result, double const val){ return result + val*val; });
976  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
977  [](double const result, double const val){ return result + val*val; });
978  return sumsqr1 < sumsqr2;
979 }
980 
981 template<class P1, class P2> inline
982 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
983  (pixel_traits<P1>::num_channels ==
984  pixel_traits<P2>::num_channels), bool>::type
985 operator<=(P1 const & lhs, P2 const & rhs)
986 {
987  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
988  [](double const result, double const val){ return result + val*val; });
989  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
990  [](double const result, double const val){ return result + val*val; });
991  return sumsqr1 <= sumsqr2;
992 }
993 
994 template<class P1, class P2> inline
995 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
996  (pixel_traits<P1>::num_channels ==
997  pixel_traits<P2>::num_channels), bool>::type
998 operator>(P1 const & lhs, P2 const & rhs)
999 {
1000  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
1001  [](double const result, double const val){ return result + val*val; });
1002  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
1003  [](double const result, double const val){ return result + val*val; });
1004  return sumsqr1 > sumsqr2;
1005 }
1006 
1007 template<class P1, class P2> inline
1008 typename std::enable_if<pixel_traits<P2>::is_multi_channel &&
1009  (pixel_traits<P1>::num_channels ==
1010  pixel_traits<P2>::num_channels), bool>::type
1011 operator>=(P1 const & lhs, P2 const & rhs)
1012 {
1013  double sumsqr1 = std::accumulate(lhs.channels.begin(),lhs.channels.end(), 0.0,
1014  [](double const result, double const val){ return result + val*val; });
1015  double sumsqr2 = std::accumulate(rhs.channels.begin(),rhs.channels.end(), 0.0,
1016  [](double const result, double const val){ return result + val*val; });
1017  return sumsqr1 >= sumsqr2;
1018 }