aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/colors/YUV.hpp
blob: 6847160f915772601db370291cd8c1d964c402b9 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#include <algorithm>
#include "RGB.h"
#include "../utility.h"

namespace meow{
  template<class T>
  inline YUV<T>::YUV(){ }
  template<class T>
  inline YUV<T>::YUV(T const& y, T const& u, T const& v){
    yuv_[0] = y; yuv_[1] = u; yuv_[2] = v;
  }
  template<class T>
  inline YUV<T>::YUV(T const* yuv){
    for(int i = 0; i < 3; i++){
      yuv_[i] = yuv[i];
    }
  }
  /////////////////// **# access #** /////////////////
  template<class T>
  inline T YUV<T>::y()           const { return yuv_[0]; }
  template<class T>
  inline T YUV<T>::u()           const { return yuv_[1]; }
  template<class T>
  inline T YUV<T>::v()           const { return yuv_[2]; }
  template<class T>
  inline T YUV<T>::yuv(size_t i) const {
    return yuv_[std::min((size_t)3 - 1, i)];
  }
  template<class T>
  inline T YUV<T>::vuy(size_t i) const {return yuv(2-i);}
  /////////////////// **# setting #** ////////////////
  template<class T>
  inline T YUV<T>::y(T const& val){return (yuv_[0]=val);}
  template<class T>
  inline T YUV<T>::u(T const& val){return (yuv_[1]=val);}
  template<class T>
  inline T YUV<T>::v(T const& val){return (yuv_[2]=val);}
  template<class T>
  inline T YUV<T>::yuv(size_t i, T const& val){
    i = std::min((size_t)3 - 1, i);
    return (yuv_[i] = val);
  }
  template<class T>
  inline T YUV<T>::vuy(size_t i, T const& val){
    return yuv(2 - i, val);
  }

  inline YUVf:: YUVf(): YUV(0.0, 0.0, 0.0){ }
  inline YUVf::~YUVf(){ }
  inline YUVf::YUVf(double const& y, double const& u, double const& v): YUV(y, u, v){ }
  inline YUVf::YUVf(double const* yuv): YUV(yuv){ }
  inline double YUVf::yMin() const { return 0.0; }
  inline double YUVf::yMax() const { return 1.0; }
  inline double YUVf::uMin() const { return 0.0; }
  inline double YUVf::uMax() const { return 1.0; }
  inline double YUVf::vMin() const { return 0.0; }
  inline double YUVf::vMax() const { return 1.0; }


  template<class YUV_T1, class YUV_T2>
  inline void YUV_to_YUV(YUV<YUV_T1> const& a, YUV<YUV_T2>* b){
    double y = normalize(a.yMin(), a.yMax(), a.y());
    double u = normalize(a.uMin(), a.uMax(), a.u());
    double v = normalize(a.vMin(), a.vMax(), a.v());
    b->y(denormalize(b->yMin(), b->yMax(), y));
    b->u(denormalize(b->uMin(), b->uMax(), u));
    b->v(denormalize(b->vMin(), b->vMax(), v));
  }
  template<class RGB_T, class YUV_T>
  inline void RGB_to_YUV(RGB<RGB_T> const& rgb, YUV<YUV_T>* yuv){
    double r = normalize(rgb.rMin(), rgb.rMax(), rgb.r());
    double g = normalize(rgb.gMin(), rgb.gMax(), rgb.g());
    double b = normalize(rgb.bMin(), rgb.bMax(), rgb.b());
    double y =  0.299 * r + 0.587 * g + 0.114 * b;
    double u = -0.169 * r - 0.331 * g + 0.500 * b + 0.5;
    double v =  0.500 * r - 0.419 * g - 0.081 * b + 0.5;
    yuv->y(denormalize(yuv->yMin(), yuv->yMax(), y));
    yuv->u(denormalize(yuv->uMin(), yuv->uMax(), u));
    yuv->v(denormalize(yuv->vMin(), yuv->vMax(), v));
  }
  template<class YUV_T, class RGB_T>
  inline void YUV_to_RGB(YUV<YUV_T> const& yuv, RGB<RGB_T>* rgb){
    double y = normalize(yuv.yMin(), yuv.yMax(), yuv.y());
    double u = normalize(yuv.uMin(), yuv.uMax(), yuv.u());
    double v = normalize(yuv.vMin(), yuv.vMax(), yuv.v());
    double r = y - 0.00093 * (u - 0.5) + 1.401687 * (v - 0.5);
    double g = y - 0.34370 * (u - 0.5) - 0.714170 * (v - 0.5);
    double b = y + 1.77216 * (u - 0.5) - 0.000990 * (v - 0.5);
    rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r));
    rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g));
    rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b));
  }
}