pixelart 0.1.3 → 0.1.4
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 +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:
|