Module: Color
- Defined in:
- lib/color.rb,
lib/color/version.rb
Overview
# Color – Color Math in Ruby
-
code: [github.com/halostatue/color](github.com/halostatue/color)
-
issues: [github.com/halostatue/color/issues](github.com/halostatue/color/issues)
-
changelog: [CHANGELOG](CHANGELOG.md)
Color is a Ruby library to provide RGB, CMYK, HSL, and other color space manipulation support to applications that require it. It provides optional named RGB colors that are commonly supported in HTML, SVG, and X11 applications.
The Color library performs purely mathematical manipulation of the colors based on color theory without reference to device color profiles (such as sRGB or Adobe RGB). For most purposes, when working with RGB and HSL color spaces, this won’t matter. Absolute color spaces (like CIE LAB and CIE XYZ) cannot be reliably converted to relative color spaces (like RGB) without color profiles. When necessary for conversions, Color provides D65 and D50 reference white values in Color::XYZ.
Color 2.1 fixes a Color::XYZ bug where the values were improperly clamped and adds more Color::XYZ white points for standard illuminants. It builds on the Color 2.0 major release, dropping support for all versions of Ruby prior to 3.2 as well as removing or renaming a number of features. The main breaking changes are:
-
Color classes are immutable Data objects; they are no longer mutable.
-
RGB named colors are no longer loaded on gem startup, but must be required explicitly (this is not done via ‘autoload` because there are more than 100 named colors with spelling variations) with `require “color/rgb/colors”`.
-
Color palettes have been removed.
-
‘Color::CSS` and `Color::CSS#[]` have been removed.
Defined Under Namespace
Classes: CIELAB, CMYK, Grayscale, HSL, RGB, XYZ, YIQ
Constant Summary collapse
- EPSILON =
The maximum “resolution” for color math; if any value is less than or equal to this value, it is treated as zero.
1e-5- TOLERANCE =
The tolerance for comparing the components of two colors. In general, colors are considered equal if all of their components are within this tolerance value of each other.
1e-4- VERSION =
:nodoc:
"2.1.1"
Class Method Summary collapse
-
.normalize(value, range = 0.0..1.0) ⇒ Object
:nodoc:.
-
.translate_range(x, to:, from: 0.0..1.0) ⇒ Object
:nodoc:.
Instance Method Summary collapse
-
#==(other) ⇒ Object
Compares the ‘other` color to this one.
-
#components ⇒ Object
It is useful to know the number of components in some cases.
-
#css_value(value, format = nil) ⇒ Object
:nodoc:.
-
#map(&block) ⇒ Object
Apply the provided block to each color component in turn, returning a new color instance.
-
#map_with(other, &block) ⇒ Object
Apply the provided block to the color component pairs in turn, returning a new color instance.
-
#scale(*factors) ⇒ Object
Multiplies each component value by the scaling factor or factors, returning a new color object with the scaled values.
-
#zip(other) ⇒ Object
Zip the color component pairs together.
Class Method Details
.normalize(value, range = 0.0..1.0) ⇒ Object
:nodoc:
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/color.rb', line 188 module_function def normalize(value, range = 0.0..1.0) # :nodoc: value = value.clamp(range) if near?(value, range.begin) range.begin elsif near?(value, range.end) range.end else value end end |
.translate_range(x, to:, from: 0.0..1.0) ⇒ Object
:nodoc:
211 212 213 214 215 216 |
# File 'lib/color.rb', line 211 module_function def translate_range(x, to:, from: 0.0..1.0) # :nodoc: a, b = [from.begin, from.end] c, d = [to.begin, to.end] y = (((x - a) * (d - c)) / (b - a)) + c y.clamp(to) end |
Instance Method Details
#==(other) ⇒ Object
Compares the ‘other` color to this one. The `other` color will be coerced to the same type as the current color. Such converted color comparisons will always be more approximate than non-converted comparisons.
All values are compared as floating-point values, so two colors will be reported equivalent if all component values are within TOLERANCE of each other.
70 71 72 |
# File 'lib/color.rb', line 70 def ==(other) other.is_a?(Color) && to_internal.zip(coerce(other).to_internal).all? { near?(_1, _2) } end |
#components ⇒ Object
It is useful to know the number of components in some cases. Since most colors are defined with three components, we define a constant value here. Color classes that require more or less should override this.
We could define this as ‘members.count`, but this would require a special case for Color::RGB regardless because there’s an additional member for RGB colors (names).
61 |
# File 'lib/color.rb', line 61 def components = 3 # :nodoc: |
#css_value(value, format = nil) ⇒ Object
:nodoc:
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/color.rb', line 122 def css_value(value, format = nil) # :nodoc: if value.nil? "none" elsif near_zero?(value) "0" else suffix = case format in :percent "%" in :degrees "deg" else "" end "%3.2f%s" % [value, suffix] end end |
#map(&block) ⇒ Object
Apply the provided block to each color component in turn, returning a new color instance.
77 |
# File 'lib/color.rb', line 77 def map(&block) = self.class.from_internal(*to_internal.map(&block)) |
#map_with(other, &block) ⇒ Object
Apply the provided block to the color component pairs in turn, returning a new color instance.
82 |
# File 'lib/color.rb', line 82 def map_with(other, &block) = self.class.from_internal(*zip(other).map(&block)) |
#scale(*factors) ⇒ Object
Multiplies each component value by the scaling factor or factors, returning a new color object with the scaled values.
If a single scaling factor is provided, it is applied to all components:
“‘ruby rgb = Color::RGB::Wheat # => RGB [#f5deb3] rgb.scale(0.75) # => RGB [#b8a786] “`
If more than one scaling factor is provided, there must be exactly one factor for each color component of the color object or an ‘ArgumentError` will be raised.
“‘ruby rgb = Color::RGB::Wheat # => RGB [#f5deb3] # 0xf5 * 0 == 0x00, 0xde * 0.5 == 0x6f, 0xb3 * 2 == 0x166 (clamped to 0xff) rgb.scale(0, 0.5, 2) # => RGB [#006fff]
rgb.scale(1, 2) # => Invalid scaling factors [1, 2] for Color::RGB (ArgumentError) “‘
109 110 111 112 113 114 115 116 117 118 119 |
# File 'lib/color.rb', line 109 def scale(*factors) if factors.size == 1 factor = factors.first map { _1 * factor } elsif factors.size != components raise ArgumentError, "Invalid scaling factors #{factors.inspect} for #{self.class}" else new_components = to_internal.zip(factors).map { _1 * _2 } self.class.from_internal(*new_components) end end |
#zip(other) ⇒ Object
Zip the color component pairs together.
86 |
# File 'lib/color.rb', line 86 def zip(other) = to_internal.zip(coerce(other).to_internal) |