abachrome 0.1.5 → 0.1.6
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 +38 -35
- data/lib/abachrome/color.rb +37 -10
- data/lib/abachrome/color_mixins/blend.rb +7 -5
- 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_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_models/cmyk.rb +159 -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 +3 -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_srgb.rb +6 -4
- data/lib/abachrome/converters/lms_to_xyz.rb +5 -3
- data/lib/abachrome/converters/lrgb_to_lms.rb +3 -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/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_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_yiq.rb +49 -0
- data/lib/abachrome/converters/xyz_to_lms.rb +5 -3
- data/lib/abachrome/converters/xyz_to_oklab.rb +5 -3
- data/lib/abachrome/converters/yiq_to_srgb.rb +47 -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 +29 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 584251d0988a5611a22766c4665f4be880d636c70af0a612d7eb39994e32e1cc
|
|
4
|
+
data.tar.gz: 0c1b82ff4874f2c74d494cdc79b5b2b4c8259c7e387441477a3a6dcb2046faad
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 10cd1fd7eb789c3e3fb0d10a1753a139ef83c388d5d22b850397995872784cf8cc2a134d7f423eb8365e609919d2814c1decd16abf9ea7941e2718f587352a46
|
|
7
|
+
data.tar.gz: a0dac04fc6b12902df2650b50794f044467c8521f352123239f862ec547970601a623d04306ab4c124af96e64cd317a77cf1781302d31d54e54d9a005c4dcce9
|
data/abachrome.gemspec
CHANGED
data/devenv.nix
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::AbcDecimal - High-precision decimal arithmetic for color calculations
|
|
2
4
|
#
|
|
3
5
|
# This class provides a wrapper around Ruby's BigDecimal to ensure consistent precision
|
|
@@ -19,6 +21,7 @@ require "forwardable"
|
|
|
19
21
|
module Abachrome
|
|
20
22
|
class AbcDecimal
|
|
21
23
|
extend Forwardable
|
|
24
|
+
|
|
22
25
|
DEFAULT_PRECISION = (ENV["ABC_DECIMAL_PRECISION"] || "24").to_i
|
|
23
26
|
|
|
24
27
|
attr_accessor :value, :precision
|
|
@@ -26,7 +29,7 @@ module Abachrome
|
|
|
26
29
|
def_delegators :@value, :to_i, :zero?, :nonzero?, :finite?
|
|
27
30
|
|
|
28
31
|
# Initializes a new AbcDecimal object with the specified value and precision.
|
|
29
|
-
#
|
|
32
|
+
#
|
|
30
33
|
# @param value [AbcDecimal, BigDecimal, Rational, #to_s] The numeric value to represent.
|
|
31
34
|
# If an AbcDecimal is provided, its internal value is used.
|
|
32
35
|
# If a BigDecimal or Rational is provided, it's used directly.
|
|
@@ -49,11 +52,11 @@ module Abachrome
|
|
|
49
52
|
end
|
|
50
53
|
|
|
51
54
|
# Returns a string representation of the decimal value.
|
|
52
|
-
#
|
|
55
|
+
#
|
|
53
56
|
# This method converts the internal value to a String, using a fixed-point
|
|
54
57
|
# notation format. If the internal value is a Rational, it's first converted
|
|
55
58
|
# to a BigDecimal with the configured precision before string conversion.
|
|
56
|
-
#
|
|
59
|
+
#
|
|
57
60
|
# @return [String] The decimal value as a string in fixed-point notation
|
|
58
61
|
def to_s
|
|
59
62
|
if @value.is_a?(Rational)
|
|
@@ -64,14 +67,14 @@ module Abachrome
|
|
|
64
67
|
end
|
|
65
68
|
|
|
66
69
|
# Converts the decimal value to a floating-point number.
|
|
67
|
-
#
|
|
70
|
+
#
|
|
68
71
|
# @return [Float] the floating-point representation of the AbcDecimal value
|
|
69
72
|
def to_f
|
|
70
73
|
@value.to_f
|
|
71
74
|
end
|
|
72
75
|
|
|
73
76
|
# Creates a new AbcDecimal from a string representation of a number.
|
|
74
|
-
#
|
|
77
|
+
#
|
|
75
78
|
# @param str [String] The string representation of a number to convert to an AbcDecimal
|
|
76
79
|
# @param precision [Integer] The precision to use for the decimal value (number of significant digits after the decimal point). Defaults to DEFAULT_PRECISION
|
|
77
80
|
# @return [AbcDecimal] A new AbcDecimal instance initialized with the given string value and precision
|
|
@@ -80,7 +83,7 @@ module Abachrome
|
|
|
80
83
|
end
|
|
81
84
|
|
|
82
85
|
# Creates a new AbcDecimal from a Rational number.
|
|
83
|
-
#
|
|
86
|
+
#
|
|
84
87
|
# @param rational [Rational] The rational number to convert to an AbcDecimal
|
|
85
88
|
# @param precision [Integer] The precision to use for the decimal representation, defaults to DEFAULT_PRECISION
|
|
86
89
|
# @return [AbcDecimal] A new AbcDecimal instance with the value of the given rational number
|
|
@@ -89,7 +92,7 @@ module Abachrome
|
|
|
89
92
|
end
|
|
90
93
|
|
|
91
94
|
# Creates a new AbcDecimal instance from a float value.
|
|
92
|
-
#
|
|
95
|
+
#
|
|
93
96
|
# @param float [Float] The floating point number to convert to an AbcDecimal
|
|
94
97
|
# @param precision [Integer] The precision to use for the decimal representation (default: DEFAULT_PRECISION)
|
|
95
98
|
# @return [AbcDecimal] A new AbcDecimal instance representing the given float value
|
|
@@ -98,7 +101,7 @@ module Abachrome
|
|
|
98
101
|
end
|
|
99
102
|
|
|
100
103
|
# Creates a new AbcDecimal from an integer value.
|
|
101
|
-
#
|
|
104
|
+
#
|
|
102
105
|
# @param integer [Integer] The integer value to convert to an AbcDecimal
|
|
103
106
|
# @param precision [Integer] The precision to use for the decimal, defaults to DEFAULT_PRECISION
|
|
104
107
|
# @return [AbcDecimal] A new AbcDecimal instance with the specified integer value and precision
|
|
@@ -119,7 +122,7 @@ module Abachrome
|
|
|
119
122
|
end
|
|
120
123
|
|
|
121
124
|
# Subtracts another numeric value from this AbcDecimal.
|
|
122
|
-
#
|
|
125
|
+
#
|
|
123
126
|
# @param other [AbcDecimal, Numeric] The value to subtract from this AbcDecimal.
|
|
124
127
|
# @return [AbcDecimal] A new AbcDecimal representing the result of the subtraction.
|
|
125
128
|
def -(other)
|
|
@@ -128,14 +131,14 @@ module Abachrome
|
|
|
128
131
|
end
|
|
129
132
|
|
|
130
133
|
# Multiplies this AbcDecimal by another value.
|
|
131
|
-
#
|
|
134
|
+
#
|
|
132
135
|
# @param other [Object] The value to multiply by. If not an AbcDecimal, it will be converted to one.
|
|
133
136
|
# @return [AbcDecimal] A new AbcDecimal instance representing the product of this decimal and the other value.
|
|
134
137
|
# @example
|
|
135
138
|
# dec1 = AbcDecimal.new(5)
|
|
136
139
|
# dec2 = AbcDecimal.new(2)
|
|
137
140
|
# result = dec1 * dec2 # => AbcDecimal representing 10
|
|
138
|
-
#
|
|
141
|
+
#
|
|
139
142
|
# # With a non-AbcDecimal value
|
|
140
143
|
# result = dec1 * 3 # => AbcDecimal representing 15
|
|
141
144
|
def *(other)
|
|
@@ -144,7 +147,7 @@ module Abachrome
|
|
|
144
147
|
end
|
|
145
148
|
|
|
146
149
|
# Divides this decimal by another value.
|
|
147
|
-
#
|
|
150
|
+
#
|
|
148
151
|
# @param other [Numeric, AbcDecimal] The divisor, which can be an AbcDecimal instance or any numeric value
|
|
149
152
|
# @return [AbcDecimal] A new AbcDecimal representing the result of the division
|
|
150
153
|
# @example
|
|
@@ -157,7 +160,7 @@ module Abachrome
|
|
|
157
160
|
end
|
|
158
161
|
|
|
159
162
|
# Performs modulo operation with another value.
|
|
160
|
-
#
|
|
163
|
+
#
|
|
161
164
|
# @param other [Numeric, AbcDecimal] The divisor for the modulo operation
|
|
162
165
|
# @return [AbcDecimal] A new AbcDecimal containing the remainder after division
|
|
163
166
|
def %(other)
|
|
@@ -166,7 +169,7 @@ module Abachrome
|
|
|
166
169
|
end
|
|
167
170
|
|
|
168
171
|
# Constrains the value to be between the specified minimum and maximum values.
|
|
169
|
-
#
|
|
172
|
+
#
|
|
170
173
|
# @param min [Numeric, AbcDecimal] The minimum value to clamp to
|
|
171
174
|
# @param max [Numeric, AbcDecimal] The maximum value to clamp to
|
|
172
175
|
# @return [AbcDecimal] A new AbcDecimal within the specified range
|
|
@@ -174,14 +177,14 @@ module Abachrome
|
|
|
174
177
|
# AbcDecimal(5).clamp(0, 10) # => 5
|
|
175
178
|
# AbcDecimal(15).clamp(0, 10) # => 10
|
|
176
179
|
# AbcDecimal(-5).clamp(0, 10) # => 0
|
|
177
|
-
def clamp(min,max)
|
|
178
|
-
@value.clamp(AbcDecimal(min),AbcDecimal(max))
|
|
180
|
+
def clamp(min, max)
|
|
181
|
+
@value.clamp(AbcDecimal(min), AbcDecimal(max))
|
|
179
182
|
end
|
|
180
183
|
|
|
181
184
|
# Raises self to the power of another value.
|
|
182
185
|
# This method handles different input types, including Rational values and
|
|
183
186
|
# other AbcDecimal instances.
|
|
184
|
-
#
|
|
187
|
+
#
|
|
185
188
|
# @param other [Numeric, Rational, AbcDecimal] The exponent to raise this value to
|
|
186
189
|
# @return [AbcDecimal] A new AbcDecimal representing self raised to the power of other
|
|
187
190
|
def **(other)
|
|
@@ -194,7 +197,7 @@ module Abachrome
|
|
|
194
197
|
end
|
|
195
198
|
|
|
196
199
|
# Allows for mixed arithmetic operations between AbcDecimal and other numeric types.
|
|
197
|
-
#
|
|
200
|
+
#
|
|
198
201
|
# @param other [Numeric] The other number to be coerced into an AbcDecimal object
|
|
199
202
|
# @return [Array<AbcDecimal>] A two-element array containing the coerced value and self,
|
|
200
203
|
# allowing Ruby to perform arithmetic operations with mixed types
|
|
@@ -205,7 +208,7 @@ module Abachrome
|
|
|
205
208
|
# Returns a string representation of the decimal value for inspection purposes.
|
|
206
209
|
# This method returns a formatted string that includes the class name and
|
|
207
210
|
# the string representation of the decimal value itself.
|
|
208
|
-
#
|
|
211
|
+
#
|
|
209
212
|
# @return [String] A string in the format "ClassName('value')"
|
|
210
213
|
def inspect
|
|
211
214
|
"#{self.class}('#{self}')"
|
|
@@ -213,7 +216,7 @@ module Abachrome
|
|
|
213
216
|
|
|
214
217
|
# Compares this decimal value with another value for equality.
|
|
215
218
|
# Attempts to convert the other value to an AbcDecimal if it isn't one already.
|
|
216
|
-
#
|
|
219
|
+
#
|
|
217
220
|
# @param other [Object] The value to compare against this AbcDecimal
|
|
218
221
|
# @return [Boolean] True if the values are equal, false otherwise
|
|
219
222
|
def ==(other)
|
|
@@ -222,7 +225,7 @@ module Abachrome
|
|
|
222
225
|
|
|
223
226
|
# Compares this AbcDecimal instance with another AbcDecimal or a value that can be
|
|
224
227
|
# converted to an AbcDecimal.
|
|
225
|
-
#
|
|
228
|
+
#
|
|
226
229
|
# @param other [Object] The value to compare with this AbcDecimal.
|
|
227
230
|
# If not an AbcDecimal, it will be converted using AbcDecimal().
|
|
228
231
|
# @return [Integer, nil] Returns -1 if self is less than other,
|
|
@@ -234,7 +237,7 @@ module Abachrome
|
|
|
234
237
|
end
|
|
235
238
|
|
|
236
239
|
# Compares this decimal with another value.
|
|
237
|
-
#
|
|
240
|
+
#
|
|
238
241
|
# @param other [Object] The value to compare with. Can be an AbcDecimal or any value
|
|
239
242
|
# convertible to AbcDecimal
|
|
240
243
|
# @return [Boolean] true if this decimal is greater than the other value, false otherwise
|
|
@@ -243,7 +246,7 @@ module Abachrome
|
|
|
243
246
|
end
|
|
244
247
|
|
|
245
248
|
# Compares this decimal value with another value.
|
|
246
|
-
#
|
|
249
|
+
#
|
|
247
250
|
# @param other [Object] The value to compare against. If not an AbcDecimal,
|
|
248
251
|
# it will be converted to one.
|
|
249
252
|
# @return [Boolean] true if this decimal is greater than or equal to the other value,
|
|
@@ -253,7 +256,7 @@ module Abachrome
|
|
|
253
256
|
end
|
|
254
257
|
|
|
255
258
|
# Compares this decimal with another value.
|
|
256
|
-
#
|
|
259
|
+
#
|
|
257
260
|
# @param other [Object] The value to compare with. Will be coerced to AbcDecimal if not already an instance.
|
|
258
261
|
# @return [Boolean] true if this decimal is less than the other value, false otherwise.
|
|
259
262
|
# @example
|
|
@@ -266,7 +269,7 @@ module Abachrome
|
|
|
266
269
|
end
|
|
267
270
|
|
|
268
271
|
# Compares this AbcDecimal with another value.
|
|
269
|
-
#
|
|
272
|
+
#
|
|
270
273
|
# @param other [AbcDecimal, Numeric] The value to compare with. If not an AbcDecimal,
|
|
271
274
|
# it will be converted to one.
|
|
272
275
|
# @return [Boolean] true if this AbcDecimal is less than or equal to the other value,
|
|
@@ -277,7 +280,7 @@ module Abachrome
|
|
|
277
280
|
|
|
278
281
|
# @overload round(*args)
|
|
279
282
|
# Rounds this decimal to a specified precision.
|
|
280
|
-
#
|
|
283
|
+
#
|
|
281
284
|
# @param args [Array] Arguments to be passed to BigDecimal#round. Can include
|
|
282
285
|
# the number of decimal places to round to and the rounding mode.
|
|
283
286
|
# @return [AbcDecimal] A new AbcDecimal instance with the rounded value
|
|
@@ -292,9 +295,9 @@ module Abachrome
|
|
|
292
295
|
end
|
|
293
296
|
|
|
294
297
|
# Returns the absolute value (magnitude) of the decimal number.
|
|
295
|
-
#
|
|
298
|
+
#
|
|
296
299
|
# Wraps BigDecimal#abs to ensure return values are properly converted to AbcDecimal.
|
|
297
|
-
#
|
|
300
|
+
#
|
|
298
301
|
# @param args [Array] Optional arguments to pass to BigDecimal#abs
|
|
299
302
|
# @return [AbcDecimal] The absolute value of the decimal number
|
|
300
303
|
def abs(*args)
|
|
@@ -304,14 +307,14 @@ module Abachrome
|
|
|
304
307
|
# Returns the square root of the AbcDecimal value.
|
|
305
308
|
# Calculates the square root by using Ruby's built-in Math.sqrt function
|
|
306
309
|
# and converting the result back to an AbcDecimal.
|
|
307
|
-
#
|
|
310
|
+
#
|
|
308
311
|
# @return [AbcDecimal] A new AbcDecimal representing the square root of the value
|
|
309
312
|
def sqrt
|
|
310
313
|
AbcDecimal(Math.sqrt(@value))
|
|
311
314
|
end
|
|
312
315
|
|
|
313
316
|
# Returns true if the internal value is negative, false otherwise.
|
|
314
|
-
#
|
|
317
|
+
#
|
|
315
318
|
# @return [Boolean] true if the value is negative, false otherwise
|
|
316
319
|
def negative?
|
|
317
320
|
@value.negative?
|
|
@@ -320,7 +323,7 @@ module Abachrome
|
|
|
320
323
|
# Calculates the arctangent of y/x using the signs of the arguments to determine the quadrant.
|
|
321
324
|
# Unlike the standard Math.atan2, this method accepts AbcDecimal objects or any values
|
|
322
325
|
# that can be converted to AbcDecimal.
|
|
323
|
-
#
|
|
326
|
+
#
|
|
324
327
|
# @param y [AbcDecimal, Numeric] The y coordinate
|
|
325
328
|
# @param x [AbcDecimal, Numeric] The x coordinate
|
|
326
329
|
# @return [AbcDecimal] The angle in radians between the positive x-axis and the ray to the point (x,y)
|
|
@@ -333,10 +336,10 @@ module Abachrome
|
|
|
333
336
|
end
|
|
334
337
|
|
|
335
338
|
# Creates a new AbcDecimal instance.
|
|
336
|
-
#
|
|
339
|
+
#
|
|
337
340
|
# This is a convenience method that allows creating AbcDecimal objects
|
|
338
341
|
# without explicitly referencing the Abachrome namespace.
|
|
339
|
-
#
|
|
342
|
+
#
|
|
340
343
|
# @param args [Array] Arguments to pass to the AbcDecimal constructor
|
|
341
344
|
# @return [Abachrome::AbcDecimal] A new AbcDecimal instance
|
|
342
345
|
def AbcDecimal(*args)
|
|
@@ -344,7 +347,7 @@ def AbcDecimal(*args)
|
|
|
344
347
|
end
|
|
345
348
|
|
|
346
349
|
# Creates a new AbcDecimal instance.
|
|
347
|
-
#
|
|
350
|
+
#
|
|
348
351
|
# @param args [Array] Arguments to pass to AbcDecimal.new
|
|
349
352
|
# @return [Abachrome::AbcDecimal] A new AbcDecimal instance
|
|
350
353
|
# @example
|
|
@@ -354,4 +357,4 @@ def AD(*args)
|
|
|
354
357
|
Abachrome::AbcDecimal.new(*args)
|
|
355
358
|
end
|
|
356
359
|
|
|
357
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
360
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
data/lib/abachrome/color.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::Color - Core color representation class
|
|
2
4
|
#
|
|
3
5
|
# This is the central color class that represents colors across multiple color spaces
|
|
@@ -27,7 +29,7 @@ module Abachrome
|
|
|
27
29
|
attr_reader :color_space, :coordinates, :alpha
|
|
28
30
|
|
|
29
31
|
# Initializes a new Color object with the specified color space, coordinates, and alpha value.
|
|
30
|
-
#
|
|
32
|
+
#
|
|
31
33
|
# @param color_space [ColorSpace] The color space for this color instance
|
|
32
34
|
# @param coordinates [Array<Numeric, String>] The color coordinates in the specified color space
|
|
33
35
|
# @param alpha [Numeric, String] The alpha (opacity) value, between 0.0 and 1.0 (default: 1.0)
|
|
@@ -51,7 +53,7 @@ module Abachrome
|
|
|
51
53
|
end
|
|
52
54
|
|
|
53
55
|
# Creates a new Color instance from RGB values
|
|
54
|
-
#
|
|
56
|
+
#
|
|
55
57
|
# @param r [Numeric] The red component value (typically 0-1)
|
|
56
58
|
# @param g [Numeric] The green component value (typically 0-1)
|
|
57
59
|
# @param b [Numeric] The blue component value (typically 0-1)
|
|
@@ -63,7 +65,7 @@ module Abachrome
|
|
|
63
65
|
end
|
|
64
66
|
|
|
65
67
|
# Creates a new Color instance from LRGB values
|
|
66
|
-
#
|
|
68
|
+
#
|
|
67
69
|
# @param r [Numeric] The red component value (typically 0-1)
|
|
68
70
|
# @param g [Numeric] The green component value (typically 0-1)
|
|
69
71
|
# @param b [Numeric] The blue component value (typically 0-1)
|
|
@@ -75,7 +77,7 @@ module Abachrome
|
|
|
75
77
|
end
|
|
76
78
|
|
|
77
79
|
# Creates a new Color object with OKLAB values.
|
|
78
|
-
#
|
|
80
|
+
#
|
|
79
81
|
# @param l [Float] The lightness component (L) of the OKLAB color space
|
|
80
82
|
# @param a [Float] The green-red component (a) of the OKLAB color space
|
|
81
83
|
# @param b [Float] The blue-yellow component (b) of the OKLAB color space
|
|
@@ -87,7 +89,7 @@ module Abachrome
|
|
|
87
89
|
end
|
|
88
90
|
|
|
89
91
|
# Creates a new color instance in the OKLCH color space.
|
|
90
|
-
#
|
|
92
|
+
#
|
|
91
93
|
# @param l [Numeric] The lightness component (L), typically in range 0..1
|
|
92
94
|
# @param c [Numeric] The chroma component (C), typically starting from 0 with no upper bound
|
|
93
95
|
# @param h [Numeric] The hue component (H) in degrees, typically in range 0..360
|
|
@@ -98,11 +100,36 @@ module Abachrome
|
|
|
98
100
|
new(space, [l, c, h], alpha)
|
|
99
101
|
end
|
|
100
102
|
|
|
103
|
+
# Creates a new Color instance from YIQ values
|
|
104
|
+
#
|
|
105
|
+
# @param y [Numeric] The luma (brightness) component, typically in range 0 to 1
|
|
106
|
+
# @param i [Numeric] The in-phase component (orange-blue), typically in range -0.5957 to 0.5957
|
|
107
|
+
# @param q [Numeric] The quadrature component (purple-green), typically in range -0.5226 to 0.5226
|
|
108
|
+
# @param alpha [Numeric] The alpha (opacity) component value (0-1), defaults to 1.0 (fully opaque)
|
|
109
|
+
# @return [Abachrome::Color] A new Color instance in the YIQ color space
|
|
110
|
+
def self.from_yiq(y, i, q, alpha = 1.0)
|
|
111
|
+
space = ColorSpace.find(:yiq)
|
|
112
|
+
new(space, [y, i, q], alpha)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Creates a new Color instance from CMYK values
|
|
116
|
+
#
|
|
117
|
+
# @param c [Numeric] The cyan component, typically in range 0 to 1
|
|
118
|
+
# @param m [Numeric] The magenta component, typically in range 0 to 1
|
|
119
|
+
# @param y [Numeric] The yellow component, typically in range 0 to 1
|
|
120
|
+
# @param k [Numeric] The key/black component, typically in range 0 to 1
|
|
121
|
+
# @param alpha [Numeric] The alpha (opacity) component value (0-1), defaults to 1.0 (fully opaque)
|
|
122
|
+
# @return [Abachrome::Color] A new Color instance in the CMYK color space
|
|
123
|
+
def self.from_cmyk(c, m, y, k, alpha = 1.0)
|
|
124
|
+
space = ColorSpace.find(:cmyk)
|
|
125
|
+
new(space, [c, m, y, k], alpha)
|
|
126
|
+
end
|
|
127
|
+
|
|
101
128
|
# Compares this color instance with another for equality.
|
|
102
|
-
#
|
|
129
|
+
#
|
|
103
130
|
# Two colors are considered equal if they have the same color space,
|
|
104
131
|
# coordinates, and alpha value.
|
|
105
|
-
#
|
|
132
|
+
#
|
|
106
133
|
# @param other [Object] The object to compare with
|
|
107
134
|
# @return [Boolean] true if the colors are equal, false otherwise
|
|
108
135
|
def ==(other)
|
|
@@ -114,7 +141,7 @@ module Abachrome
|
|
|
114
141
|
end
|
|
115
142
|
|
|
116
143
|
# Checks if this color is equal to another color object.
|
|
117
|
-
#
|
|
144
|
+
#
|
|
118
145
|
# @param other [Object] The object to compare with
|
|
119
146
|
# @return [Boolean] true if the two colors are equal, false otherwise
|
|
120
147
|
# @see ==
|
|
@@ -126,7 +153,7 @@ module Abachrome
|
|
|
126
153
|
# based on its color space, coordinates, and alpha value.
|
|
127
154
|
# The method first converts these components to strings,
|
|
128
155
|
# then computes a hash of the resulting array.
|
|
129
|
-
#
|
|
156
|
+
#
|
|
130
157
|
# @return [Integer] a hash code that can be used for equality comparison
|
|
131
158
|
# and as a hash key in Hash objects
|
|
132
159
|
def hash
|
|
@@ -168,4 +195,4 @@ module Abachrome
|
|
|
168
195
|
end
|
|
169
196
|
end
|
|
170
197
|
|
|
171
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
198
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
# Abachrome::ColorMixins::Blend - Color blending and mixing functionality
|
|
2
4
|
#
|
|
3
5
|
# This mixin provides methods for blending and mixing colors together in various color spaces.
|
|
@@ -58,7 +60,7 @@ module Abachrome
|
|
|
58
60
|
# Blends this color with another color by the specified amount.
|
|
59
61
|
# This is a destructive version of the blend method, modifying the current
|
|
60
62
|
# color in place.
|
|
61
|
-
#
|
|
63
|
+
#
|
|
62
64
|
# @param other [Abachrome::Color] The color to blend with
|
|
63
65
|
# @param amount [Float] The blend amount, between 0.0 and 1.0, where 0.0 is
|
|
64
66
|
# this color and 1.0 is the other color (default: 0.5)
|
|
@@ -72,7 +74,7 @@ module Abachrome
|
|
|
72
74
|
end
|
|
73
75
|
|
|
74
76
|
# Alias for the blend method that mixes two colors together.
|
|
75
|
-
#
|
|
77
|
+
#
|
|
76
78
|
# @param other [Abachrome::Color] The color to mix with
|
|
77
79
|
# @param amount [Float] The amount to mix, between 0.0 and 1.0, where 0.0 returns the original color and 1.0 returns the other color (default: 0.5)
|
|
78
80
|
# @return [Abachrome::Color] A new color resulting from the mix of the two colors
|
|
@@ -81,10 +83,10 @@ module Abachrome
|
|
|
81
83
|
end
|
|
82
84
|
|
|
83
85
|
# Mix the current color with another color.
|
|
84
|
-
#
|
|
86
|
+
#
|
|
85
87
|
# This method is an alias for blend!. It combines the current color with
|
|
86
88
|
# the provided color at the specified amount.
|
|
87
|
-
#
|
|
89
|
+
#
|
|
88
90
|
# @param other [Abachrome::Color] The color to mix with the current color
|
|
89
91
|
# @param amount [Numeric] The amount of the other color to mix in, from 0 to 1 (default: 0.5)
|
|
90
92
|
# @return [self] Returns the modified color object
|
|
@@ -95,4 +97,4 @@ module Abachrome
|
|
|
95
97
|
end
|
|
96
98
|
end
|
|
97
99
|
|
|
98
|
-
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
100
|
+
# Copyright (c) 2025 Durable Programming, LLC. All rights reserved.
|
|
@@ -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.
|