abachrome 0.1.5 → 0.2.0
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/abachrome.gemspec +1 -0
- data/devenv.nix +1 -1
- data/lib/abachrome/abc_decimal.rb +42 -35
- data/lib/abachrome/color.rb +61 -10
- data/lib/abachrome/color_mixins/blend.rb +7 -5
- data/lib/abachrome/color_mixins/harmonies.rb +187 -0
- data/lib/abachrome/color_mixins/lighten.rb +8 -6
- data/lib/abachrome/color_mixins/spectral_mix.rb +70 -0
- data/lib/abachrome/color_mixins/to_colorspace.rb +10 -8
- data/lib/abachrome/color_mixins/to_grayscale.rb +87 -0
- data/lib/abachrome/color_mixins/to_lms.rb +106 -0
- data/lib/abachrome/color_mixins/to_lrgb.rb +14 -12
- data/lib/abachrome/color_mixins/to_oklab.rb +16 -14
- data/lib/abachrome/color_mixins/to_oklch.rb +12 -10
- data/lib/abachrome/color_mixins/to_srgb.rb +17 -15
- data/lib/abachrome/color_mixins/to_xyz.rb +106 -0
- data/lib/abachrome/color_mixins/wcag.rb +126 -0
- data/lib/abachrome/color_models/cmyk.rb +160 -0
- data/lib/abachrome/color_models/hsv.rb +5 -3
- data/lib/abachrome/color_models/lms.rb +3 -1
- data/lib/abachrome/color_models/oklab.rb +3 -1
- data/lib/abachrome/color_models/oklch.rb +6 -4
- data/lib/abachrome/color_models/rgb.rb +4 -2
- data/lib/abachrome/color_models/xyz.rb +11 -1
- data/lib/abachrome/color_models/yiq.rb +37 -0
- data/lib/abachrome/color_space.rb +28 -14
- data/lib/abachrome/converter.rb +10 -8
- data/lib/abachrome/converters/base.rb +13 -11
- data/lib/abachrome/converters/cmyk_to_srgb.rb +42 -0
- data/lib/abachrome/converters/lms_to_lrgb.rb +5 -3
- data/lib/abachrome/converters/lms_to_oklab.rb +28 -0
- data/lib/abachrome/converters/lms_to_srgb.rb +6 -4
- data/lib/abachrome/converters/lms_to_xyz.rb +5 -3
- data/lib/abachrome/converters/lrgb_to_lms.rb +29 -1
- data/lib/abachrome/converters/lrgb_to_oklab.rb +5 -3
- data/lib/abachrome/converters/lrgb_to_srgb.rb +6 -4
- data/lib/abachrome/converters/lrgb_to_xyz.rb +5 -3
- data/lib/abachrome/converters/oklab_to_lms.rb +9 -7
- data/lib/abachrome/converters/oklab_to_lrgb.rb +7 -7
- data/lib/abachrome/converters/oklab_to_oklch.rb +4 -2
- data/lib/abachrome/converters/oklab_to_srgb.rb +4 -2
- data/lib/abachrome/converters/oklab_to_xyz.rb +29 -0
- data/lib/abachrome/converters/oklch_to_lms.rb +28 -0
- data/lib/abachrome/converters/oklch_to_lrgb.rb +5 -3
- data/lib/abachrome/converters/oklch_to_oklab.rb +5 -3
- data/lib/abachrome/converters/oklch_to_srgb.rb +6 -4
- data/lib/abachrome/converters/oklch_to_xyz.rb +6 -4
- data/lib/abachrome/converters/srgb_to_cmyk.rb +64 -0
- data/lib/abachrome/converters/srgb_to_lms.rb +29 -0
- data/lib/abachrome/converters/srgb_to_lrgb.rb +5 -3
- data/lib/abachrome/converters/srgb_to_oklab.rb +4 -2
- data/lib/abachrome/converters/srgb_to_oklch.rb +5 -3
- data/lib/abachrome/converters/srgb_to_xyz.rb +30 -0
- data/lib/abachrome/converters/srgb_to_yiq.rb +49 -0
- data/lib/abachrome/converters/xyz_to_lms.rb +5 -3
- data/lib/abachrome/converters/xyz_to_lrgb.rb +33 -0
- data/lib/abachrome/converters/xyz_to_oklab.rb +5 -3
- data/lib/abachrome/converters/xyz_to_srgb.rb +30 -0
- data/lib/abachrome/converters/yiq_to_srgb.rb +47 -0
- data/lib/abachrome/floatify.rb +282 -0
- data/lib/abachrome/gamut/base.rb +3 -3
- data/lib/abachrome/gamut/p3.rb +3 -3
- data/lib/abachrome/gamut/rec2020.rb +2 -2
- data/lib/abachrome/gamut/srgb.rb +4 -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 -149
- data/lib/abachrome/named/tailwind.rb +265 -265
- data/lib/abachrome/outputs/css.rb +2 -2
- data/lib/abachrome/palette.rb +26 -25
- data/lib/abachrome/palette_mixins/interpolate.rb +3 -1
- data/lib/abachrome/palette_mixins/resample.rb +2 -2
- data/lib/abachrome/palette_mixins/stretch_luminance.rb +2 -2
- data/lib/abachrome/parsers/css.rb +86 -71
- data/lib/abachrome/parsers/hex.rb +2 -2
- data/lib/abachrome/parsers/tailwind.rb +8 -8
- data/lib/abachrome/spectral.rb +277 -0
- data/lib/abachrome/to_abcd.rb +4 -4
- data/lib/abachrome/version.rb +2 -2
- data/lib/abachrome.rb +66 -10
- metadata +41 -3
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::Lighten - Color lightness adjustment functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for adjusting the lightness of colors by manipulating
|
|
@@ -23,7 +25,7 @@ module Abachrome
|
|
|
23
25
|
# This method works by extracting the L (lightness) component from the OKLab
|
|
24
26
|
# representation of the color and increasing it by the given amount, ensuring
|
|
25
27
|
# the result stays within the valid range of [0, 1].
|
|
26
|
-
#
|
|
28
|
+
#
|
|
27
29
|
# @param amount [Numeric] The amount to increase the lightness by, as a decimal
|
|
28
30
|
# value between 0 and 1. Defaults to 0.1 (10% increase).
|
|
29
31
|
# @return [Abachrome::Color] A new Color instance with increased lightness.
|
|
@@ -46,7 +48,7 @@ module Abachrome
|
|
|
46
48
|
# Increases the lightness of the color by the specified amount and modifies the current color object.
|
|
47
49
|
# This method changes the color in-place, mutating the current object. The color
|
|
48
50
|
# is converted to a lightness-based color space if needed to perform the operation.
|
|
49
|
-
#
|
|
51
|
+
#
|
|
50
52
|
# @param amount [Float] The amount to increase the lightness by, as a decimal value
|
|
51
53
|
# between 0 and 1. Default is 0.1 (10% increase).
|
|
52
54
|
# @return [Abachrome::Color] Returns self for method chaining.
|
|
@@ -59,10 +61,10 @@ module Abachrome
|
|
|
59
61
|
end
|
|
60
62
|
|
|
61
63
|
# Darkens a color by decreasing its lightness value.
|
|
62
|
-
#
|
|
64
|
+
#
|
|
63
65
|
# This method is effectively a convenience wrapper around the {#lighten} method,
|
|
64
66
|
# passing a negative amount value to decrease the lightness instead of increasing it.
|
|
65
|
-
#
|
|
67
|
+
#
|
|
66
68
|
# @param amount [Float] The amount to darken the color by, between 0 and 1.
|
|
67
69
|
# Defaults to 0.1 (10% darker).
|
|
68
70
|
# @return [Color] A new color instance with decreased lightness.
|
|
@@ -73,7 +75,7 @@ module Abachrome
|
|
|
73
75
|
|
|
74
76
|
# Decreases the lightness value of the color by the specified amount.
|
|
75
77
|
# Modifies the color in place.
|
|
76
|
-
#
|
|
78
|
+
#
|
|
77
79
|
# @param amount [Float] The amount to darken the color by, as a value between 0 and 1.
|
|
78
80
|
# Defaults to 0.1 (10% darker).
|
|
79
81
|
# @return [Abachrome::Color] Returns self with the modified lightness value.
|
|
@@ -85,4 +87,4 @@ module Abachrome
|
|
|
85
87
|
end
|
|
86
88
|
end
|
|
87
89
|
|
|
88
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
90
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Abachrome::ColorMixins::SpectralMix - Kubelka-Munk spectral color mixing
|
|
4
|
+
#
|
|
5
|
+
# This mixin adds spectral mixing capabilities to Color objects using the
|
|
6
|
+
# Kubelka-Munk theory for realistic paint-like color mixing.
|
|
7
|
+
#
|
|
8
|
+
# Unlike simple RGB blending or interpolation in perceptual color spaces,
|
|
9
|
+
# spectral mixing simulates how real pigments interact with light through
|
|
10
|
+
# absorption and scattering. This produces more realistic results, especially
|
|
11
|
+
# when mixing complementary colors.
|
|
12
|
+
#
|
|
13
|
+
# Key features:
|
|
14
|
+
# - Physics-based color mixing using Kubelka-Munk theory
|
|
15
|
+
# - Avoids muddy browns when mixing complementary colors
|
|
16
|
+
# - Supports tinting strength for different pigment concentrations
|
|
17
|
+
# - More realistic than linear RGB or LAB interpolation
|
|
18
|
+
|
|
19
|
+
module Abachrome
|
|
20
|
+
module ColorMixins
|
|
21
|
+
module SpectralMix
|
|
22
|
+
# Mix this color with another color using Kubelka-Munk spectral mixing.
|
|
23
|
+
#
|
|
24
|
+
# This method produces more realistic color mixing than simple RGB or LAB
|
|
25
|
+
# interpolation by simulating how real pigments absorb and scatter light.
|
|
26
|
+
#
|
|
27
|
+
# @param other [Abachrome::Color] The color to mix with
|
|
28
|
+
# @param amount [Float] The mix ratio, between 0 and 1. 0.5 means equal mixing.
|
|
29
|
+
# Values closer to 0 favor this color, values closer to 1 favor the other color.
|
|
30
|
+
# @param tinting_strength_self [Float] Tinting strength of this color (default: 1.0)
|
|
31
|
+
# Higher values mean stronger pigment concentration
|
|
32
|
+
# @param tinting_strength_other [Float] Tinting strength of other color (default: 1.0)
|
|
33
|
+
# @return [Abachrome::Color] A new color representing the spectral mix
|
|
34
|
+
#
|
|
35
|
+
# @example Mix red and blue equally
|
|
36
|
+
# red = Abachrome.from_rgb(1, 0, 0)
|
|
37
|
+
# blue = Abachrome.from_rgb(0, 0, 1)
|
|
38
|
+
# purple = red.spectral_mix(blue, 0.5)
|
|
39
|
+
#
|
|
40
|
+
# @example Mix with 25% of blue
|
|
41
|
+
# mostly_red = red.spectral_mix(blue, 0.25)
|
|
42
|
+
#
|
|
43
|
+
# @example Mix with different tinting strengths
|
|
44
|
+
# # Stronger blue pigment
|
|
45
|
+
# purple = red.spectral_mix(blue, 0.5, tinting_strength_other: 2.0)
|
|
46
|
+
def spectral_mix(other, amount = 0.5, tinting_strength_self: 1.0, tinting_strength_other: 1.0)
|
|
47
|
+
require_relative "../spectral"
|
|
48
|
+
|
|
49
|
+
# Convert amount to weights
|
|
50
|
+
# amount = 0 means 100% self, 0% other
|
|
51
|
+
# amount = 0.5 means 50% self, 50% other
|
|
52
|
+
# amount = 1 means 0% self, 100% other
|
|
53
|
+
weight_self = 1.0 - amount.to_f
|
|
54
|
+
weight_other = amount.to_f
|
|
55
|
+
|
|
56
|
+
colors = [
|
|
57
|
+
{ color: self, weight: weight_self },
|
|
58
|
+
{ color: other, weight: weight_other }
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
tinting_strengths = {
|
|
62
|
+
self => tinting_strength_self.to_f,
|
|
63
|
+
other => tinting_strength_other.to_f
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
Spectral.mix(colors, tinting_strengths: tinting_strengths)
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::ToColorspace - Color space conversion functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for converting colors between different color spaces within
|
|
@@ -20,11 +22,11 @@ module Abachrome
|
|
|
20
22
|
module ColorMixins
|
|
21
23
|
module ToColorspace
|
|
22
24
|
# Converts the current color to the specified target color space.
|
|
23
|
-
#
|
|
25
|
+
#
|
|
24
26
|
# This method transforms the current color into an equivalent color in a different
|
|
25
27
|
# color space. If the target space is the same as the current color space, no
|
|
26
28
|
# conversion is performed and the current color is returned.
|
|
27
|
-
#
|
|
29
|
+
#
|
|
28
30
|
# @param target_space [Abachrome::ColorSpace] The target color space to convert to
|
|
29
31
|
# @return [Abachrome::Color] A new color object in the target color space, or self
|
|
30
32
|
# if the target space is the same as the current color space
|
|
@@ -37,7 +39,7 @@ module Abachrome
|
|
|
37
39
|
# Converts the color object to the specified target color space in-place.
|
|
38
40
|
# This method modifies the current object by changing its color space and
|
|
39
41
|
# coordinates to match the target color space.
|
|
40
|
-
#
|
|
42
|
+
#
|
|
41
43
|
# @param target_space [Abachrome::ColorSpace] The color space to convert to
|
|
42
44
|
# @return [Abachrome::Color] Returns self with modified color space and coordinates
|
|
43
45
|
# @see #to_color_space The non-destructive version that returns a new color object
|
|
@@ -51,7 +53,7 @@ module Abachrome
|
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
# Convert this color to a different color space.
|
|
54
|
-
#
|
|
56
|
+
#
|
|
55
57
|
# @param space_name [String, Symbol] The name of the target color space to convert to.
|
|
56
58
|
# @return [Abachrome::Color] A new Color object in the specified color space.
|
|
57
59
|
# @example
|
|
@@ -64,7 +66,7 @@ module Abachrome
|
|
|
64
66
|
end
|
|
65
67
|
|
|
66
68
|
# Converts this color to the specified color space in place.
|
|
67
|
-
#
|
|
69
|
+
#
|
|
68
70
|
# @param space_name [String, Symbol] The name or identifier of the target color space to convert to.
|
|
69
71
|
# @return [Abachrome::Color] Returns self with its values converted to the specified color space.
|
|
70
72
|
# @raise [Abachrome::ColorSpaceNotFoundError] If the specified color space is not registered.
|
|
@@ -77,7 +79,7 @@ module Abachrome
|
|
|
77
79
|
end
|
|
78
80
|
|
|
79
81
|
# Convert a color to a specified color space.
|
|
80
|
-
#
|
|
82
|
+
#
|
|
81
83
|
# @param space_name [Symbol, String] The name of the color space to convert to.
|
|
82
84
|
# @return [Abachrome::Color] A new Color instance in the specified color space.
|
|
83
85
|
# @example
|
|
@@ -88,7 +90,7 @@ module Abachrome
|
|
|
88
90
|
end
|
|
89
91
|
|
|
90
92
|
# Converts the color to the specified color space and mutates the current object.
|
|
91
|
-
#
|
|
93
|
+
#
|
|
92
94
|
# @param space_name [Symbol, String] The target color space to convert to (e.g., :oklch, :rgb, :lab)
|
|
93
95
|
# @return [Abachrome::Color] Returns self after conversion
|
|
94
96
|
# @see #convert_to!
|
|
@@ -102,4 +104,4 @@ module Abachrome
|
|
|
102
104
|
end
|
|
103
105
|
end
|
|
104
106
|
|
|
105
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
107
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Abachrome::ColorMixins::ToGrayscale - Grayscale conversion mixin
|
|
4
|
+
#
|
|
5
|
+
# This mixin provides methods for converting colors to grayscale using various
|
|
6
|
+
# standard luma calculations. It supports both legacy Rec. 601 (SDTV) and modern
|
|
7
|
+
# Rec. 709 (HDTV) coefficients for accurate grayscale conversion based on human
|
|
8
|
+
# eye sensitivity.
|
|
9
|
+
#
|
|
10
|
+
# Key features:
|
|
11
|
+
# - Rec. 601 luma: Y = 0.299R + 0.587G + 0.114B (NTSC/SDTV standard)
|
|
12
|
+
# - Rec. 709 luma: Y = 0.2126R + 0.7152G + 0.0722B (HDTV standard)
|
|
13
|
+
# - Maintains alpha channel during conversion
|
|
14
|
+
# - Uses BigDecimal for precise calculations
|
|
15
|
+
#
|
|
16
|
+
# This is essential for image processing, accessibility checks, and any application
|
|
17
|
+
# that needs perceptually accurate grayscale conversion rather than simple averaging.
|
|
18
|
+
|
|
19
|
+
module Abachrome
|
|
20
|
+
module ColorMixins
|
|
21
|
+
module ToGrayscale
|
|
22
|
+
# Converts the color to grayscale using Rec. 601 luma coefficients (legacy NTSC standard).
|
|
23
|
+
# This is the same calculation used in the YIQ color space's Y component.
|
|
24
|
+
#
|
|
25
|
+
# @return [Abachrome::Color] A grayscale version of the color in sRGB space
|
|
26
|
+
def to_grayscale_601
|
|
27
|
+
rgb_color = to_srgb
|
|
28
|
+
r, g, b = rgb_color.coordinates
|
|
29
|
+
|
|
30
|
+
# Rec. 601 luma: Y = 0.299R + 0.587G + 0.114B
|
|
31
|
+
luma = (AD("0.299") * r) + (AD("0.587") * g) + (AD("0.114") * b)
|
|
32
|
+
|
|
33
|
+
Color.from_rgb(luma, luma, luma, alpha)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Converts the color to grayscale using Rec. 709 luma coefficients (HDTV standard).
|
|
37
|
+
#
|
|
38
|
+
# @return [Abachrome::Color] A grayscale version of the color in sRGB space
|
|
39
|
+
def to_grayscale_709
|
|
40
|
+
rgb_color = to_srgb
|
|
41
|
+
r, g, b = rgb_color.coordinates
|
|
42
|
+
|
|
43
|
+
# Rec. 709 luma: Y = 0.2126R + 0.7152G + 0.0722B
|
|
44
|
+
luma = (AD("0.2126") * r) + (AD("0.7152") * g) + (AD("0.0722") * b)
|
|
45
|
+
|
|
46
|
+
Color.from_rgb(luma, luma, luma, alpha)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# Converts the color to grayscale using the default Rec. 601 standard.
|
|
50
|
+
# This is an alias for to_grayscale_601 and matches the legacy behavior
|
|
51
|
+
# expected by most image processing applications.
|
|
52
|
+
#
|
|
53
|
+
# @return [Abachrome::Color] A grayscale version of the color in sRGB space
|
|
54
|
+
def to_grayscale
|
|
55
|
+
to_grayscale_601
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Calculates the relative luminance (luma) value using Rec. 601 coefficients.
|
|
59
|
+
# This returns just the Y component without creating a new color.
|
|
60
|
+
#
|
|
61
|
+
# @return [AbcDecimal] The luma value in range [0, 1]
|
|
62
|
+
def luma_601
|
|
63
|
+
rgb_color = to_srgb
|
|
64
|
+
r, g, b = rgb_color.coordinates
|
|
65
|
+
(AD("0.299") * r) + (AD("0.587") * g) + (AD("0.114") * b)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Calculates the relative luminance (luma) value using Rec. 709 coefficients.
|
|
69
|
+
# This returns just the Y component without creating a new color.
|
|
70
|
+
#
|
|
71
|
+
# @return [AbcDecimal] The luma value in range [0, 1]
|
|
72
|
+
def luma_709
|
|
73
|
+
rgb_color = to_srgb
|
|
74
|
+
r, g, b = rgb_color.coordinates
|
|
75
|
+
(AD("0.2126") * r) + (AD("0.7152") * g) + (AD("0.0722") * b)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Calculates the relative luminance using the default Rec. 601 standard.
|
|
79
|
+
# Alias for luma_601.
|
|
80
|
+
#
|
|
81
|
+
# @return [AbcDecimal] The luma value in range [0, 1]
|
|
82
|
+
def luma
|
|
83
|
+
luma_601
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
end
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Abachrome::ColorMixins::ToLms - LMS color space conversion functionality
|
|
4
|
+
#
|
|
5
|
+
# This mixin provides methods for converting colors to the LMS color space, which represents
|
|
6
|
+
# the response of the three types of cone cells in the human eye (Long, Medium, Short wavelength
|
|
7
|
+
# sensitivity). LMS serves as an intermediate color space in the OKLAB transformation pipeline
|
|
8
|
+
# and provides a foundation for perceptually uniform color representations.
|
|
9
|
+
#
|
|
10
|
+
# Key features:
|
|
11
|
+
# - Convert colors to LMS with automatic converter lookup
|
|
12
|
+
# - Both non-destructive (to_lms) and destructive (to_lms!) conversion methods
|
|
13
|
+
# - Direct access to LMS components (long, medium, short)
|
|
14
|
+
# - Utility methods for LMS array and value extraction
|
|
15
|
+
# - Optimized to return the same object when no conversion is needed
|
|
16
|
+
# - High-precision decimal arithmetic for accurate color science calculations
|
|
17
|
+
#
|
|
18
|
+
# The LMS color space uses three components: L (long wavelength), M (medium wavelength),
|
|
19
|
+
# and S (short wavelength), representing cone cell responses that bridge the gap between
|
|
20
|
+
# linear RGB and perceptually uniform color spaces like OKLAB.
|
|
21
|
+
|
|
22
|
+
require_relative "../converter"
|
|
23
|
+
|
|
24
|
+
module Abachrome
|
|
25
|
+
module ColorMixins
|
|
26
|
+
module ToLms
|
|
27
|
+
# Converts the current color to the LMS color space.
|
|
28
|
+
#
|
|
29
|
+
# If the color is already in LMS, it returns the color unchanged.
|
|
30
|
+
# Otherwise, it uses the Converter to transform the color to LMS.
|
|
31
|
+
#
|
|
32
|
+
# @return [Abachrome::Color] A new Color object in the LMS color space
|
|
33
|
+
def to_lms
|
|
34
|
+
return self if color_space.name == :lms
|
|
35
|
+
|
|
36
|
+
Converter.convert(self, :lms)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
# Converts the color to the LMS color space in place.
|
|
40
|
+
# This method transforms the current color into LMS space,
|
|
41
|
+
# modifying the original object by updating its color space
|
|
42
|
+
# and coordinates if not already in LMS.
|
|
43
|
+
#
|
|
44
|
+
# @example
|
|
45
|
+
# color = Abachrome::Color.from_hex("#ff5500")
|
|
46
|
+
# color.to_lms! # Color now uses LMS color space
|
|
47
|
+
#
|
|
48
|
+
# @return [Abachrome::Color] self, with updated color space and coordinates
|
|
49
|
+
def to_lms!
|
|
50
|
+
unless color_space.name == :lms
|
|
51
|
+
lms_color = to_lms
|
|
52
|
+
@color_space = lms_color.color_space
|
|
53
|
+
@coordinates = lms_color.coordinates
|
|
54
|
+
end
|
|
55
|
+
self
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
# Returns the L component (long wavelength) from the LMS color space.
|
|
59
|
+
#
|
|
60
|
+
# The L component represents the response of long-wavelength sensitive cone cells
|
|
61
|
+
# in the human eye, which are most sensitive to red light.
|
|
62
|
+
#
|
|
63
|
+
# @return [AbcDecimal] The L (long wavelength) value from the LMS color space
|
|
64
|
+
def long
|
|
65
|
+
to_lms.coordinates[0]
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Returns the M component (medium wavelength) from the LMS color space.
|
|
69
|
+
#
|
|
70
|
+
# The M component represents the response of medium-wavelength sensitive cone cells
|
|
71
|
+
# in the human eye, which are most sensitive to green light.
|
|
72
|
+
#
|
|
73
|
+
# @return [AbcDecimal] The M (medium wavelength) value from the LMS color space
|
|
74
|
+
def medium
|
|
75
|
+
to_lms.coordinates[1]
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Returns the S component (short wavelength) from the LMS color space.
|
|
79
|
+
#
|
|
80
|
+
# The S component represents the response of short-wavelength sensitive cone cells
|
|
81
|
+
# in the human eye, which are most sensitive to blue light.
|
|
82
|
+
#
|
|
83
|
+
# @return [AbcDecimal] The S (short wavelength) value from the LMS color space
|
|
84
|
+
def short
|
|
85
|
+
to_lms.coordinates[2]
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
# Returns the LMS color space coordinates for this color.
|
|
89
|
+
#
|
|
90
|
+
# @return [Array<AbcDecimal>] An array of LMS coordinates [L, M, S] representing the color in LMS color space
|
|
91
|
+
def lms_values
|
|
92
|
+
to_lms.coordinates
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Returns an array representation of the color's coordinates in the LMS color space.
|
|
96
|
+
#
|
|
97
|
+
# @return [Array<AbcDecimal>] An array containing the coordinates of the color
|
|
98
|
+
# in the LMS color space in the order [L, M, S]
|
|
99
|
+
def lms_array
|
|
100
|
+
to_lms.coordinates
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::ToLrgb - Linear RGB color space conversion functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for converting colors to the linear RGB (LRGB) color space,
|
|
@@ -28,7 +30,7 @@ module Abachrome
|
|
|
28
30
|
# which uses a linear relationship between the stored numeric value and
|
|
29
31
|
# the actual light intensity. If the color is already in the LRGB space,
|
|
30
32
|
# it returns the current object without conversion.
|
|
31
|
-
#
|
|
33
|
+
#
|
|
32
34
|
# @return [Abachrome::Color] A new color object in the LRGB color space,
|
|
33
35
|
# or the original object if already in LRGB space
|
|
34
36
|
def to_lrgb
|
|
@@ -39,10 +41,10 @@ module Abachrome
|
|
|
39
41
|
|
|
40
42
|
# Converts the current color to the linear RGB (LRGB) color space and updates
|
|
41
43
|
# the receiver's state. If the color is already in LRGB space, this is a no-op.
|
|
42
|
-
#
|
|
44
|
+
#
|
|
43
45
|
# Unlike #to_lrgb which returns a new color instance, this method modifies the
|
|
44
46
|
# current object by changing its color space and coordinates to the LRGB equivalent.
|
|
45
|
-
#
|
|
47
|
+
#
|
|
46
48
|
# @return [Abachrome::Color] the receiver itself, now in LRGB color space
|
|
47
49
|
def to_lrgb!
|
|
48
50
|
unless color_space.name == :lrgb
|
|
@@ -54,11 +56,11 @@ module Abachrome
|
|
|
54
56
|
end
|
|
55
57
|
|
|
56
58
|
# Returns the linear red component value of the color.
|
|
57
|
-
#
|
|
59
|
+
#
|
|
58
60
|
# This method accesses the first coordinate from the color in linear RGB space.
|
|
59
61
|
# Linear RGB values differ from standard RGB by using a non-gamma-corrected
|
|
60
62
|
# linear representation of luminance.
|
|
61
|
-
#
|
|
63
|
+
#
|
|
62
64
|
# @return [AbcDecimal] The linear red component value, typically in range [0, 1]
|
|
63
65
|
def lred
|
|
64
66
|
to_lrgb.coordinates[0]
|
|
@@ -68,7 +70,7 @@ module Abachrome
|
|
|
68
70
|
# linear RGB color space first. Linear RGB uses a different scale than standard
|
|
69
71
|
# sRGB, with values representing linear light energy rather than gamma-corrected
|
|
70
72
|
# values.
|
|
71
|
-
#
|
|
73
|
+
#
|
|
72
74
|
# @return [AbcDecimal] The linear green component value from the color's linear
|
|
73
75
|
# RGB representation
|
|
74
76
|
def lgreen
|
|
@@ -76,17 +78,17 @@ module Abachrome
|
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
# Returns the linear blue channel value of this color after conversion to linear RGB color space.
|
|
79
|
-
#
|
|
81
|
+
#
|
|
80
82
|
# This method converts the current color to the linear RGB color space and extracts the blue
|
|
81
83
|
# component (the third coordinate).
|
|
82
|
-
#
|
|
84
|
+
#
|
|
83
85
|
# @return [AbcDecimal] The linear blue component value, typically in the range [0, 1]
|
|
84
86
|
def lblue
|
|
85
87
|
to_lrgb.coordinates[2]
|
|
86
88
|
end
|
|
87
89
|
|
|
88
90
|
# Returns the coordinates of the color in the linear RGB color space.
|
|
89
|
-
#
|
|
91
|
+
#
|
|
90
92
|
# @return [Array<AbcDecimal>] An array of three AbcDecimal values representing
|
|
91
93
|
# the red, green, and blue components in linear RGB color space.
|
|
92
94
|
def lrgb_values
|
|
@@ -96,14 +98,14 @@ module Abachrome
|
|
|
96
98
|
# Returns an array of sRGB values as integers in the 0-255 range.
|
|
97
99
|
# This method converts the color to RGB, scales the values to the 0-255 range,
|
|
98
100
|
# rounds to integers, and ensures they are clamped within the valid range.
|
|
99
|
-
#
|
|
101
|
+
#
|
|
100
102
|
# @return [Array<Integer>] An array of three RGB integer values between 0-255
|
|
101
103
|
def rgb_array
|
|
102
104
|
to_rgb.coordinates.map { |c| (c * 255).round.clamp(0, 255) }
|
|
103
105
|
end
|
|
104
106
|
|
|
105
107
|
# Returns a hexadecimal string representation of the color in RGB format.
|
|
106
|
-
#
|
|
108
|
+
#
|
|
107
109
|
# @return [String] A hexadecimal color code in the format '#RRGGBB' where RR, GG, and BB
|
|
108
110
|
# are two-digit hexadecimal values for the red, green, and blue components respectively.
|
|
109
111
|
# @example
|
|
@@ -116,4 +118,4 @@ module Abachrome
|
|
|
116
118
|
end
|
|
117
119
|
end
|
|
118
120
|
|
|
119
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
121
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::ToOklab - OKLAB color space conversion functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for converting colors to the OKLAB color space, which is a
|
|
@@ -23,10 +25,10 @@ module Abachrome
|
|
|
23
25
|
module ColorMixins
|
|
24
26
|
module ToOklab
|
|
25
27
|
# Converts the current color to the OKLAB color space.
|
|
26
|
-
#
|
|
28
|
+
#
|
|
27
29
|
# If the color is already in OKLAB, it returns the color unchanged.
|
|
28
30
|
# Otherwise, it uses the Converter to transform the color to OKLAB.
|
|
29
|
-
#
|
|
31
|
+
#
|
|
30
32
|
# @return [Abachrome::Color] A new Color object in the OKLAB color space
|
|
31
33
|
def to_oklab
|
|
32
34
|
return self if color_space.name == :oklab
|
|
@@ -38,11 +40,11 @@ module Abachrome
|
|
|
38
40
|
# This method transforms the current color into OKLAB space,
|
|
39
41
|
# modifying the original object by updating its color space
|
|
40
42
|
# and coordinates if not already in OKLAB.
|
|
41
|
-
#
|
|
43
|
+
#
|
|
42
44
|
# @example
|
|
43
45
|
# color = Abachrome::Color.from_hex("#ff5500")
|
|
44
46
|
# color.to_oklab! # Color now uses OKLAB color space
|
|
45
|
-
#
|
|
47
|
+
#
|
|
46
48
|
# @return [Abachrome::Color] self, with updated color space and coordinates
|
|
47
49
|
def to_oklab!
|
|
48
50
|
unless color_space.name == :oklab
|
|
@@ -56,27 +58,27 @@ module Abachrome
|
|
|
56
58
|
# Returns the lightness component (L) of the color in the OKLAB color space.
|
|
57
59
|
# The lightness value ranges from 0 (black) to 1 (white) and represents
|
|
58
60
|
# the perceived lightness of the color.
|
|
59
|
-
#
|
|
61
|
+
#
|
|
60
62
|
# @return [AbcDecimal] The lightness (L) value from the OKLAB color space
|
|
61
63
|
def lightness
|
|
62
64
|
to_oklab.coordinates[0]
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
# Returns the L (Lightness) component from the OKLAB color space.
|
|
66
|
-
#
|
|
68
|
+
#
|
|
67
69
|
# The L value represents perceptual lightness in the OKLAB color space,
|
|
68
70
|
# typically ranging from 0 (black) to 1 (white).
|
|
69
|
-
#
|
|
71
|
+
#
|
|
70
72
|
# @return [AbcDecimal] The L (Lightness) component from the OKLAB color space
|
|
71
73
|
def l
|
|
72
74
|
to_oklab.coordinates[0]
|
|
73
75
|
end
|
|
74
76
|
|
|
75
77
|
# Returns the 'a' component from the OKLAB color space (green-red axis).
|
|
76
|
-
#
|
|
78
|
+
#
|
|
77
79
|
# The 'a' component in OKLAB represents the position on the green-red axis,
|
|
78
80
|
# with negative values being more green and positive values being more red.
|
|
79
|
-
#
|
|
81
|
+
#
|
|
80
82
|
# @return [AbcDecimal] The 'a' component value from the OKLAB color space.
|
|
81
83
|
# @see #to_oklab For the full conversion to OKLAB color space
|
|
82
84
|
def a
|
|
@@ -84,25 +86,25 @@ module Abachrome
|
|
|
84
86
|
end
|
|
85
87
|
|
|
86
88
|
# Returns the B value of the color in OKLAB color space.
|
|
87
|
-
#
|
|
89
|
+
#
|
|
88
90
|
# This method first converts the color to OKLAB color space if needed,
|
|
89
91
|
# then extracts the B component (blue-yellow axis), which is the third
|
|
90
92
|
# coordinate in the OKLAB model.
|
|
91
|
-
#
|
|
93
|
+
#
|
|
92
94
|
# @return [AbcDecimal] The B component value in OKLAB color space
|
|
93
95
|
def b
|
|
94
96
|
to_oklab.coordinates[2]
|
|
95
97
|
end
|
|
96
98
|
|
|
97
99
|
# Returns the OKLAB color space coordinates for this color.
|
|
98
|
-
#
|
|
100
|
+
#
|
|
99
101
|
# @return [Array] An array of OKLAB coordinates [L, a, b] representing the color in OKLAB color space
|
|
100
102
|
def oklab_values
|
|
101
103
|
to_oklab.coordinates
|
|
102
104
|
end
|
|
103
105
|
|
|
104
106
|
# Returns an array representation of the color's coordinates in the OKLAB color space.
|
|
105
|
-
#
|
|
107
|
+
#
|
|
106
108
|
# @return [Array<AbcDecimal>] An array containing the coordinates of the color
|
|
107
109
|
# in the OKLAB color space in the order [L, a, b]
|
|
108
110
|
def oklab_array
|
|
@@ -112,4 +114,4 @@ module Abachrome
|
|
|
112
114
|
end
|
|
113
115
|
end
|
|
114
116
|
|
|
115
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
117
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::ToOklch - OKLCH color space conversion functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for converting colors to the OKLCH color space, which is a
|
|
@@ -21,12 +23,12 @@ module Abachrome
|
|
|
21
23
|
module ColorMixins
|
|
22
24
|
module ToOklch
|
|
23
25
|
# Converts the current color to the OKLCH color space.
|
|
24
|
-
#
|
|
26
|
+
#
|
|
25
27
|
# This method transforms the color into the perceptually uniform OKLCH color space.
|
|
26
28
|
# If the color is already in OKLCH, it returns itself unchanged. If the color is in
|
|
27
29
|
# OKLAB, it directly converts from OKLAB to OKLCH. For all other color spaces, it
|
|
28
30
|
# first converts to OKLAB as an intermediate step, then converts to OKLCH.
|
|
29
|
-
#
|
|
31
|
+
#
|
|
30
32
|
# @return [Abachrome::Color] A new Color object in the OKLCH color space
|
|
31
33
|
def to_oklch
|
|
32
34
|
return self if color_space.name == :oklch
|
|
@@ -44,7 +46,7 @@ module Abachrome
|
|
|
44
46
|
# This method transforms the current color to OKLCH color space, modifying
|
|
45
47
|
# the original object instead of creating a new one. If the color is already
|
|
46
48
|
# in OKLCH space, no conversion is performed.
|
|
47
|
-
#
|
|
49
|
+
#
|
|
48
50
|
# @return [Abachrome::Color] self, allowing for method chaining
|
|
49
51
|
def to_oklch!
|
|
50
52
|
unless color_space.name == :oklch
|
|
@@ -58,7 +60,7 @@ module Abachrome
|
|
|
58
60
|
# Returns the lightness component of the color in the OKLCH color space.
|
|
59
61
|
# This method provides direct access to the first coordinate of the OKLCH
|
|
60
62
|
# representation of the color, which represents perceptual lightness.
|
|
61
|
-
#
|
|
63
|
+
#
|
|
62
64
|
# @return [AbcDecimal] the lightness value in the OKLCH color space,
|
|
63
65
|
# typically in the range of 0.0 to 1.0, where 0.0 is black and 1.0 is white
|
|
64
66
|
def lightness
|
|
@@ -67,14 +69,14 @@ module Abachrome
|
|
|
67
69
|
|
|
68
70
|
# Returns the chroma value of the color by converting it to the OKLCH color space.
|
|
69
71
|
# Chroma represents color intensity or saturation in the OKLCH color space.
|
|
70
|
-
#
|
|
72
|
+
#
|
|
71
73
|
# @return [AbcDecimal] The chroma value (second coordinate) from the OKLCH color space
|
|
72
74
|
def chroma
|
|
73
75
|
to_oklch.coordinates[1]
|
|
74
76
|
end
|
|
75
77
|
|
|
76
78
|
# Returns the hue value of the color in the OKLCH color space.
|
|
77
|
-
#
|
|
79
|
+
#
|
|
78
80
|
# @return [AbcDecimal] The hue component of the color in degrees (0-360)
|
|
79
81
|
# from the OKLCH color space representation.
|
|
80
82
|
def hue
|
|
@@ -82,7 +84,7 @@ module Abachrome
|
|
|
82
84
|
end
|
|
83
85
|
|
|
84
86
|
# Returns the OKLCH coordinates of the color.
|
|
85
|
-
#
|
|
87
|
+
#
|
|
86
88
|
# @return [Array<AbcDecimal>] Array of OKLCH coordinates [lightness, chroma, hue] where:
|
|
87
89
|
# - lightness: perceptual lightness component (0-1)
|
|
88
90
|
# - chroma: colorfulness/saturation component
|
|
@@ -92,11 +94,11 @@ module Abachrome
|
|
|
92
94
|
end
|
|
93
95
|
|
|
94
96
|
# Returns the OKLCH coordinates of the color as an array.
|
|
95
|
-
#
|
|
97
|
+
#
|
|
96
98
|
# Converts the current color to OKLCH color space and returns its coordinates
|
|
97
99
|
# as an array. The OKLCH color space represents colors using Lightness,
|
|
98
100
|
# Chroma, and Hue components in a perceptually uniform way.
|
|
99
|
-
#
|
|
101
|
+
#
|
|
100
102
|
# @return [Array<Numeric>] An array containing the OKLCH coordinates [lightness, chroma, hue]
|
|
101
103
|
def oklch_array
|
|
102
104
|
to_oklch.coordinates
|
|
@@ -105,4 +107,4 @@ module Abachrome
|
|
|
105
107
|
end
|
|
106
108
|
end
|
|
107
109
|
|
|
108
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
110
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|