Skip to content

Instantly share code, notes, and snippets.

@hastern
Last active May 15, 2021 13:49
Show Gist options
  • Save hastern/d981b9c545afbfdf715002b00d310d2c to your computer and use it in GitHub Desktop.
Save hastern/d981b9c545afbfdf715002b00d310d2c to your computer and use it in GitHub Desktop.
Quick and Dirty Renderer for TILED JSON maps
#!/usr/bin/env python
import argparse
import json
import pathlib
from PIL import Image
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="TILED map renderer")
parser.add_argument("map", type=pathlib.Path, action="append", default=[])
parser.add_argument("--size", type=int, nargs=2, metavar=("W", "H"))
args = parser.parse_args()
tiles = {}
for map_file in args.map:
if map_file.suffix != ".json":
continue
raw = map_file.read_text()
content = json.loads(raw)
for tileset in content["tilesets"]:
print(
f'Processing tileset: {tileset["name"]}: {tileset["tilecount"]} tiles from {tileset["image"]}. GID: {tileset["firstgid"]}'
)
gid = tileset["firstgid"]
w, h = tileset["tileheight"], tileset["tilewidth"]
width = tileset["columns"] * tileset["tilewidth"]
if width != tileset["imagewidth"]:
print("WARNING: Image width is doesn't properly fit all columns")
with Image.open(tileset["image"]).convert("RGBA") as img:
for y in range(0, tileset["imageheight"], h):
for x in range(0, width, w):
bbox = [x, y, x + w, y + h]
tiles[gid] = img.crop(bbox)
gid += 1
img_width = content["width"] * content["tilewidth"]
img_height = content["height"] * content["tileheight"]
print(f"Full output image will be {img_width}x{img_height}")
img_map = Image.new("RGBA", [img_width, img_height])
for layer in content["layers"]:
if not "data" in layer:
continue
print(f"Processing layer: {layer['name']}")
for idx, dat in enumerate(layer["data"]):
x = (idx % content["width"]) * content["tilewidth"]
y = (idx // content["width"]) * content["tileheight"]
if dat > 0:
if dat & 0xE000_0000:
tile = tiles[dat & 0x1FFF_FFFF]
if dat & 0x2000_0000: # X/Y Swap
tile = tile.transpose(Image.TRANSPOSE)
if dat & 0x8000_0000: # Horizontal Flip
tile = tile.transpose(Image.FLIP_LEFT_RIGHT)
if dat & 0x4000_0000: # Vertical Flip
tile = tile.transpose(Image.FLIP_TOP_BOTTOM)
else:
tile = tiles[dat]
img_map.alpha_composite(tile, dest=(x, y))
if args.size is not None and any((d > 0) for d in args.size):
w, h = args.size
if w < 0:
w = img_width // (img_height // h)
elif h < 0:
h = img_height // (img_width // w)
print(f"Resize image to {w}x{h}")
img_map = img_map.resize((w, h))
outfile = map_file.with_suffix(".png")
print(f"Saving result to {outfile}")
img_map.save(outfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment