pixelart 1.2.2 → 1.3.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+
@@ -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
@@ -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
+
@@ -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
+