colorspace 0.1.0 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c139dfc8f81959c4676b6626d5e72bcca448b829213a624f9bced835e662ce3e
4
- data.tar.gz: 7eadea0f02c8d3b44c6c11c7bca30b66cb1ce2e5f8630c81c9ab3bea7af58d56
3
+ metadata.gz: 9400e62857f08e86defabffe2f88ae73dc05ac5f05cc29f575a86917a2121c45
4
+ data.tar.gz: 8e38f06fc5d6d804a2cb81bcc3dbc0e2176987f9c7890088d62809998b1bcc73
5
5
  SHA512:
6
- metadata.gz: 867d76ec2efb1ca07ec2d8da0308fdeea8f1e2437277e6cb6d9b3a3d839b003abb1b3020bc0b81160625b536e856c717f15f2dd8ce5361fe49959cc025b546c3
7
- data.tar.gz: 78ea353372d5c30ae12c5e3c0c61744b9a587b0d4db1f3c733b10cb0f3e106079ba753eed6aae3d70b11f86ad595027f4fc76733c8a881f7d3bca13df5f3cda1
6
+ metadata.gz: 6abdcfa05487d616ad1972ac847bbc38744ceda59fd203b46327db3f3e7a7b162f8b2b201335c0d4f23dde49a05828f3fbbcf51d9358a82267b0ae20d2ad9969
7
+ data.tar.gz: e6e3d20acac710720d55f0e5d42fc9b7e32ee61c8eab857a24211ccd0e12224bbff7591d4a5a6d02c628d82dd56e73fce3cb0f5bb8a04ee9a9307dc5d41edfc7
data/.rubocop.yml CHANGED
@@ -38,3 +38,6 @@ Style/DataInheritance:
38
38
 
39
39
  Style/ParallelAssignment:
40
40
  Enabled: false
41
+
42
+ Gemspec/RequireMFA:
43
+ Enabled: false
data/Gemfile.lock CHANGED
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- colorspace (0.1.0)
4
+ colorspace (0.1.1)
5
+ matrix (~> 0.4)
5
6
 
6
7
  GEM
7
8
  remote: https://rubygems.org/
@@ -9,6 +10,7 @@ GEM
9
10
  ast (2.4.2)
10
11
  json (2.7.1)
11
12
  language_server-protocol (3.17.0.3)
13
+ matrix (0.4.2)
12
14
  minitest (5.20.0)
13
15
  parallel (1.24.0)
14
16
  parser (3.2.2.4)
data/colorspace.gemspec CHANGED
@@ -33,7 +33,6 @@ Gem::Specification.new do |spec|
33
33
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
34
34
  spec.require_paths = ['lib']
35
35
 
36
- # Uncomment to register a new dependency of your gem
37
- # spec.add_dependency "example-gem", "~> 1.0"
36
+ spec.add_dependency 'matrix', '~> 0.4'
38
37
  # spec.metadata['rubygems_mfa_required'] = 'true'
39
38
  end
@@ -0,0 +1,175 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'matrix'
4
+
5
+ # Library for working with RGB, XYZ, and LAB colorspaces
6
+ module Colorspace
7
+ # rubocop: disable Layout/SpaceInsideArrayLiteralBrackets
8
+ # rubocop: disable Layout/ExtraSpacing
9
+ RGB_XYZ_MATRIX = Matrix[
10
+ [ 0.4124564, 0.3575761, 0.1804375 ],
11
+ [ 0.2126729, 0.7151522, 0.0721750 ],
12
+ [ 0.0193339, 0.1191920, 0.9503041 ]
13
+ ].freeze
14
+
15
+ XYZ_RGB_MATRIX = Matrix[
16
+ [ 3.2404542, -1.5371385, -0.4985314 ],
17
+ [ -0.9692660, 1.8760108, 0.0415560 ],
18
+ [ 0.0556434, -0.2040259, 1.0572252 ]
19
+ ].freeze
20
+ # rubocop: enable Layout/ExtraSpacing
21
+ # rubocop: enable Layout/SpaceInsideArrayLiteralBrackets
22
+
23
+ ##
24
+ # A tristimulus value in the CIE 1931 space.
25
+ class XYZTristimulus < Data.define(:x, :y, :z)
26
+ # @dynamic x, y, z, initialize
27
+
28
+ def to_srgb_linear
29
+ r, g, b = (XYZ_RGB_MATRIX * Matrix[[x], [y], [z]]).to_a.flatten
30
+
31
+ SRGBLinearColor.new(r:, g:, b:)
32
+ end
33
+
34
+ def to_srgb
35
+ to_srgb_linear.gamma_compress
36
+ end
37
+
38
+ private def scale_f(val)
39
+ delta = 6.0 / 29
40
+ t = val
41
+
42
+ if t > delta**3
43
+ t**(1.0 / 3)
44
+ else
45
+ (t / (3 * (delta**2))) + (4.0 / 29)
46
+ end
47
+ end
48
+
49
+ # rubocop: disable Metrics/AbcSize
50
+ def to_cielab(illuminant: D65)
51
+ x_, y_, z_ = x * 100, y * 100, z * 100
52
+ xn, yn, zn = illuminant.x, illuminant.y, illuminant.z
53
+
54
+ l = (116 * scale_f(y_ / yn)) - 16
55
+ a = 500 * (scale_f(x_ / xn) - scale_f(y_ / yn))
56
+ b = 200 * (scale_f(y_ / yn) - scale_f(z_ / zn))
57
+
58
+ CIELABColor.new(l:, a:, b:)
59
+ end
60
+ # rubocop: enable Metrics/AbcSize
61
+
62
+ def to_ary = [x, y, z]
63
+ def to_a = to_ary
64
+ end
65
+
66
+ D65 = XYZTristimulus.new(x: 95.047, y: 100.0, z: 108.883)
67
+ D50 = XYZTristimulus.new(x: 96.42, y: 100.0, z: 82.51)
68
+
69
+ ##
70
+ # An RGB value in the sRGB colorspace.
71
+ class SRGBColor < Data.define(:r, :g, :b)
72
+ # @dynamic r, g, b, initialize
73
+ def self.from_hex(hex)
74
+ r, g, b = hex.chars.last(6).each_slice(2)
75
+ .map { |c| c.join.to_i(16) / 255.0 }
76
+
77
+ new(r: r || 0.0, g: g || 0.0, b: b || 0.0)
78
+ end
79
+
80
+ def to_hex
81
+ [r, g, b].map { |val|
82
+ (val * 255).round.clamp(0, 255).to_s(16).rjust(2, '0')
83
+ }.join
84
+ end
85
+
86
+ private def gamma_expand_one(val)
87
+ if val <= 0.04045
88
+ val / 12.92
89
+ else
90
+ ((val + 0.055) / 1.055)**2.4
91
+ end
92
+ end
93
+
94
+ def to_xyz
95
+ gamma_expand.to_xyz
96
+ end
97
+
98
+ def gamma_expand
99
+ SRGBLinearColor.new(
100
+ r: gamma_expand_one(r),
101
+ g: gamma_expand_one(g),
102
+ b: gamma_expand_one(b)
103
+ )
104
+ end
105
+
106
+ def to_ary = [r, g, b]
107
+ def to_a = to_ary
108
+ end
109
+
110
+ ##
111
+ # A gamma-expanded ("linear light") RGB value in the sRGB colorspace.
112
+ class SRGBLinearColor < Data.define(:r, :g, :b)
113
+ def to_xyz
114
+ x, y, z = (RGB_XYZ_MATRIX * Matrix[[r], [g], [b]]).to_a.flatten
115
+ XYZTristimulus.new(x:, y:, z:)
116
+ end
117
+
118
+ private def gamma_compress_one(val)
119
+ if val <= 0.0031308
120
+ 12.92 * val
121
+ else
122
+ (1.055 * (val**(1.0 / 2.4))) - 0.055
123
+ end
124
+ end
125
+
126
+ def gamma_compress
127
+ SRGBColor.new(
128
+ r: gamma_compress_one(r),
129
+ g: gamma_compress_one(g),
130
+ b: gamma_compress_one(b)
131
+ )
132
+ end
133
+
134
+ def to_ary = [r, g, b]
135
+ def to_a = to_ary
136
+ end
137
+
138
+ ##
139
+ # A color in the CIE LAB color space.
140
+ class CIELABColor < Data.define(:l, :a, :b)
141
+ def self.from_hex(...)
142
+ SRGBColor.from_hex(...).to_xyz.to_cielab
143
+ end
144
+
145
+ def to_hex
146
+ to_xyz.to_srgb.to_hex
147
+ end
148
+
149
+ # rubocop: disable Metrics/AbcSize
150
+ def to_xyz(illuminant: D65)
151
+ xn, yn, zn = illuminant.x, illuminant.y, illuminant.z
152
+
153
+ p = (l + 16) / 116.0
154
+
155
+ x = xn * ((p + (a / 500.0))**3) / 100.0
156
+ y = yn * (p**3) / 100.0
157
+ z = zn * ((p - (b / 200.0))**3) / 100.0
158
+
159
+ XYZTristimulus.new(x:, y:, z:)
160
+ end
161
+ # rubocop: enable Metrics/AbcSize
162
+
163
+ def cie76(other)
164
+ (((other.l - l)**2) + ((other.a - a)**2) + ((other.b - b)**2))**0.5
165
+ end
166
+
167
+ def ciede2000(other)
168
+ # TODO: write this
169
+ cie76(other)
170
+ end
171
+
172
+ def to_ary = [l, a, b]
173
+ def to_a = to_ary
174
+ end
175
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Colorspace
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.2'
5
5
  end
data/lib/colorspace.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative 'colorspace/version'
4
+ require_relative 'colorspace/colorlib'
4
5
 
5
6
  module Colorspace
6
7
  class Error < StandardError; end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: colorspace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Anna Kudriavtsev
@@ -9,7 +9,21 @@ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
11
  date: 1980-01-01 00:00:00.000000000 Z
12
- dependencies: []
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: matrix
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.4'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.4'
13
27
  description:
14
28
  email:
15
29
  - anna328p@gmail.com
@@ -29,6 +43,7 @@ files:
29
43
  - flake.lock
30
44
  - flake.nix
31
45
  - lib/colorspace.rb
46
+ - lib/colorspace/colorlib.rb
32
47
  - lib/colorspace/version.rb
33
48
  - shell.nix
34
49
  - sig/colorspace.rbs