24 #ifndef AGG_COLOR_RGBA_INCLUDED 25 #define AGG_COLOR_RGBA_INCLUDED 28 #include "agg_basics.h" 29 #include "agg_gamma_lut.h" 35 struct order_rgb {
enum rgb_e { R=0, G=1, B=2, N=3 }; };
36 struct order_bgr {
enum bgr_e { B=0, G=1, R=2, N=3 }; };
37 struct order_rgba {
enum rgba_e { R=0, G=1, B=2, A=3, N=4 }; };
38 struct order_argb {
enum argb_e { A=0, R=1, G=2, B=3, N=4 }; };
39 struct order_abgr {
enum abgr_e { A=0, B=1, G=2, R=3, N=4 }; };
40 struct order_bgra {
enum bgra_e { B=0, G=1, R=2, A=3, N=4 }; };
49 typedef double value_type;
60 rgba(
double r_,
double g_,
double b_,
double a_=1.0) :
61 r(r_), g(g_), b(b_), a(a_) {}
64 rgba(
const rgba& c,
double a_) : r(c.r), g(c.g), b(c.b), a(a_) {}
81 rgba& opacity(
double a_)
84 else if (a_ > 1) a = 1;
90 double opacity()
const 105 rgba& premultiply(
double a_)
107 if (a <= 0 || a_ <= 0)
141 rgba gradient(
rgba c,
double k)
const 144 ret.r = r + (c.r - r) * k;
145 ret.g = g + (c.g - g) * k;
146 ret.b = b + (c.b - b) * k;
147 ret.a = a + (c.a - a) * k;
160 rgba& operator*=(
double k)
170 static rgba no_color() {
return rgba(0,0,0,0); }
173 static rgba from_wavelength(
double wl,
double gamma = 1.0);
176 explicit rgba(
double wavelen,
double gamma=1.0)
178 *
this = from_wavelength(wavelen, gamma);
188 inline rgba operator*(
const rgba& a,
double b)
194 inline rgba rgba::from_wavelength(
double wl,
double gamma)
196 rgba t(0.0, 0.0, 0.0);
198 if (wl >= 380.0 && wl <= 440.0)
200 t.r = -1.0 * (wl - 440.0) / (440.0 - 380.0);
203 else if (wl >= 440.0 && wl <= 490.0)
205 t.g = (wl - 440.0) / (490.0 - 440.0);
208 else if (wl >= 490.0 && wl <= 510.0)
211 t.b = -1.0 * (wl - 510.0) / (510.0 - 490.0);
213 else if (wl >= 510.0 && wl <= 580.0)
215 t.r = (wl - 510.0) / (580.0 - 510.0);
218 else if (wl >= 580.0 && wl <= 645.0)
221 t.g = -1.0 * (wl - 645.0) / (645.0 - 580.0);
223 else if (wl >= 645.0 && wl <= 780.0)
229 if (wl > 700.0) s = 0.3 + 0.7 * (780.0 - wl) / (780.0 - 700.0);
230 else if (wl < 420.0) s = 0.3 + 0.7 * (wl - 380.0) / (420.0 - 380.0);
232 t.r = std::pow(t.r * s, gamma);
233 t.g = std::pow(t.g * s, gamma);
234 t.b = std::pow(t.b * s, gamma);
238 inline rgba rgba_pre(
double r,
double g,
double b,
double a)
240 return rgba(r, g, b, a).premultiply();
245 template<
class Colorspace>
248 typedef int8u value_type;
249 typedef int32u calc_type;
250 typedef int32 long_type;
254 base_scale = 1 << base_shift,
255 base_mask = base_scale - 1,
256 base_MSB = 1 << (base_shift - 1)
284 dst.r = value_type(uround(src.r * base_mask));
285 dst.g = value_type(uround(src.g * base_mask));
286 dst.b = value_type(uround(src.b * base_mask));
287 dst.a = value_type(uround(src.a * base_mask));
301 dst.r = src.r / 255.0;
302 dst.g = src.g / 255.0;
303 dst.b = src.b / 255.0;
304 dst.a = src.a / 255.0;
320 rgba8T(
unsigned r_,
unsigned g_,
unsigned b_,
unsigned a_ = base_mask) :
333 rgba8T(
const self_type& c,
unsigned a_) :
334 r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
344 operator rgba()
const 352 static AGG_INLINE
double to_double(value_type a)
354 return double(a) / base_mask;
358 static AGG_INLINE value_type from_double(
double a)
360 return value_type(uround(a * base_mask));
364 static AGG_INLINE value_type empty_value()
370 static AGG_INLINE value_type full_value()
376 AGG_INLINE
bool is_transparent()
const 382 AGG_INLINE
bool is_opaque()
const 384 return a == base_mask;
388 static AGG_INLINE value_type invert(value_type x)
390 return base_mask - x;
395 static AGG_INLINE value_type multiply(value_type a, value_type b)
397 calc_type t = a * b + base_MSB;
398 return value_type(((t >> base_shift) + t) >> base_shift);
402 static AGG_INLINE value_type demultiply(value_type a, value_type b)
412 else return value_type((a * base_mask + (b >> 1)) / b);
417 static AGG_INLINE T downscale(T a)
419 return a >> base_shift;
424 static AGG_INLINE T downshift(T a,
unsigned n)
432 static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
434 return multiply(a, b);
438 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
440 return multiply(b, a);
445 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
447 return p + q - multiply(p, a);
452 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
454 int t = (q - p) * a + base_MSB - (p > q);
455 return value_type(p + (((t >> base_shift) + t) >> base_shift));
466 self_type& transparent()
473 self_type& opacity(
double a_)
476 else if (a_ > 1) a = 1;
477 else a = (value_type)uround(a_ *
double(base_mask));
482 double opacity()
const 484 return double(a) / double(base_mask);
488 AGG_INLINE self_type& premultiply()
507 AGG_INLINE self_type& premultiply(
unsigned a_)
509 if (a != base_mask || a_ < base_mask)
511 if (a == 0 || a_ == 0)
517 calc_type r_ = (calc_type(r) * a_) / a;
518 calc_type g_ = (calc_type(g) * a_) / a;
519 calc_type b_ = (calc_type(b) * a_) / a;
520 r = value_type((r_ > a_) ? a_ : r_);
521 g = value_type((g_ > a_) ? a_ : g_);
522 b = value_type((b_ > a_) ? a_ : b_);
530 AGG_INLINE self_type& demultiply()
540 calc_type r_ = (calc_type(r) * base_mask) / a;
541 calc_type g_ = (calc_type(g) * base_mask) / a;
542 calc_type b_ = (calc_type(b) * base_mask) / a;
543 r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
544 g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
545 b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
552 AGG_INLINE self_type gradient(
const self_type& c,
double k)
const 555 calc_type ik = uround(k * base_mask);
556 ret.r = lerp(r, c.r, ik);
557 ret.g = lerp(g, c.g, ik);
558 ret.b = lerp(b, c.b, ik);
559 ret.a = lerp(a, c.a, ik);
564 AGG_INLINE
void add(
const self_type& c,
unsigned cover)
566 calc_type cr, cg, cb, ca;
567 if (cover == cover_mask)
569 if (c.a == base_mask)
584 cr = r + mult_cover(c.r, cover);
585 cg = g + mult_cover(c.g, cover);
586 cb = b + mult_cover(c.b, cover);
587 ca = a + mult_cover(c.a, cover);
589 r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
590 g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
591 b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
592 a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
596 template<
class GammaLUT>
597 AGG_INLINE
void apply_gamma_dir(
const GammaLUT& gamma)
605 template<
class GammaLUT>
606 AGG_INLINE
void apply_gamma_inv(
const GammaLUT& gamma)
614 static self_type no_color() {
return self_type(0,0,0,0); }
617 static self_type from_wavelength(
double wl,
double gamma = 1.0)
619 return self_type(rgba::from_wavelength(wl, gamma));
628 inline rgba8 rgb8_packed(
unsigned v)
630 return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF);
634 inline rgba8 bgr8_packed(
unsigned v)
636 return rgba8(v & 0xFF, (v >> 8) & 0xFF, (v >> 16) & 0xFF);
640 inline rgba8 argb8_packed(
unsigned v)
642 return rgba8((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, v >> 24);
646 template<
class GammaLUT>
647 rgba8 rgba8_gamma_dir(rgba8 c,
const GammaLUT& gamma)
649 return rgba8(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
653 template<
class GammaLUT>
654 rgba8 rgba8_gamma_inv(rgba8 c,
const GammaLUT& gamma)
656 return rgba8(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
664 typedef int16u value_type;
665 typedef int32u calc_type;
666 typedef int64 long_type;
670 base_scale = 1 << base_shift,
671 base_mask = base_scale - 1,
672 base_MSB = 1 << (base_shift - 1)
685 rgba16(
unsigned r_,
unsigned g_,
unsigned b_,
unsigned a_=base_mask) :
692 rgba16(
const self_type& c,
unsigned a_) :
693 r(c.r), g(c.g), b(c.b), a(value_type(a_)) {}
697 r((value_type)uround(c.r *
double(base_mask))),
698 g((value_type)uround(c.g *
double(base_mask))),
699 b((value_type)uround(c.b *
double(base_mask))),
700 a((value_type)uround(c.a *
double(base_mask))) {}
704 r(value_type((value_type(c.r) << 8) | c.r)),
705 g(value_type((value_type(c.g) << 8) | c.g)),
706 b(value_type((value_type(c.b) << 8) | c.b)),
707 a(value_type((value_type(c.a) << 8) | c.a)) {}
717 operator rgba()
const 727 operator rgba8()
const 729 return rgba8(r >> 8, g >> 8, b >> 8, a >> 8);
733 operator srgba8()
const 744 static AGG_INLINE
double to_double(value_type a)
746 return double(a) / base_mask;
750 static AGG_INLINE value_type from_double(
double a)
752 return value_type(uround(a * base_mask));
756 static AGG_INLINE value_type empty_value()
762 static AGG_INLINE value_type full_value()
768 AGG_INLINE
bool is_transparent()
const 774 AGG_INLINE
bool is_opaque()
const 776 return a == base_mask;
780 static AGG_INLINE value_type invert(value_type x)
782 return base_mask - x;
787 static AGG_INLINE value_type multiply(value_type a, value_type b)
789 calc_type t = a * b + base_MSB;
790 return value_type(((t >> base_shift) + t) >> base_shift);
794 static AGG_INLINE value_type demultiply(value_type a, value_type b)
804 else return value_type((a * base_mask + (b >> 1)) / b);
809 static AGG_INLINE T downscale(T a)
811 return a >> base_shift;
816 static AGG_INLINE T downshift(T a,
unsigned n)
824 static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
826 return multiply(a, (b << 8) | b);
830 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
832 return multiply((a << 8) | a, b) >> 8;
837 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
839 return p + q - multiply(p, a);
844 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
846 int t = (q - p) * a + base_MSB - (p > q);
847 return value_type(p + (((t >> base_shift) + t) >> base_shift));
858 self_type& transparent()
865 AGG_INLINE self_type& opacity(
double a_)
869 a = value_type(uround(a_ *
double(base_mask)));
874 double opacity()
const 876 return double(a) / double(base_mask);
880 AGG_INLINE self_type& premultiply()
899 AGG_INLINE self_type& premultiply(
unsigned a_)
901 if (a < base_mask || a_ < base_mask)
903 if (a == 0 || a_ == 0)
909 calc_type r_ = (calc_type(r) * a_) / a;
910 calc_type g_ = (calc_type(g) * a_) / a;
911 calc_type b_ = (calc_type(b) * a_) / a;
912 r = value_type((r_ > a_) ? a_ : r_);
913 g = value_type((g_ > a_) ? a_ : g_);
914 b = value_type((b_ > a_) ? a_ : b_);
922 AGG_INLINE self_type& demultiply()
932 calc_type r_ = (calc_type(r) * base_mask) / a;
933 calc_type g_ = (calc_type(g) * base_mask) / a;
934 calc_type b_ = (calc_type(b) * base_mask) / a;
935 r = value_type((r_ > calc_type(base_mask)) ? calc_type(base_mask) : r_);
936 g = value_type((g_ > calc_type(base_mask)) ? calc_type(base_mask) : g_);
937 b = value_type((b_ > calc_type(base_mask)) ? calc_type(base_mask) : b_);
944 AGG_INLINE self_type gradient(
const self_type& c,
double k)
const 947 calc_type ik = uround(k * base_mask);
948 ret.r = lerp(r, c.r, ik);
949 ret.g = lerp(g, c.g, ik);
950 ret.b = lerp(b, c.b, ik);
951 ret.a = lerp(a, c.a, ik);
956 AGG_INLINE
void add(
const self_type& c,
unsigned cover)
958 calc_type cr, cg, cb, ca;
959 if (cover == cover_mask)
961 if (c.a == base_mask)
976 cr = r + mult_cover(c.r, cover);
977 cg = g + mult_cover(c.g, cover);
978 cb = b + mult_cover(c.b, cover);
979 ca = a + mult_cover(c.a, cover);
981 r = (value_type)((cr > calc_type(base_mask)) ? calc_type(base_mask) : cr);
982 g = (value_type)((cg > calc_type(base_mask)) ? calc_type(base_mask) : cg);
983 b = (value_type)((cb > calc_type(base_mask)) ? calc_type(base_mask) : cb);
984 a = (value_type)((ca > calc_type(base_mask)) ? calc_type(base_mask) : ca);
988 template<
class GammaLUT>
989 AGG_INLINE
void apply_gamma_dir(
const GammaLUT& gamma)
997 template<
class GammaLUT>
998 AGG_INLINE
void apply_gamma_inv(
const GammaLUT& gamma)
1006 static self_type no_color() {
return self_type(0,0,0,0); }
1009 static self_type from_wavelength(
double wl,
double gamma = 1.0)
1011 return self_type(rgba::from_wavelength(wl, gamma));
1017 template<
class GammaLUT>
1018 rgba16 rgba16_gamma_dir(
rgba16 c,
const GammaLUT& gamma)
1020 return rgba16(gamma.dir(c.r), gamma.dir(c.g), gamma.dir(c.b), c.a);
1024 template<
class GammaLUT>
1025 rgba16 rgba16_gamma_inv(
rgba16 c,
const GammaLUT& gamma)
1027 return rgba16(gamma.inv(c.r), gamma.inv(c.g), gamma.inv(c.b), c.a);
1033 typedef float value_type;
1034 typedef double calc_type;
1035 typedef double long_type;
1047 rgba32(value_type r_, value_type g_, value_type b_, value_type a_= 1) :
1048 r(r_), g(g_), b(b_), a(a_) {}
1051 rgba32(
const self_type& c,
float a_) :
1052 r(c.r), g(c.g), b(c.b), a(a_) {}
1056 r(value_type(c.r)), g(value_type(c.g)), b(value_type(c.b)), a(value_type(c.a)) {}
1060 r(value_type(c.r / 255.0)),
1061 g(value_type(c.g / 255.0)),
1062 b(value_type(c.b / 255.0)),
1063 a(value_type(c.a / 255.0)) {}
1066 rgba32(
const srgba8& c) :
1074 r(value_type(c.r / 65535.0)),
1075 g(value_type(c.g / 65535.0)),
1076 b(value_type(c.b / 65535.0)),
1077 a(value_type(c.a / 65535.0)) {}
1080 operator rgba()
const 1082 return rgba(r, g, b, a);
1086 operator rgba8()
const 1096 operator srgba8()
const 1109 uround(r * 65535.0),
1110 uround(g * 65535.0),
1111 uround(b * 65535.0),
1112 uround(a * 65535.0));
1116 static AGG_INLINE
double to_double(value_type a)
1122 static AGG_INLINE value_type from_double(
double a)
1124 return value_type(a);
1128 static AGG_INLINE value_type empty_value()
1134 static AGG_INLINE value_type full_value()
1140 AGG_INLINE
bool is_transparent()
const 1146 AGG_INLINE
bool is_opaque()
const 1152 static AGG_INLINE value_type invert(value_type x)
1158 static AGG_INLINE value_type multiply(value_type a, value_type b)
1160 return value_type(a * b);
1164 static AGG_INLINE value_type demultiply(value_type a, value_type b)
1166 return (b == 0) ? 0 : value_type(a / b);
1170 template<
typename T>
1171 static AGG_INLINE T downscale(T a)
1177 template<
typename T>
1178 static AGG_INLINE T downshift(T a,
unsigned n)
1180 return n > 0 ? a / (1 << n) : a;
1184 static AGG_INLINE value_type mult_cover(value_type a, cover_type b)
1186 return value_type(a * b / cover_mask);
1190 static AGG_INLINE cover_type scale_cover(cover_type a, value_type b)
1192 return cover_type(uround(a * b));
1197 static AGG_INLINE value_type prelerp(value_type p, value_type q, value_type a)
1199 return (1 - a) * p + q;
1204 static AGG_INLINE value_type lerp(value_type p, value_type q, value_type a)
1210 return (1 - a) * p + a * q;
1221 self_type& transparent()
1228 AGG_INLINE self_type& opacity(
double a_)
1231 else if (a_ > 1) a = 1;
1232 else a = value_type(a_);
1237 double opacity()
const 1243 AGG_INLINE self_type& premultiply()
1262 AGG_INLINE self_type& demultiply()
1281 AGG_INLINE self_type gradient(
const self_type& c,
double k)
const 1284 ret.r = value_type(r + (c.r - r) * k);
1285 ret.g = value_type(g + (c.g - g) * k);
1286 ret.b = value_type(b + (c.b - b) * k);
1287 ret.a = value_type(a + (c.a - a) * k);
1292 AGG_INLINE
void add(
const self_type& c,
unsigned cover)
1294 if (cover == cover_mask)
1311 r += mult_cover(c.r, cover);
1312 g += mult_cover(c.g, cover);
1313 b += mult_cover(c.b, cover);
1314 a += mult_cover(c.a, cover);
1323 template<
class GammaLUT>
1324 AGG_INLINE
void apply_gamma_dir(
const GammaLUT& gamma)
1332 template<
class GammaLUT>
1333 AGG_INLINE
void apply_gamma_inv(
const GammaLUT& gamma)
1341 static self_type no_color() {
return self_type(0,0,0,0); }
1344 static self_type from_wavelength(
double wl,
double gamma = 1)
1346 return self_type(rgba::from_wavelength(wl, gamma));