#!/usr/bin/env python from __future__ import print_function from PIL import Image import re, sys, json, os try: from urllib import quote as urlquote # Python 2.X except ImportError: from urllib.parse import quote as urlquote # Python 3+ def fitbox (boxw, boxh, w, h): rw = boxw rh = int(rw * (float(h) / w)) if (rh >= boxh): rh = boxh rw = int(rh * (float(w) / h)) return rw, rh def tile_image (im, maxz=0, tilew=256, tileh=256, base=".", template="z{0[z]}y{0[y]}x{0[x]}.jpg", bgcolor=(0,0,0), margin_right=0, margin_bottom=0): z = 0 boxw, boxh = tilew, tileh alpha = bgcolor != None # not template.endswith("jpg") while True: rw, rh = fitbox(boxw, boxh, im.size[0], im.size[1]) rim = im.resize((rw-margin_right, rh-margin_bottom), Image.ANTIALIAS) if bgcolor: tim = Image.new("RGB", (boxw, boxh), bgcolor) tim.paste(rim, (0, 0)) else: tim = Image.new("RGBA", (boxw, boxh)) tim.paste(rim, (0, 0)) rows, cols = 2**z, 2**z for r in range(rows): for c in range(cols): ix = c*tilew iy = r*tileh cim = tim.crop((ix, iy, ix+tilew, iy+tileh)) op = base + template.format({'z':z, 'x':c, 'y':r}) # if not alpha: # cim = cim.convert("RGB") cim.save(op) z += 1 if z>maxz: break boxw *= 2 boxh *= 2 def expand_template (x): return re.sub(r"{(\w+?)}", "{0[\\1]}", x) if __name__ == "__main__": from argparse import ArgumentParser ap = ArgumentParser("Generate image tiles and output JSON for a collection of images") ap.add_argument("input", nargs="+") ap.add_argument("--basepath", default=".") ap.add_argument("--baseuri", default="") ap.add_argument("--tilespath", default="tiles", help="name of path to create in the same folder as the original") ap.add_argument("--tilewidth", type=int, default=256) ap.add_argument("--tileheight", type=int, default=256) ap.add_argument("--zoom", type=int, default=3) ap.add_argument("--tilename", default="z{z}y{y}x{x}.png") ap.add_argument("--force", default=False, action="store_true") args = ap.parse_args() """ leafygal format: {id: original, tiles: "template", name: filename} """ tilenamex = expand_template(args.tilename) #bgcolor = (0, 0, 0) bgcolor = None items = [] for imgpath in args.input: parent = os.path.split(imgpath)[0] basename = os.path.basename(imgpath) path = os.path.join(parent, args.tilespath, basename) item = { 'id': urlquote(imgpath), 'name': basename, 'tiles': os.path.join(path, args.tilename) } tile0 = os.path.join(path, tilenamex.format({'x': 0, 'y': 0, 'z': 0})) items.append(item) if not os.path.exists(tile0) or args.force: print ("Tiling {0}".format(imgpath), file=sys.stderr) try: im = Image.open(imgpath) try: os.makedirs(path) except OSError: pass tile_image(im, args.zoom, args.tilewidth, args.tileheight, path+"/", tilenamex, bgcolor) # tiles.append(t) except IOError as e: print ("Missing {0}, skipping".format(n), file=sys.stderr) items = items[:-1] data = { '@context': { 'id': '@id', 'aa': 'http://activearchives.org/terms', 'name': 'aa:filename', 'tiles': 'aa:tiles' }, '@graph': items } print (json.dumps(data, indent=2))