## rgb.pkg
#
# RGB colors
#
# See also:
#
src/lib/x-kit/xclient/src/color/hue-saturation-value.pkg#
src/lib/x-kit/xclient/src/color/rgb8.pkg# Compiled by:
#
src/lib/x-kit/xclient/xclient-internals.sublibstipulate
include package rw_float_vector; # Enable vec[i] and vec[i] := f notations.
#
package f8b = eight_byte_float; # eight_byte_float is from
src/lib/std/eight-byte-float.pkg package fv = rw_float_vector; # rw_float_vector is from
src/lib/std/rw-float-vector.pkgherein
package rgb
: Rgb # Rgb is from
src/lib/x-kit/xclient/src/color/rgb.api {
# We represent an RGB color value by a
# record of 64-bit floats holding
# red, green, blue in that order.
# (The compiler will optimize this to
# a very efficient packed representation.)
#
Rgb = { red: Float,
green: Float,
blue: Float
};
fun rgb_from_floats (red, green, blue) # Should do some sort of validation (restriction to [0,1) interval). What exception should we throw? Or should we silently truncate? XXX BUGGO FIXME.
=
{ red, green, blue };
fun rgb_to_floats (rgb: Rgb)
=
(rgb.red, rgb.green, rgb.blue); # Eventually we'll probably want to suppress index checking here for speed, using unsafe:: operations or whatever. XXX BUGGO FIXME.
fun rgb_from_unts (red, green, blue)
=
{ red => unt_to_float red,
green => unt_to_float green,
blue => unt_to_float blue
}
where
fun unt_to_float u
=
{ i = unt::to_int u;
f = f8b::from_int i;
f = f / 65535.0; # Our unts run 0 -> 65535.
f;
};
end;
fun rgb_to_unts { red, green, blue }
=
( float_to_unt red,
float_to_unt green,
float_to_unt blue
)
where
fun float_to_unt f
=
{ f = (f < 0.0) ?? 0.0 :: f;
f = (f > 1.0) ?? 1.0 :: f;
f = f * 65535.99; # Our unts run 0 -> 65535.
unt::from_int (f8b::truncate f);
};
end;
fun same_rgb (a: Rgb, b: Rgb)
= f8b::(====) (a.red, b.red )
and f8b::(====) (a.green, b.green)
and f8b::(====) (a.blue, b.blue )
;
# Ensure that all color components
# are in 0.0 -> 1.0 inclusive:
#
fun rgb_normalize (rgb as { red, green, blue })
=
{ if (red >= 0.0 and red <= 0.0
and green >= 0.0 and green <= 0.0
and blue >= 0.0 and blue <= 0.0
)
rgb;
else
red = red >= 0.0 ?? red :: 0.0;
red = red <= 1.0 ?? red :: 1.0;
#
green = green >= 0.0 ?? green :: 0.0;
green = green <= 1.0 ?? green :: 1.0;
#
blue = blue >= 0.0 ?? blue :: 0.0;
blue = blue <= 1.0 ?? blue :: 1.0;
#
{ red, green, blue };
fi;
};
fun rgb_to_string (c: Rgb)
=
sprintf "{ red => %g, green => %g, blue => %g }"
c.red c.green c.blue;
fun rgb_complement (c: Rgb) # Set each component c to (1.0-c).
=
{ red => 1.0 - c.red,
green => 1.0 - c.green,
blue => 1.0 - c.blue
};
fun rgb_scale (w: Float, a: Rgb) # Multiply color components by given factor, then clip to 0.0 -> 1.0 range.
=
{ red = w * a.red;
green = w * a.green;
blue = w * a.blue;
rgb_normalize { red, green, blue };
};
fun rgb_mix01 (w: Float, a: Rgb, b: Rgb) # Linear interpolation in RGB space. 0.0 yields first color, 1.0 yields second color. (The "01" in name is mnemonic of the 0.0 -> 1.0 arg range.)
=
{ red => (1.0 - w) * a.red + w * b.red,
green => (1.0 - w) * a.green + w * b.green,
blue => (1.0 - w) * a.blue + w * b.blue
};
fun rgb_mix11 (w: Float, a: Rgb, b: Rgb) # Linear interpolation in RGB space. -1.0 yields first color, 1.0 yields second color. (The "11" in name is mnemonic of the -1.0 -> 1.0 arg range.)
=
rgb_mix01 ((w + 1.0) * 0.5, a, b);
fun rgb_from_name colorname
=
rgb_from_floats (x11_color_name::to_floats colorname);
fun rgb_to_grayscale (c: Rgb)
=
( 0.2126 * c.red # Rec 601 coefficients -- see http://en.wikipedia.org/wiki/Luma_(video)
+ 0.7152 * c.green
+ 0.0722 * c.blue);
fun rgb_is_light (c: Rgb) # TRUE iff (rgb_to_grayscale c) > 0.5.
=
(rgb_to_grayscale c) > 0.5;
# Predefine a few common colors for convenience:
#
black = rgb_from_floats (0.0, 0.0, 0.0);
gray = rgb_from_floats (0.5, 0.5, 0.5);
white = rgb_from_floats (1.0, 1.0, 1.0);
#
red = rgb_from_floats (1.0, 0.0, 0.0);
green = rgb_from_floats (0.0, 1.0, 0.0);
blue = rgb_from_floats (0.0, 0.0, 1.0);
#
cyan = rgb_from_floats (0.0, 1.0, 1.0);
magenta = rgb_from_floats (1.0, 0.0, 1.0);
yellow = rgb_from_floats (1.0, 1.0, 0.0);
};
end;
## COPYRIGHT (c) 1994 by AT&T Bell Laboratories
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.