pixelart 1.3.0 → 1.3.1

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 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