aboutsummaryrefslogtreecommitdiffstats
path: root/meowpp/colors
diff options
context:
space:
mode:
authorcathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
committercathook <b01902109@csie.ntu.edu.tw>2014-06-01 13:56:57 +0800
commitd5052f1c296dddf51b3e83d59bf3e3c1952cb2d0 (patch)
tree16f7920c5079e0aefcf9509d2dbab59c464d42bd /meowpp/colors
parentbd58f63900410ec4764031f2e6de2d75e91434b3 (diff)
downloadmeow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.gz
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.bz2
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.lz
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.xz
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.tar.zst
meow-d5052f1c296dddf51b3e83d59bf3e3c1952cb2d0.zip
big chnage
Diffstat (limited to 'meowpp/colors')
-rw-r--r--meowpp/colors/!readme.asciidoc78
-rw-r--r--meowpp/colors/Color3_Space.h78
-rw-r--r--meowpp/colors/HSL_Space.h188
-rw-r--r--meowpp/colors/HSV_Space.h188
-rw-r--r--meowpp/colors/RGB_Space.h168
-rw-r--r--meowpp/colors/YUV_Space.h131
6 files changed, 831 insertions, 0 deletions
diff --git a/meowpp/colors/!readme.asciidoc b/meowpp/colors/!readme.asciidoc
new file mode 100644
index 0000000..28b097a
--- /dev/null
+++ b/meowpp/colors/!readme.asciidoc
@@ -0,0 +1,78 @@
+
+
+一些 *color space* 以及這些space的 *transformate function* 都放在這資料夾下
+
+[NOTE]
+目前transformation function的準確率還很低, 有待以後加強
+
+===== Color3_Space.h
+
+`class Color3_Space<T>` *Channel Number = 3* 的 Color Space 的共通 *Base class*
+
+===== RGB_Space.h
+
+Channel分別是
+
+* Red
+* Green
+* Blue
+
+.Classes
+* `meow::RGBi_Space` 用 'int' 存資料, 每個channel數值合法範圍是 *0~255*
+* `meow::RGBf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0.0~1.0*
+
+.Functions
+* `meow::colorTransformation(in, *out)` for
+** RGBi_Space <--> RGBf_Space
+
+===== YUV_Space.h
+
+Channel分別是
+
+* Y 明度
+* U 色度
+* V 濃度
+
+.Classes
+* `meow::YUVf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0*
+
+.Functions
+* `meow::colorTransformation(in, *out)` for
+** YUVf_Space <--> RGBi_Space
+** YUVf_Space <--> RGBf_Space
+
+===== HSL_Space.h
+
+Channel分別是
+
+* H 色調
+* S 飽和度
+* L 亮度
+
+.Classes
+* `meow::HSLf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0*
+
+.Functions
+* `meow::colorTransformation(in, *out)` for
+** HSLf_Space <--> RGBi_Space
+** HSLf_Space <--> RGBf_Space
+** HSLf_Space <--> YUVf_Space
+
+===== HSV_Space.h
+
+Channel分別是
+
+* H 色調
+* S 飽和度
+* V 亮度
+
+.Classes
+* `meow::HSVf_Space` 用 'double' 存資料, 每個channel數值合法範圍是 *0~1.0*
+
+.Functions
+* `meow::colorTransformation(in, *out)` for
+** HSVf_Space <--> RGBi_Space
+** HSVf_Space <--> RGBf_Space
+** HSVf_Space <--> YUVf_Space
+** HSVf_Space <--> HSLf_Space
+
diff --git a/meowpp/colors/Color3_Space.h b/meowpp/colors/Color3_Space.h
new file mode 100644
index 0000000..87e215b
--- /dev/null
+++ b/meowpp/colors/Color3_Space.h
@@ -0,0 +1,78 @@
+#ifndef colors_Color3_Space_H__
+#define colors_Color3_Space_H__
+
+#include <cstdlib>
+
+#include "../Self.h"
+#include "../geo/Vectors.h"
+#include "../math/Matrix.h"
+#include "../math/utility.h"
+
+namespace meow {
+
+/*!
+ * @brief 以三個channel所組成的色彩空間
+ *
+ * @author cat_leopard
+ */
+template<class T>
+class Color3_Space {
+protected:
+ Vector3D<T> min_;
+ Vector3D<T> max_;
+ Vector3D<T> val_;
+ Color3_Space(Vector3D<T> const& min_bound,
+ Vector3D<T> const& max_bound,
+ Vector3D<T> const& init_value) {
+ min_ = min_bound;
+ max_ = max_bound;
+ val_ = init_value;
+ }
+ Color3_Space(Color3_Space const& b) {
+ min_ = b.min_;
+ max_ = b.max_;
+ copyFrom(b);
+ }
+public:
+ virtual ~Color3_Space() { }
+ Color3_Space<T>& copyFrom(Color3_Space<T> const& b) {
+ val_ = b.val_;
+ return *this;
+ }
+ template<class T2>
+ Color3_Space<T>& copyFrom(Color3_Space<T2> const& b) {
+ for (size_t i = 0; i < 3; i++) {
+ val(i, ratioMapping((double)b.min(i), (double)b.max(i), (double)b.rgb(i),
+ (double)min(i), (double)max(i)));
+ }
+ }
+ Vector3D<T> const& minV() const { return min_; }
+ Vector3D<T> const& maxV() const { return max_; }
+ Vector3D<T> const& valV() const { return val_; }
+ Vector3D<T> const& valV(Vector3D<T> const& vv) { val_ = vv; return val(); }
+ Vector3D<T> & valVGet() { return val_; }
+ T const& min(size_t id) const { return minV()(id); }
+ T const& max(size_t id) const { return maxV()(id); }
+ T const& val(size_t id) const { return valV()(id); }
+ T const& val(size_t i, T const& c) {
+ if (i == 0) val_.x(c);
+ else if (i == 1) val_.y(c);
+ else if (i == 2) val_.z(c);
+ return val(i);
+ }
+ T& valGet(size_t id) {
+ if (id == 0) return valVGet().xGet();
+ else if (id == 1) return valVGet().yGet();
+ else return valVGet().zGet();
+ }
+ Matrix<T> matrix() const {
+ Matrix<T> ret(3, 1);
+ for (size_t i = 0; i < 3; i++) {
+ ret(i, 0, val(i));
+ }
+ }
+};
+
+} // meow
+
+#endif // colors_Color3_Space_H__
diff --git a/meowpp/colors/HSL_Space.h b/meowpp/colors/HSL_Space.h
new file mode 100644
index 0000000..f70eab1
--- /dev/null
+++ b/meowpp/colors/HSL_Space.h
@@ -0,0 +1,188 @@
+#ifndef colors_HSL_Space_H__
+#define colors_HSL_Space_H__
+
+#include "Color3_Space.h"
+#include "../geo/Vectors.h"
+
+#include "RGB_Space.h"
+#include "YUV_Space.h"
+#include "../math/utility.h"
+
+#include <cstdlib>
+
+namespace meow {
+
+/*!
+ * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
+ *
+ * 其中範圍都介於0.0~1.0之間
+ *
+ * @author cat_leopard
+ */
+class HSLf_Space: public Color3_Space<double> {
+public:
+ HSLf_Space(): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
+ Vector3D<double>(PI*2.0, 1.0, 1.0),
+ Vector3D<double>( 0.0, 0.0, 0.0)) {
+ }
+ HSLf_Space(double c): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
+ Vector3D<double>(PI*2.0, 1.0, 1.0),
+ Vector3D<double>( c, c, c))
+ { }
+ HSLf_Space(Vector3D<double> const& v):
+ Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(v)) {
+ }
+ HSLf_Space(HSL_Space const& b): Color3_Space<double>(b) {
+ }
+ ~HSLf_Space() {
+ }
+ double const& hslMin(size_t i) const { return min(i); }
+ double const& hMin( ) const { return min(0); }
+ double const& sMin( ) const { return min(1); }
+ double const& lMin( ) const { return min(2); }
+ double const& hslMax(size_t i) const { return max(i); }
+ double const& hMax( ) const { return max(0); }
+ double const& sMax( ) const { return max(1); }
+ double const& lMax( ) const { return max(2); }
+ double const& hsl(size_t i) const { return val(i); }
+ double const& h( ) const { return hsl(0); }
+ double const& s( ) const { return hsl(1); }
+ double const& l( ) const { return hsl(2); }
+ double const& hsl(size_t i, double c) { return val(i, c); }
+ double const& h( double c) { return hsl(0, c); }
+ double const& s( double c) { return hsl(1, c); }
+ double const& l( double c) { return hsl(2, c); }
+ double& hslGet(size_t i) { return valGet(i); }
+ double& hGet( ) { return hslGet(0); }
+ double& sGet( ) { return hslGet(1); }
+ double& lGet( ) { return hslGet(2); }
+ HSLf_Space& operator=(HSLf_Space const& b) {
+ copyFrom(b);
+ return *this;
+ }
+ HSLf_Space operator+(HSLf_Space const& b) const {
+ return HSLf_Space(val_ + b.val_);
+ }
+ HSLf_Space operator-(HSLf_Space const& b) const {
+ return HSLf_Space(val_ - b.val_);
+ }
+ HSLf_Space operator*(double const& c) const {
+ return HSLf_Space(val_ * c);
+ }
+ HSLf_Space operator/(double const& c) const {
+ return HSLf_Space(val_ / c);
+ }
+ double operator*(HSLf_Space const& b) const {
+ return val_ * b.val_;
+ }
+};
+
+/*!
+ * @brief \c RGBf_Space to \c HSLf_Space
+ */
+inline void colorTransformate(RGBf_Space const& rgb, HSLf_Space* hsl) {
+ 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 mx = std::max(std::max(r, g), b);
+ double mn = std::min(std::min(r, g), b);
+ double h, s, l;
+ if (mx == mn ) h = 0;
+ else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn);
+ else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0;
+ else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0;
+ else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0;
+ l = 0.5 * (mx + mn);
+ if (l == 0 || mx == mn) s = 0;
+ else if(l < 0.5 ) s = (mx - mn) / (2.0 * l);
+ else s = (mx - mn) / (2 - 2.0 * l);
+ hsl->h(h);
+ hsl->s(s);
+ hsl->l(l);
+}
+
+/*!
+ * @brief \c YUVf_Space to \c HSLf_Space
+ */
+inline void colorTransformate(YUVf_Space const& yuv, HSLf_Space* hsl) {
+ RGBf_Space tmp;
+ colorTransformate(yuv, &tmp);
+ colorTransformate(tmp, hsl);
+}
+
+/*!
+ * @brief \c HSLf_Space to \c RGBf_Space
+ */
+inline void colorTransformate(HSLf_Space const& hsl, RGBf_Space* rgb) {
+ double h = normalize(hsl.hMin(), hsl.hMax(), hsl.h());
+ double s = normalize(hsl.sMin(), hsl.sMax(), hsl.s());
+ double l = normalize(hsl.lMin(), hsl.lMax(), hsl.l());
+ if(s == 0){
+ rgb->r(denormalize(rgb->rMin(), rgb->rMax(), l));
+ rgb->g(denormalize(rgb->gMin(), rgb->gMax(), l));
+ rgb->b(denormalize(rgb->bMin(), rgb->bMax(), l));
+ return ;
+ }
+ double q = (l < 0.5 ? (l * (1 + s)) : (l + s - (l * s)));
+ double p = 2 * l - q;
+ double t_r = h + 1.0 / 3.0;
+ double t_g = h;
+ double t_b = h - 1.0 / 3.0;
+ if(t_r < 0) t_r = t_r + 1.0;
+ if(t_r > 1) t_r = t_r - 1.0;
+ if(t_g < 0) t_g = t_g + 1.0;
+ if(t_g > 1) t_g = t_g - 1.0;
+ if(t_b < 0) t_b = t_b + 1.0;
+ if(t_b > 1) t_b = t_b - 1.0;
+ double r, g, b;
+ if (t_r < 1.0 / 6.0) r = p + (q - p) * 6 * t_r;
+ else if(t_r < 0.5 ) r = q;
+ else if(t_r < 2.0 / 3.0) r = p + (q - p) * 6 * (2.0 / 3.0 - t_r);
+ else r = p;
+ if (t_g < 1.0 / 6.0) g = p + (q - p) * 6 * t_g;
+ else if(t_g < 0.5 ) g = q;
+ else if(t_g < 2.0 / 3.0) g = p + (q - p) * 6 * (2.0 / 3.0 - t_g);
+ else g = p;
+ if (t_b < 1.0 / 6.0) b = p + (q - p) * 6 * t_b;
+ else if(t_b < 0.5 ) b = q;
+ else if(t_b < 2.0 / 3.0) b = p + (q - p) * 6 * (2.0 / 3.0 - t_b);
+ else b = p;
+ rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r));
+ rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g));
+ rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b));
+}
+
+/*!
+ * @brief \c HSLf_Space to \c YUVf_Space
+ */
+inline void colorTransformate(HSLf_Space const& hsl, YUVf_Space* yuv) {
+ RGBf_Space tmp;
+ colorTransformate(hsl, &tmp);
+ colorTransformate(tmp, yuv);
+}
+
+/*!
+ * @brief \c HSLf_Space to \c RGBi_Space
+ */
+inline void colorTransformate(HSLf_Space const& hsl, RGBi_Space* rgb) {
+ RGBf_Space tmp;
+ colorTransformate(hsl, &tmp);
+ rgb->copyFrom(tmp);
+}
+
+
+/*!
+ * @brief \c RGBi_Space to \c HSLf_Space
+ */
+inline void colorTransformate(RGBi_Space const& rgb, HSLf_Space* hsl) {
+ RGBf_Space tmp;
+ tmp.copyFrom(rgb);
+ colorTransformate(rgb, hsl);
+}
+
+} // meow
+
+
+#endif // colors_HSL_Space_H__
diff --git a/meowpp/colors/HSV_Space.h b/meowpp/colors/HSV_Space.h
new file mode 100644
index 0000000..96ba33c
--- /dev/null
+++ b/meowpp/colors/HSV_Space.h
@@ -0,0 +1,188 @@
+#ifndef colors_HSV_Space_H__
+#define colors_HSV_Space_H__
+
+#include "Color3_Space.h"
+#include "../geo/Vectors.h"
+
+#include "RGB_Space.h"
+#include "YUV_Space.h"
+#include "HSL_Space.h"
+#include "../math/utility.h"
+
+#include <cstdlib>
+
+namespace meow {
+
+/*!
+ * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
+ *
+ * 其中範圍都介於0.0~1.0之間
+ *
+ * @author cat_leopard
+ */
+class HSVf_Space: public Color3_Space<double> {
+public:
+ HSVf_Space(): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
+ Vector3D<double>(PI*2.0, 1.0, 1.0),
+ Vector3D<double>( 0.0, 0.0, 0.0)) {
+ }
+ HSVf_Space(double c): Color3_Space<double>(Vector3D<double>( 0.0, 0.0, 0.0),
+ Vector3D<double>(PI*2.0, 1.0, 1.0),
+ Vector3D<double>( c, c, c))
+ { }
+ HSVf_Space(Vector3D<double> const& v):
+ Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(v)) {
+ }
+ HSVf_Space(HSV_Space const& b): Color3_Space<double>(b) {
+ }
+ ~HSVf_Space() {
+ }
+ double const& hsvMin(size_t i) const { return min(i); }
+ double const& hMin( ) const { return min(0); }
+ double const& sMin( ) const { return min(1); }
+ double const& vMin( ) const { return min(2); }
+ double const& hsvMax(size_t i) const { return max(i); }
+ double const& hMax( ) const { return max(0); }
+ double const& sMax( ) const { return max(1); }
+ double const& vMax( ) const { return max(2); }
+ double const& hsv(size_t i) const { return val(i); }
+ double const& h( ) const { return hsv(0); }
+ double const& s( ) const { return hsv(1); }
+ double const& v( ) const { return hsv(2); }
+ double const& hsv(size_t i, double c) { return val(i, c); }
+ double const& h( double c) { return hsv(0, c); }
+ double const& s( double c) { return hsv(1, c); }
+ double const& v( double c) { return hsv(2, c); }
+ double& hsvGet(size_t i) { return valGet(i); }
+ double& hGet( ) { return hsvGet(0); }
+ double& sGet( ) { return hsvGet(1); }
+ double& vGet( ) { return hsvGet(2); }
+ HSVf_Space& operator=(HSVf_Space const& b) {
+ copyFrom(b);
+ return *this;
+ }
+ HSVf_Space operator+(HSVf_Space const& b) const {
+ return HSVf_Space(val_ + b.val_);
+ }
+ HSVf_Space operator-(HSVf_Space const& b) const {
+ return HSVf_Space(val_ - b.val_);
+ }
+ HSVf_Space operator*(double const& c) const {
+ return HSVf_Space(val_ * c);
+ }
+ HSVf_Space operator/(double const& c) const {
+ return HSVf_Space(val_ / c);
+ }
+ double operator*(HSVf_Space const& b) const {
+ return val_ * b.val_;
+ }
+};
+
+/*!
+ * @brief \c RGBf_Space to \c HSVf_Space
+ */
+inline void colorTransformate(RGBf_Space const& rgb, HSVf_Space* hsv) {
+ 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 mx = std::max(std::max(r, g), b);
+ double mn = std::min(std::min(r, g), b);
+ double h, s, v;
+ if (mx == mn ) h = 0;
+ else if(mx == r && g >= b) h = PI/3.0 * (g-b) / (mx-mn);
+ else if(mx == r && g < b) h = PI/3.0 * (g-b) / (mx-mn) + PI * 2.0;
+ else if(mx == g ) h = PI/3.0 * (b-r) / (mx-mn) + PI/3.0*2.0;
+ else h = PI/3.0 * (r-g) / (mx-mn) + PI/3.0*4.0;
+ if(mx == 0) s = 0;
+ else s = 1 - mn / mx;
+ v = mx;
+ hsv->h(h);
+ hsv->s(s);
+ hsv->v(v);
+}
+
+/*!
+ * @brief \c YUVf_Space to \c HSVf_Space
+ */
+inline void colorTransformate(YUVf_Space const& yuv, HSVf_Space* hsv) {
+ RGBf_Space tmp;
+ colorTransformate( yuv, &tmp);
+ colorTransformate(*tmp, hsv);
+}
+
+/*!
+ * @brief \c HSLf_Space to \c HSVf_Space
+ */
+inline void colorTransformate(HSLf_Space const& hsl, HSVf_Space* hsv) {
+ RGBf_Space tmp;
+ colorTransformate( hsl, &tmp);
+ colorTransformate(*tmp, hsv);
+}
+
+/*!
+ * @brief \c HSVf_Space to \c RGBf_Space
+ */
+inline void colorTransformate(HSVf_Space const& hsv, RGBf_Space* rgb) {
+ double h = normalize(hsv.hMin(), hsv.hMax(), hsv.h()) * 360;
+ double s = normalize(hsv.sMin(), hsv.sMax(), hsv.s());
+ double v = normalize(hsv.vMin(), hsv.vMax(), hsv.v());
+ int hi = (int)h / 60 % 6;
+ double f = h / 60.0 - hi;
+ double p = v * (1 - s);
+ double q = v * (1 - f * s);
+ double t = v * (1 - (1 - f) * s);
+ double r, g, b;
+ if (hi == 0){ r = v; g = t; b = p; }
+ else if(hi == 1){ r = q; g = v; b = p; }
+ else if(hi == 2){ r = p; g = v; b = t; }
+ else if(hi == 3){ r = p; g = q; b = v; }
+ else if(hi == 4){ r = t; g = p; b = v; }
+ else { r = v; g = p; b = q; }
+ rgb->r(denormalize(rgb->rMin(), rgb->rMax(), r));
+ rgb->g(denormalize(rgb->gMin(), rgb->gMax(), g));
+ rgb->b(denormalize(rgb->bMin(), rgb->bMax(), b));
+}
+
+/*!
+ * @brief \c HSVf_Space to \c YUVf_Space
+ */
+inline void colorTransformate(HSVf_Space const& hsv, YUVf_Space* yuv) {
+ RGBf_Space tmp;
+ colorTransformate( hsv, &tmp);
+ colorTransformate(*tmp, yuv);
+}
+
+/*!
+ * @brief \c HSVf_Space to \c HSLf_Space
+ */
+inline void colorTransformate(HSVf_Space const& hsv, HSLf_Space* hsl) {
+ RGBf_Space tmp;
+ colorTransformate( hsv, &tmp);
+ colorTransformate(*tmp, hsl);
+}
+
+/*!
+ * @brief \c HSVf_Space to \c RGBi_Space
+ */
+inline void colorTransformate(HSVf_Space const& hsv, RGBi_Space* rgb) {
+ RGBf_Space tmp;
+ colorTransformate(hsv, &tmp);
+ rgb->copyFrom(tmp);
+}
+
+
+/*!
+ * @brief \c RGBi_Space to \c HSVf_Space
+ */
+inline void colorTransformate(RGBi_Space const& rgb, HSVf_Space* hsv) {
+ RGBf_Space tmp;
+ tmp.copyFrom(rgb);
+ colorTransformate(rgb, hsv);
+}
+
+} // meow
+
+
+#endif // colors_HSV_Space_H__
diff --git a/meowpp/colors/RGB_Space.h b/meowpp/colors/RGB_Space.h
new file mode 100644
index 0000000..ea04598
--- /dev/null
+++ b/meowpp/colors/RGB_Space.h
@@ -0,0 +1,168 @@
+#ifndef colors_RGB_Space_H__
+#define colors_RGB_Space_H__
+
+#include "Color3_Space.h"
+#include "../geo/Vectors.h"
+#include "../math/utility.h"
+
+#include <cstdlib>
+
+namespace meow {
+
+/*!
+ * @brief 以整數 \b Red, \b Green, \b Blue 三個值所組成的色彩空間
+ *
+ * 其中範圍都介於0~255之間
+ *
+ * @author cat_leopard
+ */
+class RGBi_Space: public Color3_Space<int> {
+public:
+ RGBi_Space(): Color3_Space<int>(Vector3D<int>( 0, 0, 0),
+ Vector3D<int>(255, 255, 255),
+ Vector3D<int>( 0, 0, 0)) {
+ }
+ RGBi_Space(int c): Color3_Space<int>(Vector3D<int>( 0, 0, 0),
+ Vector3D<int>(255, 255, 255),
+ Vector3D<int>( c, c, c)) {
+ }
+ RGBi_Space(Vector3D<int> const& v):
+ Color3_Space<int>(Vector3D<int>( 0, 0, 0),
+ Vector3D<int>(255, 255, 255),
+ Vector3D<int>(v)) {
+ }
+ RGBi_Space(RGBi_Space const& b): Color3_Space<int>(b) {
+ }
+ ~RGBi_Space() {
+ }
+ int const& rgbMin(size_t i) const { return min(i); }
+ int const& rMin( ) const { return min(0); }
+ int const& gMin( ) const { return min(1); }
+ int const& bMin( ) const { return min(2); }
+ int const& rgbMax(size_t i) const { return max(i); }
+ int const& rMax( ) const { return max(0); }
+ int const& gMax( ) const { return max(1); }
+ int const& bMax( ) const { return max(2); }
+ int const& rgb(size_t i) const { return val(i); }
+ int const& r( ) const { return rgb(0); }
+ int const& g( ) const { return rgb(1); }
+ int const& b( ) const { return rgb(2); }
+ int const& rgb(size_t i, int c) { return val(i, c); }
+ int const& r( int c) { return rgb(0, c); }
+ int const& g( int c) { return rgb(1, c); }
+ int const& b( int c) { return rgb(2, c); }
+ int& rgbGet(size_t i) { return valGet(i); }
+ int& rGet( ) { return rgbGet(0); }
+ int& gGet( ) { return rgbGet(1); }
+ int& bGet( ) { return rgbGet(2); }
+ RGBi_Space& operator=(RGBi_Space const& b) {
+ copyFrom(b);
+ return *this;
+ }
+ RGBi_Space operator+(RGBi_Space const& b) const {
+ return RGBi_Space(val_ + b.val_);
+ }
+ RGBi_Space operator-(RGBi_Space const& b) const {
+ return RGBi_Space(val_ - b.val_);
+ }
+ RGBi_Space operator*(int c) const {
+ return RGBi_Space(val_ * c);
+ }
+ RGBi_Space operator/(int c) const {
+ return RGBi_Space(val_ / c);
+ }
+ int operator*(RGBi_Space const& b) const {
+ return val_ * b.val_;
+ }
+};
+
+/*!
+ * @brief 以浮點數\b Red, \b Green, \b Blue 三個值所組成的色彩空間
+ *
+ * 其中範圍都介於0.0~1.0之間
+ *
+ * @author cat_leopard
+ */
+class RGBf_Space: public Color3_Space<double> {
+public:
+ RGBf_Space(): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(0.0, 0.0, 0.0)) {
+ }
+ RGBf_Space(double c): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>( c, c, c)) {
+ }
+ RGBf_Space(Vector3D<double> const& v):
+ Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(v)) {
+ }
+ RGBf_Space(RGBf_Space const& b): Color3_Space<double>(b) {
+ }
+ ~RGBf_Space() {
+ }
+ double const& rgbMin(size_t i) const { return min(i); }
+ double const& rMin( ) const { return min(0); }
+ double const& gMin( ) const { return min(1); }
+ double const& bMin( ) const { return min(2); }
+ double const& rgbMax(size_t i) const { return max(i); }
+ double const& rMax( ) const { return max(0); }
+ double const& gMax( ) const { return max(1); }
+ double const& bMax( ) const { return max(2); }
+ double const& rgb(size_t i) const { return val(i); }
+ double const& r( ) const { return rgb(0); }
+ double const& g( ) const { return rgb(1); }
+ double const& b( ) const { return rgb(2); }
+ double const& rgb(size_t i, double c) { return val(i, c); }
+ double const& r( double c) { return rgb(0, c); }
+ double const& g( double c) { return rgb(1, c); }
+ double const& b( double c) { return rgb(2, c); }
+ double& rgbGet(size_t i) { return valGet(i); }
+ double& rGet( ) { return rgbGet(0); }
+ double& gGet( ) { return rgbGet(1); }
+ double& bGet( ) { return rgbGet(2); }
+ RGBf_Space& operator=(RGBf_Space const& b) {
+ copyFrom(b);
+ return *this;
+ }
+ RGBf_Space operator+(RGBf_Space const& b) const {
+ return RGBf_Space(val_ + b.val_);
+ }
+ RGBf_Space operator-(RGBf_Space const& b) const {
+ return RGBf_Space(val_ - b.val_);
+ }
+ RGBf_Space operator*(double const& c) const {
+ return RGBf_Space(val_ * c);
+ }
+ RGBf_Space operator/(double const& c) const {
+ return RGBf_Space(val_ / c);
+ }
+ double operator*(RGBf_Space const& b) const {
+ return val_ * b.val_;
+ }
+};
+
+/*!
+ * @brief \c RGBi_Space to \c RGBf_Space
+ */
+inline void colorTransformate(RGBi_Space const& a, RGBf_Space* b) {
+ for (size_t i = 0; i < 3; ++i) {
+ b->rgb(i, ratioMapping<double>(a.rgbMin(i), a.rgbMax(i), a.rgb(i),
+ b->rgbMin(i), b->rgbMax(i)));
+ }
+}
+
+/*!
+ * @brief \c RGBf_Space to \c RGBi_Space
+ */
+inline void colorTransformate(RGBf_Space const& a, RGBi_Space* b) {
+ for (size_t i = 0; i < 3; ++i) {
+ b->rgb(i, ratioMapping<double>(a.rgbMin(i), a.rgbMax(i), a.rgb(i),
+ b->rgbMin(i), b->rgbMax(i)));
+ }
+}
+
+} // meow
+
+#endif // colors_RGB_Space_H__
diff --git a/meowpp/colors/YUV_Space.h b/meowpp/colors/YUV_Space.h
new file mode 100644
index 0000000..651caaf
--- /dev/null
+++ b/meowpp/colors/YUV_Space.h
@@ -0,0 +1,131 @@
+#ifndef colors_YUV_Space_H__
+#define colors_YUV_Space_H__
+
+#include "Color3_Space.h"
+#include "../geo/Vectors.h"
+
+#include "RGB_Space.h"
+#include "../math/utility.h"
+
+#include <cstdlib>
+
+namespace meow {
+
+/*!
+ * @brief 以浮點數\b Y(亮度), \b U(色度), \b V(濃度) 三個值所組成的色彩空間
+ *
+ * 其中範圍都介於0.0~1.0之間
+ *
+ * @author cat_leopard
+ */
+class YUVf_Space: public Color3_Space<double> {
+public:
+ YUVf_Space(): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(0.0, 0.0, 0.0)) {
+ }
+ YUVf_Space(double c): Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>( c, c, c)) {
+ }
+ YUVf_Space(Vector3D<double> const& v):
+ Color3_Space<double>(Vector3D<double>(0.0, 0.0, 0.0),
+ Vector3D<double>(1.0, 1.0, 1.0),
+ Vector3D<double>(v)) {
+ }
+ YUVf_Space(YUV_Space const& b): Color3_Space<double>(b) {
+ }
+ ~YUVf_Space() {
+ }
+ double const& yuvMin(size_t i) const { return min(i); }
+ double const& yMin( ) const { return min(0); }
+ double const& uMin( ) const { return min(1); }
+ double const& vMin( ) const { return min(2); }
+ double const& yuvMax(size_t i) const { return max(i); }
+ double const& yMax( ) const { return max(0); }
+ double const& uMax( ) const { return max(1); }
+ double const& vMax( ) const { return max(2); }
+ double const& yuv(size_t i) const { return val(i); }
+ double const& y( ) const { return yuv(0); }
+ double const& u( ) const { return yuv(1); }
+ double const& v( ) const { return yuv(2); }
+ double const& yuv(size_t i, double c) { return val(i, c); }
+ double const& y( double c) { return yuv(0, c); }
+ double const& u( double c) { return yuv(1, c); }
+ double const& v( double c) { return yuv(2, c); }
+ double& yuvGet(size_t i) { return valGet(i); }
+ double& yGet( ) { return yuvGet(0); }
+ double& uGet( ) { return yuvGet(1); }
+ double& vGet( ) { return yuvGet(2); }
+ YUVf_Space& operator=(YUVf_Space const& b) {
+ copyFrom(b);
+ return *this;
+ }
+ YUVf_Space operator+(YUVf_Space const& b) const {
+ return YUVf_Space(val_ + b.val_);
+ }
+ YUVf_Space operator-(YUVf_Space const& b) const {
+ return YUVf_Space(val_ - b.val_);
+ }
+ YUVf_Space operator*(double const& c) const {
+ return YUVf_Space(val_ * c);
+ }
+ YUVf_Space operator/(double const& c) const {
+ return YUVf_Space(val_ / c);
+ }
+ double operator*(YUVf_Space const& b) const {
+ return val_ * b.val_;
+ }
+};
+
+/*!
+ * @brief \c RGBf_Space to \c YUVf_Space
+ */
+inline void colorTransformate(RGBf_Space const& rgb, YUVf_Space* 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));
+}
+
+/*!
+ * @brief \c YUVf_Space to \c RGBf_Space
+ */
+inline void colorTransformate(YUVf_Space const& yuv, RGBf_Space* 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));
+}
+
+/*!
+ * @brief \c RGBi_Space to \c YUVf_Space
+ */
+inline void colorTransformate(RGBi_Space const& rgb, YUVf_Space* yuv) {
+ RGBf_Space tmp;
+ tmp.copyFrom(rgb);
+ colorTransformate(tmp, yuv);
+}
+
+/*!
+ * @brief \c YUVf_Space to \c RGBi_Space
+ */
+inline void colorTransformate(YUVf_Space const& yuv, RGBi_Space* rgb) {
+ RGBf_Space tmp;
+ colorTransformate(yuv, &tmp);
+ rgb->copyFrom(tmp);
+}
+
+} // meow
+
+#endif // colors_YUV_H__