pixelart 1.2.2 → 1.3.1
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/CHANGELOG.md +3 -3
- data/Manifest.txt +5 -0
- data/README.md +290 -290
- data/Rakefile +32 -32
- data/lib/pixelart/base.rb +93 -84
- data/lib/pixelart/blur.rb +19 -19
- data/lib/pixelart/circle.rb +46 -0
- data/lib/pixelart/color.rb +131 -131
- data/lib/pixelart/composite.rb +154 -154
- data/lib/pixelart/generator.rb +199 -0
- data/lib/pixelart/gradient.rb +106 -106
- data/lib/pixelart/image.rb +283 -272
- data/lib/pixelart/led.rb +37 -37
- data/lib/pixelart/misc.rb +66 -66
- data/lib/pixelart/palette.rb +72 -72
- data/lib/pixelart/pixelator.rb +165 -165
- data/lib/pixelart/sample.rb +120 -0
- data/lib/pixelart/silhouette.rb +35 -35
- data/lib/pixelart/sketch.rb +69 -69
- data/lib/pixelart/spots.rb +146 -146
- data/lib/pixelart/stripes.rb +116 -0
- data/lib/pixelart/transparent.rb +60 -60
- data/lib/pixelart/ukraine.rb +20 -0
- data/lib/pixelart/vector.rb +163 -163
- data/lib/pixelart/version.rb +22 -22
- data/lib/pixelart.rb +12 -12
- metadata +11 -6
@@ -0,0 +1,120 @@
|
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
class Image
|
4
|
+
|
5
|
+
def self.calc_sample_steps( width, new_width,
|
6
|
+
center: true,
|
7
|
+
debug: false )
|
8
|
+
## todo/fix: assert new_width is smaller than width
|
9
|
+
if debug
|
10
|
+
puts
|
11
|
+
puts "==> from: #{width}px to: #{new_width}px"
|
12
|
+
end
|
13
|
+
|
14
|
+
indexes = []
|
15
|
+
|
16
|
+
base_step = width / new_width ## pixels per pixel
|
17
|
+
|
18
|
+
err_step = (width % new_width) * 2 ## multiply by 2
|
19
|
+
denominator = new_width * 2 # denominator (in de - nenner e.g. 1/nenner 4/nenner)
|
20
|
+
|
21
|
+
overflow = err_step*new_width/denominator ## todo/check - assert that div is always WITHOUT remainder!!!!!
|
22
|
+
|
23
|
+
if debug
|
24
|
+
puts
|
25
|
+
puts "base_step (pixels per pixel):"
|
26
|
+
puts " #{base_step} - #{base_step} * #{new_width}px = #{base_step*new_width}px"
|
27
|
+
puts "err_step (in 1/#{width}*2):"
|
28
|
+
puts " #{err_step} / #{denominator} - #{err_step*new_width} / #{denominator} = +#{err_step*new_width/denominator}px overflow"
|
29
|
+
puts
|
30
|
+
end
|
31
|
+
|
32
|
+
# initial pixel offset
|
33
|
+
index = 0
|
34
|
+
err = err_step/2 ## note: start off with +err_step/2 to add overflow pixel in the "middle"
|
35
|
+
|
36
|
+
|
37
|
+
index += if center.is_a?( Integer )
|
38
|
+
center
|
39
|
+
elsif center
|
40
|
+
base_step/2
|
41
|
+
else
|
42
|
+
0 # use 0px offset
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
new_width.times do |i|
|
47
|
+
if err >= denominator ## overflow
|
48
|
+
puts " -- overflow #{err}/#{denominator} - add +1 pixel offset to #{i}" if debug
|
49
|
+
index += 1
|
50
|
+
err -= denominator
|
51
|
+
end
|
52
|
+
|
53
|
+
puts " #{i} => #{index} -- #{err} / #{denominator}" if debug
|
54
|
+
|
55
|
+
|
56
|
+
indexes[i] = index
|
57
|
+
|
58
|
+
index += base_step
|
59
|
+
err += err_step
|
60
|
+
end
|
61
|
+
|
62
|
+
indexes
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
|
67
|
+
## todo/check: rename to sample to resample or downsample - why? why not?
|
68
|
+
def sample( steps_x, steps_y=steps_x,
|
69
|
+
top_x: 0, top_y: 0 )
|
70
|
+
width = steps_x.size
|
71
|
+
height = steps_y.size
|
72
|
+
puts " downsampling from #{self.width}x#{self.height} to #{width}x#{height}..."
|
73
|
+
|
74
|
+
dest = Image.new( width, height )
|
75
|
+
|
76
|
+
steps_x.each_with_index do |step_x, x|
|
77
|
+
steps_y.each_with_index do |step_y, y|
|
78
|
+
pixel = self[top_x+step_x, top_y+step_y]
|
79
|
+
|
80
|
+
dest[x,y] = pixel
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
dest
|
85
|
+
end
|
86
|
+
alias_method :pixelate, :sample
|
87
|
+
|
88
|
+
|
89
|
+
def sample_debug( steps_x, steps_y=steps_x,
|
90
|
+
color: Color.parse( '#ffff00' ),
|
91
|
+
top_x: 0,
|
92
|
+
top_y: 0) ## add a yellow pixel
|
93
|
+
|
94
|
+
## todo/fix: get a clone of the image (DO NOT modify in place)
|
95
|
+
|
96
|
+
img = self
|
97
|
+
|
98
|
+
steps_x.each_with_index do |step_x, x|
|
99
|
+
steps_y.each_with_index do |step_y, y|
|
100
|
+
base_x = top_x+step_x
|
101
|
+
base_y = top_y+step_y
|
102
|
+
|
103
|
+
img[base_x,base_y] = color
|
104
|
+
|
105
|
+
## add more colors
|
106
|
+
img[base_x+1,base_y] = color
|
107
|
+
img[base_x+2,base_y] = color
|
108
|
+
|
109
|
+
img[base_x,base_y+1] = color
|
110
|
+
img[base_x,base_y+2] = color
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
self
|
115
|
+
end
|
116
|
+
alias_method :pixelate_debug, :sample_debug
|
117
|
+
|
118
|
+
end # class Image
|
119
|
+
end # module Pixelart
|
120
|
+
|
data/lib/pixelart/silhouette.rb
CHANGED
@@ -1,35 +1,35 @@
|
|
1
|
-
module Pixelart
|
2
|
-
|
3
|
-
|
4
|
-
## todo/check:
|
5
|
-
## use a different name for silhouette
|
6
|
-
## - why not - outline ???
|
7
|
-
## or - shadow ???
|
8
|
-
## or - profile ???
|
9
|
-
## or - figure ???
|
10
|
-
## or - shape ???
|
11
|
-
## or - form ???
|
12
|
-
|
13
|
-
class Image
|
14
|
-
def silhouette( color='#000000' )
|
15
|
-
color = Color.parse( color )
|
16
|
-
|
17
|
-
img = Image.new( @img.width, @img.height )
|
18
|
-
|
19
|
-
@img.width.times do |x|
|
20
|
-
@img.height.times do |y|
|
21
|
-
pixel = @img[x,y]
|
22
|
-
|
23
|
-
img[x,y] = if pixel == Color::TRANSPARENT # transparent (0)
|
24
|
-
Color::TRANSPARENT
|
25
|
-
else
|
26
|
-
color
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
img
|
31
|
-
end
|
32
|
-
|
33
|
-
end # class Image
|
34
|
-
|
35
|
-
end # module Pixelart
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
|
4
|
+
## todo/check:
|
5
|
+
## use a different name for silhouette
|
6
|
+
## - why not - outline ???
|
7
|
+
## or - shadow ???
|
8
|
+
## or - profile ???
|
9
|
+
## or - figure ???
|
10
|
+
## or - shape ???
|
11
|
+
## or - form ???
|
12
|
+
|
13
|
+
class Image
|
14
|
+
def silhouette( color='#000000' )
|
15
|
+
color = Color.parse( color )
|
16
|
+
|
17
|
+
img = Image.new( @img.width, @img.height )
|
18
|
+
|
19
|
+
@img.width.times do |x|
|
20
|
+
@img.height.times do |y|
|
21
|
+
pixel = @img[x,y]
|
22
|
+
|
23
|
+
img[x,y] = if pixel == Color::TRANSPARENT # transparent (0)
|
24
|
+
Color::TRANSPARENT
|
25
|
+
else
|
26
|
+
color
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
img
|
31
|
+
end
|
32
|
+
|
33
|
+
end # class Image
|
34
|
+
|
35
|
+
end # module Pixelart
|
data/lib/pixelart/sketch.rb
CHANGED
@@ -1,69 +1,69 @@
|
|
1
|
-
module Pixelart
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
class Image
|
6
|
-
def sketch( sketch=4, line: 1 )
|
7
|
-
# todo: line - find a better name eg. line_strenght/width or such?
|
8
|
-
width = @img.width*sketch + (@img.width+1)*line
|
9
|
-
height = @img.height*sketch + (@img.height+1)*line
|
10
|
-
|
11
|
-
puts " #{width}x#{height}"
|
12
|
-
|
13
|
-
img = Image.new( width, height, Color::WHITE )
|
14
|
-
|
15
|
-
@img.width.times do |x|
|
16
|
-
@img.height.times do |y|
|
17
|
-
pixel = @img[x,y]
|
18
|
-
|
19
|
-
## get surrounding pixels - if "out-of-bound" use transparent (0)
|
20
|
-
left = x == 0 ? Color::TRANSPARENT : @img[x-1,y]
|
21
|
-
top = y == 0 ? Color::TRANSPARENT : @img[x ,y-1]
|
22
|
-
|
23
|
-
if pixel != left ## draw vertical line
|
24
|
-
(sketch+line*2).times do |n|
|
25
|
-
line.times do |m|
|
26
|
-
img[ x*sketch + line*x + m,
|
27
|
-
n + y*sketch + line*y] = Color::BLACK
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
if pixel != top ## draw horizontal line
|
33
|
-
(sketch+line*2).times do |n|
|
34
|
-
line.times do |m|
|
35
|
-
img[n + x*sketch + line*x,
|
36
|
-
y*sketch + line*y + m] = Color::BLACK
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
|
42
|
-
## check special edge case for x and y to add "finish-up" right and bottom line
|
43
|
-
if x == @img.width-1 && pixel != Color::TRANSPARENT
|
44
|
-
## draw vertical line
|
45
|
-
(sketch+line*2).times do |n|
|
46
|
-
line.times do |m|
|
47
|
-
img[ (x+1)*sketch + line*(x+1) + m,
|
48
|
-
n + y*sketch + line*y] = Color::BLACK
|
49
|
-
end
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
if y== @img.height-1 && pixel != Color::TRANSPARENT
|
54
|
-
## draw horizontal line
|
55
|
-
(sketch+line*2).times do |n|
|
56
|
-
line.times do |m|
|
57
|
-
img[n + x*sketch + line*x,
|
58
|
-
(y+1)*sketch + line*(y+1) + m] = Color::BLACK
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
img
|
66
|
-
end
|
67
|
-
end # class Image
|
68
|
-
end # module Pixelart
|
69
|
-
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
class Image
|
6
|
+
def sketch( sketch=4, line: 1 )
|
7
|
+
# todo: line - find a better name eg. line_strenght/width or such?
|
8
|
+
width = @img.width*sketch + (@img.width+1)*line
|
9
|
+
height = @img.height*sketch + (@img.height+1)*line
|
10
|
+
|
11
|
+
puts " #{width}x#{height}"
|
12
|
+
|
13
|
+
img = Image.new( width, height, Color::WHITE )
|
14
|
+
|
15
|
+
@img.width.times do |x|
|
16
|
+
@img.height.times do |y|
|
17
|
+
pixel = @img[x,y]
|
18
|
+
|
19
|
+
## get surrounding pixels - if "out-of-bound" use transparent (0)
|
20
|
+
left = x == 0 ? Color::TRANSPARENT : @img[x-1,y]
|
21
|
+
top = y == 0 ? Color::TRANSPARENT : @img[x ,y-1]
|
22
|
+
|
23
|
+
if pixel != left ## draw vertical line
|
24
|
+
(sketch+line*2).times do |n|
|
25
|
+
line.times do |m|
|
26
|
+
img[ x*sketch + line*x + m,
|
27
|
+
n + y*sketch + line*y] = Color::BLACK
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
if pixel != top ## draw horizontal line
|
33
|
+
(sketch+line*2).times do |n|
|
34
|
+
line.times do |m|
|
35
|
+
img[n + x*sketch + line*x,
|
36
|
+
y*sketch + line*y + m] = Color::BLACK
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
## check special edge case for x and y to add "finish-up" right and bottom line
|
43
|
+
if x == @img.width-1 && pixel != Color::TRANSPARENT
|
44
|
+
## draw vertical line
|
45
|
+
(sketch+line*2).times do |n|
|
46
|
+
line.times do |m|
|
47
|
+
img[ (x+1)*sketch + line*(x+1) + m,
|
48
|
+
n + y*sketch + line*y] = Color::BLACK
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
if y== @img.height-1 && pixel != Color::TRANSPARENT
|
54
|
+
## draw horizontal line
|
55
|
+
(sketch+line*2).times do |n|
|
56
|
+
line.times do |m|
|
57
|
+
img[n + x*sketch + line*x,
|
58
|
+
(y+1)*sketch + line*(y+1) + m] = Color::BLACK
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
img
|
66
|
+
end
|
67
|
+
end # class Image
|
68
|
+
end # module Pixelart
|
69
|
+
|
data/lib/pixelart/spots.rb
CHANGED
@@ -1,146 +1,146 @@
|
|
1
|
-
module Pixelart
|
2
|
-
|
3
|
-
class Image
|
4
|
-
|
5
|
-
|
6
|
-
def spots_hidef( spot=10,
|
7
|
-
spacing: 0,
|
8
|
-
center: nil,
|
9
|
-
radius: nil,
|
10
|
-
background: nil,
|
11
|
-
lightness: nil,
|
12
|
-
odd: false )
|
13
|
-
|
14
|
-
width = @img.width*spot+(@img.width-1)*spacing
|
15
|
-
height = @img.height*spot+(@img.height-1)*spacing
|
16
|
-
|
17
|
-
## puts " #{width}x#{height}"
|
18
|
-
|
19
|
-
## settings in a hash for "pretty printing" in comments
|
20
|
-
settings = { spot: spot
|
21
|
-
}
|
22
|
-
|
23
|
-
settings[ :spacing ] = spacing if spacing
|
24
|
-
settings[ :center ] = center if center
|
25
|
-
settings[ :radius ] = radius if radius
|
26
|
-
settings[ :background ] = background if background
|
27
|
-
settings[ :lightness ] = lightness if lightness
|
28
|
-
settings[ :odd ] = odd if odd
|
29
|
-
|
30
|
-
|
31
|
-
v = Vector.new( width, height, header: <<TXT )
|
32
|
-
generated by pixelart/v#{VERSION} on #{Time.now.utc}
|
33
|
-
|
34
|
-
spots_hidef with settings:
|
35
|
-
#{settings.to_json}
|
36
|
-
TXT
|
37
|
-
|
38
|
-
|
39
|
-
min_center, max_center = center ? center : [0,0]
|
40
|
-
min_radius, max_radius = radius ? radius : [0,0]
|
41
|
-
|
42
|
-
## note: allow passing in array of colors (will get randomally picked)
|
43
|
-
background_colors = if background
|
44
|
-
## check for array; otherwise assume single color passed in
|
45
|
-
background_ary = background.is_a?( Array) ? background : [background]
|
46
|
-
background_ary.map { |background| Color.parse( background ) }
|
47
|
-
else
|
48
|
-
[0] # transparent (default - no background)
|
49
|
-
end
|
50
|
-
|
51
|
-
|
52
|
-
min_lightness, max_lightness = lightness ? lightness : [0.0,0.0]
|
53
|
-
|
54
|
-
|
55
|
-
@img.width.times do |x|
|
56
|
-
@img.height.times do |y|
|
57
|
-
color = @img[ x, y ]
|
58
|
-
|
59
|
-
if color == 0 ## transparent
|
60
|
-
next if background.nil?
|
61
|
-
|
62
|
-
color = if background_colors.size == 1
|
63
|
-
background_colors[0]
|
64
|
-
else ## pick random background color
|
65
|
-
background_colors[ rand( background_colors.size ) ]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
|
70
|
-
if lightness
|
71
|
-
## todo/check: make it work with alpha too
|
72
|
-
h,s,l = Color.to_hsl( color, include_alpha: false )
|
73
|
-
|
74
|
-
h = h % 360 ## make sure h(ue) is always positive!!!
|
75
|
-
|
76
|
-
## note: rand() return between 0.0 and 1.0
|
77
|
-
l_diff = min_lightness +
|
78
|
-
(max_lightness-min_lightness)*rand()
|
79
|
-
|
80
|
-
lnew = [1.0, l+l_diff].min
|
81
|
-
lnew = [0.0, lnew].max
|
82
|
-
|
83
|
-
## print " #{l}+#{l_diff}=#{lnew} "
|
84
|
-
|
85
|
-
color = Color.from_hsl( h,
|
86
|
-
[1.0, s].min,
|
87
|
-
lnew )
|
88
|
-
end
|
89
|
-
|
90
|
-
## note: return hexstring with leading #
|
91
|
-
# e.g. 0 becomes #00000000
|
92
|
-
# and so on
|
93
|
-
color_hex = Color.to_hex( color, include_alpha: true )
|
94
|
-
|
95
|
-
cx_offset,
|
96
|
-
cy_offset = if center ## randomize (offset off center +/-)
|
97
|
-
[(spot/2 + min_center) + rand( max_center-min_center ),
|
98
|
-
(spot/2 + min_center) + rand( max_center-min_center )]
|
99
|
-
else
|
100
|
-
[spot/2, ## center
|
101
|
-
spot/2]
|
102
|
-
end
|
103
|
-
|
104
|
-
cx = x*spot + x*spacing + cx_offset
|
105
|
-
cy = y*spot + y*spacing + cx_offset
|
106
|
-
|
107
|
-
r = if radius ## randomize (radius +/-)
|
108
|
-
min_radius + rand( max_radius-min_radius )
|
109
|
-
else
|
110
|
-
spot/2
|
111
|
-
end
|
112
|
-
|
113
|
-
cx += spot/2 if odd && (y % 2 == 1) ## add odd offset
|
114
|
-
|
115
|
-
|
116
|
-
v.circle( cx: cx, cy: cy, r: r, fill: color_hex)
|
117
|
-
end
|
118
|
-
end
|
119
|
-
v
|
120
|
-
end ## method spots_hidef
|
121
|
-
alias_method :spots_hd, :spots_hidef
|
122
|
-
|
123
|
-
|
124
|
-
def spots( spot=10,
|
125
|
-
spacing: 0,
|
126
|
-
center: nil,
|
127
|
-
radius: nil,
|
128
|
-
background: nil,
|
129
|
-
lightness: nil,
|
130
|
-
odd: false )
|
131
|
-
|
132
|
-
v = spots_hidef( spot,
|
133
|
-
spacing: spacing,
|
134
|
-
center: center,
|
135
|
-
radius: radius,
|
136
|
-
background: background,
|
137
|
-
lightness: lightness,
|
138
|
-
odd: odd )
|
139
|
-
|
140
|
-
v.to_image
|
141
|
-
end
|
142
|
-
|
143
|
-
|
144
|
-
end # class Image
|
145
|
-
end # class Pixelart
|
146
|
-
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
class Image
|
4
|
+
|
5
|
+
|
6
|
+
def spots_hidef( spot=10,
|
7
|
+
spacing: 0,
|
8
|
+
center: nil,
|
9
|
+
radius: nil,
|
10
|
+
background: nil,
|
11
|
+
lightness: nil,
|
12
|
+
odd: false )
|
13
|
+
|
14
|
+
width = @img.width*spot+(@img.width-1)*spacing
|
15
|
+
height = @img.height*spot+(@img.height-1)*spacing
|
16
|
+
|
17
|
+
## puts " #{width}x#{height}"
|
18
|
+
|
19
|
+
## settings in a hash for "pretty printing" in comments
|
20
|
+
settings = { spot: spot
|
21
|
+
}
|
22
|
+
|
23
|
+
settings[ :spacing ] = spacing if spacing
|
24
|
+
settings[ :center ] = center if center
|
25
|
+
settings[ :radius ] = radius if radius
|
26
|
+
settings[ :background ] = background if background
|
27
|
+
settings[ :lightness ] = lightness if lightness
|
28
|
+
settings[ :odd ] = odd if odd
|
29
|
+
|
30
|
+
|
31
|
+
v = Vector.new( width, height, header: <<TXT )
|
32
|
+
generated by pixelart/v#{VERSION} on #{Time.now.utc}
|
33
|
+
|
34
|
+
spots_hidef with settings:
|
35
|
+
#{settings.to_json}
|
36
|
+
TXT
|
37
|
+
|
38
|
+
|
39
|
+
min_center, max_center = center ? center : [0,0]
|
40
|
+
min_radius, max_radius = radius ? radius : [0,0]
|
41
|
+
|
42
|
+
## note: allow passing in array of colors (will get randomally picked)
|
43
|
+
background_colors = if background
|
44
|
+
## check for array; otherwise assume single color passed in
|
45
|
+
background_ary = background.is_a?( Array) ? background : [background]
|
46
|
+
background_ary.map { |background| Color.parse( background ) }
|
47
|
+
else
|
48
|
+
[0] # transparent (default - no background)
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
min_lightness, max_lightness = lightness ? lightness : [0.0,0.0]
|
53
|
+
|
54
|
+
|
55
|
+
@img.width.times do |x|
|
56
|
+
@img.height.times do |y|
|
57
|
+
color = @img[ x, y ]
|
58
|
+
|
59
|
+
if color == 0 ## transparent
|
60
|
+
next if background.nil?
|
61
|
+
|
62
|
+
color = if background_colors.size == 1
|
63
|
+
background_colors[0]
|
64
|
+
else ## pick random background color
|
65
|
+
background_colors[ rand( background_colors.size ) ]
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
if lightness
|
71
|
+
## todo/check: make it work with alpha too
|
72
|
+
h,s,l = Color.to_hsl( color, include_alpha: false )
|
73
|
+
|
74
|
+
h = h % 360 ## make sure h(ue) is always positive!!!
|
75
|
+
|
76
|
+
## note: rand() return between 0.0 and 1.0
|
77
|
+
l_diff = min_lightness +
|
78
|
+
(max_lightness-min_lightness)*rand()
|
79
|
+
|
80
|
+
lnew = [1.0, l+l_diff].min
|
81
|
+
lnew = [0.0, lnew].max
|
82
|
+
|
83
|
+
## print " #{l}+#{l_diff}=#{lnew} "
|
84
|
+
|
85
|
+
color = Color.from_hsl( h,
|
86
|
+
[1.0, s].min,
|
87
|
+
lnew )
|
88
|
+
end
|
89
|
+
|
90
|
+
## note: return hexstring with leading #
|
91
|
+
# e.g. 0 becomes #00000000
|
92
|
+
# and so on
|
93
|
+
color_hex = Color.to_hex( color, include_alpha: true )
|
94
|
+
|
95
|
+
cx_offset,
|
96
|
+
cy_offset = if center ## randomize (offset off center +/-)
|
97
|
+
[(spot/2 + min_center) + rand( max_center-min_center ),
|
98
|
+
(spot/2 + min_center) + rand( max_center-min_center )]
|
99
|
+
else
|
100
|
+
[spot/2, ## center
|
101
|
+
spot/2]
|
102
|
+
end
|
103
|
+
|
104
|
+
cx = x*spot + x*spacing + cx_offset
|
105
|
+
cy = y*spot + y*spacing + cx_offset
|
106
|
+
|
107
|
+
r = if radius ## randomize (radius +/-)
|
108
|
+
min_radius + rand( max_radius-min_radius )
|
109
|
+
else
|
110
|
+
spot/2
|
111
|
+
end
|
112
|
+
|
113
|
+
cx += spot/2 if odd && (y % 2 == 1) ## add odd offset
|
114
|
+
|
115
|
+
|
116
|
+
v.circle( cx: cx, cy: cy, r: r, fill: color_hex)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
v
|
120
|
+
end ## method spots_hidef
|
121
|
+
alias_method :spots_hd, :spots_hidef
|
122
|
+
|
123
|
+
|
124
|
+
def spots( spot=10,
|
125
|
+
spacing: 0,
|
126
|
+
center: nil,
|
127
|
+
radius: nil,
|
128
|
+
background: nil,
|
129
|
+
lightness: nil,
|
130
|
+
odd: false )
|
131
|
+
|
132
|
+
v = spots_hidef( spot,
|
133
|
+
spacing: spacing,
|
134
|
+
center: center,
|
135
|
+
radius: radius,
|
136
|
+
background: background,
|
137
|
+
lightness: lightness,
|
138
|
+
odd: odd )
|
139
|
+
|
140
|
+
v.to_image
|
141
|
+
end
|
142
|
+
|
143
|
+
|
144
|
+
end # class Image
|
145
|
+
end # class Pixelart
|
146
|
+
|