#!/usr/bin/env python3 import argparse import json import subprocess import sys def analyze_pillow(path, compare=None): from PIL import Image, ImageChops, ImageStat img = Image.open(path).convert("RGB") stat = ImageStat.Stat(img) result = { "ok": True, "path": path, "width": img.width, "height": img.height, "mean_rgb": stat.mean, "extrema": stat.extrema, } if compare: other = Image.open(compare).convert("RGB") diff = ImageChops.difference(img, other) dstat = ImageStat.Stat(diff) result["compare"] = compare result["diff_mean_rgb"] = dstat.mean result["diff_extrema"] = dstat.extrema return result def analyze_magick(path): result = subprocess.run( ["magick", "identify", "-format", "%w %h %[fx:mean]", path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, ) if result.returncode != 0: return {"ok": False, "path": path, "error": result.stderr.strip()} parts = result.stdout.strip().split() return { "ok": True, "path": path, "width": int(parts[0]), "height": int(parts[1]), "mean": float(parts[2]), } def main(): parser = argparse.ArgumentParser() parser.add_argument("image") parser.add_argument("--compare") parser.add_argument("--json", dest="json_path") args = parser.parse_args() try: result = analyze_pillow(args.image, args.compare) except Exception: result = analyze_magick(args.image) data = json.dumps(result, sort_keys=True) if args.json_path: with open(args.json_path, "w", encoding="utf-8") as f: f.write(data + "\n") else: print(data) return 0 if result.get("ok") else 1 if __name__ == "__main__": sys.exit(main())