pixelart 1.3.2 → 1.3.3
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 +0 -3
- data/README.md +6 -0
- data/Rakefile +1 -0
- data/lib/pixelart/base.rb +6 -31
- data/lib/pixelart/version.rb +1 -1
- data/lib/pixelart.rb +10 -0
- metadata +16 -5
- data/lib/pixelart/color.rb +0 -131
- data/lib/pixelart/gradient.rb +0 -106
- data/lib/pixelart/palette.rb +0 -72
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0724e3e1f83da6ef84325d79706a2f59d773eb31478f1e4d797ff582dad64a4a
|
4
|
+
data.tar.gz: 7d75ebe3aef0abb3e3d142bf787995bbcdf797416912a387601110a3547d08fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6afe87fa92ec1de03bad71cd5f2ba298f78287b77f514a6c74cae6747c1e1d62790d722c07fb0a5d049dcf9966d4fa0a473688e71c717de534420f4746b711f2
|
7
|
+
data.tar.gz: 0b1a7cf13cdffa7410a6c0246f894d3ca5f1e3b1347fd90b9f7cbe9ed3cff4b4fc87c6704d80854b5337aa5f17e24631c28bc8188e4c6f86422e862d22949d43
|
data/Manifest.txt
CHANGED
@@ -6,14 +6,11 @@ lib/pixelart.rb
|
|
6
6
|
lib/pixelart/base.rb
|
7
7
|
lib/pixelart/blur.rb
|
8
8
|
lib/pixelart/circle.rb
|
9
|
-
lib/pixelart/color.rb
|
10
9
|
lib/pixelart/composite.rb
|
11
10
|
lib/pixelart/generator.rb
|
12
|
-
lib/pixelart/gradient.rb
|
13
11
|
lib/pixelart/image.rb
|
14
12
|
lib/pixelart/led.rb
|
15
13
|
lib/pixelart/misc.rb
|
16
|
-
lib/pixelart/palette.rb
|
17
14
|
lib/pixelart/pixelator.rb
|
18
15
|
lib/pixelart/sample.rb
|
19
16
|
lib/pixelart/silhouette.rb
|
data/README.md
CHANGED
@@ -288,3 +288,9 @@ Just install the gem:
|
|
288
288
|
|
289
289
|
The scripts are dedicated to the public domain.
|
290
290
|
Use it as you please with no restrictions whatsoever.
|
291
|
+
|
292
|
+
|
293
|
+
|
294
|
+
## Questions? Comments?
|
295
|
+
|
296
|
+
Post them on the [D.I.Y. Punk (Pixel) Art reddit](https://old.reddit.com/r/DIYPunkArt). Thanks.
|
data/Rakefile
CHANGED
data/lib/pixelart/base.rb
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
###
|
2
|
+
# base module
|
3
|
+
require 'pixelart/colors'
|
4
|
+
|
5
|
+
|
6
|
+
|
1
7
|
###############
|
2
8
|
# 3rd party
|
3
9
|
require 'chunky_png'
|
@@ -11,23 +17,9 @@ require 'mini_magick'
|
|
11
17
|
require 'csvreader'
|
12
18
|
|
13
19
|
|
14
|
-
## stdlib
|
15
|
-
require 'pp'
|
16
|
-
require 'time'
|
17
|
-
require 'date'
|
18
|
-
require 'fileutils'
|
19
|
-
|
20
|
-
require 'json'
|
21
|
-
require 'yaml'
|
22
|
-
|
23
|
-
|
24
|
-
|
25
20
|
|
26
21
|
## our own code
|
27
22
|
require 'pixelart/version' # note: let version always go first
|
28
|
-
require 'pixelart/color'
|
29
|
-
require 'pixelart/gradient'
|
30
|
-
require 'pixelart/palette'
|
31
23
|
require 'pixelart/image'
|
32
24
|
require 'pixelart/composite'
|
33
25
|
|
@@ -73,21 +65,4 @@ require 'pixelart/blur'
|
|
73
65
|
|
74
66
|
|
75
67
|
|
76
|
-
|
77
|
-
|
78
|
-
##########
|
79
|
-
# add some spelling convenience variants
|
80
|
-
PixelArt = Pixelart
|
81
|
-
|
82
|
-
module Pixelart
|
83
|
-
Palette256 = Palette8Bit = Palette8bit
|
84
|
-
|
85
|
-
Palette256Image = Palette8BitImage = Palette8bitImage =
|
86
|
-
ImagePalette256 = ImagePalette8Bit = ImagePalette8bit
|
87
|
-
|
88
|
-
CompositeImage = ImageComposite
|
89
|
-
end
|
90
|
-
|
91
|
-
|
92
|
-
|
93
68
|
puts Pixelart.banner # say hello
|
data/lib/pixelart/version.rb
CHANGED
data/lib/pixelart.rb
CHANGED
@@ -9,4 +9,14 @@ require 'pixelart/base' # aka "strict(er)" version
|
|
9
9
|
include Pixelart
|
10
10
|
|
11
11
|
|
12
|
+
##########
|
13
|
+
# add some spelling convenience variants
|
14
|
+
|
15
|
+
|
16
|
+
module Pixelart
|
17
|
+
Palette256Image = Palette8BitImage = Palette8bitImage =
|
18
|
+
ImagePalette256 = ImagePalette8Bit = ImagePalette8bit
|
19
|
+
|
20
|
+
CompositeImage = ImageComposite
|
21
|
+
end
|
12
22
|
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixelart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.3.
|
4
|
+
version: 1.3.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gerald Bauer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-07-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pixelart-colors
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: chunky_png
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -104,14 +118,11 @@ files:
|
|
104
118
|
- lib/pixelart/base.rb
|
105
119
|
- lib/pixelart/blur.rb
|
106
120
|
- lib/pixelart/circle.rb
|
107
|
-
- lib/pixelart/color.rb
|
108
121
|
- lib/pixelart/composite.rb
|
109
122
|
- lib/pixelart/generator.rb
|
110
|
-
- lib/pixelart/gradient.rb
|
111
123
|
- lib/pixelart/image.rb
|
112
124
|
- lib/pixelart/led.rb
|
113
125
|
- lib/pixelart/misc.rb
|
114
|
-
- lib/pixelart/palette.rb
|
115
126
|
- lib/pixelart/pixelator.rb
|
116
127
|
- lib/pixelart/sample.rb
|
117
128
|
- lib/pixelart/silhouette.rb
|
data/lib/pixelart/color.rb
DELETED
@@ -1,131 +0,0 @@
|
|
1
|
-
module Pixelart
|
2
|
-
|
3
|
-
|
4
|
-
class Color
|
5
|
-
TRANSPARENT = 0 # rgba( 0, 0, 0, 0)
|
6
|
-
BLACK = 0xff # rgba( 0, 0, 0,255)
|
7
|
-
WHITE = 0xffffffff # rgba(255,255,255,255)
|
8
|
-
|
9
|
-
|
10
|
-
def self.parse( color )
|
11
|
-
if color.is_a?( Integer ) ## e.g. assumes ChunkyPNG::Color.rgb() or such
|
12
|
-
color ## pass through as is 1:1
|
13
|
-
elsif color.is_a?( Array ) ## assume array of hsl(a) e. g. [180, 0.86, 0.88]
|
14
|
-
from_hsl( *color )
|
15
|
-
elsif color.is_a?( String )
|
16
|
-
if color.downcase == 'transparent' ## special case for builtin colors
|
17
|
-
TRANSPARENT
|
18
|
-
else
|
19
|
-
## note: return an Integer !!! (not a Color class or such!!! )
|
20
|
-
from_hex( color )
|
21
|
-
end
|
22
|
-
else
|
23
|
-
raise ArgumentError, "unknown color format; cannot parse - expected rgb hex string e.g. d3d3d3"
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def self.from_hex( hex )
|
28
|
-
## Creates a color by converting it from a string in hex notation.
|
29
|
-
##
|
30
|
-
## It supports colors with (#rrggbbaa) or without (#rrggbb)
|
31
|
-
## alpha channel as well as the 3-digit short format (#rgb)
|
32
|
-
## for those without. Color strings may include
|
33
|
-
## the prefix "0x" or "#"".
|
34
|
-
ChunkyPNG::Color.from_hex( hex )
|
35
|
-
end
|
36
|
-
|
37
|
-
def self.from_hsl( hue, saturation, lightness, alpha=255)
|
38
|
-
ChunkyPNG::Color.from_hsl( hue,
|
39
|
-
saturation,
|
40
|
-
lightness,
|
41
|
-
alpha )
|
42
|
-
end
|
43
|
-
|
44
|
-
|
45
|
-
def self.to_hex( color, include_alpha: true )
|
46
|
-
ChunkyPNG::Color.to_hex( color, include_alpha )
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.to_hsl( color, include_alpha: true )
|
50
|
-
# Returns an array with the separate HSL components of a color.
|
51
|
-
ChunkyPNG::Color.to_hsl( color, include_alpha )
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.r( color ) ChunkyPNG::Color.r( color ); end
|
55
|
-
def self.g( color ) ChunkyPNG::Color.g( color ); end
|
56
|
-
def self.b( color ) ChunkyPNG::Color.b( color ); end
|
57
|
-
|
58
|
-
def self.rgb( r, g, b ) ChunkyPNG::Color.rgb( r, g, b); end
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
## known built-in color names
|
63
|
-
def self.build_names
|
64
|
-
names = {
|
65
|
-
'#00000000' => 'TRANSPARENT',
|
66
|
-
'#000000ff' => 'BLACK',
|
67
|
-
'#ffffffff' => 'WHITE',
|
68
|
-
}
|
69
|
-
|
70
|
-
## auto-add grayscale 1 to 254
|
71
|
-
(1..254).each do |n|
|
72
|
-
hex = "#" + ('%02x' % n)*3
|
73
|
-
hex << "ff" ## add alpha channel (255)
|
74
|
-
names[ hex ] = "8-BIT GRAYSCALE ##{n}"
|
75
|
-
end
|
76
|
-
|
77
|
-
names
|
78
|
-
end
|
79
|
-
|
80
|
-
NAMES = build_names
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
def self.format( color )
|
85
|
-
rgb = [r(color),
|
86
|
-
g(color),
|
87
|
-
b(color)]
|
88
|
-
|
89
|
-
# rgb in hex (string format)
|
90
|
-
# note: do NOT include alpha channel for now - why? why not?
|
91
|
-
hex = "#" + rgb.map{|num| '%02x' % num }.join
|
92
|
-
|
93
|
-
hsl = to_hsl( color )
|
94
|
-
## get alpha channel (transparency) for hsla
|
95
|
-
alpha = hsl[3]
|
96
|
-
|
97
|
-
|
98
|
-
buf = ''
|
99
|
-
buf << hex
|
100
|
-
buf << " / "
|
101
|
-
buf << "rgb("
|
102
|
-
buf << "%3d " % rgb[0]
|
103
|
-
buf << "%3d " % rgb[1]
|
104
|
-
buf << "%3d)" % rgb[2]
|
105
|
-
buf << " - "
|
106
|
-
buf << "hsl("
|
107
|
-
buf << "%3d° " % (hsl[0] % 360)
|
108
|
-
buf << "%3d%% " % (hsl[1]*100+0.5).to_i
|
109
|
-
buf << "%3d%%)" % (hsl[2]*100+0.5).to_i
|
110
|
-
|
111
|
-
if alpha != 255
|
112
|
-
buf << " - α(%3d%%)" % (alpha*100/255+0.5).to_i
|
113
|
-
else
|
114
|
-
buf << " " ## add empty for 255 (full opacity)
|
115
|
-
end
|
116
|
-
|
117
|
-
## note: add alpha channel to hex
|
118
|
-
alpha_hex = '%02x' % alpha
|
119
|
-
name = NAMES[ hex+alpha_hex ]
|
120
|
-
buf << " - #{name}" if name
|
121
|
-
|
122
|
-
buf
|
123
|
-
end
|
124
|
-
class << self
|
125
|
-
alias_method :fmt, :format
|
126
|
-
end
|
127
|
-
|
128
|
-
end # class Color
|
129
|
-
end # module Pixelart
|
130
|
-
|
131
|
-
|
data/lib/pixelart/gradient.rb
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
|
2
|
-
## inspired / helped by
|
3
|
-
## https://en.wikipedia.org/wiki/List_of_software_palettes#Color_gradient_palettes
|
4
|
-
## https://github.com/mistic100/tinygradient
|
5
|
-
## https://mistic100.github.io/tinygradient/
|
6
|
-
## https://bsouthga.dev/posts/color-gradients-with-python
|
7
|
-
|
8
|
-
|
9
|
-
module Pixelart
|
10
|
-
|
11
|
-
class Gradient
|
12
|
-
|
13
|
-
def initialize( *stops )
|
14
|
-
## note: convert stop colors to rgb triplets e.g.
|
15
|
-
## from #ffffff to [255,255,255]
|
16
|
-
## #000000 to [0,0,0] etc.
|
17
|
-
@stops = stops.map do |stop|
|
18
|
-
stop = Color.parse( stop )
|
19
|
-
[Color.r(stop), Color.g(stop), Color.b(stop)]
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
|
24
|
-
def colors( steps )
|
25
|
-
segments = @stops.size - 1
|
26
|
-
|
27
|
-
## note: gradient will include start (first)
|
28
|
-
## AND stop color (last) - stop color is NOT excluded for now!!
|
29
|
-
if segments == 1
|
30
|
-
start = @stops[0]
|
31
|
-
stop = @stops[1]
|
32
|
-
|
33
|
-
gradient = linear_gradient( start, stop, steps,
|
34
|
-
include_stop: true )
|
35
|
-
else
|
36
|
-
steps_per_segment, mod = steps.divmod( segments )
|
37
|
-
raise ArgumentError, "steps (#{steps}) must be divisible by # of segments (#{segments}); expected mod of 0 but got #{mod}" if mod != 0
|
38
|
-
|
39
|
-
gradient = []
|
40
|
-
segments.times do |segment|
|
41
|
-
start = @stops[segment]
|
42
|
-
stop = @stops[segment+1]
|
43
|
-
include_stop = (segment == segments-1) ## note: only include stop if last segment!!
|
44
|
-
|
45
|
-
# print " segment #{segment+1}/#{segments} #{steps_per_segment} color(s) - "
|
46
|
-
# print " start: #{start.inspect} "
|
47
|
-
# print include_stop ? 'include' : 'exclude'
|
48
|
-
# print " stop: #{stop.inspect}"
|
49
|
-
# print "\n"
|
50
|
-
|
51
|
-
gradient += linear_gradient( start, stop, steps_per_segment,
|
52
|
-
include_stop: include_stop )
|
53
|
-
end
|
54
|
-
end
|
55
|
-
|
56
|
-
## convert to color (Integer)
|
57
|
-
gradient.map do |color|
|
58
|
-
Color.rgb( *color )
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
def interpolate( start, stop, steps, n )
|
65
|
-
## note: n - expected to start with 1,2,3,etc.
|
66
|
-
color = []
|
67
|
-
3.times do |i|
|
68
|
-
stepize = Float(stop[i] - start[i]) / Float(steps-1)
|
69
|
-
value = stepize * n
|
70
|
-
## convert back to Integer from Float
|
71
|
-
## add 0.5 for rounding up (starting with 0.5) - why? why not?
|
72
|
-
value = (value+0.5).to_i
|
73
|
-
value = start[i] + value
|
74
|
-
|
75
|
-
color << value
|
76
|
-
end
|
77
|
-
color
|
78
|
-
end
|
79
|
-
|
80
|
-
|
81
|
-
def linear_gradient( start, stop, steps,
|
82
|
-
include_stop: true )
|
83
|
-
|
84
|
-
gradient = [start] ## auto-add start color (first color in gradient)
|
85
|
-
|
86
|
-
if include_stop
|
87
|
-
1.upto( steps-2 ).each do |n| ## sub two (-2), that is, start and stop color
|
88
|
-
gradient << interpolate( start, stop, steps, n )
|
89
|
-
end
|
90
|
-
# note: use original passed in stop color (should match calculated)
|
91
|
-
gradient << stop
|
92
|
-
else
|
93
|
-
1.upto( steps-1 ).each do |n| ## sub one (-1), that is, start color only
|
94
|
-
## note: add one (+1) to steps because stop color gets excluded (not included)!!
|
95
|
-
gradient << interpolate( start, stop, steps+1, n )
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
|
-
gradient
|
100
|
-
end
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
end # class Gradient
|
105
|
-
end # module Pixelart
|
106
|
-
|
data/lib/pixelart/palette.rb
DELETED
@@ -1,72 +0,0 @@
|
|
1
|
-
module Pixelart
|
2
|
-
|
3
|
-
|
4
|
-
class Palette8bit # or use Palette256 alias?
|
5
|
-
|
6
|
-
|
7
|
-
## auto-add grayscale 0 to 255
|
8
|
-
## e.g. rgb(0,0,0)
|
9
|
-
## rgb(1,1,1)
|
10
|
-
## rgb(2,2,2)
|
11
|
-
## ...
|
12
|
-
## rgb(255,255,255)
|
13
|
-
GRAYSCALE = (0..255).map { |n| Color.rgb( n, n, n ) }
|
14
|
-
|
15
|
-
|
16
|
-
## 8x32 gradient color stops
|
17
|
-
## see https://en.wikipedia.org/wiki/List_of_software_palettes#Color_gradient_palettes
|
18
|
-
|
19
|
-
SEPIA_STOPS = [
|
20
|
-
['080400', '262117'],
|
21
|
-
['272218', '453E2F'],
|
22
|
-
['463F30', '645C48'],
|
23
|
-
['655D48', '837A60'],
|
24
|
-
|
25
|
-
['847A60', 'A29778'],
|
26
|
-
['A39878', 'C1B590'],
|
27
|
-
['C2B691', 'E0D2A8'],
|
28
|
-
['E1D3A9', 'FEEFBF'],
|
29
|
-
]
|
30
|
-
|
31
|
-
BLUE_STOPS = [
|
32
|
-
['000000', '001F3E'],
|
33
|
-
['002040', '003F7E'],
|
34
|
-
['004080', '005FBD'],
|
35
|
-
['0060BF', '007FFD'],
|
36
|
-
|
37
|
-
['0080FF', '009FFF'],
|
38
|
-
['00A0FF', '00BFFF'],
|
39
|
-
['00C0FF', '00DFFF'],
|
40
|
-
['00E0FF', '00FEFF'],
|
41
|
-
]
|
42
|
-
|
43
|
-
FALSE_STOPS = [
|
44
|
-
['FF00FF', '6400FF'],
|
45
|
-
['5F00FF', '003CFF'],
|
46
|
-
['0041FF', '00DCFF'],
|
47
|
-
['00E1FF', '00FF82'],
|
48
|
-
|
49
|
-
['00FF7D', '1EFF00'],
|
50
|
-
['23FF00', 'BEFF00'],
|
51
|
-
['C3FF00', 'FFA000'],
|
52
|
-
['FF9B00', 'FF0000'],
|
53
|
-
]
|
54
|
-
|
55
|
-
|
56
|
-
def self.build_palette( gradients )
|
57
|
-
colors_per_gradient, mod = 256.divmod( gradients.size )
|
58
|
-
raise ArgumentError, "8bit palette - 256 must be divisible by # of gradients (#{gradients.size}; expected mod of 0 but got #{mod}" if mod != 0
|
59
|
-
|
60
|
-
colors = []
|
61
|
-
gradients.each do |stops|
|
62
|
-
colors += Gradient.new( *stops ).colors( colors_per_gradient )
|
63
|
-
end
|
64
|
-
colors
|
65
|
-
end
|
66
|
-
|
67
|
-
SEPIA = build_palette( SEPIA_STOPS )
|
68
|
-
BLUE = build_palette( BLUE_STOPS )
|
69
|
-
FALSE = build_palette( FALSE_STOPS )
|
70
|
-
end # class Palette8bit
|
71
|
-
end # module Pixelart
|
72
|
-
|