pixelart 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Manifest.txt +3 -0
- data/README.md +47 -3
- data/lib/pixelart.rb +6 -22
- data/lib/pixelart/base.rb +35 -0
- data/lib/pixelart/color.rb +70 -0
- data/lib/pixelart/gradient.rb +62 -52
- data/lib/pixelart/image.rb +59 -11
- data/lib/pixelart/misc.rb +40 -0
- data/lib/pixelart/palette.rb +72 -0
- data/lib/pixelart/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 627a2802ea7e3ad7a10490ea4f721d57a4007669fe59a0b6cc17fb798c60b7a7
|
4
|
+
data.tar.gz: 8edd801f96debe5b664f31180510ea103469f1f62e5f4ee88959046718350b7f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8bdff35694d0212e5c48799be188b1cfeef29bd24e48f46fab6e387f5dcdcde3063105db5fd1cab21f8b03ce12c1420fb5abed0f59ae42801b57164ff6682e08
|
7
|
+
data.tar.gz: de54f3cc88c6dd7e198abdba49eb7549c1ae18c018a24695ccc676dee94360b9fed68f0e415ce92060993fd1323f4c5cfd40831b5411bf7db0fb008d67951f60
|
data/Manifest.txt
CHANGED
data/README.md
CHANGED
@@ -58,7 +58,7 @@ Note: The color 0 (transparent) is auto-magically added / defined.
|
|
58
58
|
And let's mint a mooncat image:
|
59
59
|
|
60
60
|
``` ruby
|
61
|
-
img =
|
61
|
+
img = Image.parse( pixels, colors: colors )
|
62
62
|
img.save( './i/mooncat_white.png' )
|
63
63
|
```
|
64
64
|
|
@@ -91,7 +91,7 @@ colors = [
|
|
91
91
|
And let's start minting:
|
92
92
|
|
93
93
|
``` ruby
|
94
|
-
img =
|
94
|
+
img = Image.parse( pixels, colors: colors )
|
95
95
|
img.save( './i/mooncat_black.png' )
|
96
96
|
|
97
97
|
img3x = img.zoom( 3 )
|
@@ -214,7 +214,7 @@ colors = {
|
|
214
214
|
And let's mint an imperial master image:
|
215
215
|
|
216
216
|
``` ruby
|
217
|
-
img =
|
217
|
+
img = Image.parse( pixels, colors: colors )
|
218
218
|
img.save( './i/vader.png' )
|
219
219
|
```
|
220
220
|
|
@@ -233,6 +233,50 @@ Voila!
|
|
233
233
|
|
234
234
|
|
235
235
|
|
236
|
+
## Modular "Base" Version
|
237
|
+
|
238
|
+
|
239
|
+
Note: By default if you require pixelart
|
240
|
+
all classes inside the `Pixelart` module such as `Image`, `Color`, `Gradient`, `Palette8bit`, etc. get "top-leveled", that is,
|
241
|
+
included in the top level e.g.:
|
242
|
+
|
243
|
+
``` ruby
|
244
|
+
require 'pixelart/base'
|
245
|
+
include Pixelart
|
246
|
+
```
|
247
|
+
|
248
|
+
And now you can use all classes without
|
249
|
+
the `Pixelart::` module scope e.g.:
|
250
|
+
|
251
|
+
``` ruby
|
252
|
+
gradient = Gradient.new( '000000', 'ffffff' )
|
253
|
+
|
254
|
+
pp colors = gradient.colors( 256 )
|
255
|
+
puts '---'
|
256
|
+
pp colors.map { |color| Color.to_hex( color ) }
|
257
|
+
```
|
258
|
+
|
259
|
+
vs
|
260
|
+
|
261
|
+
``` ruby
|
262
|
+
gradient = Pixelart::Gradient.new( '000000', 'ffffff' )
|
263
|
+
|
264
|
+
pp colors = gradient.colors( 256 )
|
265
|
+
puts '---'
|
266
|
+
pp colors.map { |color| Pixelart::Color.to_hex( color ) }
|
267
|
+
```
|
268
|
+
|
269
|
+
|
270
|
+
For a "stricter" modular version require the "base" version
|
271
|
+
that always requires the `Pixelart::` module scope e.g.:
|
272
|
+
|
273
|
+
``` ruby
|
274
|
+
require 'pixelart/base'
|
275
|
+
```
|
276
|
+
|
277
|
+
|
278
|
+
|
279
|
+
|
236
280
|
## Install
|
237
281
|
|
238
282
|
Just install the gem:
|
data/lib/pixelart.rb
CHANGED
@@ -1,26 +1,10 @@
|
|
1
|
-
## 3rd party
|
2
|
-
require 'chunky_png'
|
3
1
|
|
4
|
-
##
|
5
|
-
require '
|
6
|
-
require 'time'
|
7
|
-
require 'date'
|
8
|
-
require 'fileutils'
|
2
|
+
## our own code (without "top-level" shortcuts e.g. "modular version")
|
3
|
+
require 'pixelart/base' # aka "strict(er)" version
|
9
4
|
|
10
5
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
require 'pixelart/image'
|
6
|
+
###
|
7
|
+
# add convenience top-level shortcuts / aliases
|
8
|
+
# make Image, Color, Palette8bit, etc top-level
|
9
|
+
include Pixelart
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
### add some convenience shortcuts
|
22
|
-
PixelArt = Pixelart
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
puts Pixelart.banner # say hello
|
@@ -0,0 +1,35 @@
|
|
1
|
+
## 3rd party
|
2
|
+
require 'chunky_png'
|
3
|
+
|
4
|
+
## stdlib
|
5
|
+
require 'pp'
|
6
|
+
require 'time'
|
7
|
+
require 'date'
|
8
|
+
require 'fileutils'
|
9
|
+
|
10
|
+
|
11
|
+
## our own code
|
12
|
+
require 'pixelart/version' # note: let version always go first
|
13
|
+
require 'pixelart/color'
|
14
|
+
require 'pixelart/gradient'
|
15
|
+
require 'pixelart/palette'
|
16
|
+
require 'pixelart/image'
|
17
|
+
|
18
|
+
require 'pixelart/misc' ## misc helpers
|
19
|
+
|
20
|
+
|
21
|
+
##########
|
22
|
+
# add some spelling convenience variants
|
23
|
+
PixelArt = Pixelart
|
24
|
+
|
25
|
+
module Pixelart
|
26
|
+
Palette256 = Palette8Bit = Palette8bit
|
27
|
+
|
28
|
+
class Image
|
29
|
+
Palette256 = Palette8Bit = Palette8bit
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
|
34
|
+
|
35
|
+
puts Pixelart.banner # say hello
|
data/lib/pixelart/color.rb
CHANGED
@@ -7,6 +7,7 @@ class Color
|
|
7
7
|
WHITE = 0xffffffff # rgba(255,255,255,255)
|
8
8
|
|
9
9
|
|
10
|
+
|
10
11
|
def self.parse( color )
|
11
12
|
if color.is_a?( Integer ) ## e.g. assumes ChunkyPNG::Color.rgb() or such
|
12
13
|
color ## pass through as is 1:1
|
@@ -56,6 +57,75 @@ class Color
|
|
56
57
|
def self.b( color ) ChunkyPNG::Color.b( color ); end
|
57
58
|
|
58
59
|
def self.rgb( r, g, b ) ChunkyPNG::Color.rgb( r, g, b); end
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
## known built-in color names
|
64
|
+
def self.build_names
|
65
|
+
names = {
|
66
|
+
'#00000000' => 'TRANSPARENT',
|
67
|
+
'#000000ff' => 'BLACK',
|
68
|
+
'#ffffffff' => 'WHITE',
|
69
|
+
}
|
70
|
+
|
71
|
+
## auto-add grayscale 1 to 254
|
72
|
+
(1..254).each do |n|
|
73
|
+
hex = "#" + ('%02x' % n)*3
|
74
|
+
hex << "ff" ## add alpha channel (255)
|
75
|
+
names[ hex ] = "8-BIT GRAYSCALE ##{n}"
|
76
|
+
end
|
77
|
+
|
78
|
+
names
|
79
|
+
end
|
80
|
+
|
81
|
+
NAMES = build_names
|
82
|
+
|
83
|
+
|
84
|
+
|
85
|
+
def self.format( color )
|
86
|
+
rgb = [r(color),
|
87
|
+
g(color),
|
88
|
+
b(color)]
|
89
|
+
|
90
|
+
# rgb in hex (string format)
|
91
|
+
# note: do NOT include alpha channel for now - why? why not?
|
92
|
+
hex = "#" + rgb.map{|num| '%02x' % num }.join
|
93
|
+
|
94
|
+
hsl = to_hsl( color )
|
95
|
+
## get alpha channel (transparency) for hsla
|
96
|
+
alpha = hsl[3]
|
97
|
+
|
98
|
+
|
99
|
+
buf = ''
|
100
|
+
buf << hex
|
101
|
+
buf << " / "
|
102
|
+
buf << "rgb("
|
103
|
+
buf << "%3d " % rgb[0]
|
104
|
+
buf << "%3d " % rgb[1]
|
105
|
+
buf << "%3d)" % rgb[2]
|
106
|
+
buf << " - "
|
107
|
+
buf << "hsl("
|
108
|
+
buf << "%3d° " % (hsl[0] % 360)
|
109
|
+
buf << "%3d%% " % (hsl[1]*100+0.5).to_i
|
110
|
+
buf << "%3d%%)" % (hsl[2]*100+0.5).to_i
|
111
|
+
|
112
|
+
if alpha != 255
|
113
|
+
buf << " - α(%3d%%)" % (alpha*100/255+0.5).to_i
|
114
|
+
else
|
115
|
+
buf << " " ## add empty for 255 (full opacity)
|
116
|
+
end
|
117
|
+
|
118
|
+
## note: add alpha channel to hex
|
119
|
+
alpha_hex = '%02x' % alpha
|
120
|
+
name = NAMES[ hex+alpha_hex ]
|
121
|
+
buf << " - #{name}" if name
|
122
|
+
|
123
|
+
buf
|
124
|
+
end
|
125
|
+
class << self
|
126
|
+
alias_method :fmt, :format
|
127
|
+
end
|
128
|
+
|
59
129
|
end # class Color
|
60
130
|
end # module Pixelart
|
61
131
|
|
data/lib/pixelart/gradient.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
|
2
|
-
## inspired by
|
2
|
+
## inspired / helped by
|
3
3
|
## https://en.wikipedia.org/wiki/List_of_software_palettes#Color_gradient_palettes
|
4
4
|
## https://github.com/mistic100/tinygradient
|
5
5
|
## https://mistic100.github.io/tinygradient/
|
6
|
+
## https://bsouthga.dev/posts/color-gradients-with-python
|
6
7
|
|
7
8
|
|
8
9
|
module Pixelart
|
@@ -21,23 +22,36 @@ class Gradient
|
|
21
22
|
|
22
23
|
|
23
24
|
def colors( steps )
|
24
|
-
|
25
|
-
|
26
|
-
##
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
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
|
38
54
|
end
|
39
|
-
## note: use original passed in stop color (should match calculated)
|
40
|
-
gradient << stop
|
41
55
|
|
42
56
|
## convert to color (Integer)
|
43
57
|
gradient.map do |color|
|
@@ -45,52 +59,48 @@ class Gradient
|
|
45
59
|
end
|
46
60
|
end
|
47
61
|
|
48
|
-
##
|
49
|
-
# Linearly compute the step size between start and end
|
50
|
-
## (not normalized)
|
51
|
-
# @param {StepValue} start
|
52
|
-
# @param {StepValue} end
|
53
|
-
# @param {number} steps - number of desired steps
|
54
|
-
#@return {StepValue}
|
55
62
|
|
56
|
-
def stepize(start, stop, steps)
|
57
|
-
step = []
|
58
63
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
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
|
65
74
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
# @param {number} i - color index
|
71
|
-
# @return {StepValue}
|
75
|
+
color << value
|
76
|
+
end
|
77
|
+
color
|
78
|
+
end
|
72
79
|
|
73
|
-
RGB_MAX = [256, 256, 256]
|
74
|
-
def interpolate( step, start, i )
|
75
|
-
color = []
|
76
80
|
|
77
|
-
|
78
|
-
|
81
|
+
def linear_gradient( start, stop, steps,
|
82
|
+
include_stop: true )
|
79
83
|
|
80
|
-
|
81
|
-
color[k] + RGB_MAX[k]
|
82
|
-
else
|
83
|
-
color[k] % RGB_MAX[k]
|
84
|
-
end
|
84
|
+
gradient = [start] ## auto-add start color (first color in gradient)
|
85
85
|
|
86
|
-
|
87
|
-
|
88
|
-
|
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
|
89
97
|
end
|
90
|
-
|
98
|
+
|
99
|
+
gradient
|
91
100
|
end
|
92
101
|
|
93
102
|
|
103
|
+
|
94
104
|
end # class Gradient
|
95
105
|
end # module Pixelart
|
96
106
|
|
data/lib/pixelart/image.rb
CHANGED
@@ -65,19 +65,71 @@ alias_method :scale, :zoom
|
|
65
65
|
|
66
66
|
|
67
67
|
|
68
|
+
#######################
|
69
|
+
## filter / effects
|
68
70
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
72
|
-
end.to_h
|
71
|
+
def grayscale
|
72
|
+
img = @img.grayscale
|
73
|
+
Image.new( img.width, img.height, img )
|
73
74
|
end
|
74
75
|
|
75
76
|
## add replace_colors alias too? - why? why not?
|
76
77
|
def change_colors( color_map )
|
78
|
+
color_map = _parse_color_map( color_map )
|
79
|
+
|
77
80
|
img = @img.dup ## note: make a deep copy!!!
|
78
|
-
|
79
|
-
|
81
|
+
_change_colors!( img, color_map )
|
82
|
+
|
83
|
+
## wrap into Pixelart::Image - lets you use zoom() and such
|
84
|
+
Image.new( img.width, img.height, img )
|
85
|
+
end
|
86
|
+
alias_method :recolor, :change_colors
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
## predefined palette8bit color maps
|
91
|
+
## (grayscale to sepia/blue/false/etc.)
|
92
|
+
## - todo/check - keep "shortcut" convenience predefined map - why? why not?
|
93
|
+
PALETTE8BIT = {
|
94
|
+
sepia: Palette8bit::GRAYSCALE.zip( Palette8bit::SEPIA ).to_h,
|
95
|
+
blue: Palette8bit::GRAYSCALE.zip( Palette8bit::BLUE ).to_h,
|
96
|
+
false: Palette8bit::GRAYSCALE.zip( Palette8bit::FALSE ).to_h,
|
97
|
+
}
|
98
|
+
|
99
|
+
def change_palette8bit( palette )
|
100
|
+
## step 0: mapping from grayscale to new 8bit palette (256 colors)
|
101
|
+
color_map = if palette.is_a( String ) || palette.is_a( Symbol )
|
102
|
+
PALETTE8BIT[ palette.to_sym ]
|
103
|
+
## todo/fix: check for missing/undefined palette not found - why? why not?
|
104
|
+
else
|
105
|
+
## make sure we have colors all in Integer not names, hex, etc.
|
106
|
+
palette = _parse_colors( palette )
|
107
|
+
Palette8bit::GRAYSCALE.zip( palette ).to_h
|
108
|
+
end
|
109
|
+
|
110
|
+
## step 1: convert to grayscale (256 colors)
|
111
|
+
img = @img.grayscale
|
112
|
+
_change_colors!( img, color_map )
|
113
|
+
|
114
|
+
## wrap into Pixelart::Image - lets you use zoom() and such
|
115
|
+
Image.new( img.width, img.height, img )
|
116
|
+
end
|
117
|
+
alias_method :change_palette256, :change_palette8bit
|
118
|
+
|
119
|
+
|
120
|
+
####
|
121
|
+
## private helpers
|
122
|
+
def _parse_colors( colors )
|
123
|
+
colors.map {|color| Color.parse( color ) }
|
124
|
+
end
|
125
|
+
|
126
|
+
def _parse_color_map( color_map )
|
127
|
+
color_map.map do |k,v|
|
128
|
+
[Color.parse(k), Color.parse(v)]
|
129
|
+
end.to_h
|
130
|
+
end
|
80
131
|
|
132
|
+
def _change_colors!( img, color_map )
|
81
133
|
img.width.times do |x|
|
82
134
|
img.height.times do |y|
|
83
135
|
color = img[x,y]
|
@@ -85,12 +137,7 @@ def change_colors( color_map )
|
|
85
137
|
img[x,y] = new_color if new_color
|
86
138
|
end
|
87
139
|
end
|
88
|
-
|
89
|
-
## wrap into Pixelart::Image - lets you use zoom() and such
|
90
|
-
Image.new( img.width, img.height, img )
|
91
140
|
end
|
92
|
-
alias_method :recolor, :change_colors
|
93
|
-
|
94
141
|
|
95
142
|
|
96
143
|
|
@@ -124,6 +171,7 @@ def []=( x, y, value ) @img[x,y]=value; end
|
|
124
171
|
def pixels() @img.pixels; end
|
125
172
|
|
126
173
|
## return image ref - use a different name - why? why not?
|
174
|
+
## change to to_image - why? why not?
|
127
175
|
def image() @img; end
|
128
176
|
|
129
177
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module Pixelart
|
2
|
+
|
3
|
+
|
4
|
+
class Image
|
5
|
+
class Palette8bit < Image # or use Palette256 alias?
|
6
|
+
def initialize( colors, size: 1, spacing: nil )
|
7
|
+
## todo/check: change size arg to pixel or such? better name/less confusing - why? why not?
|
8
|
+
|
9
|
+
## todo/check: assert colors MUST have 256 colors!!!!
|
10
|
+
|
11
|
+
## use a "smart" default if no spacing set
|
12
|
+
## 0 for for (pixel) size == 1
|
13
|
+
## 1 for the rest
|
14
|
+
spacing = size == 1 ? 0 : 1 if spacing.nil?
|
15
|
+
|
16
|
+
img = ChunkyPNG::Image.new( 32*size+(32-1)*spacing,
|
17
|
+
8*size+(8-1)*spacing )
|
18
|
+
|
19
|
+
colors.each_with_index do |color,i|
|
20
|
+
y,x = i.divmod( 32 )
|
21
|
+
if size > 1
|
22
|
+
size.times do |n|
|
23
|
+
size.times do |m|
|
24
|
+
img[ x*size+n+spacing*x,
|
25
|
+
y*size+m+spacing*y] = color
|
26
|
+
end
|
27
|
+
end
|
28
|
+
else
|
29
|
+
img[x,y] = color
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
super( img.width, img.height, img )
|
34
|
+
end
|
35
|
+
end # class Palette8bit
|
36
|
+
|
37
|
+
end # class Image
|
38
|
+
end # module Pixelart
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,72 @@
|
|
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
|
+
|
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.1.
|
4
|
+
version: 0.1.4
|
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-04-
|
11
|
+
date: 2021-04-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: chunky_png
|
@@ -73,9 +73,12 @@ files:
|
|
73
73
|
- README.md
|
74
74
|
- Rakefile
|
75
75
|
- lib/pixelart.rb
|
76
|
+
- lib/pixelart/base.rb
|
76
77
|
- lib/pixelart/color.rb
|
77
78
|
- lib/pixelart/gradient.rb
|
78
79
|
- lib/pixelart/image.rb
|
80
|
+
- lib/pixelart/misc.rb
|
81
|
+
- lib/pixelart/palette.rb
|
79
82
|
- lib/pixelart/version.rb
|
80
83
|
homepage: https://github.com/cryptocopycats/mooncats
|
81
84
|
licenses:
|