diff options
Diffstat (limited to 'build.py')
-rwxr-xr-x | build.py | 231 |
1 files changed, 0 insertions, 231 deletions
diff --git a/build.py b/build.py deleted file mode 100755 index 9dccb8e..0000000 --- a/build.py +++ /dev/null @@ -1,231 +0,0 @@ -#!/usr/bin/env python3 -import jinja2 -import PIL.Image -import PIL.ImageOps -import argparse -import json -import yaml -import os -import re -import hashlib -import glob -from datetime import datetime - -imagereg = re.compile("([a-z0-9]*)\\..*") -thumbsize = 480 - - -def hashfile(fname): - md5 = hashlib.md5() - print(fname) - with open(fname, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - md5.update(chunk) - - return md5 - - -def parse_res(res): - return int(res) - - -class FileLoader(jinja2.BaseLoader): - def get_source(self, environment, template): - if not os.path.exists(template): - raise jinja2.TemplateNotFound(template) - mtime = os.path.getmtime(template) - with open(template, "r") as f: - source = f.read() - return source, template, lambda: mtime == os.path.getmtime(template) - - -class ImageLocation: - def __init__(self, folder, extension): - self.folder = folder - self.stuff = {} - self.ext = extension - - self.unused = set() - self.existing = {} - - if not os.path.isdir(folder): - os.mkdir(folder) - - self.look() - - self.tmpname = os.path.join(folder, "tmp") - - def look(self): - for name in os.listdir(self.folder): - m = imagereg.match(name) - if m is not None: - fhash = m.group(1) - - self.unused.add(fhash) - self.existing[fhash] = name - - def convert(self, imgname, resolution): - # First determine the hash from settings - thash = hashlib.md5( - bytes( - f"{resolution}+{self.ext}" + imgname, - encoding="utf8") - ).hexdigest() - - # Now check if it exists - if thash in self.existing: - print(f"Skipping file {imgname}[{thash}]") - return self.existing[thash], thash - - # Okay convert it - fname = f"{thash}.{self.ext}" - print(f"Converting file {imgname} to {fname}") - - tmpname = f"{self.tmpname}.{self.ext}" - with PIL.Image.open(imgname) as im: - target_height = resolution - im = PIL.ImageOps.exif_transpose(im) - if im.size[0] > target_height: - res = (int((im.size[0] / im.size[1]) * target_height), target_height) - im = im.resize(res, PIL.Image.ANTIALIAS) - - im.save(tmpname) - - os.rename(tmpname, os.path.join(self.folder, fname)) - - self.existing[thash] = fname - self.unused.add(thash) - - return fname, thash - - def fetch(self, imgname, resolution, relto=None): - # Check if we already have it - fname, hash = self.convert(imgname, resolution) - - # Mark the hash as used - self.unused.remove(hash) - - if relto is not None: - full = os.path.join(self.folder, fname) - return os.path.relpath(full, start=relto) - - return fname - - def clean(self): - print("Running cleanup") - for uhash in self.unused: - fname = os.path.join(self.folder, self.existing[uhash]) - print(f"Removing file {fname}") - os.remove(fname) - - -class Image: - def __init__(self, filename): - self.name = os.path.basename(filename) - self.filename = filename - self.description = "" - self.url = "" - self.thumburl = "" - self.fullurl = "" - self.file = filename - - self.taken = None - self.load_metadata() - - def load_metadata(self): - try: - with PIL.Image.open(self.filename) as im: - taken_str = im.getexif()[36867] - except KeyError: - print(f"Could not load date from image {self.filename}") - return - - self.taken = datetime.strptime(taken_str, "%Y:%m:%d %H:%M:%S") - - -def value_or_default(val, default=None): - if val is None: - return default - return val - - -class Loader: - def __init__(self, config_file, loadpath): - self.config = Loader.__load_config(config_file) - - self.loadpath = loadpath - - self.images = [] - - def __load_config(config_file): - config = {} - with open(config_file, "r") as f: - config = yaml.safe_load(f) - - print(f"Loaded config: {config}") - return config - - def load(self, imagehook=None, clear=False): - # Clear if neccesary - if clear: - self.images = [] - - # First find all images from glob - for image in glob.iglob(os.path.join(self.loadpath, self.config["imageglob"])): - img = Image(image) - img.description = self.config["info"].get(img.name, "") - - if imagehook is not None: - img = imagehook(img) - - self.images.append(img) - - self.images = sorted(self.images, - key=lambda img: value_or_default(img.taken, - datetime.min), - reverse=True) - - def to_json(self): - jsonable = [img.__dict__ for img in self.images] - return json.dumps(jsonable) - - -parser = argparse.ArgumentParser() -parser.add_argument("--dest", "-d", default="dist", help="where to put resulting files") -parser.add_argument("--size", "-s", type=int, default="1080", help="size to scale web images to") -parser.add_argument("--commit", "-g", help="git commit hash to announce") -parser.add_argument("--clean", help="clean unused image files", action="store_true") -parser.add_argument("--config", "-c", default=None, help="where to load image definitions from") -parser.add_argument("--template", "-t", default="index.html.j2", help="html template to use") -parser.add_argument("--cgit", "-w", help="cgit repo base url") -parser.add_argument("load", help="where to load full size images from") -parser.add_argument("--ext", "-e", default="png", help="image extension to use") - -args = parser.parse_args() - -if args.config is None: - args.config = os.path.join(args.load, "imginfo.yml") - -context = { - "cgit": args.cgit, - "git": args.commit - } - -loader = Loader(args.config, args.load) -loc = ImageLocation(os.path.join(args.dest, "imgs"), args.ext) - - -def imgload(img): - if context["cgit"] is not None: - img.fullurl = os.path.join(context["cgit"], "plain", img.name) - - img.url = loc.fetch(img.file, args.size, relto=args.dest) - img.thumburl = loc.fetch(img.file, thumbsize, relto=args.dest) - - return img - - -loader.load(imgload, clear=True) - -with open(os.path.join(args.dest, "imgs", "index.json"), "w") as f: - f.write(loader.to_json()) |