abachrome 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.envrc +3 -0
- data/README.md +10 -0
- data/Rakefile +12 -0
- data/devenv.lock +88 -17
- data/devenv.nix +2 -1
- data/devenv.yaml +5 -12
- data/lib/abachrome/abc_decimal.rb +202 -8
- data/lib/abachrome/color.rb +77 -2
- data/lib/abachrome/color_mixins/blend.rb +53 -2
- data/lib/abachrome/color_mixins/lighten.rb +49 -2
- data/lib/abachrome/color_mixins/to_colorspace.rb +67 -2
- data/lib/abachrome/color_mixins/to_lrgb.rb +70 -2
- data/lib/abachrome/color_mixins/to_oklab.rb +67 -2
- data/lib/abachrome/color_mixins/to_oklch.rb +60 -2
- data/lib/abachrome/color_mixins/to_srgb.rb +77 -2
- data/lib/abachrome/color_models/hsv.rb +25 -2
- data/lib/abachrome/color_models/oklab.rb +19 -2
- data/lib/abachrome/color_models/oklch.rb +42 -2
- data/lib/abachrome/color_models/rgb.rb +28 -2
- data/lib/abachrome/color_space.rb +76 -2
- data/lib/abachrome/converter.rb +57 -3
- data/lib/abachrome/converters/base.rb +69 -2
- data/lib/abachrome/converters/lrgb_to_oklab.rb +28 -2
- data/lib/abachrome/converters/lrgb_to_srgb.rb +27 -2
- data/lib/abachrome/converters/oklab_to_lrgb.rb +34 -2
- data/lib/abachrome/converters/oklab_to_oklch.rb +31 -2
- data/lib/abachrome/converters/oklab_to_srgb.rb +27 -2
- data/lib/abachrome/converters/oklch_to_lrgb.rb +25 -2
- data/lib/abachrome/converters/oklch_to_oklab.rb +27 -2
- data/lib/abachrome/converters/oklch_to_srgb.rb +26 -2
- data/lib/abachrome/converters/srgb_to_lrgb.rb +26 -2
- data/lib/abachrome/converters/srgb_to_oklab.rb +28 -2
- data/lib/abachrome/converters/srgb_to_oklch.rb +27 -2
- data/lib/abachrome/gamut/base.rb +2 -2
- data/lib/abachrome/gamut/p3.rb +2 -2
- data/lib/abachrome/gamut/rec2020.rb +2 -2
- data/lib/abachrome/gamut/srgb.rb +20 -2
- data/lib/abachrome/illuminants/base.rb +2 -2
- data/lib/abachrome/illuminants/d50.rb +2 -2
- data/lib/abachrome/illuminants/d55.rb +2 -2
- data/lib/abachrome/illuminants/d65.rb +2 -2
- data/lib/abachrome/illuminants/d75.rb +2 -2
- data/lib/abachrome/named/css.rb +149 -158
- data/lib/abachrome/outputs/css.rb +2 -2
- data/lib/abachrome/palette.rb +112 -2
- data/lib/abachrome/palette_mixins/interpolate.rb +20 -2
- data/lib/abachrome/palette_mixins/resample.rb +2 -2
- data/lib/abachrome/palette_mixins/stretch_luminance.rb +2 -2
- data/lib/abachrome/parsers/hex.rb +2 -2
- data/lib/abachrome/to_abcd.rb +10 -2
- data/lib/abachrome/version.rb +2 -2
- data/lib/abachrome.rb +78 -2
- data/logo.png +0 -0
- data/logo.webp +0 -0
- metadata +15 -67
@@ -1,8 +1,33 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorMixins::ToOklch - OKLCH color space conversion functionality
|
2
|
+
#
|
3
|
+
# This mixin provides methods for converting colors to the OKLCH color space, which is a
|
4
|
+
# cylindrical representation of the OKLAB color space using lightness, chroma, and hue
|
5
|
+
# coordinates. OKLCH offers intuitive color manipulation through its polar coordinate
|
6
|
+
# system where hue is represented as an angle and chroma represents colorfulness.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Convert colors to OKLCH with automatic converter lookup
|
10
|
+
# - Both non-destructive (to_oklch) and destructive (to_oklch!) conversion methods
|
11
|
+
# - Direct access to OKLCH components (lightness, chroma, hue)
|
12
|
+
# - Utility methods for OKLCH array and value extraction
|
13
|
+
# - Optimized to return the same object when no conversion is needed
|
14
|
+
# - High-precision decimal arithmetic for accurate color science calculations
|
15
|
+
#
|
16
|
+
# The OKLCH color space uses three components: L (lightness), C (chroma/colorfulness),
|
17
|
+
# and h (hue angle in degrees), providing an intuitive interface for color adjustments
|
18
|
+
# that better matches human perception compared to traditional RGB-based color spaces.
|
2
19
|
|
3
20
|
module Abachrome
|
4
21
|
module ColorMixins
|
5
22
|
module ToOklch
|
23
|
+
# Converts the current color to the OKLCH color space.
|
24
|
+
#
|
25
|
+
# This method transforms the color into the perceptually uniform OKLCH color space.
|
26
|
+
# If the color is already in OKLCH, it returns itself unchanged. If the color is in
|
27
|
+
# OKLAB, it directly converts from OKLAB to OKLCH. For all other color spaces, it
|
28
|
+
# first converts to OKLAB as an intermediate step, then converts to OKLCH.
|
29
|
+
#
|
30
|
+
# @return [Abachrome::Color] A new Color object in the OKLCH color space
|
6
31
|
def to_oklch
|
7
32
|
return self if color_space.name == :oklch
|
8
33
|
|
@@ -15,6 +40,12 @@ module Abachrome
|
|
15
40
|
end
|
16
41
|
end
|
17
42
|
|
43
|
+
# Converts the color to OKLCH color space in-place.
|
44
|
+
# This method transforms the current color to OKLCH color space, modifying
|
45
|
+
# the original object instead of creating a new one. If the color is already
|
46
|
+
# in OKLCH space, no conversion is performed.
|
47
|
+
#
|
48
|
+
# @return [Abachrome::Color] self, allowing for method chaining
|
18
49
|
def to_oklch!
|
19
50
|
unless color_space.name == :oklch
|
20
51
|
oklch_color = to_oklch
|
@@ -24,25 +55,52 @@ module Abachrome
|
|
24
55
|
self
|
25
56
|
end
|
26
57
|
|
58
|
+
# Returns the lightness component of the color in the OKLCH color space.
|
59
|
+
# This method provides direct access to the first coordinate of the OKLCH
|
60
|
+
# representation of the color, which represents perceptual lightness.
|
61
|
+
#
|
62
|
+
# @return [AbcDecimal] the lightness value in the OKLCH color space,
|
63
|
+
# typically in the range of 0.0 to 1.0, where 0.0 is black and 1.0 is white
|
27
64
|
def lightness
|
28
65
|
to_oklch.coordinates[0]
|
29
66
|
end
|
30
67
|
|
68
|
+
# Returns the chroma value of the color by converting it to the OKLCH color space.
|
69
|
+
# Chroma represents color intensity or saturation in the OKLCH color space.
|
70
|
+
#
|
71
|
+
# @return [AbcDecimal] The chroma value (second coordinate) from the OKLCH color space
|
31
72
|
def chroma
|
32
73
|
to_oklch.coordinates[1]
|
33
74
|
end
|
34
75
|
|
76
|
+
# Returns the hue value of the color in the OKLCH color space.
|
77
|
+
#
|
78
|
+
# @return [AbcDecimal] The hue component of the color in degrees (0-360)
|
79
|
+
# from the OKLCH color space representation.
|
35
80
|
def hue
|
36
81
|
to_oklch.coordinates[2]
|
37
82
|
end
|
38
83
|
|
84
|
+
# Returns the OKLCH coordinates of the color.
|
85
|
+
#
|
86
|
+
# @return [Array<AbcDecimal>] Array of OKLCH coordinates [lightness, chroma, hue] where:
|
87
|
+
# - lightness: perceptual lightness component (0-1)
|
88
|
+
# - chroma: colorfulness/saturation component
|
89
|
+
# - hue: hue angle in degrees (0-360)
|
39
90
|
def oklch_values
|
40
91
|
to_oklch.coordinates
|
41
92
|
end
|
42
93
|
|
94
|
+
# Returns the OKLCH coordinates of the color as an array.
|
95
|
+
#
|
96
|
+
# Converts the current color to OKLCH color space and returns its coordinates
|
97
|
+
# as an array. The OKLCH color space represents colors using Lightness,
|
98
|
+
# Chroma, and Hue components in a perceptually uniform way.
|
99
|
+
#
|
100
|
+
# @return [Array<Numeric>] An array containing the OKLCH coordinates [lightness, chroma, hue]
|
43
101
|
def oklch_array
|
44
102
|
to_oklch.coordinates
|
45
103
|
end
|
46
104
|
end
|
47
105
|
end
|
48
|
-
end
|
106
|
+
end
|
@@ -1,21 +1,52 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorMixins::ToSrgb - sRGB color space conversion functionality
|
2
|
+
#
|
3
|
+
# This mixin provides methods for converting colors to the sRGB color space, which is the
|
4
|
+
# standard RGB color space used in most displays and web applications. sRGB uses gamma
|
5
|
+
# correction to better match human visual perception compared to linear RGB, making it
|
6
|
+
# ideal for display purposes and color output in digital media.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Convert colors to sRGB with automatic converter lookup
|
10
|
+
# - Both non-destructive (to_srgb/to_rgb) and destructive (to_srgb!/to_rgb!) conversion methods
|
11
|
+
# - Direct access to sRGB components (red, green, blue)
|
12
|
+
# - Utility methods for RGB array and hex string output
|
13
|
+
# - Optimized to return the same object when no conversion is needed
|
14
|
+
# - High-precision decimal arithmetic for accurate color science calculations
|
15
|
+
#
|
16
|
+
# The sRGB color space is the default RGB color space for web content and most consumer
|
17
|
+
# displays, providing a standardized way to represent colors that will appear consistently
|
18
|
+
# across different devices and applications.
|
2
19
|
|
3
20
|
require_relative "../converter"
|
4
21
|
|
5
22
|
module Abachrome
|
6
23
|
module ColorMixins
|
7
24
|
module ToSrgb
|
25
|
+
# Converts the current color to the sRGB color space.
|
26
|
+
#
|
27
|
+
# If the color is already in the sRGB color space, returns the color instance
|
28
|
+
# unchanged. Otherwise, performs a color space conversion from the current
|
29
|
+
# color space to sRGB.
|
30
|
+
#
|
31
|
+
# @return [Abachrome::Color] A new Color instance in the sRGB color space,
|
32
|
+
# or self if already in sRGB
|
8
33
|
def to_srgb
|
9
34
|
return self if color_space.name == :srgb
|
10
35
|
|
11
36
|
Converter.convert(self, :srgb)
|
12
37
|
end
|
13
38
|
|
39
|
+
# Alias for #to_srgb method.
|
40
|
+
#
|
41
|
+
# @return [Abachrome::Color] The color converted to sRGB color space
|
14
42
|
def to_rgb
|
15
43
|
# assume they mean srgb
|
16
44
|
to_srgb
|
17
45
|
end
|
18
46
|
|
47
|
+
# Converts the color to the sRGB color space, mutating the current object.
|
48
|
+
# If the color is already in sRGB space, this method does nothing.
|
49
|
+
# @return [Abachrome::Color] self for method chaining
|
19
50
|
def to_srgb!
|
20
51
|
unless color_space.name == :srgb
|
21
52
|
srgb_color = to_srgb
|
@@ -25,39 +56,83 @@ module Abachrome
|
|
25
56
|
self
|
26
57
|
end
|
27
58
|
|
59
|
+
# Converts the current color to sRGB color space in place.
|
60
|
+
# This is an alias for {#to_srgb!} as RGB commonly refers to sRGB
|
61
|
+
# in web and design contexts.
|
62
|
+
#
|
63
|
+
# @return [self] Returns self after converting to sRGB
|
28
64
|
def to_rgb!
|
29
65
|
# assume they mean srgb
|
30
66
|
to_srgb!
|
31
67
|
end
|
32
68
|
|
69
|
+
# Returns the red component of the color in the sRGB color space.
|
70
|
+
#
|
71
|
+
# @return [AbcDecimal] The red component value in the sRGB color space,
|
72
|
+
# normalized between 0 and 1.
|
33
73
|
def red
|
34
74
|
to_srgb.coordinates[0]
|
35
75
|
end
|
36
76
|
|
77
|
+
# Returns the green component of the color in sRGB space.
|
78
|
+
#
|
79
|
+
# This method converts the current color to sRGB color space if needed,
|
80
|
+
# then extracts the green component (second coordinate).
|
81
|
+
#
|
82
|
+
# @return [AbcDecimal] The green component value in the sRGB color space, typically in the range 0-1
|
37
83
|
def green
|
38
84
|
to_srgb.coordinates[1]
|
39
85
|
end
|
40
86
|
|
87
|
+
# Returns the blue component of the color in sRGB color space.
|
88
|
+
#
|
89
|
+
# This method converts the current color to sRGB if needed and
|
90
|
+
# extracts the third coordinate value (blue).
|
91
|
+
#
|
92
|
+
# @return [AbcDecimal] The blue component value in sRGB space, typically in range 0-1
|
41
93
|
def blue
|
42
94
|
to_srgb.coordinates[2]
|
43
95
|
end
|
44
96
|
|
97
|
+
# Returns the RGB color values in the sRGB color space.
|
98
|
+
#
|
99
|
+
# @return [Array<AbcDecimal>] An array of three AbcDecimal values representing
|
100
|
+
# the red, green, and blue color components in the sRGB color space.
|
45
101
|
def srgb_values
|
46
102
|
to_srgb.coordinates
|
47
103
|
end
|
48
104
|
|
105
|
+
# Returns the RGB values of the color as coordinates in the sRGB color space.
|
106
|
+
#
|
107
|
+
# @return [Array<Abachrome::AbcDecimal>] The RGB coordinates (red, green, blue) in sRGB color space
|
49
108
|
def rgb_values
|
50
109
|
to_srgb.coordinates
|
51
110
|
end
|
52
111
|
|
112
|
+
# Returns an array of RGB values (0-255) for this color.
|
113
|
+
#
|
114
|
+
# This method converts the color to sRGB, then scales the component values
|
115
|
+
# from the 0-1 range to the 0-255 range commonly used in RGB color codes.
|
116
|
+
# Values are rounded to the nearest integer and clamped between 0 and 255.
|
117
|
+
#
|
118
|
+
# @return [Array<Integer>] An array of three integers representing the [R, G, B]
|
119
|
+
# values in the 0-255 range
|
53
120
|
def rgb_array
|
54
121
|
to_srgb.coordinates.map { |c| (c * 255).round.clamp(0, 255) }
|
55
122
|
end
|
56
123
|
|
124
|
+
# Returns a hexadecimal representation of this color in sRGB color space.
|
125
|
+
# Converts the color to sRGB, then formats it as a hexadecimal string.
|
126
|
+
#
|
127
|
+
# @return [String] A string in the format "#RRGGBB" where RR, GG, and BB are
|
128
|
+
# the hexadecimal representations of the red, green, and blue components,
|
129
|
+
# each ranging from 00 to FF.
|
130
|
+
# @example
|
131
|
+
# color.rgb_hex #=> "#3a7bc8"
|
57
132
|
def rgb_hex
|
58
133
|
r, g, b = rgb_array
|
59
134
|
format("#%02x%02x%02x", r, g, b)
|
60
135
|
end
|
61
136
|
end
|
62
137
|
end
|
63
|
-
end
|
138
|
+
end
|
@@ -1,4 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorModels::HSV - HSV color space model definition
|
2
|
+
#
|
3
|
+
# This module defines the HSV (Hue, Saturation, Value) color model within the Abachrome
|
4
|
+
# color manipulation library. HSV provides an intuitive way to represent colors using
|
5
|
+
# cylindrical coordinates where hue represents the color type, saturation represents
|
6
|
+
# the intensity or purity of the color, and value represents the brightness.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Registers the HSV color space with coordinate names [hue, saturation, value]
|
10
|
+
# - Validates HSV coordinates to ensure all components are within the [0, 1] range
|
11
|
+
# - Uses normalized 0-1 values internally for consistency with other color models
|
12
|
+
# - Provides a more intuitive interface for color adjustments compared to RGB
|
13
|
+
# - Supports conversion to and from other color spaces through the converter system
|
14
|
+
#
|
15
|
+
# The HSV model is particularly useful for color picking interfaces and applications
|
16
|
+
# where users need to adjust color properties in a way that matches human perception
|
17
|
+
# of color relationships. All coordinate values are stored as AbcDecimal objects to
|
18
|
+
# maintain precision during color science calculations.
|
2
19
|
|
3
20
|
module Abachrome
|
4
21
|
module ColorModels
|
@@ -11,6 +28,12 @@ module Abachrome
|
|
11
28
|
|
12
29
|
register :hsv, "HSV", %w[hue saturation value]
|
13
30
|
|
31
|
+
# Validates whether the coordinates are valid for the HSV color model.
|
32
|
+
# Each component (hue, saturation, value) must be in the range [0, 1].
|
33
|
+
#
|
34
|
+
# @param coordinates [Array<Numeric>] An array of three values representing
|
35
|
+
# hue (h), saturation (s), and value (v) in the range [0, 1]
|
36
|
+
# @return [Boolean] true if all coordinates are within valid ranges, false otherwise
|
14
37
|
def valid_coordinates?(coordinates)
|
15
38
|
h, s, v = coordinates
|
16
39
|
h >= 0 && h <= 1.0 &&
|
@@ -19,4 +42,4 @@ module Abachrome
|
|
19
42
|
end
|
20
43
|
end
|
21
44
|
end
|
22
|
-
end
|
45
|
+
end
|
@@ -1,4 +1,21 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorModels::Oklab - OKLAB color space model definition
|
2
|
+
#
|
3
|
+
# This module defines the OKLAB color model within the Abachrome color manipulation library.
|
4
|
+
# OKLAB is a perceptually uniform color space designed for better color manipulation and
|
5
|
+
# comparison, providing more intuitive lightness adjustments and color blending compared
|
6
|
+
# to traditional RGB color spaces.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Registers the OKLAB color space with coordinate names [lightness, a, b]
|
10
|
+
# - Uses L (lightness) ranging from 0 (black) to 1 (white)
|
11
|
+
# - Uses a and b components representing green-red and blue-yellow axes respectively
|
12
|
+
# - Provides perceptually uniform color space for accurate color science calculations
|
13
|
+
# - Serves as an intermediate color space for conversions to OKLCH and other models
|
14
|
+
# - Maintains high precision through AbcDecimal arithmetic for color transformations
|
15
|
+
#
|
16
|
+
# The OKLAB model is particularly useful for color adjustments that need to appear natural
|
17
|
+
# to human perception, such as lightness modifications, color blending, and gamut mapping
|
18
|
+
# operations where perceptual uniformity is important.
|
2
19
|
|
3
20
|
module Abachrome
|
4
21
|
module ColorModels
|
@@ -13,4 +30,4 @@ ColorSpace.register(
|
|
13
30
|
%w[l a b],
|
14
31
|
nil,
|
15
32
|
["ok-lab"]
|
16
|
-
)
|
33
|
+
)
|
@@ -1,8 +1,33 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorModels::Oklch - OKLCH color space model definition
|
2
|
+
#
|
3
|
+
# This module defines the OKLCH color model within the Abachrome color manipulation library.
|
4
|
+
# OKLCH is a cylindrical representation of the OKLAB color space using lightness, chroma, and hue
|
5
|
+
# coordinates. OKLCH offers intuitive color manipulation through its polar coordinate
|
6
|
+
# system where hue is represented as an angle and chroma represents colorfulness.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Registers the OKLCH color space with coordinate names [lightness, chroma, hue]
|
10
|
+
# - Provides conversion utilities between OKLCH and OKLAB color spaces
|
11
|
+
# - Uses L (lightness) ranging from 0 (black) to 1 (white)
|
12
|
+
# - Uses C (chroma) representing colorfulness intensity starting from 0
|
13
|
+
# - Uses h (hue) as an angle in degrees from 0 to 360
|
14
|
+
# - Includes normalization methods for proper coordinate ranges
|
15
|
+
# - Maintains high precision through AbcDecimal arithmetic for color transformations
|
16
|
+
#
|
17
|
+
# The OKLCH model is particularly useful for color adjustments that need to appear natural
|
18
|
+
# to human perception, such as hue shifts, saturation modifications, and lightness changes
|
19
|
+
# where the cylindrical coordinate system provides more intuitive control compared to
|
20
|
+
# rectangular color spaces.
|
2
21
|
|
3
22
|
module Abachrome
|
4
23
|
module ColorModels
|
5
24
|
class Oklch
|
25
|
+
# Normalizes OKLCH color values to their standard ranges.
|
26
|
+
#
|
27
|
+
# @param l [Numeric] The lightness component, will be clamped to range 0-1
|
28
|
+
# @param c [Numeric] The chroma component, will be clamped to range 0-1
|
29
|
+
# @param h [Numeric] The hue component in degrees, will be normalized to range 0-360
|
30
|
+
# @return [Array<AbcDecimal>] Array containing the normalized [lightness, chroma, hue] values
|
6
31
|
def self.normalize(l, c, h)
|
7
32
|
l = AbcDecimal(l)
|
8
33
|
c = AbcDecimal(c)
|
@@ -19,6 +44,12 @@ module Abachrome
|
|
19
44
|
[l, c, h]
|
20
45
|
end
|
21
46
|
|
47
|
+
# Converts OKLCH color coordinates to OKLab color coordinates.
|
48
|
+
#
|
49
|
+
# @param l [Numeric] The lightness value in the OKLCH color space
|
50
|
+
# @param c [Numeric] The chroma value in the OKLCH color space
|
51
|
+
# @param h [Numeric] The hue value in degrees in the OKLCH color space
|
52
|
+
# @return [Array<Numeric>] An array containing the OKLab coordinates [l, a, b]
|
22
53
|
def self.to_oklab(l, c, h)
|
23
54
|
# Convert OKLCH to OKLab
|
24
55
|
h_rad = h * Math::PI / 180
|
@@ -27,6 +58,15 @@ module Abachrome
|
|
27
58
|
[l, a, b]
|
28
59
|
end
|
29
60
|
|
61
|
+
# Converts OKLab color coordinates to OKLCH color coordinates.
|
62
|
+
#
|
63
|
+
# @param l [Numeric] The lightness component from OKLab.
|
64
|
+
# @param a [Numeric] The green-red component from OKLab.
|
65
|
+
# @param b [Numeric] The blue-yellow component from OKLab.
|
66
|
+
# @return [Array<Numeric>] An array containing the OKLCH values [l, c, h] where:
|
67
|
+
# - l is the lightness component (unchanged from OKLab)
|
68
|
+
# - c is the chroma component (calculated from a and b)
|
69
|
+
# - h is the hue angle in degrees (0-360)
|
30
70
|
def self.from_oklab(l, a, b)
|
31
71
|
# Convert OKLab to OKLCH
|
32
72
|
c = Math.sqrt((a * a) + (b * b))
|
@@ -44,4 +84,4 @@ ColorSpace.register(
|
|
44
84
|
%w[lightness chroma hue],
|
45
85
|
nil,
|
46
86
|
["ok-lch"]
|
47
|
-
)
|
87
|
+
)
|
@@ -1,9 +1,35 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorModels::RGB - RGB color space model utilities
|
2
|
+
#
|
3
|
+
# This module provides utility methods for the RGB color model within the Abachrome
|
4
|
+
# color manipulation library. RGB represents colors using red, green, and blue
|
5
|
+
# components, which is the most common color model for digital displays and web
|
6
|
+
# applications.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Normalizes RGB component values to the [0, 1] range from various input formats
|
10
|
+
# - Handles percentage values (with % suffix) by dividing by 100
|
11
|
+
# - Handles 0-255 range values by dividing by 255
|
12
|
+
# - Handles 0-1 range values directly without conversion
|
13
|
+
# - Supports string and numeric input types for flexible color specification
|
14
|
+
# - Maintains high precision through AbcDecimal arithmetic for color calculations
|
15
|
+
#
|
16
|
+
# The RGB model serves as a foundation for sRGB and linear RGB color spaces,
|
17
|
+
# providing the basic coordinate normalization needed for accurate color
|
18
|
+
# representation and conversion between different RGB-based color spaces.
|
2
19
|
|
3
20
|
module Abachrome
|
4
21
|
module ColorModels
|
5
22
|
class RGB
|
6
23
|
class << self
|
24
|
+
# Normalizes RGB color component values to the [0,1] range.
|
25
|
+
#
|
26
|
+
# @param r [String, Numeric] Red component. If string with % suffix, interpreted as percentage;
|
27
|
+
# if string without suffix or numeric > 1, interpreted as 0-255 range value;
|
28
|
+
# if numeric ≤ 1, used directly.
|
29
|
+
# @param g [String, Numeric] Green component. Same interpretation as red component.
|
30
|
+
# @param b [String, Numeric] Blue component. Same interpretation as red component.
|
31
|
+
# @return [Array<AbcDecimal>] Array of three normalized components as AbcDecimal objects,
|
32
|
+
# each in the range [0,1].
|
7
33
|
def normalize(r, g, b)
|
8
34
|
[r, g, b].map do |value|
|
9
35
|
case value
|
@@ -25,4 +51,4 @@ module Abachrome
|
|
25
51
|
end
|
26
52
|
end
|
27
53
|
end
|
28
|
-
end
|
54
|
+
end
|
@@ -1,20 +1,57 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::ColorSpace - Core color space definition and registry system
|
2
|
+
#
|
3
|
+
# This module provides the foundation for managing color spaces within the Abachrome library.
|
4
|
+
# It implements a registry system for storing and retrieving color space definitions, along
|
5
|
+
# with the ColorSpace class that encapsulates color space properties including coordinate
|
6
|
+
# names, white points, and color models.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Global registry for color space registration and lookup with alias support
|
10
|
+
# - Color space definition with configurable coordinates, white points, and color models
|
11
|
+
# - Built-in registration of standard color spaces (sRGB, linear RGB, HSL, LAB, OKLAB, OKLCH)
|
12
|
+
# - Equality comparison and hash support for color space objects
|
13
|
+
# - Flexible initialization through block-based configuration
|
14
|
+
# - Support for color space aliases (e.g., :rgb as alias for :srgb)
|
15
|
+
#
|
16
|
+
# The ColorSpace class serves as the foundation for the Color class and converter system,
|
17
|
+
# providing the metadata needed for proper color representation and transformation between
|
18
|
+
# different color spaces. All registered color spaces are accessible through the registry
|
19
|
+
# class methods and can be extended with custom color space definitions.
|
2
20
|
|
3
21
|
module Abachrome
|
4
22
|
class ColorSpace
|
5
23
|
class << self
|
24
|
+
# A registry of all registered color spaces.
|
25
|
+
#
|
26
|
+
# @return [Hash] A memoized hash where keys are color space identifiers and values are the corresponding color space objects
|
6
27
|
def registry
|
7
28
|
@registry ||= {}
|
8
29
|
end
|
9
30
|
|
31
|
+
# Registers a new color space with the specified name.
|
32
|
+
#
|
33
|
+
# @param name [String, Symbol] The identifier for the color space
|
34
|
+
# @param block [Proc] A block that configures the color space properties
|
35
|
+
# @return [Abachrome::ColorSpace] The newly created color space instance added to the registry
|
10
36
|
def register(name, &block)
|
11
37
|
registry[name.to_sym] = new(name, &block)
|
12
38
|
end
|
13
39
|
|
40
|
+
# Aliases a color space name to an existing registered color space.
|
41
|
+
#
|
42
|
+
# This method creates an alias for an existing color space in the registry,
|
43
|
+
# allowing the same color space to be accessed through multiple names.
|
44
|
+
#
|
45
|
+
# @param name [Symbol, String] The existing color space name already registered
|
46
|
+
# @param aliased_name [Symbol, String] The new alias name to register
|
47
|
+
# @return [void]
|
14
48
|
def alias(name, aliased_name)
|
15
49
|
registry[aliased_name.to_sym] = registry[name.to_sym]
|
16
50
|
end
|
17
51
|
|
52
|
+
# @param name [String, Symbol] The name of the color space to find
|
53
|
+
# @return [Abachrome::ColorSpace] The color space with the given name
|
54
|
+
# @raise [ArgumentError] If no color space with the given name exists in the registry
|
18
55
|
def find(name)
|
19
56
|
registry[name.to_sym] or raise ArgumentError, "Unknown color space: #{name}"
|
20
57
|
end
|
@@ -22,37 +59,74 @@ module Abachrome
|
|
22
59
|
|
23
60
|
attr_reader :name, :coordinates, :white_point, :color_model
|
24
61
|
|
62
|
+
# Initialize a new ColorSpace instance.
|
63
|
+
#
|
64
|
+
# @param name [String, Symbol] The name of the color space, which will be converted to a symbol
|
65
|
+
# @return [Abachrome::ColorSpace] A new instance of ColorSpace
|
66
|
+
# @yield [self] Yields self to the block for configuration if a block is given
|
25
67
|
def initialize(name)
|
26
68
|
@name = name.to_sym
|
27
69
|
yield self if block_given?
|
28
70
|
end
|
29
71
|
|
72
|
+
# Sets the color coordinates for the current color space.
|
73
|
+
#
|
74
|
+
# @param [Array] coords The coordinate values that define a color in this color space.
|
75
|
+
# Multiple arguments or a single flat array can be provided.
|
76
|
+
# @return [Array] The flattened array of coordinates.
|
30
77
|
def coordinates=(*coords)
|
31
78
|
@coordinates = coords.flatten
|
32
79
|
end
|
33
80
|
|
81
|
+
# Sets the white point reference used by the color space.
|
82
|
+
#
|
83
|
+
# The white point is a reference that defines what is considered "white" in a color space.
|
84
|
+
# Common values include :D50, :D65, etc.
|
85
|
+
#
|
86
|
+
# @param point [Symbol, String] The white point reference to use (will be converted to Symbol)
|
87
|
+
# @return [Symbol] The newly set white point
|
34
88
|
def white_point=(point)
|
35
89
|
@white_point = point.to_sym
|
36
90
|
end
|
37
91
|
|
92
|
+
# Sets the color model for the color space.
|
93
|
+
#
|
94
|
+
# @param model [String, Symbol] The new color model to set for this color space
|
95
|
+
# @return [Symbol] The color model as a symbolized value
|
38
96
|
def color_model=(model)
|
39
97
|
@color_model = model.to_sym
|
40
98
|
end
|
41
99
|
|
100
|
+
# Compares this ColorSpace instance with another to check for equality.
|
101
|
+
#
|
102
|
+
# Two ColorSpace objects are considered equal if they have the same name.
|
103
|
+
#
|
104
|
+
# @param other [Object] The object to compare against
|
105
|
+
# @return [Boolean] true if other is a ColorSpace with the same name, false otherwise
|
42
106
|
def ==(other)
|
43
107
|
return false unless other.is_a?(ColorSpace)
|
44
108
|
|
45
109
|
name == other.name
|
46
110
|
end
|
47
111
|
|
112
|
+
# Checks if two color spaces are equal.
|
113
|
+
#
|
114
|
+
# @param other [Abachrome::ColorSpace] The color space to compare with
|
115
|
+
# @return [Boolean] true if the color spaces are equal, false otherwise
|
48
116
|
def eql?(other)
|
49
117
|
self == other
|
50
118
|
end
|
51
119
|
|
120
|
+
# Returns a hash value for the color space based on its name.
|
121
|
+
#
|
122
|
+
# @return [Integer] A hash value computed from the color space name that can be
|
123
|
+
# used for equality comparison and as a hash key.
|
52
124
|
def hash
|
53
125
|
name.hash
|
54
126
|
end
|
55
127
|
|
128
|
+
# Returns the identifier for the color space, which is currently the same as its name.
|
129
|
+
# @return [String, Symbol] the identifier of the color space
|
56
130
|
def id
|
57
131
|
name
|
58
132
|
end
|
@@ -94,4 +168,4 @@ module Abachrome
|
|
94
168
|
s.white_point = :D65
|
95
169
|
s.color_model = :oklch
|
96
170
|
end
|
97
|
-
end
|
171
|
+
end
|
data/lib/abachrome/converter.rb
CHANGED
@@ -1,16 +1,53 @@
|
|
1
|
-
#
|
1
|
+
# Abachrome::Converter - Color space conversion registry and orchestration system
|
2
|
+
#
|
3
|
+
# This module provides the central registry and conversion orchestration for transforming colors
|
4
|
+
# between different color spaces within the Abachrome library. It manages a registry of converter
|
5
|
+
# classes that handle transformations between specific color space pairs (e.g., sRGB to OKLAB,
|
6
|
+
# OKLCH to linear RGB) and provides the main conversion interface used throughout the library.
|
7
|
+
#
|
8
|
+
# Key features:
|
9
|
+
# - Global registry for color space converter registration with automatic discovery
|
10
|
+
# - Converter lookup and routing between source and target color spaces
|
11
|
+
# - Automatic registration of all converter classes found in the Converters namespace
|
12
|
+
# - Conversion orchestration that finds appropriate converters based on color model compatibility
|
13
|
+
# - Support for multi-step conversions through intermediate color spaces when needed
|
14
|
+
# - Integration with the ColorSpace system for proper color space identification
|
15
|
+
#
|
16
|
+
# The Converter system serves as the backbone for all color transformations in Abachrome,
|
17
|
+
# enabling seamless conversion between any registered color spaces while maintaining the
|
18
|
+
# precision and accuracy required for color science calculations. Converter classes follow
|
19
|
+
# a naming convention (FromSpaceToSpace) for automatic registration and discovery.
|
2
20
|
|
3
21
|
module Abachrome
|
4
22
|
class Converter
|
5
23
|
class << self
|
24
|
+
# Returns the registry hash used to store color space converters.
|
25
|
+
#
|
26
|
+
# This method lazily initializes and returns the hash used internally to store
|
27
|
+
# converter mappings between different color spaces. This registry is a central
|
28
|
+
# repository that maps color space pairs to their appropriate conversion functions.
|
29
|
+
#
|
30
|
+
# @return [Hash] The converter registry hash, mapping color space pairs to converter functions
|
6
31
|
def registry
|
7
32
|
@registry ||= {}
|
8
33
|
end
|
9
34
|
|
35
|
+
# Register a converter class for transforming colors between two specific color spaces.
|
36
|
+
#
|
37
|
+
# @param from_space [Symbol, String] The source color space identifier
|
38
|
+
# @param to_space [Symbol, String] The destination color space identifier
|
39
|
+
# @param converter_class [Class] The converter class that implements the transformation
|
40
|
+
# @return [Class] The registered converter class
|
10
41
|
def register(from_space, to_space, converter_class)
|
11
42
|
registry[[from_space.to_s, to_space.to_s]] = converter_class
|
12
43
|
end
|
13
44
|
|
45
|
+
# Converts a color from its current color space to the specified target color space.
|
46
|
+
#
|
47
|
+
# @param color [Abachrome::Color] The color to convert
|
48
|
+
# @param to_space_name [String, Symbol] The name of the target color space
|
49
|
+
# @return [Abachrome::Color] The color converted to the target color space
|
50
|
+
# @raise [RuntimeError] If no converter is found between the source and target color models
|
14
51
|
def convert(color, to_space_name)
|
15
52
|
to_space = ColorSpace.find(to_space_name)
|
16
53
|
return color if color.color_space == to_space
|
@@ -23,7 +60,19 @@ module Abachrome
|
|
23
60
|
converter.convert(color)
|
24
61
|
end
|
25
62
|
|
26
|
-
#
|
63
|
+
# @api private
|
64
|
+
# @since 0.1.0
|
65
|
+
# @example
|
66
|
+
# converter = Abachrome::Converter.new
|
67
|
+
# converter.register_all_converters
|
68
|
+
#
|
69
|
+
# Automatically registers all converter classes found in the Converters namespace.
|
70
|
+
# The method iterates through constants in the Converters module, identifies classes
|
71
|
+
# with naming pattern "FromSpaceToSpace" (e.g., LrgbToOklab), extracts the source
|
72
|
+
# and destination color spaces from the class name, and registers the converter
|
73
|
+
# class for the corresponding color space conversion.
|
74
|
+
#
|
75
|
+
# @return [void]
|
27
76
|
def register_all_converters
|
28
77
|
Converters.constants.each do |const_name|
|
29
78
|
const = Converters.const_get(const_name)
|
@@ -42,6 +91,11 @@ module Abachrome
|
|
42
91
|
|
43
92
|
private
|
44
93
|
|
94
|
+
# Retrieves a converter function between two color spaces from the registry.
|
95
|
+
#
|
96
|
+
# @param from_space_name [String, Symbol] The source color space name
|
97
|
+
# @param to_space_name [String, Symbol] The target color space name
|
98
|
+
# @return [Proc, nil] The conversion function if registered, or nil if no converter exists for the specified color spaces
|
45
99
|
def find_converter(from_space_name, to_space_name)
|
46
100
|
registry[[from_space_name.to_s, to_space_name.to_s]]
|
47
101
|
end
|
@@ -56,4 +110,4 @@ module Abachrome
|
|
56
110
|
|
57
111
|
# Auto-register all converters
|
58
112
|
Converter.register_all_converters
|
59
|
-
end
|
113
|
+
end
|