pixelart 1.3.0 → 1.3.1

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: f203be5e0f2e2a06f88711fd51da837fb71212e58c0bc9aef80358f661f10f58
4
- data.tar.gz: f1377fcab0ec03d91ca692ed8d6e2222bacf5aedc5e477121c4cf1950968ad22
3
+ metadata.gz: a9cb1460263f319b98c4d333f6caa42118eb94f583f9cc6cdaa5bfa6bc4316b9
4
+ data.tar.gz: 2deabe3c3bc35c62d249e0ff5178d23f986d1131c96daf53a8d36fde51cd6de8
5
5
  SHA512:
6
- metadata.gz: b3c11e63d1764934b71a62410c23e14af07b42da9ce046a5853b92d493809abd3bede1ef3b40c025e61fd28d9efcb77f87bc31a9997def982dd65e67b62da0a0
7
- data.tar.gz: 78f8de9b81fa1ed6c6a77a5ea3bc6414aef36837314f5a2a073c1ab4683b31899c5bcdfe3be85ad7e3c5159f3ee708d9f231e97799f2262378f5b7b49998119a
6
+ metadata.gz: 57213049f46aac9a612adb3d9e236ce03aa336318705cabaed98f1f87557dc5dc08a73a7f50254852ab0c3c988ca0ed3d5b3ba6666925640ab837692c573be7c
7
+ data.tar.gz: 9ff7ae16a77eca4b2d4deb65b98747aa053ab97ab15b0f8a40d373f5ecb96dcd2c18d2fdfd18beca0c06a5e9330719dd2df1a3be1efac07c8f008dfa0b4db614
data/Manifest.txt CHANGED
@@ -8,12 +8,14 @@ lib/pixelart/blur.rb
8
8
  lib/pixelart/circle.rb
9
9
  lib/pixelart/color.rb
10
10
  lib/pixelart/composite.rb
11
+ lib/pixelart/generator.rb
11
12
  lib/pixelart/gradient.rb
12
13
  lib/pixelart/image.rb
13
14
  lib/pixelart/led.rb
14
15
  lib/pixelart/misc.rb
15
16
  lib/pixelart/palette.rb
16
17
  lib/pixelart/pixelator.rb
18
+ lib/pixelart/sample.rb
17
19
  lib/pixelart/silhouette.rb
18
20
  lib/pixelart/sketch.rb
19
21
  lib/pixelart/spots.rb
data/lib/pixelart/base.rb CHANGED
@@ -31,12 +31,18 @@ require 'pixelart/palette'
31
31
  require 'pixelart/image'
32
32
  require 'pixelart/composite'
33
33
 
34
+ require 'pixelart/sample' ## (down)sample / pixelate
35
+
34
36
 
35
37
  require 'pixelart/pixelator'
36
38
 
37
39
  require 'pixelart/misc' ## misc helpers
38
40
  require 'pixelart/stripes'
39
41
 
42
+
43
+ require 'pixelart/generator' ## generate images from text via spritesheets
44
+
45
+
40
46
  #########################
41
47
  # (special) effects / filters / etc
42
48
  require 'pixelart/circle'
@@ -0,0 +1,199 @@
1
+ ####
2
+ # "simple" generator (no different sizes, genders, etc.)
3
+ # uses built-in spritesheet for (archetypes &) attributes
4
+
5
+
6
+ module Pixelart
7
+
8
+ class Metadata
9
+ class Sprite
10
+ attr_reader :id, :name, :type, :more_names
11
+
12
+ def initialize( id:,
13
+ name:,
14
+ type:,
15
+ more_names: [] )
16
+ @id = id # zero-based index eg. 0,1,2,3, etc.
17
+ @name = name
18
+ @type = type
19
+ @more_names = more_names
20
+ end
21
+ end # class Metadata::Sprite
22
+ end # class Metadata
23
+
24
+
25
+
26
+
27
+ class Generator
28
+
29
+ ######
30
+ # static helpers - (turn into "true" static self.class methods - why? why not?)
31
+ #
32
+ def self.normalize_key( str )
33
+ ## add & e.g. B&W
34
+ ## add ' e.g. McDonald's Red
35
+ str.downcase.gsub(/[ ()&°'_-]/, '').strip
36
+ end
37
+
38
+ def self.normalize_name( str )
39
+ ## normalize spaces in more names
40
+ str.strip.gsub( /[ ]{2,}/, ' ' )
41
+ end
42
+
43
+ def normalize_key( str ) self.class.normalize_key( str ); end
44
+ def normalize_name( str ) self.class.normalize_name( str ); end
45
+
46
+
47
+
48
+ def build_attributes_by_name( recs )
49
+ h = {}
50
+ recs.each_with_index do |rec|
51
+ names = [rec.name] + rec.more_names
52
+
53
+ names.each do |name|
54
+ key = normalize_key( name )
55
+
56
+ if h[ key ]
57
+ puts "!!! ERROR - attribute name is not unique:"
58
+ pp rec
59
+ puts "duplicate:"
60
+ pp h[key]
61
+ exit 1
62
+ end
63
+ h[ key ] = rec
64
+ end
65
+ end
66
+ ## pp h
67
+ h
68
+ end
69
+
70
+
71
+ def build_recs( recs ) ## build and normalize (meta data) records
72
+ ## sort by id
73
+ recs = recs.sort do |l,r|
74
+ l['id'].to_i( 10 ) <=> r['id'].to_i( 10 ) # use base10 (decimal)
75
+ end
76
+
77
+ ## assert all recs are in order by id (0 to size)
78
+ recs.each_with_index do |rec, exp_id|
79
+ id = rec['id'].to_i(10)
80
+ if id != exp_id
81
+ puts "!! ERROR - meta data record ids out-of-order - expected id #{exp_id}; got #{id}"
82
+ exit 1
83
+ end
84
+ end
85
+
86
+ ## convert to "wrapped / immutable" kind-of struct
87
+ recs = recs.map do |rec|
88
+ id = rec['id'].to_i( 10 )
89
+ name = normalize_name( rec['name'] )
90
+ type = rec['type']
91
+
92
+ more_names = (rec['more_names'] || '').split( '|' )
93
+ more_names = more_names.map {|str| normalize_name( str ) }
94
+
95
+ Metadata::Sprite.new(
96
+ id: id,
97
+ name: name,
98
+ type: type,
99
+ more_names: more_names )
100
+ end
101
+ recs
102
+ end # method build_recs
103
+
104
+
105
+
106
+ def initialize( image_path="./spritesheet.png",
107
+ meta_path="./spritesheet.csv",
108
+ width: 24,
109
+ height: 24 )
110
+ @width = width
111
+ @height = height
112
+
113
+ @sheet = ImageComposite.read( image_path, width: @width, height: @height )
114
+ recs = CsvHash.read( meta_path )
115
+
116
+ @recs = build_recs( recs )
117
+
118
+ ## lookup by "case/space-insensitive" name / key
119
+ @attributes_by_name = build_attributes_by_name( @recs )
120
+ end
121
+
122
+
123
+ def spritesheet() @sheet; end
124
+ alias_method :sheet, :spritesheet
125
+
126
+
127
+ def records() @recs; end
128
+ alias_method :meta, :records
129
+
130
+
131
+
132
+
133
+ def find_meta( q )
134
+ key = normalize_key( q ) ## normalize q(uery) string/symbol
135
+
136
+ rec = @attributes_by_name[ key ]
137
+ if rec
138
+ puts " lookup >#{key}< => #{rec.id}: #{rec.name} / #{rec.type}"
139
+ else
140
+ puts "!! WARN - no lookup found for key >#{key}<"
141
+ end
142
+
143
+ rec
144
+ end
145
+
146
+ def find( q )
147
+ rec = find_meta( q )
148
+
149
+ ## return image if record found
150
+ rec ? @sheet[ rec.id ] : nil
151
+ end
152
+
153
+
154
+ def to_recs( *values )
155
+ recs = []
156
+
157
+ attribute_names = values
158
+
159
+ attribute_names.each do |attribute_name|
160
+ attribute = find_meta( attribute_name )
161
+ if attribute.nil?
162
+ puts "!! ERROR - attribute >#{attribute_name}< not found; sorry"
163
+ exit 1
164
+ end
165
+ recs << attribute
166
+ end
167
+
168
+ recs
169
+ end
170
+
171
+
172
+
173
+
174
+ def generate_image( *values, background: nil )
175
+
176
+ ids = if values[0].is_a?( Integer ) ## assume integer number (indexes)
177
+ values
178
+ else ## assume strings (names)
179
+ to_recs( *values ).map { |rec| rec.id }
180
+ end
181
+
182
+
183
+ img = Image.new( @width, @height )
184
+
185
+ if background ## for now assume background is (simply) color
186
+ img.compose!( Image.new( @width, @height, background ) )
187
+ end
188
+
189
+ ids.each do |id|
190
+ img.compose!( @sheet[ id ] )
191
+ end
192
+
193
+ img
194
+ end
195
+ alias_method :generate, :generate_image
196
+
197
+ end # class Generator
198
+
199
+ end # module Pixelart
@@ -0,0 +1,120 @@
1
+ module Pixelart
2
+
3
+ class Image
4
+
5
+ def self.calc_sample_steps( width, new_width,
6
+ center: true,
7
+ debug: false )
8
+ ## todo/fix: assert new_width is smaller than width
9
+ if debug
10
+ puts
11
+ puts "==> from: #{width}px to: #{new_width}px"
12
+ end
13
+
14
+ indexes = []
15
+
16
+ base_step = width / new_width ## pixels per pixel
17
+
18
+ err_step = (width % new_width) * 2 ## multiply by 2
19
+ denominator = new_width * 2 # denominator (in de - nenner e.g. 1/nenner 4/nenner)
20
+
21
+ overflow = err_step*new_width/denominator ## todo/check - assert that div is always WITHOUT remainder!!!!!
22
+
23
+ if debug
24
+ puts
25
+ puts "base_step (pixels per pixel):"
26
+ puts " #{base_step} - #{base_step} * #{new_width}px = #{base_step*new_width}px"
27
+ puts "err_step (in 1/#{width}*2):"
28
+ puts " #{err_step} / #{denominator} - #{err_step*new_width} / #{denominator} = +#{err_step*new_width/denominator}px overflow"
29
+ puts
30
+ end
31
+
32
+ # initial pixel offset
33
+ index = 0
34
+ err = err_step/2 ## note: start off with +err_step/2 to add overflow pixel in the "middle"
35
+
36
+
37
+ index += if center.is_a?( Integer )
38
+ center
39
+ elsif center
40
+ base_step/2
41
+ else
42
+ 0 # use 0px offset
43
+ end
44
+
45
+
46
+ new_width.times do |i|
47
+ if err >= denominator ## overflow
48
+ puts " -- overflow #{err}/#{denominator} - add +1 pixel offset to #{i}" if debug
49
+ index += 1
50
+ err -= denominator
51
+ end
52
+
53
+ puts " #{i} => #{index} -- #{err} / #{denominator}" if debug
54
+
55
+
56
+ indexes[i] = index
57
+
58
+ index += base_step
59
+ err += err_step
60
+ end
61
+
62
+ indexes
63
+ end
64
+
65
+
66
+
67
+ ## todo/check: rename to sample to resample or downsample - why? why not?
68
+ def sample( steps_x, steps_y=steps_x,
69
+ top_x: 0, top_y: 0 )
70
+ width = steps_x.size
71
+ height = steps_y.size
72
+ puts " downsampling from #{self.width}x#{self.height} to #{width}x#{height}..."
73
+
74
+ dest = Image.new( width, height )
75
+
76
+ steps_x.each_with_index do |step_x, x|
77
+ steps_y.each_with_index do |step_y, y|
78
+ pixel = self[top_x+step_x, top_y+step_y]
79
+
80
+ dest[x,y] = pixel
81
+ end
82
+ end
83
+
84
+ dest
85
+ end
86
+ alias_method :pixelate, :sample
87
+
88
+
89
+ def sample_debug( steps_x, steps_y=steps_x,
90
+ color: Color.parse( '#ffff00' ),
91
+ top_x: 0,
92
+ top_y: 0) ## add a yellow pixel
93
+
94
+ ## todo/fix: get a clone of the image (DO NOT modify in place)
95
+
96
+ img = self
97
+
98
+ steps_x.each_with_index do |step_x, x|
99
+ steps_y.each_with_index do |step_y, y|
100
+ base_x = top_x+step_x
101
+ base_y = top_y+step_y
102
+
103
+ img[base_x,base_y] = color
104
+
105
+ ## add more colors
106
+ img[base_x+1,base_y] = color
107
+ img[base_x+2,base_y] = color
108
+
109
+ img[base_x,base_y+1] = color
110
+ img[base_x,base_y+2] = color
111
+ end
112
+ end
113
+
114
+ self
115
+ end
116
+ alias_method :pixelate_debug, :sample_debug
117
+
118
+ end # class Image
119
+ end # module Pixelart
120
+
@@ -3,7 +3,7 @@ module Pixelart
3
3
 
4
4
  MAJOR = 1
5
5
  MINOR = 3
6
- PATCH = 0
6
+ PATCH = 1
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: 1.3.0
4
+ version: 1.3.1
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-05-03 00:00:00.000000000 Z
11
+ date: 2022-05-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: chunky_png
@@ -106,12 +106,14 @@ files:
106
106
  - lib/pixelart/circle.rb
107
107
  - lib/pixelart/color.rb
108
108
  - lib/pixelart/composite.rb
109
+ - lib/pixelart/generator.rb
109
110
  - lib/pixelart/gradient.rb
110
111
  - lib/pixelart/image.rb
111
112
  - lib/pixelart/led.rb
112
113
  - lib/pixelart/misc.rb
113
114
  - lib/pixelart/palette.rb
114
115
  - lib/pixelart/pixelator.rb
116
+ - lib/pixelart/sample.rb
115
117
  - lib/pixelart/silhouette.rb
116
118
  - lib/pixelart/sketch.rb
117
119
  - lib/pixelart/spots.rb