pixelart 1.2.1 → 1.3.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/CHANGELOG.md +3 -3
- data/Manifest.txt +5 -0
- data/README.md +290 -291
- data/Rakefile +32 -32
- data/lib/pixelart/base.rb +87 -81
- 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 -100
- data/lib/pixelart/gradient.rb +106 -106
- data/lib/pixelart/image.rb +283 -266
- 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/silhouette.rb +35 -0
- 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 -0
- 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
data/lib/pixelart/vector.rb
CHANGED
|
@@ -1,163 +1,163 @@
|
|
|
1
|
-
module Pixelart
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class Vector # holds a vector graphics image (in source)
|
|
5
|
-
|
|
6
|
-
class Shape; end
|
|
7
|
-
class Circle < Shape
|
|
8
|
-
def initialize( cx, cy, r, fill: )
|
|
9
|
-
@cx = cx
|
|
10
|
-
@cy = cy
|
|
11
|
-
@r = r
|
|
12
|
-
@fill = fill
|
|
13
|
-
end
|
|
14
|
-
|
|
15
|
-
def to_svg
|
|
16
|
-
%Q{<circle cx="#{@cx}" cy="#{@cy}" r="#{@r}" fill="#{@fill}" />}
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def to_magick
|
|
20
|
-
## circle
|
|
21
|
-
## give the center and any point on the perimeter (boundary)
|
|
22
|
-
px = @cx+@r
|
|
23
|
-
py = @cy
|
|
24
|
-
"-fill '#{@fill}' -draw 'circle #{@cx},#{@cy},#{px},#{py}'"
|
|
25
|
-
end
|
|
26
|
-
end # class Circle
|
|
27
|
-
|
|
28
|
-
class Path < Shape
|
|
29
|
-
def initialize( fill:, stroke: )
|
|
30
|
-
@commands = []
|
|
31
|
-
@fill = fill
|
|
32
|
-
@stroke = stroke
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def move_to( x, y ) ## add a move_to instruction
|
|
36
|
-
@commands << ['M', x, y]
|
|
37
|
-
self
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def line_to( x, y )
|
|
41
|
-
@commands << ['L', x, y]
|
|
42
|
-
self
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def line( *coords ) ## move_to/line_to all-in-one shortcut
|
|
46
|
-
## todo/check - assert coords has at least two x/y pairs - why? why not?
|
|
47
|
-
move_to( *coords[0..1] )
|
|
48
|
-
coords[2..-1].each_slice( 2) do |coord|
|
|
49
|
-
line_to( *coord )
|
|
50
|
-
end
|
|
51
|
-
self
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
def to_svg
|
|
57
|
-
buf = %Q{<path style="stroke: #{@stroke}; fill: #{@fill || 'none'};" }
|
|
58
|
-
buf << %Q{d="}
|
|
59
|
-
last_command = ''
|
|
60
|
-
@commands.each_with_index do |command,i|
|
|
61
|
-
buf << " " if i > 0 # add space separator
|
|
62
|
-
|
|
63
|
-
## "optimize" - that is, do not repead command if same as before
|
|
64
|
-
buf << command[0] if command[0] != last_command
|
|
65
|
-
buf << "#{command[1]} #{command[2]}"
|
|
66
|
-
last_command = command[0]
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
buf << %Q{"}
|
|
70
|
-
buf << "/>"
|
|
71
|
-
buf
|
|
72
|
-
end
|
|
73
|
-
end # class Path
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
def initialize( width, height, header: nil )
|
|
78
|
-
@width = width
|
|
79
|
-
@height = height
|
|
80
|
-
|
|
81
|
-
@header = header
|
|
82
|
-
@shapes = []
|
|
83
|
-
end
|
|
84
|
-
|
|
85
|
-
def circle( cx:, cy:, r:, fill: )
|
|
86
|
-
@shapes << Circle.new( cx, cy, r, fill: fill )
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
## note: default stroke (color) to black (#000000) for now - why? why not?
|
|
90
|
-
def path( stroke: '#000000', fill: nil )
|
|
91
|
-
path = Path.new( stroke: stroke, fill: fill )
|
|
92
|
-
@shapes << path
|
|
93
|
-
|
|
94
|
-
path ## note: MUST return "inner" path shape for chaining "dsl-like" methods / commands
|
|
95
|
-
end
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
def to_image
|
|
100
|
-
## use an empty image (canvas) with transparent background
|
|
101
|
-
## as magick input image
|
|
102
|
-
canvas = Image.new( @width, @height )
|
|
103
|
-
canvas.save( MAGICK_INPUT )
|
|
104
|
-
|
|
105
|
-
## note: magick command line might get way too long, thus,
|
|
106
|
-
## save commands to a script
|
|
107
|
-
## note: save magick input first (see above) before save script
|
|
108
|
-
## will (auto-)create missing directories in path (if missing)
|
|
109
|
-
|
|
110
|
-
File.open( MAGICK_SCRIPT, 'w:utf-8' ) do |f|
|
|
111
|
-
f.write( "#{MAGICK_INPUT} \\\n" )
|
|
112
|
-
@shapes.each do |shape|
|
|
113
|
-
f.write( "#{shape.to_magick} \\\n" )
|
|
114
|
-
end
|
|
115
|
-
f.write( "-write #{MAGICK_OUTPUT}\n" )
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
MiniMagick::Tool::Magick.new do |magick|
|
|
119
|
-
magick.script( MAGICK_SCRIPT )
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
Image.read( MAGICK_OUTPUT )
|
|
123
|
-
end
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
def to_svg
|
|
127
|
-
buf = String.new('')
|
|
128
|
-
|
|
129
|
-
if @header
|
|
130
|
-
buf << "<!--\n"
|
|
131
|
-
## auto-indent lines by five (5) spaces for now
|
|
132
|
-
@header.each_line do |line|
|
|
133
|
-
buf << " #{line}"
|
|
134
|
-
end
|
|
135
|
-
buf << "\n-->\n\n"
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
buf << %Q{<svg version="1.1" width="#{@width}" height="#{@height}" xmlns="http://www.w3.org/2000/svg">\n}
|
|
139
|
-
@shapes.each do |shape|
|
|
140
|
-
buf << " #{shape.to_svg}\n"
|
|
141
|
-
end
|
|
142
|
-
buf << "</svg>"
|
|
143
|
-
buf
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
def save( path, format: nil )
|
|
148
|
-
if format && format.downcase == 'png' ## support png with image magick
|
|
149
|
-
img = to_image
|
|
150
|
-
img.save( path )
|
|
151
|
-
else
|
|
152
|
-
# make sure outdir exits
|
|
153
|
-
outdir = File.dirname( path )
|
|
154
|
-
FileUtils.mkdir_p( outdir ) unless Dir.exist?( outdir )
|
|
155
|
-
File.open( path, 'w:utf-8' ) do |f|
|
|
156
|
-
f.write( to_svg )
|
|
157
|
-
end
|
|
158
|
-
end
|
|
159
|
-
end
|
|
160
|
-
alias_method :write, :save
|
|
161
|
-
|
|
162
|
-
end # class Vector
|
|
163
|
-
end # module Pixelart
|
|
1
|
+
module Pixelart
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class Vector # holds a vector graphics image (in source)
|
|
5
|
+
|
|
6
|
+
class Shape; end
|
|
7
|
+
class Circle < Shape
|
|
8
|
+
def initialize( cx, cy, r, fill: )
|
|
9
|
+
@cx = cx
|
|
10
|
+
@cy = cy
|
|
11
|
+
@r = r
|
|
12
|
+
@fill = fill
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def to_svg
|
|
16
|
+
%Q{<circle cx="#{@cx}" cy="#{@cy}" r="#{@r}" fill="#{@fill}" />}
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def to_magick
|
|
20
|
+
## circle
|
|
21
|
+
## give the center and any point on the perimeter (boundary)
|
|
22
|
+
px = @cx+@r
|
|
23
|
+
py = @cy
|
|
24
|
+
"-fill '#{@fill}' -draw 'circle #{@cx},#{@cy},#{px},#{py}'"
|
|
25
|
+
end
|
|
26
|
+
end # class Circle
|
|
27
|
+
|
|
28
|
+
class Path < Shape
|
|
29
|
+
def initialize( fill:, stroke: )
|
|
30
|
+
@commands = []
|
|
31
|
+
@fill = fill
|
|
32
|
+
@stroke = stroke
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def move_to( x, y ) ## add a move_to instruction
|
|
36
|
+
@commands << ['M', x, y]
|
|
37
|
+
self
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def line_to( x, y )
|
|
41
|
+
@commands << ['L', x, y]
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def line( *coords ) ## move_to/line_to all-in-one shortcut
|
|
46
|
+
## todo/check - assert coords has at least two x/y pairs - why? why not?
|
|
47
|
+
move_to( *coords[0..1] )
|
|
48
|
+
coords[2..-1].each_slice( 2) do |coord|
|
|
49
|
+
line_to( *coord )
|
|
50
|
+
end
|
|
51
|
+
self
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def to_svg
|
|
57
|
+
buf = %Q{<path style="stroke: #{@stroke}; fill: #{@fill || 'none'};" }
|
|
58
|
+
buf << %Q{d="}
|
|
59
|
+
last_command = ''
|
|
60
|
+
@commands.each_with_index do |command,i|
|
|
61
|
+
buf << " " if i > 0 # add space separator
|
|
62
|
+
|
|
63
|
+
## "optimize" - that is, do not repead command if same as before
|
|
64
|
+
buf << command[0] if command[0] != last_command
|
|
65
|
+
buf << "#{command[1]} #{command[2]}"
|
|
66
|
+
last_command = command[0]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
buf << %Q{"}
|
|
70
|
+
buf << "/>"
|
|
71
|
+
buf
|
|
72
|
+
end
|
|
73
|
+
end # class Path
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def initialize( width, height, header: nil )
|
|
78
|
+
@width = width
|
|
79
|
+
@height = height
|
|
80
|
+
|
|
81
|
+
@header = header
|
|
82
|
+
@shapes = []
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def circle( cx:, cy:, r:, fill: )
|
|
86
|
+
@shapes << Circle.new( cx, cy, r, fill: fill )
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
## note: default stroke (color) to black (#000000) for now - why? why not?
|
|
90
|
+
def path( stroke: '#000000', fill: nil )
|
|
91
|
+
path = Path.new( stroke: stroke, fill: fill )
|
|
92
|
+
@shapes << path
|
|
93
|
+
|
|
94
|
+
path ## note: MUST return "inner" path shape for chaining "dsl-like" methods / commands
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def to_image
|
|
100
|
+
## use an empty image (canvas) with transparent background
|
|
101
|
+
## as magick input image
|
|
102
|
+
canvas = Image.new( @width, @height )
|
|
103
|
+
canvas.save( MAGICK_INPUT )
|
|
104
|
+
|
|
105
|
+
## note: magick command line might get way too long, thus,
|
|
106
|
+
## save commands to a script
|
|
107
|
+
## note: save magick input first (see above) before save script
|
|
108
|
+
## will (auto-)create missing directories in path (if missing)
|
|
109
|
+
|
|
110
|
+
File.open( MAGICK_SCRIPT, 'w:utf-8' ) do |f|
|
|
111
|
+
f.write( "#{MAGICK_INPUT} \\\n" )
|
|
112
|
+
@shapes.each do |shape|
|
|
113
|
+
f.write( "#{shape.to_magick} \\\n" )
|
|
114
|
+
end
|
|
115
|
+
f.write( "-write #{MAGICK_OUTPUT}\n" )
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
MiniMagick::Tool::Magick.new do |magick|
|
|
119
|
+
magick.script( MAGICK_SCRIPT )
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
Image.read( MAGICK_OUTPUT )
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def to_svg
|
|
127
|
+
buf = String.new('')
|
|
128
|
+
|
|
129
|
+
if @header
|
|
130
|
+
buf << "<!--\n"
|
|
131
|
+
## auto-indent lines by five (5) spaces for now
|
|
132
|
+
@header.each_line do |line|
|
|
133
|
+
buf << " #{line}"
|
|
134
|
+
end
|
|
135
|
+
buf << "\n-->\n\n"
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
buf << %Q{<svg version="1.1" width="#{@width}" height="#{@height}" xmlns="http://www.w3.org/2000/svg">\n}
|
|
139
|
+
@shapes.each do |shape|
|
|
140
|
+
buf << " #{shape.to_svg}\n"
|
|
141
|
+
end
|
|
142
|
+
buf << "</svg>"
|
|
143
|
+
buf
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
def save( path, format: nil )
|
|
148
|
+
if format && format.downcase == 'png' ## support png with image magick
|
|
149
|
+
img = to_image
|
|
150
|
+
img.save( path )
|
|
151
|
+
else
|
|
152
|
+
# make sure outdir exits
|
|
153
|
+
outdir = File.dirname( path )
|
|
154
|
+
FileUtils.mkdir_p( outdir ) unless Dir.exist?( outdir )
|
|
155
|
+
File.open( path, 'w:utf-8' ) do |f|
|
|
156
|
+
f.write( to_svg )
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
alias_method :write, :save
|
|
161
|
+
|
|
162
|
+
end # class Vector
|
|
163
|
+
end # module Pixelart
|
data/lib/pixelart/version.rb
CHANGED
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
module Pixelart
|
|
3
|
-
|
|
4
|
-
MAJOR = 1
|
|
5
|
-
MINOR =
|
|
6
|
-
PATCH =
|
|
7
|
-
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
|
8
|
-
|
|
9
|
-
def self.version
|
|
10
|
-
VERSION
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def self.banner
|
|
14
|
-
"pixelart/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.root
|
|
18
|
-
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
end # module Pixelart
|
|
22
|
-
|
|
1
|
+
|
|
2
|
+
module Pixelart
|
|
3
|
+
|
|
4
|
+
MAJOR = 1
|
|
5
|
+
MINOR = 3
|
|
6
|
+
PATCH = 0
|
|
7
|
+
VERSION = [MAJOR,MINOR,PATCH].join('.')
|
|
8
|
+
|
|
9
|
+
def self.version
|
|
10
|
+
VERSION
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.banner
|
|
14
|
+
"pixelart/#{VERSION} on Ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE}) [#{RUBY_PLATFORM}] in (#{root})"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def self.root
|
|
18
|
+
File.expand_path( File.dirname(File.dirname(File.dirname(__FILE__))) )
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end # module Pixelart
|
|
22
|
+
|
data/lib/pixelart.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
## our own code (without "top-level" shortcuts e.g. "modular version")
|
|
3
|
-
require 'pixelart/base' # aka "strict(er)" version
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
###
|
|
7
|
-
# add convenience top-level shortcuts / aliases
|
|
8
|
-
# make Image, Color, Palette8bit, etc top-level
|
|
9
|
-
include Pixelart
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
|
|
2
|
+
## our own code (without "top-level" shortcuts e.g. "modular version")
|
|
3
|
+
require 'pixelart/base' # aka "strict(er)" version
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
###
|
|
7
|
+
# add convenience top-level shortcuts / aliases
|
|
8
|
+
# make Image, Color, Palette8bit, etc top-level
|
|
9
|
+
include Pixelart
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
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: 1.
|
|
4
|
+
version: 1.3.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:
|
|
11
|
+
date: 2022-05-03 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: chunky_png
|
|
@@ -78,14 +78,14 @@ dependencies:
|
|
|
78
78
|
requirements:
|
|
79
79
|
- - "~>"
|
|
80
80
|
- !ruby/object:Gem::Version
|
|
81
|
-
version: '3.
|
|
81
|
+
version: '3.23'
|
|
82
82
|
type: :development
|
|
83
83
|
prerelease: false
|
|
84
84
|
version_requirements: !ruby/object:Gem::Requirement
|
|
85
85
|
requirements:
|
|
86
86
|
- - "~>"
|
|
87
87
|
- !ruby/object:Gem::Version
|
|
88
|
-
version: '3.
|
|
88
|
+
version: '3.23'
|
|
89
89
|
description: pixelart - mint your own pixel art images off chain using any design
|
|
90
90
|
(in ascii text) in any colors; incl. 2x/4x/8x zoom for bigger sizes
|
|
91
91
|
email: wwwmake@googlegroups.com
|
|
@@ -103,6 +103,7 @@ files:
|
|
|
103
103
|
- lib/pixelart.rb
|
|
104
104
|
- lib/pixelart/base.rb
|
|
105
105
|
- lib/pixelart/blur.rb
|
|
106
|
+
- lib/pixelart/circle.rb
|
|
106
107
|
- lib/pixelart/color.rb
|
|
107
108
|
- lib/pixelart/composite.rb
|
|
108
109
|
- lib/pixelart/gradient.rb
|
|
@@ -111,11 +112,15 @@ files:
|
|
|
111
112
|
- lib/pixelart/misc.rb
|
|
112
113
|
- lib/pixelart/palette.rb
|
|
113
114
|
- lib/pixelart/pixelator.rb
|
|
115
|
+
- lib/pixelart/silhouette.rb
|
|
114
116
|
- lib/pixelart/sketch.rb
|
|
115
117
|
- lib/pixelart/spots.rb
|
|
118
|
+
- lib/pixelart/stripes.rb
|
|
119
|
+
- lib/pixelart/transparent.rb
|
|
120
|
+
- lib/pixelart/ukraine.rb
|
|
116
121
|
- lib/pixelart/vector.rb
|
|
117
122
|
- lib/pixelart/version.rb
|
|
118
|
-
homepage: https://github.com/
|
|
123
|
+
homepage: https://github.com/pixelartexchange/pixelart
|
|
119
124
|
licenses:
|
|
120
125
|
- Public Domain
|
|
121
126
|
metadata: {}
|
|
@@ -136,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
136
141
|
- !ruby/object:Gem::Version
|
|
137
142
|
version: '0'
|
|
138
143
|
requirements: []
|
|
139
|
-
rubygems_version: 3.
|
|
144
|
+
rubygems_version: 3.3.7
|
|
140
145
|
signing_key:
|
|
141
146
|
specification_version: 4
|
|
142
147
|
summary: pixelart - mint your own pixel art images off chain using any design (in
|