class SnesUtils::Png2Snes
Public Class Methods
new(file_path, bpp:4, alpha:nil)
click to toggle source
# File lib/png2snes/png2snes.rb, line 3 def initialize(file_path, bpp:4, alpha:nil) @file_path = file_path @file_dir = File.dirname(@file_path) @file_name = File.basename(@file_path, File.extname(@file_path)) @image = ChunkyPNG::Image.from_file(@file_path) @pixels = pixels_to_bgr5 @palette = @pixels.uniq @char_size = 8 raise ArgumentError, 'BPP must be 2, 4, or 8' unless [2, 4, 8].include? bpp @bpp = bpp raise ArgumentError, 'Image width and height must be a multiple of sprite size' if (@image.width % @char_size != 0) or (@image.height % @char_size != 0) unshift_alpha(alpha) if alpha fill_palette end
Public Instance Methods
extract_bitplanes(sprite)
click to toggle source
# File lib/png2snes/png2snes.rb, line 81 def extract_bitplanes sprite bitplanes = [] (0..@bpp-1).each do |plane| bitplanes.push sprite.map { |p| p[plane] } end bitplanes end
extract_sprites()
click to toggle source
# File lib/png2snes/png2snes.rb, line 61 def extract_sprites pixel_idx = pixel_indices sprite_per_row = @image.width / @char_size sprite_per_col = @image.height / @char_size sprite_per_sheet = sprite_per_row * sprite_per_col sprites = [] (0..sprite_per_sheet-1).each do |s| sprite = [] (0..@char_size-1).each do |r| offset = (s/sprite_per_row)*sprite_per_row * @char_size**2 + s % sprite_per_row * @char_size sprite += pixel_idx[offset + r*sprite_per_row*@char_size, @char_size] end sprites.push(sprite) end sprites end
fill_palette()
click to toggle source
# File lib/png2snes/png2snes.rb, line 36 def fill_palette target_size = 2**@bpp missing_colors = target_size - @palette.count raise ArgumentError, "Palette size too large for target BPP (#{@palette.count})" if missing_colors < 0 @palette += [0] * missing_colors end
pixel_indices()
click to toggle source
# File lib/png2snes/png2snes.rb, line 55 def pixel_indices pix_idx = @pixels.map { |p| @palette.index(p) } pix_idx_bin = pix_idx.map { |i| "%0#{@bpp}b" % i } pix_idx_bin.map { |i| i.reverse } end
pixels_to_bgr5()
click to toggle source
# File lib/png2snes/png2snes.rb, line 22 def pixels_to_bgr5 @image.pixels.map do |c| r = ((c >> 24) & 0xff) >> 3 g = ((c >> 16) & 0xff) >> 3 b = ((c >> 8) & 0xff) >> 3 r | (g << 5) | (b << 10) end end
unshift_alpha(alpha)
click to toggle source
# File lib/png2snes/png2snes.rb, line 32 def unshift_alpha(alpha) @palette.unshift(alpha) end
write(hex, file_path)
click to toggle source
# File lib/png2snes/png2snes.rb, line 44 def write hex, file_path File.open(file_path, 'w+b') do |file| file.write([hex.join].pack('H*')) end end
write_image()
click to toggle source
# File lib/png2snes/png2snes.rb, line 90 def write_image sprite_per_row = @image.width / @char_size sprites = extract_sprites sprites_bitplanes = sprites.map { |s| extract_bitplanes s } image_bits = "" sprites_bitplanes.each do |sprite_bitplanes| sprite_bitplane_pairs = sprite_bitplanes.each_slice(2).to_a bitplane_bits = "" sprite_bitplane_pairs.each do |bitplane| (0..@char_size-1).each do |r| offset = r*@char_size bitplane_bits += bitplane[0][offset, @char_size].join + bitplane[1][offset, @char_size].join end end image_bits += bitplane_bits end image_hex = image_bits.scan(/.{8}/).map { |b| "%02x" % b.to_i(2) } write image_hex, File.expand_path("#{@file_name}.bin", @file_dir) end
write_palette()
click to toggle source
# File lib/png2snes/png2snes.rb, line 50 def write_palette palette_hex = @palette.map { |c| ('%04x' % c).scan(/.{2}/).reverse.join } write palette_hex, File.expand_path("#{@file_name}-pal.bin", @file_dir) end