* mcgarvey@eng.utah.edu
*/
-#ifndef __COLOR_H__
-#define __COLOR_H__
+#ifndef _COLOR_H_
+#define _COLOR_H_
#include "common.h"
/*
* Initialize a color.
*/
-__fast__
+INLINE_MAYBE
void color_init(color_t* c, colorchan_t r, colorchan_t g, colorchan_t b, colorchan_t a)
{
c->r = r;
/*
* Create a new color, copied by value.
*/
-__fast__
+INLINE_MAYBE
color_t color_new(colorchan_t r, colorchan_t g, colorchan_t b, colorchan_t a)
{
color_t c;
/*
- * Define integer types for a 32-bit RGBA color representation.
+ * Get a pointer to the color data.
*/
-typedef uint32_t rgba_t;
-typedef uint8_t rgbachan_t;
+INLINE_MAYBE
+const scal_t* color_data(const color_t* c)
+{
+ return &c->r;
+}
+
/*
- * Create a new color from a 32-bit RGBA value.
+ * Print the color to stdout.
*/
-__fast__
-color_t color_from_rgba(rgba_t n)
+INLINE_MAYBE
+void color_print(color_t c)
{
- colorchan_t r = (colorchan_t)UNPACK(n, 3) / S(255.0);
- colorchan_t g = (colorchan_t)UNPACK(n, 2) / S(255.0);
- colorchan_t b = (colorchan_t)UNPACK(n, 1) / S(255.0);
- colorchan_t a = (colorchan_t)UNPACK(n, 0) / S(255.0);
- return color_new(r, g, b, a);
+#if (SCALAR_SIZE == 8)
+ const char* fmt = "[ %9.5lf %9.5lf %9.5lf %9.5lf ]";
+#else
+ const char* fmt = "[ %9.5f %9.5f %9.5f %9.5f ]";
+#endif
+ printf(fmt, c.r, c.g, c.b, c.a);
+}
+
+
+/*
+ * Add two colors together.
+ */
+INLINE_MAYBE
+color_t color_add(color_t c1, color_t c2)
+{
+ return color_new(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b, c1.a);
+}
+
+/*
+ * Add three colors together.
+ */
+INLINE_MAYBE
+color_t color_add2(color_t c1, color_t c2, color_t c3)
+{
+ return color_add(color_add(c1, c2), c3);
+}
+
+/*
+ * Multiply two colors together.
+ */
+INLINE_MAYBE
+color_t color_mult(color_t c1, color_t c2)
+{
+ c1.r *= c2.r;
+ c1.g *= c2.g;
+ c1.b *= c2.b;
+ return c1;
+}
+
+/*
+ * Scale a color by some scalar coefficient.
+ */
+INLINE_MAYBE
+color_t color_scale(color_t c, scal_t k)
+{
+ c.r *= k;
+ c.g *= k;
+ c.b *= k;
+ return c;
}
+/*
+ * Scale a color by another color and some scalar coefficient.
+ */
+INLINE_MAYBE
+color_t color_scale2(color_t c1, color_t c2, scal_t k)
+{
+ return color_scale(color_mult(c1, c2), k);
+}
+
+INLINE_MAYBE
+color_t color_blend(color_t d, color_t s)
+{
+ d.r = (S(1.0) - s.a) * d.r + s.a * s.r;
+ d.g = (S(1.0) - s.a) * d.g + s.a * s.g;
+ d.b = (S(1.0) - s.a) * d.b + s.a * s.b;
+ return d;
+}
+
+/*
+ * Clamp a color's channels to the normal range of 0.0 to 1.0.
+ */
+INLINE_MAYBE
+color_t color_clamp(color_t c)
+{
+ c.r = scal_clamp(c.r, S(0.0), S(1.0));
+ c.g = scal_clamp(c.g, S(0.0), S(1.0));
+ c.b = scal_clamp(c.b, S(0.0), S(1.0));
+ c.a = scal_clamp(c.a, S(0.0), S(1.0));
+ return c;
+}
+
+
+/*
+ * Interpolate smoothly between two colors with an alpha value.
+ */
+INLINE_MAYBE
+color_t color_interp(color_t c1, color_t c2, scal_t a)
+{
+ return color_new(c1.r * (S(1.0) - a) + c2.r * a,
+ c1.g * (S(1.0) - a) + c2.g * a,
+ c1.b * (S(1.0) - a) + c2.b * a, c1.a);
+}
+
+/*
+ * Interpolate smoothly between three colors with barycentric coordinates.
+ */
+INLINE_MAYBE
+color_t color_interp2(color_t c1, color_t c2, color_t c3, scal_t b[3])
+{
+ return color_new(c1.r * b[0] + c2.r * b[1] + c3.r * b[2],
+ c1.g * b[0] + c2.g * b[1] + c3.g * b[2],
+ c1.b * b[0] + c2.b * b[1] + c3.b * b[2], c1.a);
+}
+
+
+/*
+ * Define integer types for a 32-bit RGBA color representation.
+ */
+typedef uint8_t rgbachan_t;
+typedef uint32_t rgba_t;
+
/*
* Split a color into 8-bit RGBA channels.
*/
-__fast__
+INLINE_MAYBE
void color_split(color_t c, rgbachan_t* r, rgbachan_t* g, rgbachan_t* b, rgbachan_t* a)
{
if (r) *r = (rgbachan_t)(c.r * S(255.0));
if (a) *a = (rgbachan_t)(c.a * S(255.0));
}
+/*
+ * Create a new color from a 32-bit RGBA value.
+ */
+INLINE_MAYBE
+color_t color_from_rgba(rgba_t n)
+{
+ union {
+ rgba_t rgba;
+ struct {
+ rgbachan_t r, g, b, a;
+ } chan;
+ } u;
+ u.rgba = n;
+ colorchan_t r = (colorchan_t)u.chan.r / S(255.0);
+ colorchan_t g = (colorchan_t)u.chan.g / S(255.0);
+ colorchan_t b = (colorchan_t)u.chan.b / S(255.0);
+ colorchan_t a = (colorchan_t)u.chan.a / S(255.0);
+ return color_new(r, g, b, a);
+}
+
/*
* Convert a color to a 32-bit RGBA value.
*/
-__fast__
+INLINE_MAYBE
rgba_t rgba_from_color(color_t c)
{
- rgbachan_t r, g, b, a;
- color_split(c, &r, &g, &b, &a);
- return ((rgba_t)r << 24) | ((rgba_t)g << 16) | ((rgba_t)b << 8) | (rgba_t)a;
+ union {
+ rgba_t rgba;
+ struct {
+ rgbachan_t r, g, b, a;
+ } chan;
+ } u;
+ color_split(c, &u.chan.r, &u.chan.g, &u.chan.b, &u.chan.a);
+ return u.rgba;
}
-#endif // __COLOR_H__
+#endif // _COLOR_H_