"""Small-thumbnail quality heuristics. Never delete or modify source photos.""" import hashlib from io import BytesIO from PIL import Image, ImageFilter, ImageOps, ImageStat def photo_quality(data): with Image.open(BytesIO(data)) as source: image = ImageOps.exif_transpose(source).convert("L") image.thumbnail((256, 256)) brightness = ImageStat.Stat(image).mean[0] edges = image.filter(ImageFilter.FIND_EDGES) sharpness = ImageStat.Stat( edges.crop((2, 2, max(3, image.width - 2), max(3, image.height - 2))) ).var[0] small = image.resize((9, 8)) pixels = list(small.tobytes()) bits = "".join( "1" if pixels[y * 9 + x] > pixels[y * 9 + x + 1] else "0" for y in range(8) for x in range(8) ) return { "brightness": round(brightness, 2), "sharpness": round(sharpness, 2), "fingerprint": f"{int(bits, 2):016x}", "sha256": hashlib.sha256(data).hexdigest(), } def passes(result, source): return ( result["sharpness"] >= source.minimum_sharpness and source.minimum_brightness <= result["brightness"] <= source.maximum_brightness )