pixelart 0.1.4 → 0.2.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 +4 -4
- data/Manifest.txt +2 -0
- data/README.md +8 -8
- data/Rakefile +1 -1
- data/lib/pixelart/base.rb +8 -3
- data/lib/pixelart/color.rb +0 -1
- data/lib/pixelart/image.rb +28 -9
- data/lib/pixelart/led.rb +37 -0
- data/lib/pixelart/misc.rb +30 -4
- data/lib/pixelart/pixelator.rb +117 -0
- data/lib/pixelart/version.rb +2 -2
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4ebe6ddb193d15d611f37461ebca0f7de77d9df6d14c0078eeb483fcdcaf505e
|
4
|
+
data.tar.gz: 773ab34615671bb06b4e8b8e77096cc9e44588ec5c1b04662474e410a0382223
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50f927ae70136c40e9d8bcac7c7c87641dc51427fbf5abaf2a88f1312327e83f59689b597b91e0d9003887a349b10fd20ce4be2ba7bf7baf1b9cebd2df2ee7b5
|
7
|
+
data.tar.gz: 6afea4ef51112243f065b7071d26c4ae6a70b3c408015838ab01a02d38a3a53ff3f14f04c7cd9746520c6be10f4153eba8b6533e4a52726dc531a7d54e250c29
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -3,8 +3,8 @@
|
|
3
3
|
pixelart - mint your own pixel art images off chain using any design (in ascii text) in any colors; incl. 2x/4x/8x zoom for bigger sizes
|
4
4
|
|
5
5
|
|
6
|
-
* home :: [github.com/
|
7
|
-
* bugs :: [github.com/
|
6
|
+
* home :: [github.com/rubycoco/pixel](https://github.com/rubycoco/pixel)
|
7
|
+
* bugs :: [github.com/rubycoco/pixel/issues](https://github.com/rubycoco/pixel/issues)
|
8
8
|
* gem :: [rubygems.org/gems/pixelart](https://rubygems.org/gems/pixelart)
|
9
9
|
* rdoc :: [rubydoc.info/gems/pixelart](http://rubydoc.info/gems/pixelart)
|
10
10
|
|
@@ -71,8 +71,8 @@ img3x.save( './i/mooncat_white-3x.png' )
|
|
71
71
|
|
72
72
|
Voila!
|
73
73
|
|
74
|
-

|
75
|
+

|
76
76
|
|
77
77
|
|
78
78
|
|
@@ -100,8 +100,8 @@ img3x.save( './i/mooncat_black-3x.png' )
|
|
100
100
|
|
101
101
|
Voila! Black is the new White!
|
102
102
|
|
103
|
-

|
104
|
+

|
105
105
|
|
106
106
|
|
107
107
|
|
@@ -227,8 +227,8 @@ img5x.save( './i/vader5x.png' )
|
|
227
227
|
|
228
228
|
Voila!
|
229
229
|
|
230
|
-

|
231
|
+

|
232
232
|
|
233
233
|
|
234
234
|
|
data/Rakefile
CHANGED
@@ -8,7 +8,7 @@ Hoe.spec 'pixelart' do
|
|
8
8
|
self.summary = "pixelart - mint your own pixel art images off chain using any design (in ascii text) in any colors; incl. 2x/4x/8x zoom for bigger sizes"
|
9
9
|
self.description = summary
|
10
10
|
|
11
|
-
self.urls = { home: 'https://github.com/
|
11
|
+
self.urls = { home: 'https://github.com/rubycoco/pixel' }
|
12
12
|
|
13
13
|
self.author = 'Gerald Bauer'
|
14
14
|
self.email = 'wwwmake@googlegroups.com'
|
data/lib/pixelart/base.rb
CHANGED
@@ -15,8 +15,14 @@ require 'pixelart/gradient'
|
|
15
15
|
require 'pixelart/palette'
|
16
16
|
require 'pixelart/image'
|
17
17
|
|
18
|
+
require 'pixelart/pixelator'
|
19
|
+
|
18
20
|
require 'pixelart/misc' ## misc helpers
|
19
21
|
|
22
|
+
require 'pixelart/led' ## (special) effects / filters
|
23
|
+
|
24
|
+
|
25
|
+
|
20
26
|
|
21
27
|
##########
|
22
28
|
# add some spelling convenience variants
|
@@ -25,9 +31,8 @@ PixelArt = Pixelart
|
|
25
31
|
module Pixelart
|
26
32
|
Palette256 = Palette8Bit = Palette8bit
|
27
33
|
|
28
|
-
|
29
|
-
|
30
|
-
end
|
34
|
+
Palette256Image = Palette8BitImage = Palette8bitImage =
|
35
|
+
ImagePalette256 = ImagePalette8Bit = ImagePalette8bit
|
31
36
|
end
|
32
37
|
|
33
38
|
|
data/lib/pixelart/color.rb
CHANGED
data/lib/pixelart/image.rb
CHANGED
@@ -9,7 +9,14 @@ def self.read( path ) ## convenience helper
|
|
9
9
|
end
|
10
10
|
|
11
11
|
|
12
|
-
|
12
|
+
|
13
|
+
CHARS = '.@xo^~%*+=:' ## todo/check: rename to default chars or such? why? why not?
|
14
|
+
|
15
|
+
## todo/check: support default chars encoding auto-of-the-box always
|
16
|
+
## or require user-defined chars to be passed in - why? why not?
|
17
|
+
def self.parse( pixels, colors:, chars: CHARS )
|
18
|
+
has_keys = colors.is_a?(Hash) ## check if passed-in user-defined keys (via hash table)?
|
19
|
+
|
13
20
|
colors = parse_colors( colors )
|
14
21
|
pixels = parse_pixels( pixels )
|
15
22
|
|
@@ -20,7 +27,19 @@ def self.parse( pixels, colors: )
|
|
20
27
|
|
21
28
|
pixels.each_with_index do |row,y|
|
22
29
|
row.each_with_index do |color,x|
|
23
|
-
pixel =
|
30
|
+
pixel = if has_keys ## if passed-in user-defined keys check only the user-defined keys
|
31
|
+
colors[color]
|
32
|
+
else
|
33
|
+
## try map ascii art char (.@xo etc.) to color index (0,1,2)
|
34
|
+
## if no match found - fallback on assuming draw by number (0 1 2 etc.) encoding
|
35
|
+
pos = chars.index( color )
|
36
|
+
if pos
|
37
|
+
colors[ pos.to_s ]
|
38
|
+
else ## assume nil (not found)
|
39
|
+
colors[ color ]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
24
43
|
img[x,y] = pixel
|
25
44
|
end # each row
|
26
45
|
end # each data
|
@@ -98,7 +117,7 @@ PALETTE8BIT = {
|
|
98
117
|
|
99
118
|
def change_palette8bit( palette )
|
100
119
|
## step 0: mapping from grayscale to new 8bit palette (256 colors)
|
101
|
-
color_map = if palette.is_a( String ) || palette.is_a( Symbol )
|
120
|
+
color_map = if palette.is_a?( String ) || palette.is_a?( Symbol )
|
102
121
|
PALETTE8BIT[ palette.to_sym ]
|
103
122
|
## todo/fix: check for missing/undefined palette not found - why? why not?
|
104
123
|
else
|
@@ -170,6 +189,9 @@ def []=( x, y, value ) @img[x,y]=value; end
|
|
170
189
|
|
171
190
|
def pixels() @img.pixels; end
|
172
191
|
|
192
|
+
### todo/check: add colors() e.g. @img.pixels.uniq - why? why not?
|
193
|
+
|
194
|
+
|
173
195
|
## return image ref - use a different name - why? why not?
|
174
196
|
## change to to_image - why? why not?
|
175
197
|
def image() @img; end
|
@@ -183,10 +205,7 @@ def self.parse_pixels( pixels )
|
|
183
205
|
data = []
|
184
206
|
pixels.each_line do |line|
|
185
207
|
line = line.strip
|
186
|
-
if line.empty?
|
187
|
-
puts "!! WARN: skipping empty line in pixel art source"
|
188
|
-
next
|
189
|
-
end
|
208
|
+
next if line.start_with?( '#' ) || line.empty? ## note: allow comments and empty lines
|
190
209
|
|
191
210
|
## note: allow multiple spaces or tabs to separate pixel codes
|
192
211
|
## e.g. o o o o o o o o o o o o dg lg w w lg w lg lg dg dg w w lg dg o o o o o o o o o o o
|
@@ -197,12 +216,13 @@ def self.parse_pixels( pixels )
|
|
197
216
|
end
|
198
217
|
|
199
218
|
|
219
|
+
|
200
220
|
def self.parse_colors( colors )
|
201
221
|
if colors.is_a?( Array ) ## convenience shortcut
|
202
222
|
## note: always auto-add color 0 as pre-defined transparent - why? why not?
|
203
223
|
h = { '0' => Color::TRANSPARENT }
|
204
224
|
colors.each_with_index do |color, i|
|
205
|
-
|
225
|
+
h[ (i+1).to_s ] = Color.parse( color )
|
206
226
|
end
|
207
227
|
h
|
208
228
|
else ## assume hash table with color map
|
@@ -215,7 +235,6 @@ def self.parse_colors( colors )
|
|
215
235
|
end
|
216
236
|
|
217
237
|
|
218
|
-
|
219
238
|
end # class Image
|
220
239
|
end # module Pixelart
|
221
240
|
|
data/lib/pixelart/led.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
|
4
|
+
class Image
|
5
|
+
def led( led=8, spacing: 2, round_corner: false )
|
6
|
+
|
7
|
+
width = @img.width*led + (@img.width-1)*spacing
|
8
|
+
height = @img.height*led + (@img.height-1)*spacing
|
9
|
+
|
10
|
+
puts " #{width}x#{height}"
|
11
|
+
|
12
|
+
img = Image.new( width, height, Color::BLACK )
|
13
|
+
|
14
|
+
@img.width.times do |x|
|
15
|
+
@img.height.times do |y|
|
16
|
+
pixel = @img[x,y]
|
17
|
+
pixel = Color::BLACK if pixel == Color::TRANSPARENT
|
18
|
+
led.times do |n|
|
19
|
+
led.times do |m|
|
20
|
+
## round a little - drop all four corners for now
|
21
|
+
next if round_corner &&
|
22
|
+
[[0,0],[0,1],[1,0],[1,1],[0,2],[2,0],
|
23
|
+
[0,led-1],[0,led-2],[1,led-1],[1,led-2],[0,led-3],[2,led-1],
|
24
|
+
[led-1,0],[led-1,1],[led-2,0],[led-2,1],[led-1,2],[led-3,0],
|
25
|
+
[led-1,led-1],[led-1,led-2],[led-2,led-1],[led-2,led-2],[led-1,led-3],[led-3,led-1],
|
26
|
+
].include?( [n,m] )
|
27
|
+
img[x*led+n + spacing*x,
|
28
|
+
y*led+m + spacing*y] = pixel
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
img
|
34
|
+
end
|
35
|
+
end # class Image
|
36
|
+
end # module Pixelart
|
37
|
+
|
data/lib/pixelart/misc.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
module Pixelart
|
2
2
|
|
3
3
|
|
4
|
-
class Image
|
5
|
-
class Palette8bit < Image # or use Palette256 alias?
|
4
|
+
class ImagePalette8bit < Image # or use Palette256 alias?
|
6
5
|
def initialize( colors, size: 1, spacing: nil )
|
7
6
|
## todo/check: change size arg to pixel or such? better name/less confusing - why? why not?
|
8
7
|
|
@@ -16,6 +15,9 @@ class Palette8bit < Image # or use Palette256 alias?
|
|
16
15
|
img = ChunkyPNG::Image.new( 32*size+(32-1)*spacing,
|
17
16
|
8*size+(8-1)*spacing )
|
18
17
|
|
18
|
+
|
19
|
+
colors =colors.map {|color| Color.parse( color ) }
|
20
|
+
|
19
21
|
colors.each_with_index do |color,i|
|
20
22
|
y,x = i.divmod( 32 )
|
21
23
|
if size > 1
|
@@ -32,9 +34,33 @@ class Palette8bit < Image # or use Palette256 alias?
|
|
32
34
|
|
33
35
|
super( img.width, img.height, img )
|
34
36
|
end
|
35
|
-
end # class
|
37
|
+
end # class ImagePalette8bit
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
class ImageColorBar < Image
|
42
|
+
## make a color bar
|
43
|
+
## keep auto-zoom 24x or such - why? why not?
|
44
|
+
def initialize( colors, size: 24 )
|
45
|
+
img = ChunkyPNG::Image.new( colors.size*size,
|
46
|
+
size,
|
47
|
+
ChunkyPNG::Color::WHITE ) # why? why not?
|
48
|
+
|
49
|
+
colors = colors.map {|color| Color.parse( color ) }
|
50
|
+
|
51
|
+
colors.each_with_index do |color,i|
|
52
|
+
size.times do |x|
|
53
|
+
size.times do |y|
|
54
|
+
img[x+size*i,y] = color
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
super( img.width, img.height, img )
|
60
|
+
end
|
61
|
+
end # class ImageColorBar
|
62
|
+
|
36
63
|
|
37
|
-
end # class Image
|
38
64
|
end # module Pixelart
|
39
65
|
|
40
66
|
|
@@ -0,0 +1,117 @@
|
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
|
4
|
+
class Pixelator # or use Minifier or such - rename - why? why not?
|
5
|
+
|
6
|
+
def initialize( img, width=24, height=24 )
|
7
|
+
@img = img.is_a?( Image ) ? img.image : img ## "unwrap" if Pixelart::Image
|
8
|
+
@width = width
|
9
|
+
@height = height
|
10
|
+
|
11
|
+
## calculate pixel size / density / resolution
|
12
|
+
## how many pixels per pixel?
|
13
|
+
@xsize, @xoverflow = img.width.divmod( width )
|
14
|
+
@ysize, @yoverflow = img.height.divmod( height )
|
15
|
+
|
16
|
+
puts "minify image size from (#{@img.width}x#{@img.height}) to (#{width}x#{height})"
|
17
|
+
puts " pixel size (#{@xsize}x#{@ysize}) - #{@xsize*@ysize} pixel(s) per pixel"
|
18
|
+
puts " overflow x: #{@xoverflow}, y: #{@yoverflow} pixel(s)" if @xoverflow > 0 || @yoverflow > 0
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
def grid( spacing: 10 )
|
23
|
+
width = @img.width + (@width-1)*spacing
|
24
|
+
height = @img.height + (@height-1)*spacing
|
25
|
+
|
26
|
+
img = ChunkyPNG::Image.new( width, height, ChunkyPNG::Color::WHITE )
|
27
|
+
|
28
|
+
@img.width.times do |x|
|
29
|
+
xpixel = x/@xsize
|
30
|
+
@img.height.times do |y|
|
31
|
+
ypixel = y/@ysize
|
32
|
+
|
33
|
+
## clip overflow pixels
|
34
|
+
xpixel = @width-1 if xpixel >= @width
|
35
|
+
ypixel = @height-1 if ypixel >= @height
|
36
|
+
|
37
|
+
color = @img[x,y]
|
38
|
+
img[x + spacing*xpixel,
|
39
|
+
y + spacing*ypixel] = color
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
Image.new( img.width, img.height, img ) ## wrap in Pixelart::Image - why? why not?
|
44
|
+
end
|
45
|
+
|
46
|
+
|
47
|
+
# pixels by coordinates (x/y) with color statistics / usage
|
48
|
+
def pixels
|
49
|
+
@pixels ||= begin
|
50
|
+
pixels = []
|
51
|
+
@img.width.times do |x|
|
52
|
+
xpixel = x/@xsize
|
53
|
+
@img.height.times do |y|
|
54
|
+
ypixel = y/@ysize
|
55
|
+
|
56
|
+
## skip/cut off overflow pixels
|
57
|
+
next if xpixel >= @width || ypixel >= @height
|
58
|
+
|
59
|
+
color = @img[x,y]
|
60
|
+
colors = pixels[xpixel+ypixel*@width] ||= Hash.new(0)
|
61
|
+
colors[ color ] += 1
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
## sort pixel colors by usage / count (highest first)
|
66
|
+
pixels = pixels.map do |pixel|
|
67
|
+
pixel.sort do |l,r|
|
68
|
+
r[1] <=> l[1]
|
69
|
+
end.to_h
|
70
|
+
end
|
71
|
+
pixels
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def pixel(x,y) pixels[x+y*@width]; end
|
76
|
+
alias_method :[], :pixel
|
77
|
+
|
78
|
+
|
79
|
+
def can_pixelate?
|
80
|
+
# check if any pixel has NOT a color with a 50% majority?
|
81
|
+
count = 0
|
82
|
+
@width.times do |x|
|
83
|
+
@height.times do |y|
|
84
|
+
pixel = pixel( x, y )
|
85
|
+
sum = pixel.values.sum
|
86
|
+
color_count = pixel.values[0]
|
87
|
+
if color_count < (sum/2)
|
88
|
+
count += 1
|
89
|
+
## todo/check: stor warn in a public errors or warns array - why? why not?
|
90
|
+
puts "!! WARN #{count} - pixel (#{x}/#{y}) - no majority (50%) color:"
|
91
|
+
pp pixel
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
count == 0 ## return true if not warnings found
|
97
|
+
end
|
98
|
+
alias_method :pixelate?, :can_pixelate?
|
99
|
+
|
100
|
+
|
101
|
+
def pixelate
|
102
|
+
img = ChunkyPNG::Image.new( @width, @height )
|
103
|
+
|
104
|
+
@width.times do |x|
|
105
|
+
@height.times do |y|
|
106
|
+
pixel = pixel( x, y )
|
107
|
+
color = pixel.keys[0]
|
108
|
+
img[x,y] = color
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
Image.new( img.width, img.height, img ) ## wrap in Pixelart::Image - why? why not?
|
113
|
+
end
|
114
|
+
end # class Pixelator
|
115
|
+
end # module Pixelart
|
116
|
+
|
117
|
+
|
data/lib/pixelart/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixelart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-
|
11
|
+
date: 2021-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chunky_png
|
@@ -77,10 +77,12 @@ files:
|
|
77
77
|
- lib/pixelart/color.rb
|
78
78
|
- lib/pixelart/gradient.rb
|
79
79
|
- lib/pixelart/image.rb
|
80
|
+
- lib/pixelart/led.rb
|
80
81
|
- lib/pixelart/misc.rb
|
81
82
|
- lib/pixelart/palette.rb
|
83
|
+
- lib/pixelart/pixelator.rb
|
82
84
|
- lib/pixelart/version.rb
|
83
|
-
homepage: https://github.com/
|
85
|
+
homepage: https://github.com/rubycoco/pixel
|
84
86
|
licenses:
|
85
87
|
- Public Domain
|
86
88
|
metadata: {}
|