Last active
September 16, 2018 18:14
-
-
Save thisredone/cd903dfed45821f4d84efa7b508f72ab to your computer and use it in GitHub Desktop.
Cut images into tiles of the same size and glue together into a tileset
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env ruby | |
require 'fileutils' | |
require 'pry' | |
SIZE = ARGV[0].to_i | |
max_tileset_width = 7 | |
wanted_geometry = "#{SIZE}x#{SIZE}" | |
FileUtils.mkdir_p 'tiles' | |
items = [] | |
Dir['*.png'].each do |file| | |
next if file == 'tileset.png' | |
dims = `identify #{file}`[/\d+x\d+/].split('x').map(&:to_i) | |
tiling = dims.map { |d| (d.to_f / 128).ceil.to_i } | |
max_tileset_width += 1 if tiling[1] > max_tileset_width | |
if dims == [SIZE, SIZE] | |
items << { tile: tiling, item: 'tiles/' + file} | |
`cp #{file} tiles/` | |
next | |
end | |
virtual_canvas_dims = tiling.map { |d| d * 128 } | |
offsets = dims.zip(virtual_canvas_dims).map { |(size, full)| full - size } | |
repage = [virtual_canvas_dims.join('x'), offsets.join('+')].join('+') | |
basename = File.basename(file, '.png') | |
puts "#{file} (#{dims.join 'x'}): #{virtual_canvas_dims.join 'x'}+#{offsets.join 'x'}" | |
`convert #{file} -alpha on -repage #{repage} -crop #{wanted_geometry} +repage tiles/#{basename}-crop-%02d.png` | |
cropped = Dir["tiles/#{basename}-crop*"] | |
cropped.each do |cropped_file| | |
`convert -size #{wanted_geometry} xc:none #{cropped_file} -gravity south -composite #{cropped_file}` | |
end | |
`montage -background none #{cropped.join ' '} -geometry +0+0 -tile #{tiling.join 'x'} tiles/#{file}` | |
items << { tile: tiling, item: 'tiles/' + file } | |
`rm #{cropped.join ' '}` | |
end | |
sorted = items.group_by { |x| x[:tile][1] }.sort_by(&:first).map(&:last).map { |group| group.sort_by { |x| x[:tile][0] } } | |
matrix = [Array.new(max_tileset_width)] | |
row_index = 0 | |
y = 0 | |
add_row = -> prev_height do | |
matrix << Array.new(max_tileset_width) | |
row_index += 1 | |
y += prev_height | |
end | |
sorted.each.with_index do |group, group_index| | |
group_height = group.first[:tile][1] | |
group.each do |item| | |
width = item[:tile][0] | |
add_row.(group_height) if matrix[row_index].count(nil) < width | |
cell_index = matrix[row_index].index(nil) | |
(0...width).each do |offset| | |
matrix[row_index][cell_index + offset] = true | |
end | |
item[:place] = [cell_index, y] | |
end | |
add_row.(group_height) if matrix[row_index].first && group_index != sorted.size - 1 | |
end | |
items = sorted.flatten | |
result = items.map do |x| | |
[ | |
x[:item], | |
'-geometry', | |
'+' + x[:place].map { |t| t * SIZE }.join('+'), | |
'-composite' | |
].join(' ') | |
end.join(' ') | |
height = items.last[:tile][1] * SIZE + y * SIZE | |
width = max_tileset_width * SIZE | |
`convert -size #{width}x#{height} xc:none #{result} tileset.png` |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Takes PNG images from the current directory, cuts them to be the same size and places the resulting tiles in
tiles/
directory. Tiles are then combined into thetileset.png
Installation
Needs Ruby and Imagemagick. Can be used in Windows but only with "Windows Subsystem for Linux" (or Cygwin).
Usage