Generating a tile sheet from many images
Using isometric image assets that correlate to 3D models to create a 3D environment with. The assets used are from Kenney.
Cropping and adding multiple images into a tileset is inefficient and time-consuming. I decided to write a Python script that automates this.
The script imports Image for writing, cropping and creating images and ElementTree to read, edit and create XML files that create a file describing every tile and their names in the Tiled format.
from PIL import Image
import xml.etree.ElementTree as ET
import xml.dom.minidom
import os.path, sys
import math
path = "C:\\Users\\Dion-\\Documents\\Development\\Tiled\\TestAssets"
newpath = path + "\\exported\\"
dirs = os.listdir(path)
# Setting the points for cropped image
left = 191
top = 181
right = 130
bottom = 168
#image related
imgWidth, imgHeight = Image.open(
os.path.join( path, dirs[0] )
).crop((left, top, right + left, bottom + top)).size
print( "Image size: " + str(imgWidth) + ", " + str(imgHeight) )
#tileset related
columns = 24
rows = math.floor( len(dirs) / columns ) + 1
spacing = 5
tilesetWidth = ( imgWidth + spacing ) * columns
tilesetHeight = ( imgHeight + spacing ) * rows
tilesetWidth = round(tilesetWidth)
tilesetHeight = round(tilesetHeight)
imgTileset = Image.new('RGBA', (tilesetWidth, tilesetHeight))
def cropAllToTileset():
itemCount = 0
curCol = 0
curRow = 0
dom_tileset = ET.Element('tileset')
for item in dirs:
fullpath = os.path.join(path, item)
if os.path.isfile(fullpath):
im = Image.open(fullpath)
f, e = os.path.splitext(fullpath)
imCrop = im.crop((left, top, right + left, bottom + top))
imgTileset.paste( imCrop.copy(), ((imgWidth + spacing) * curCol, (imgHeight + spacing) * curRow) )
#construct dom
dom_tile = ET.SubElement(dom_tileset, 'tile')
dom_tile.set('id', str(itemCount))
dom_properties = ET.SubElement(dom_tile, 'properties')
dom_property = ET.SubElement(dom_properties, 'property')
dom_property.set('name', 'obj_name')
dom_property.set('value', os.path.basename(f))
itemCount += 1
# count correct rows for tileset
if (itemCount % columns) == 0:
curRow += 1
curCol = 0
else:
curCol += 1
if not os.path.exists(newpath + "\\tileset\\"):
os.makedirs(newpath + "\\tileset\\")
#write image
imgTileset.save( newpath + "\\tileset\\" + "tileset_" + str(imgWidth) + "x" + str(imgHeight) + ".png" , "png", quality=100 )
#write dom xml
mydata = '<root>' + str(ET.tostring(dom_tileset, encoding='utf-8', method='xml')) + '</root>'
myfile = open(newpath + "\\tileset\\" + "items2.xml", "w")
dom_final = xml.dom.minidom.parseString(mydata).toprettyxml()
myfile.write(dom_final)
print("Done")
# https://stackoverflow.com/questions/47785918/python-pil-crop-all-images-in-a-folder
def crop():
for item in dirs:
fullpath = os.path.join(path, item)
if os.path.isfile(fullpath):
im = Image.open(fullpath)
f, e = os.path.splitext(fullpath)
imCrop = im.crop((left, top, right + left, bottom + top))
if not os.path.exists(newpath):
os.makedirs(newpath)
imCrop.save( newpath + os.path.basename(f) + ".png", "png", quality=100 )
#crop()
cropAllToTileset()