Class: Pixelart::Image
- Inherits:
-
Object
- Object
- Pixelart::Image
- Defined in:
- lib/pixelart/base.rb,
lib/pixelart/misc.rb,
lib/pixelart/image.rb
Direct Known Subclasses
Defined Under Namespace
Classes: Palette8bit
Constant Summary collapse
- Palette256 =
Palette8Bit = Palette8bit
- PALETTE8BIT =
predefined palette8bit color maps
(grayscale to sepia/blue/false/etc.) - todo/check - keep "shortcut" convenience predefined map - why? why not? { sepia: Palette8bit::GRAYSCALE.zip( Palette8bit::SEPIA ).to_h, blue: Palette8bit::GRAYSCALE.zip( Palette8bit::BLUE ).to_h, false: Palette8bit::GRAYSCALE.zip( Palette8bit::FALSE ).to_h, }
Class Method Summary collapse
- .parse(pixels, colors:) ⇒ Object
- .parse_colors(colors) ⇒ Object
-
.parse_pixels(pixels) ⇒ Object
helpers.
-
.read(path) ⇒ Object
convenience helper.
Instance Method Summary collapse
- #[](x, y) ⇒ Object
- #[]=(x, y, value) ⇒ Object
- #_change_colors!(img, color_map) ⇒ Object
- #_parse_color_map(color_map) ⇒ Object
-
#_parse_colors(colors) ⇒ Object
private helpers.
-
#change_colors(color_map) ⇒ Object
(also: #recolor)
add replace_colors alias too? - why? why not?.
- #change_palette8bit(palette) ⇒ Object (also: #change_palette256)
- #compose!(other, x = 0, y = 0) ⇒ Object (also: #paste!)
-
#grayscale ⇒ Object
filter / effects.
- #height ⇒ Object
-
#image ⇒ Object
return image ref - use a different name - why? why not? change to to_image - why? why not?.
-
#initialize(width, height, initial = Color::TRANSPARENT) ⇒ Image
constructor
A new instance of Image.
- #pixels ⇒ Object
-
#save(path, constraints = {}) ⇒ Object
(also: #write)
(image) delegates todo/check: add some more??.
- #width ⇒ Object
- #zoom(zoom = 2) ⇒ Object (also: #scale)
Constructor Details
#initialize(width, height, initial = Color::TRANSPARENT) ⇒ Image
Returns a new instance of Image.
33 34 35 36 37 38 39 40 41 |
# File 'lib/pixelart/image.rb', line 33 def initialize( width, height, initial=Color::TRANSPARENT ) if initial.is_a?( ChunkyPNG::Image ) @img = initial else ## todo/check - initial - use parse_color here too e.g. allow "#fff" too etc. @img = ChunkyPNG::Image.new( width, height, initial ) end end |
Class Method Details
.parse(pixels, colors:) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/pixelart/image.rb', line 12 def self.parse( pixels, colors: ) colors = parse_colors( colors ) pixels = parse_pixels( pixels ) width = pixels.reduce(1) {|width,row| row.size > width ? row.size : width } height = pixels.size img = new( width, height ) pixels.each_with_index do |row,y| row.each_with_index do |color,x| pixel = colors[color] img[x,y] = pixel end # each row end # each data img end |
.parse_colors(colors) ⇒ Object
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
# File 'lib/pixelart/image.rb', line 200 def self.parse_colors( colors ) if colors.is_a?( Array ) ## convenience shortcut ## note: always auto-add color 0 as pre-defined transparent - why? why not? h = { '0' => Color::TRANSPARENT } colors.each_with_index do |color, i| h[ (i+1).to_s ] = Color.parse( color ) end h else ## assume hash table with color map ## convert into ChunkyPNG::Color colors.map do |key,color| ## always convert key to string why? why not? use symbol? [ key.to_s, Color.parse( color ) ] end.to_h end end |
.parse_pixels(pixels) ⇒ Object
helpers
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/pixelart/image.rb', line 182 def self.parse_pixels( pixels ) data = [] pixels.each_line do |line| line = line.strip if line.empty? puts "!! WARN: skipping empty line in pixel art source" next end ## note: allow multiple spaces or tabs to separate pixel codes ## 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 ## or data << line.split( /[ \t]+/) end data end |
.read(path) ⇒ Object
convenience helper
5 6 7 8 9 |
# File 'lib/pixelart/image.rb', line 5 def self.read( path ) ## convenience helper img_inner = ChunkyPNG::Image.from_file( path ) img = new( img_inner.width, img_inner.height, img_inner ) img end |
Instance Method Details
#[](x, y) ⇒ Object
168 |
# File 'lib/pixelart/image.rb', line 168 def []( x, y ) @img[x,y]; end |
#[]=(x, y, value) ⇒ Object
169 |
# File 'lib/pixelart/image.rb', line 169 def []=( x, y, value ) @img[x,y]=value; end |
#_change_colors!(img, color_map) ⇒ Object
132 133 134 135 136 137 138 139 140 |
# File 'lib/pixelart/image.rb', line 132 def _change_colors!( img, color_map ) img.width.times do |x| img.height.times do |y| color = img[x,y] new_color = color_map[color] img[x,y] = new_color if new_color end end end |
#_parse_color_map(color_map) ⇒ Object
126 127 128 129 130 |
# File 'lib/pixelart/image.rb', line 126 def _parse_color_map( color_map ) color_map.map do |k,v| [Color.parse(k), Color.parse(v)] end.to_h end |
#_parse_colors(colors) ⇒ Object
private helpers
122 123 124 |
# File 'lib/pixelart/image.rb', line 122 def _parse_colors( colors ) colors.map {|color| Color.parse( color ) } end |
#change_colors(color_map) ⇒ Object Also known as: recolor
add replace_colors alias too? - why? why not?
77 78 79 80 81 82 83 84 85 |
# File 'lib/pixelart/image.rb', line 77 def change_colors( color_map ) color_map = _parse_color_map( color_map ) img = @img.dup ## note: make a deep copy!!! _change_colors!( img, color_map ) ## wrap into Pixelart::Image - lets you use zoom() and such Image.new( img.width, img.height, img ) end |
#change_palette8bit(palette) ⇒ Object Also known as: change_palette256
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/pixelart/image.rb', line 99 def change_palette8bit( palette ) ## step 0: mapping from grayscale to new 8bit palette (256 colors) color_map = if palette.is_a( String ) || palette.is_a( Symbol ) PALETTE8BIT[ palette.to_sym ] ## todo/fix: check for missing/undefined palette not found - why? why not? else ## make sure we have colors all in Integer not names, hex, etc. palette = _parse_colors( palette ) Palette8bit::GRAYSCALE.zip( palette ).to_h end ## step 1: convert to grayscale (256 colors) img = @img.grayscale _change_colors!( img, color_map ) ## wrap into Pixelart::Image - lets you use zoom() and such Image.new( img.width, img.height, img ) end |
#compose!(other, x = 0, y = 0) ⇒ Object Also known as: paste!
159 160 161 |
# File 'lib/pixelart/image.rb', line 159 def compose!( other, x=0, y=0 ) @img.compose!( other.image, x, y ) ## note: "unwrap" inner image ref end |
#grayscale ⇒ Object
filter / effects
71 72 73 74 |
# File 'lib/pixelart/image.rb', line 71 def grayscale img = @img.grayscale Image.new( img.width, img.height, img ) end |
#height ⇒ Object
166 |
# File 'lib/pixelart/image.rb', line 166 def height() @img.height; end |
#image ⇒ Object
return image ref - use a different name - why? why not?
change to to_image - why? why not?
175 |
# File 'lib/pixelart/image.rb', line 175 def image() @img; end |
#pixels ⇒ Object
171 |
# File 'lib/pixelart/image.rb', line 171 def pixels() @img.pixels; end |
#save(path, constraints = {}) ⇒ Object Also known as: write
(image) delegates
todo/check: add some more??
148 149 150 151 152 153 154 155 |
# File 'lib/pixelart/image.rb', line 148 def save( path, constraints = {} ) # step 1: make sure outdir exits outdir = File.dirname( path ) FileUtils.mkdir_p( outdir ) unless Dir.exist?( outdir ) # step 2: save @img.save( path, constraints ) end |
#width ⇒ Object
165 |
# File 'lib/pixelart/image.rb', line 165 def width() @img.width; end |
#zoom(zoom = 2) ⇒ Object Also known as: scale
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/pixelart/image.rb', line 45 def zoom( zoom=2 ) ## create a new zoom factor x image (2x, 3x, etc.) img = Image.new( @img.width*zoom, @img.height*zoom ) @img.height.times do |y| @img.width.times do |x| pixel = @img[x,y] zoom.times do |n| zoom.times do |m| img[n+zoom*x,m+zoom*y] = pixel end end end # each x end # each y img end |