color_hash 0.1.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 +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +12 -0
- data/Gemfile.lock +57 -0
- data/README.md +67 -0
- data/Rakefile +12 -0
- data/color_hash.gemspec +32 -0
- data/lib/color_hash/generator.rb +153 -0
- data/lib/color_hash/version.rb +5 -0
- data/lib/color_hash.rb +32 -0
- data/sig/color_hash.rbs +4 -0
- metadata +58 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ddbbc3200aa561a17d07ecbd7c209822e97d276d35965dfc6027ac16cd3dfd4c
|
4
|
+
data.tar.gz: 68bda518a95968b69339e1b30e94b45bd42e14948fec050194944b5a2ec19a0b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7156629804899b663856449220ecb2e159b4d75ff29dc58634c19c7628e83bcf739bbfe779a507a23e111f2472729e2d9c42cd131544af01b341254565bde553
|
7
|
+
data.tar.gz: 35d4e8451d94797e33c7c9aecfc3d3e9484120ceabca55410b7fb20cd8f9705a8c83f792967f77080c29da2ce939fafd471cf16242613ff75894de4b23599656
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
color_hash (0.1.0)
|
5
|
+
|
6
|
+
GEM
|
7
|
+
remote: https://rubygems.org/
|
8
|
+
specs:
|
9
|
+
ast (2.4.2)
|
10
|
+
diff-lcs (1.5.0)
|
11
|
+
json (2.6.2)
|
12
|
+
parallel (1.22.1)
|
13
|
+
parser (3.1.2.1)
|
14
|
+
ast (~> 2.4.1)
|
15
|
+
rainbow (3.1.1)
|
16
|
+
rake (13.0.6)
|
17
|
+
regexp_parser (2.6.1)
|
18
|
+
rexml (3.2.5)
|
19
|
+
rspec (3.11.0)
|
20
|
+
rspec-core (~> 3.11.0)
|
21
|
+
rspec-expectations (~> 3.11.0)
|
22
|
+
rspec-mocks (~> 3.11.0)
|
23
|
+
rspec-core (3.11.0)
|
24
|
+
rspec-support (~> 3.11.0)
|
25
|
+
rspec-expectations (3.11.1)
|
26
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
+
rspec-support (~> 3.11.0)
|
28
|
+
rspec-mocks (3.11.1)
|
29
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
30
|
+
rspec-support (~> 3.11.0)
|
31
|
+
rspec-support (3.11.1)
|
32
|
+
rubocop (1.36.0)
|
33
|
+
json (~> 2.3)
|
34
|
+
parallel (~> 1.10)
|
35
|
+
parser (>= 3.1.2.1)
|
36
|
+
rainbow (>= 2.2.2, < 4.0)
|
37
|
+
regexp_parser (>= 1.8, < 3.0)
|
38
|
+
rexml (>= 3.2.5, < 4.0)
|
39
|
+
rubocop-ast (>= 1.20.1, < 2.0)
|
40
|
+
ruby-progressbar (~> 1.7)
|
41
|
+
unicode-display_width (>= 1.4.0, < 3.0)
|
42
|
+
rubocop-ast (1.21.0)
|
43
|
+
parser (>= 3.1.1.0)
|
44
|
+
ruby-progressbar (1.11.0)
|
45
|
+
unicode-display_width (2.3.0)
|
46
|
+
|
47
|
+
PLATFORMS
|
48
|
+
arm64-darwin-21
|
49
|
+
|
50
|
+
DEPENDENCIES
|
51
|
+
color_hash!
|
52
|
+
rake (~> 13.0)
|
53
|
+
rspec (~> 3.0)
|
54
|
+
rubocop (~> 1.21)
|
55
|
+
|
56
|
+
BUNDLED WITH
|
57
|
+
2.3.17
|
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
# ColorHash
|
2
|
+
|
3
|
+
Generate a color based on a given String, by calculating a color value from the String's hash. The result is deterministic: the same value will always result in the same color (so long as the hash function remains deterministic).
|
4
|
+
|
5
|
+
Generated colours can be useful to dynamically generate tags like these:
|
6
|
+

|
7
|
+
|
8
|
+
## Installation
|
9
|
+
|
10
|
+
Install the gem and add to the application's Gemfile by executing:
|
11
|
+
|
12
|
+
```sh
|
13
|
+
$ bundle add color_hash
|
14
|
+
```
|
15
|
+
|
16
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
17
|
+
|
18
|
+
```sh
|
19
|
+
$ gem install color_hash
|
20
|
+
```
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
By default, `ColorHash` will generate color values in the Hue range between `[0..360]`, and with a lightness and saturation value of one of `[0.35, 0.5, 0.65]`.
|
25
|
+
|
26
|
+
```ruby
|
27
|
+
color_hash = ColorHash.new()
|
28
|
+
|
29
|
+
hex = color_hash.hex("Hello World!")
|
30
|
+
hsl = color_hash.hsl("Hello World!")
|
31
|
+
rgb = color_hash.rgb("Hello World!")
|
32
|
+
```
|
33
|
+
|
34
|
+
The resulting values are going to be:
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
hex = "#d2797c"
|
38
|
+
hsl = [358, 0.5, 0.65]
|
39
|
+
rgb = [210, 121, 124]
|
40
|
+
```
|
41
|
+
|
42
|
+
You can customize the desired `hue` range(s), `saturation` and `lightness` values by passing the corresponding arguments to the constructor. For example, to generate colors in the blue spectrum:
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
color_hash = ColorHash.new(hue: [{min: 180, max: 240}])
|
46
|
+
color = color_hash.hex("Hello World!")
|
47
|
+
```
|
48
|
+
|
49
|
+
will result in a `color` value of:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
color = "#79acd2"
|
53
|
+
```
|
54
|
+
|
55
|
+
## Development
|
56
|
+
|
57
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
58
|
+
|
59
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
60
|
+
|
61
|
+
## Contributing
|
62
|
+
|
63
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kuyio/color_hash.
|
64
|
+
|
65
|
+
## Attribution
|
66
|
+
|
67
|
+
See https://github.com/zenozeng/color-hash for the original implementation in JavaScript.
|
data/Rakefile
ADDED
data/color_hash.gemspec
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/color_hash/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "color_hash"
|
7
|
+
spec.version = ColorHash::VERSION
|
8
|
+
spec.authors = ["Nicolas Bettenburg"]
|
9
|
+
spec.email = ["nicbet@kuy.io"]
|
10
|
+
|
11
|
+
spec.summary = "Generate a color based on the given string."
|
12
|
+
spec.description = "Generate a color based on the given string (in the HSL color space)."
|
13
|
+
spec.homepage = "https://github.com/kuyio/color_hash"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["allowed_push_host"] = "https://rubygems.org"
|
17
|
+
|
18
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
19
|
+
spec.metadata["source_code_uri"] = "https://github.com/kuyio/color_hash"
|
20
|
+
spec.metadata["changelog_uri"] = "https://github.com/kuyio/color_hash/CHANGELOG.md"
|
21
|
+
|
22
|
+
# Specify which files should be added to the gem when it is released.
|
23
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
24
|
+
spec.files = Dir.chdir(__dir__) do
|
25
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
26
|
+
(f == __FILE__) || f.match(%r{\A(?:(?:doc|bin|test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
|
27
|
+
end
|
28
|
+
end
|
29
|
+
spec.bindir = "exe"
|
30
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
31
|
+
spec.require_paths = ["lib"]
|
32
|
+
end
|
@@ -0,0 +1,153 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ColorHash
|
4
|
+
# A ColorHash::Generator can be used to calculate the color value for a given String.
|
5
|
+
# You can specify the desired hue, lightness and saturation (HSL) ranges
|
6
|
+
# for the resulting color value, as well as the hash algorithm to be used
|
7
|
+
# for converting Strings to the numbered color space.
|
8
|
+
#
|
9
|
+
# Ruby implementation of https://github.com/zenozeng/color-hash
|
10
|
+
class Generator
|
11
|
+
# Creates a new ColorHash instance described by the given hue, saturation
|
12
|
+
# and lightness ranges, as well as a Hash function.
|
13
|
+
#
|
14
|
+
# Hue values shall range between [0..360] degrees and are given
|
15
|
+
# as a Hash of the format {min: hue_min, max: hue_max}.
|
16
|
+
# If you provide multiple hue ranges passed in an Array,
|
17
|
+
# the given String will be binned to one of the hue ranges
|
18
|
+
# based on the calculated hash.
|
19
|
+
#
|
20
|
+
# Lightness is described as a floating number between 0.0 and 1.0.
|
21
|
+
# If you provide multiple lightness values passed in an Array,
|
22
|
+
# the given String will be binned to one of the lightness values
|
23
|
+
# based on the calculated hash.
|
24
|
+
#
|
25
|
+
# Saturation is described as a floating number between 0.0 and 1.0
|
26
|
+
# If you provide multiple saturation values passed in an Array,
|
27
|
+
# the given String will be binned to one of the saturation values
|
28
|
+
# based on the calculated hash.
|
29
|
+
|
30
|
+
def initialize(
|
31
|
+
hue: [{ min: 0, max: 360 }],
|
32
|
+
lightness: [0.35, 0.5, 0.65],
|
33
|
+
saturation: [0.35, 0.5, 0.65],
|
34
|
+
hash: :bkdr
|
35
|
+
)
|
36
|
+
@lightness = lightness
|
37
|
+
@saturation = saturation
|
38
|
+
@hue = hue
|
39
|
+
@hash_func = hash
|
40
|
+
end
|
41
|
+
|
42
|
+
# Magic
|
43
|
+
HUE_RESOLUTION = 727
|
44
|
+
|
45
|
+
# rubocop:disable Metrics/AbcSize
|
46
|
+
# Calculates an HSL color value returned as an Array of the form [H, S, L]
|
47
|
+
# from a given string.
|
48
|
+
#
|
49
|
+
# H Hue ∈ [0, 360)
|
50
|
+
# S Saturation ∈ [0, 1]
|
51
|
+
# L Lightness ∈ [0, 1]
|
52
|
+
def hsl(str)
|
53
|
+
hash = send("hash_#{@hash_func}", str)
|
54
|
+
|
55
|
+
hr = @hue[hash % @hue.count]
|
56
|
+
h = ((hash / @hue.count) % HUE_RESOLUTION) * (hr[:max] - hr[:min]) / HUE_RESOLUTION + hr[:min]
|
57
|
+
|
58
|
+
# h = hash % 359
|
59
|
+
|
60
|
+
hash = (hash / 360.0).ceil
|
61
|
+
s = @saturation[hash % @saturation.count.to_f]
|
62
|
+
|
63
|
+
hash = (hash / @saturation.count.to_f).ceil
|
64
|
+
l = @lightness[hash % @lightness.count]
|
65
|
+
|
66
|
+
[h, s, l]
|
67
|
+
end
|
68
|
+
# rubocop:enable Metrics/AbcSize
|
69
|
+
|
70
|
+
# Calculates an RGB color value returned as an Array of the form [R, G, B]
|
71
|
+
# from a given string.
|
72
|
+
#
|
73
|
+
# R, G, B ∈ [0, 255]
|
74
|
+
def rgb(str)
|
75
|
+
hsl2rgb(*hsl(str))
|
76
|
+
end
|
77
|
+
|
78
|
+
# rubocop:disable Metrics/AbcSize
|
79
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
80
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
81
|
+
# rubocop:disable Metrics/MethodLength
|
82
|
+
# Converts a color specified by its hue, saturation and lightness to an RGB value
|
83
|
+
def hsl2rgb(hue, saturation, lightness)
|
84
|
+
hue /= 360.0
|
85
|
+
q_factor = lightness < 0.5 ? lightness * (1.0 + saturation) : (lightness + saturation) - (lightness * saturation)
|
86
|
+
p_factor = 2.0 * lightness - q_factor
|
87
|
+
|
88
|
+
[hue + (1.0 / 3.0), hue, hue - (1.0 / 3.0)].map do |color|
|
89
|
+
color += 1.0 if (color / 0.5) < 0.0
|
90
|
+
color -= 1.0 if color > 1
|
91
|
+
|
92
|
+
color = if color < (1.0 / 6.0)
|
93
|
+
p_factor + (q_factor - p_factor) * 6.0 * color
|
94
|
+
elsif color < 0.5
|
95
|
+
q_factor
|
96
|
+
elsif color < (2.0 / 3.0)
|
97
|
+
p_factor + (q_factor - p_factor) * 6.0 * ((2.0 / 3.0) - color)
|
98
|
+
else
|
99
|
+
p_factor
|
100
|
+
end
|
101
|
+
|
102
|
+
(color * 255.0).round
|
103
|
+
end
|
104
|
+
end
|
105
|
+
# rubocop:enable Metrics/AbcSize
|
106
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
107
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
108
|
+
# rubocop:enable Metrics/MethodLength
|
109
|
+
|
110
|
+
# Calculates an Hexadecimal color value from a given string.
|
111
|
+
# Returns a 6 digits hex string starting with '#'.
|
112
|
+
def hex(str)
|
113
|
+
rgb2hex(rgb(str))
|
114
|
+
end
|
115
|
+
|
116
|
+
# Convers a color specified by its RGB value to a hexadecimal color value.
|
117
|
+
def rgb2hex(rgb)
|
118
|
+
hex = "#"
|
119
|
+
rgb.each do |c|
|
120
|
+
hex += "0" if c < 16
|
121
|
+
hex += c.to_s(16)
|
122
|
+
end
|
123
|
+
|
124
|
+
hex
|
125
|
+
end
|
126
|
+
|
127
|
+
# Calculate a SHA2-256 based hash of the given string
|
128
|
+
def hash_sha256(str)
|
129
|
+
digest = Digest::SHA2.hexdigest(str)
|
130
|
+
digest[0, 8].to_i(16)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Calculate a BKDR based hash of the given string
|
134
|
+
# For additional details on this hash function,
|
135
|
+
# see Brian Kernighan and Dennis Ritchie's book
|
136
|
+
# "The C Programming language".
|
137
|
+
def hash_bkdr(str)
|
138
|
+
seed = 131
|
139
|
+
seed2 = 137
|
140
|
+
hash = 0
|
141
|
+
# makes hash more sensitive for short string like 'a', 'b', 'c'
|
142
|
+
str += "x"
|
143
|
+
# Number.MAX_SAFE_INTEGER equals 9007199254740991
|
144
|
+
max_safe = 9_007_199_254_740_991 / seed2
|
145
|
+
str.each_codepoint.map do |c|
|
146
|
+
hash = (hash / seed2).floor if hash > max_safe
|
147
|
+
hash = hash * seed + c
|
148
|
+
end
|
149
|
+
|
150
|
+
hash
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
data/lib/color_hash.rb
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "color_hash/version"
|
4
|
+
require_relative "color_hash/generator"
|
5
|
+
|
6
|
+
# Generate a color in HSL space from a given String
|
7
|
+
module ColorHash
|
8
|
+
class ArgumentError < StandardError; end
|
9
|
+
|
10
|
+
# Creates a new instance of a ColorHash Generator
|
11
|
+
#
|
12
|
+
# Hue values shall range between [0..360] degrees and are given
|
13
|
+
# as a Hash of the format {min: hue_min, max: hue_max}.
|
14
|
+
# If you provide multiple hue ranges passed in an Array,
|
15
|
+
# the given String will be binned to one of the hue ranges
|
16
|
+
# based on the calculated hash.
|
17
|
+
#
|
18
|
+
# Lightness is described as a floating number between 0.0 and 1.0.
|
19
|
+
# If you provide multiple lightness values passed in an Array,
|
20
|
+
# the given String will be binned to one of the lightness values
|
21
|
+
# based on the calculated hash.
|
22
|
+
#
|
23
|
+
# Saturation is described as a floating number between 0.0 and 1.0
|
24
|
+
# If you provide multiple saturation values passed in an Array,
|
25
|
+
# the given String will be binned to one of the saturation values
|
26
|
+
# based on the calculated hash.
|
27
|
+
#
|
28
|
+
# The Hash function can be either :bkdr (default) or :sha256
|
29
|
+
def self.new(hue: [{ min: 0, max: 360 }], lightness: [0.35, 0.5, 0.65], saturation: [0.35, 0.5, 0.65], hash: :bkdr)
|
30
|
+
ColorHash::Generator.new(hue: hue, lightness: lightness, saturation: saturation, hash: hash)
|
31
|
+
end
|
32
|
+
end
|
data/sig/color_hash.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: color_hash
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nicolas Bettenburg
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2022-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description: Generate a color based on the given string (in the HSL color space).
|
14
|
+
email:
|
15
|
+
- nicbet@kuy.io
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".rspec"
|
21
|
+
- ".rubocop.yml"
|
22
|
+
- CHANGELOG.md
|
23
|
+
- Gemfile
|
24
|
+
- Gemfile.lock
|
25
|
+
- README.md
|
26
|
+
- Rakefile
|
27
|
+
- color_hash.gemspec
|
28
|
+
- lib/color_hash.rb
|
29
|
+
- lib/color_hash/generator.rb
|
30
|
+
- lib/color_hash/version.rb
|
31
|
+
- sig/color_hash.rbs
|
32
|
+
homepage: https://github.com/kuyio/color_hash
|
33
|
+
licenses: []
|
34
|
+
metadata:
|
35
|
+
allowed_push_host: https://rubygems.org
|
36
|
+
homepage_uri: https://github.com/kuyio/color_hash
|
37
|
+
source_code_uri: https://github.com/kuyio/color_hash
|
38
|
+
changelog_uri: https://github.com/kuyio/color_hash/CHANGELOG.md
|
39
|
+
post_install_message:
|
40
|
+
rdoc_options: []
|
41
|
+
require_paths:
|
42
|
+
- lib
|
43
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.6.0
|
48
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: '0'
|
53
|
+
requirements: []
|
54
|
+
rubygems_version: 3.3.17
|
55
|
+
signing_key:
|
56
|
+
specification_version: 4
|
57
|
+
summary: Generate a color based on the given string.
|
58
|
+
test_files: []
|