pixelart 0.1.8 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3c72ac16513ce785c2bfcd63fe1d230950d03d597e0def19d4a35034b743d513
4
- data.tar.gz: dd3fcd6b2af8eaade1f9dc7bc7566af24ee3b5688d86363845cfc4794ee426d5
3
+ metadata.gz: c77200956faad2093e12cba99a8f8a3339941e612406701a795eecdcdd8248d8
4
+ data.tar.gz: d3dfbf4c9d278db95219b695dc55cea1b31debd8b5a08a20305135526d3618d1
5
5
  SHA512:
6
- metadata.gz: 4f299efeddddc2fe143595fbee1fa5b68fedd39f643da7700e25702398f5d3d3a5adc141268fa127dc669db476a41d64971b563997653ee1b2e0af8d418163eb
7
- data.tar.gz: e8cc7732cc24c04bcfb076f0ae48f088f2a48c4e83f23b897b194ae7def003effd8c08da8c0a7cde08fb55ea09ae2bf2ce0d9c017d38b759531e53881c5e7871
6
+ metadata.gz: db9abc2122d9727e2fee58c54913174983ff3dd03d2e2658c4b0a84d80114f0f482673d2b7e51fea61dbbb423f1df05eb5e027ba51d741ab86dc7e16d6f2eb72
7
+ data.tar.gz: 36c0733c3c5e15f18cca6787185eb2229fa8d7a98c3d037cf781295b8d32fc74be542a433de1504981afb984d9234730191dcf14443b3f614cd3dc9139d4fa7e
data/Manifest.txt CHANGED
@@ -5,10 +5,12 @@ Rakefile
5
5
  lib/pixelart.rb
6
6
  lib/pixelart/base.rb
7
7
  lib/pixelart/color.rb
8
+ lib/pixelart/composite.rb
8
9
  lib/pixelart/gradient.rb
9
10
  lib/pixelart/image.rb
10
11
  lib/pixelart/led.rb
11
12
  lib/pixelart/misc.rb
12
13
  lib/pixelart/palette.rb
13
14
  lib/pixelart/pixelator.rb
15
+ lib/pixelart/sketch.rb
14
16
  lib/pixelart/version.rb
data/lib/pixelart/base.rb CHANGED
@@ -14,13 +14,14 @@ require 'pixelart/color'
14
14
  require 'pixelart/gradient'
15
15
  require 'pixelart/palette'
16
16
  require 'pixelart/image'
17
+ require 'pixelart/composite'
17
18
 
18
19
  require 'pixelart/pixelator'
19
20
 
20
21
  require 'pixelart/misc' ## misc helpers
21
22
 
22
- require 'pixelart/led' ## (special) effects / filters
23
-
23
+ require 'pixelart/led' ## (special) effects / filters
24
+ require 'pixelart/sketch'
24
25
 
25
26
 
26
27
 
@@ -33,6 +34,8 @@ module Pixelart
33
34
 
34
35
  Palette256Image = Palette8BitImage = Palette8bitImage =
35
36
  ImagePalette256 = ImagePalette8Bit = ImagePalette8bit
37
+
38
+ CompositeImage = ImageComposite
36
39
  end
37
40
 
38
41
 
@@ -0,0 +1,77 @@
1
+ module Pixelart
2
+
3
+ class ImageComposite < Image # check: (re)name to Collage, Sheet, Sprites, or such?
4
+
5
+ ## default tile width / height in pixel -- check: (re)name to sprite or such? why? why not?
6
+ TILE_WIDTH = 24
7
+ TILE_HEIGHT = 24
8
+
9
+
10
+ def initialize( *args, **kwargs )
11
+ @tile_width = kwargs[:width] || kwargs[:tile_width] || TILE_WIDTH
12
+ @tile_height = kwargs[:height] || kwargs[:tile_height] || TILE_HEIGHT
13
+
14
+ ## todo/fix: check type - args[0] is Image!!!
15
+ if args.size == 1 ## assume "copy" c'tor with passed in image
16
+ img = args[0] ## pass image through as-is
17
+
18
+ @tile_cols = img.width / @tile_width ## e.g. 2400/24 = 100
19
+ @tile_rows = img.height / @tile_height ## e.g. 2400/24 = 100
20
+ @tile_count = @tile_cols * @tile_rows ## ## 10000 = 100x100 (2400x2400 pixel)
21
+ elsif args.size == 2 || args.size == 0 ## cols, rows
22
+ ## todo/fix: check type - args[0] & args[1] is Integer!!!!!
23
+ ## todo/check - find a better name for cols/rows - why? why not?
24
+ @tile_cols = args[0] || 3
25
+ @tile_rows = args[1] || 3
26
+ @tile_count = 0 # (track) current index (of added images)
27
+
28
+ img = ChunkyPNG::Image.new( @tile_cols * @tile_width,
29
+ @tile_rows * @tile_height )
30
+ else
31
+ raise ArgumentError, "cols, rows or image arguments expected; got: #{args.inspect}"
32
+ end
33
+
34
+ puts " #{img.height}x#{img.width} (height x width)"
35
+
36
+ super( nil, nil, img )
37
+ end
38
+
39
+
40
+ def count() @tile_count; end
41
+ alias_method :size, :count ## add size alias (confusing if starting with 0?) - why? why not?
42
+
43
+ #####
44
+ # set / add tile
45
+
46
+ def add( image )
47
+ y, x = @tile_count.divmod( @tile_cols )
48
+
49
+ puts " [#{@tile_count}] @ (#{x}/#{y}) #{image.width}x#{image.height} (height x width)"
50
+
51
+ ## note: image.image - "unwrap" the "raw" ChunkyPNG::Image
52
+ @img.compose!( image.image, x*@tile_width, y*@tile_height )
53
+ @tile_count += 1
54
+ end
55
+ alias_method :<<, :add
56
+
57
+
58
+
59
+ ######
60
+ # get tile
61
+
62
+ def tile( index )
63
+ y, x = index.divmod( @tile_cols )
64
+ img = @img.crop( x*@tile_width, y*@tile_height, @tile_width, @tile_height )
65
+ Image.new( img.width, img.height, img ) ## wrap in pixelart image
66
+ end
67
+
68
+ def []( *args ) ## overload - why? why not?
69
+ if args.size == 1
70
+ index = args[0]
71
+ tile( index )
72
+ else
73
+ super ## e.g [x,y] --- get pixel
74
+ end
75
+ end
76
+ end # class ImageComposite
77
+ end # module Pixelart
@@ -9,7 +9,14 @@ def self.read( path ) ## convenience helper
9
9
  end
10
10
 
11
11
 
12
- def self.parse( pixels, colors: )
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 = colors[color]
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
@@ -31,6 +50,9 @@ end
31
50
 
32
51
 
33
52
  def initialize( width, height, initial=Color::TRANSPARENT )
53
+ ### todo/fix:
54
+ ## change params to *args only - why? why not?
55
+ ## make width/height optional if image passed in?
34
56
 
35
57
  if initial.is_a?( ChunkyPNG::Image )
36
58
  @img = initial
@@ -73,6 +95,13 @@ def grayscale
73
95
  Image.new( img.width, img.height, img )
74
96
  end
75
97
 
98
+ def mirror
99
+ img = @img.mirror
100
+ Image.new( img.width, img.height, img )
101
+ end
102
+ alias_method :flip_vertically, :mirror
103
+
104
+
76
105
  ## add replace_colors alias too? - why? why not?
77
106
  def change_colors( color_map )
78
107
  color_map = _parse_color_map( color_map )
@@ -170,6 +199,9 @@ def []=( x, y, value ) @img[x,y]=value; end
170
199
 
171
200
  def pixels() @img.pixels; end
172
201
 
202
+ ### todo/check: add colors() e.g. @img.pixels.uniq - why? why not?
203
+
204
+
173
205
  ## return image ref - use a different name - why? why not?
174
206
  ## change to to_image - why? why not?
175
207
  def image() @img; end
@@ -183,10 +215,7 @@ def self.parse_pixels( pixels )
183
215
  data = []
184
216
  pixels.each_line do |line|
185
217
  line = line.strip
186
- if line.empty?
187
- puts "!! WARN: skipping empty line in pixel art source"
188
- next
189
- end
218
+ next if line.start_with?( '#' ) || line.empty? ## note: allow comments and empty lines
190
219
 
191
220
  ## note: allow multiple spaces or tabs to separate pixel codes
192
221
  ## 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 +226,13 @@ def self.parse_pixels( pixels )
197
226
  end
198
227
 
199
228
 
229
+
200
230
  def self.parse_colors( colors )
201
231
  if colors.is_a?( Array ) ## convenience shortcut
202
232
  ## note: always auto-add color 0 as pre-defined transparent - why? why not?
203
233
  h = { '0' => Color::TRANSPARENT }
204
234
  colors.each_with_index do |color, i|
205
- h[ (i+1).to_s ] = Color.parse( color )
235
+ h[ (i+1).to_s ] = Color.parse( color )
206
236
  end
207
237
  h
208
238
  else ## assume hash table with color map
@@ -215,7 +245,6 @@ def self.parse_colors( colors )
215
245
  end
216
246
 
217
247
 
218
-
219
248
  end # class Image
220
249
  end # module Pixelart
221
250
 
data/lib/pixelart/misc.rb CHANGED
@@ -15,6 +15,9 @@ class ImagePalette8bit < Image # or use Palette256 alias?
15
15
  img = ChunkyPNG::Image.new( 32*size+(32-1)*spacing,
16
16
  8*size+(8-1)*spacing )
17
17
 
18
+
19
+ colors =colors.map {|color| Color.parse( color ) }
20
+
18
21
  colors.each_with_index do |color,i|
19
22
  y,x = i.divmod( 32 )
20
23
  if size > 1
@@ -32,6 +35,32 @@ class ImagePalette8bit < Image # or use Palette256 alias?
32
35
  super( img.width, img.height, img )
33
36
  end
34
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
+
63
+
35
64
  end # module Pixelart
36
65
 
37
66
 
@@ -76,7 +76,7 @@ class Pixelator # or use Minifier or such - rename - why? why not?
76
76
  alias_method :[], :pixel
77
77
 
78
78
 
79
- def can_pixelate?
79
+ def can_pixelate?( threshold: 50 )
80
80
  # check if any pixel has NOT a color with a 50% majority?
81
81
  count = 0
82
82
  @width.times do |x|
@@ -84,10 +84,13 @@ class Pixelator # or use Minifier or such - rename - why? why not?
84
84
  pixel = pixel( x, y )
85
85
  sum = pixel.values.sum
86
86
  color_count = pixel.values[0]
87
- if color_count < (sum/2)
87
+
88
+ threshold_count = sum / (100/threshold)
89
+ if color_count < threshold_count
88
90
  count += 1
91
+ puts "!! #{color_count} < #{threshold_count} (#{threshold}%)"
89
92
  ## 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:"
93
+ puts "!! WARN #{count} - pixel (#{x}/#{y}) - no majority (#{threshold}%) color:"
91
94
  pp pixel
92
95
  end
93
96
  end
@@ -111,7 +114,52 @@ class Pixelator # or use Minifier or such - rename - why? why not?
111
114
 
112
115
  Image.new( img.width, img.height, img ) ## wrap in Pixelart::Image - why? why not?
113
116
  end
117
+
118
+ def outline
119
+ ## create a two color outline (transparent and non-transparent color)
120
+ img = ChunkyPNG::Image.new( @width, @height )
121
+
122
+ @width.times do |x|
123
+ @height.times do |y|
124
+ pixel = pixel( x, y )
125
+ ## calculate pixel count for transparent and non-transparent parts
126
+ ## note:
127
+ ## also count all colors with alpha channel < 200 to transparent!!
128
+ transparent_count, color_count = pixel.reduce([0,0]) do |mem, (color,count)|
129
+ hsl = Color.to_hsl( color )
130
+ ## get alpha channel (transparency) for hsla
131
+ ## 0-255 max.
132
+ alpha = hsl[3]
133
+ if color == 0x00 || alpha < 200
134
+ mem[0] += count
135
+ else
136
+ mem[1] += count
137
+ end
138
+ mem
139
+ end
140
+
141
+ print "."
142
+ if transparent_count > 0 && color_count > 0
143
+ print "(#{x}/#{y}=>#{transparent_count}/#{color_count})"
144
+ end
145
+
146
+ ## todo/check:
147
+ ## warn if sum_transparent == sum_color
148
+ ## or within "threshold" e.g. below 55% or 58% or such - why? why not?
149
+ ## or add treshold as param to outline?
150
+ color = if transparent_count > color_count
151
+ 0x0
152
+ else
153
+ 0x0000ffff ## use blue for now
154
+ end
155
+
156
+ img[x,y] = color
157
+ end
158
+ end
159
+ print "\n"
160
+
161
+ Image.new( img.width, img.height, img ) ## wrap in Pixelart::Image - why? why not?
162
+ end
114
163
  end # class Pixelator
115
164
  end # module Pixelart
116
165
 
117
-
@@ -0,0 +1,69 @@
1
+ module Pixelart
2
+
3
+
4
+
5
+ class Image
6
+ def sketch( sketch=4, line: 1 )
7
+ # todo: line - find a better name eg. line_strenght/width or such?
8
+ width = @img.width*sketch + (@img.width+1)*line
9
+ height = @img.height*sketch + (@img.height+1)*line
10
+
11
+ puts " #{width}x#{height}"
12
+
13
+ img = Image.new( width, height, Color::WHITE )
14
+
15
+ @img.width.times do |x|
16
+ @img.height.times do |y|
17
+ pixel = @img[x,y]
18
+
19
+ ## get surrounding pixels - if "out-of-bound" use transparent (0)
20
+ left = x == 0 ? Color::TRANSPARENT : @img[x-1,y]
21
+ top = y == 0 ? Color::TRANSPARENT : @img[x ,y-1]
22
+
23
+ if pixel != left ## draw vertical line
24
+ (sketch+line*2).times do |n|
25
+ line.times do |m|
26
+ img[ x*sketch + line*x + m,
27
+ n + y*sketch + line*y] = Color::BLACK
28
+ end
29
+ end
30
+ end
31
+
32
+ if pixel != top ## draw horizontal line
33
+ (sketch+line*2).times do |n|
34
+ line.times do |m|
35
+ img[n + x*sketch + line*x,
36
+ y*sketch + line*y + m] = Color::BLACK
37
+ end
38
+ end
39
+ end
40
+
41
+
42
+ ## check special edge case for x and y to add "finish-up" right and bottom line
43
+ if x == @img.width-1 && pixel != Color::TRANSPARENT
44
+ ## draw vertical line
45
+ (sketch+line*2).times do |n|
46
+ line.times do |m|
47
+ img[ (x+1)*sketch + line*(x+1) + m,
48
+ n + y*sketch + line*y] = Color::BLACK
49
+ end
50
+ end
51
+ end
52
+
53
+ if y== @img.height-1 && pixel != Color::TRANSPARENT
54
+ ## draw horizontal line
55
+ (sketch+line*2).times do |n|
56
+ line.times do |m|
57
+ img[n + x*sketch + line*x,
58
+ (y+1)*sketch + line*(y+1) + m] = Color::BLACK
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+
65
+ img
66
+ end
67
+ end # class Image
68
+ end # module Pixelart
69
+
@@ -1,9 +1,9 @@
1
1
 
2
2
  module Pixelart
3
3
 
4
- MAJOR = 0
5
- MINOR = 1
6
- PATCH = 8
4
+ MAJOR = 1
5
+ MINOR = 0
6
+ PATCH = 0
7
7
  VERSION = [MAJOR,MINOR,PATCH].join('.')
8
8
 
9
9
  def self.version
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.8
4
+ version: 1.0.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-04-25 00:00:00.000000000 Z
11
+ date: 2021-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png
@@ -75,12 +75,14 @@ files:
75
75
  - lib/pixelart.rb
76
76
  - lib/pixelart/base.rb
77
77
  - lib/pixelart/color.rb
78
+ - lib/pixelart/composite.rb
78
79
  - lib/pixelart/gradient.rb
79
80
  - lib/pixelart/image.rb
80
81
  - lib/pixelart/led.rb
81
82
  - lib/pixelart/misc.rb
82
83
  - lib/pixelart/palette.rb
83
84
  - lib/pixelart/pixelator.rb
85
+ - lib/pixelart/sketch.rb
84
86
  - lib/pixelart/version.rb
85
87
  homepage: https://github.com/rubycoco/pixel
86
88
  licenses: