-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpalette.rb
More file actions
85 lines (76 loc) · 2.48 KB
/
palette.rb
File metadata and controls
85 lines (76 loc) · 2.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
class Palette
attr_reader :angles, :angle_offset, :ranges, :saturation_jitter, :lightness_jitter, :minimum_color_distance, :initial_saturation, :initial_lightness
def initialize(angles:, ranges:, lightness_jitter: 0, saturation_jitter: 0, angle_offset: 0, minimum_color_distance: 0, initial_saturation: 0, initial_lightness: 0)
if angles.count != ranges.count
raise "Palette must be passed same number of angles and ranges"
end
@angle_offset = angle_offset
@angles = angles.map {|a| a + @angle_offset}
@ranges = ranges
@saturation_jitter = saturation_jitter
@lightness_jitter = lightness_jitter
@minimum_color_distance = minimum_color_distance
@initial_saturation = initial_saturation
@initial_lightness = initial_lightness
end
def self.triad
new(angles: [0, 120, 240],
ranges: [15, 15, 15],
minimum_hue_offset: 10,
lightness_jitter: 5,
saturation_jitter: 5)
end
def self.elizabeth_custom
new(angles: [0, 70, 310],
ranges: [50, 50, 50],
minimum_hue_offset: 10,
lightness_jitter: 20,
saturation_jitter: 10,
minimum_color_distance: 5)
end
def self.v1_demo
new(angle_offset: 10,
angles: [0, 210],
ranges: [90, 30],
minimum_color_distance: 15,
lightness_jitter: 20,
saturation_jitter: 10,
initial_lightness: 55,
initial_saturation: 45)
end
def generate(count:, existing_palette: nil)
existing_palette ||= [random_color_within_slices]
max_retries = 100
while count > 1
new_color = next_color(existing_palette.first)
if max_retries == 0 || existing_palette.all? {|c| c.distance_from(new_color) >= minimum_color_distance }
existing_palette << new_color
count -= 1
else
max_retries -= 1
end
end
existing_palette
end
def random_color_within_slices
color = Color.new(
rand(degree_ranges.sample),
initial_saturation || 30,
initial_lightness || 50
)
end
def degree_ranges
angles.zip(ranges).map{|p| (p[0]..(p[0]+ p[1]))}
end
def next_color(color)
slice_index = rand(angles.count).to_i
hue = angles[slice_index] + rand(ranges[slice_index])
saturation_offset = ((rand * saturation_jitter * 2) - saturation_jitter)
lightness_offset = ((rand * lightness_jitter * 2) - lightness_jitter)
Color.new(
hue % 360,
color.saturation + saturation_offset,
color.lightness + lightness_offset
)
end
end