reddit-image-wall-getter/reddit_imgs/_thumbnailize.py

119 lines
5.1 KiB
Python

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
import json
from pathlib import Path
import PIL
import PIL.Image
import PIL.ImageOps
import subprocess
import filetype
import hashlib
import uuid
def main():
pass
def thumbnailize(target_file: Path):
thumbs_dict = dict()
target = target_file.parent
target_hashfile = target.joinpath(target_file.name+'.sha256')
target_meta = target.joinpath('_meta.json')
meta = json.loads(target_meta.read_text())
ext = meta['ext']
thumb_sizes = [4, 8, 16, 24, 32, 48, 64, 72, 96, 128]
thumbs_dir = target.joinpath('thumbs')
thumbs_dir.mkdir(parents=True, exist_ok=True)
thumbs_dict['sizes'] = thumb_sizes
thumbs_dict['full'] = target_hashfile.read_text()
thumbs_dict['thumbs'] = None
for size in thumb_sizes:
thumb_file = thumbs_dir.joinpath(f"thumb_{size}.png",)
thumb_hashfile = thumbs_dir.joinpath(f"thumb_{size}.png.md5",)
if not thumb_file.exists():
gen_thumb(ext, target_file, thumb_file, size)
if thumb_file.exists():
if thumbs_dict['thumbs'] is None:
thumbs_dict['thumbs'] = dict()
thumbs_dict['thumbs'][f'{size}'] = dict()
if not thumb_hashfile.exists():
m = hashlib.md5()
m.update(thumb_file.read_bytes())
thumb_hashfile.write_text(m.hexdigest())
thumbs_dict['thumbs'][f'{size}']['rectangular'] = thumb_hashfile.read_text()
thumbs_dict['thumb'] = thumb_hashfile.read_text()
for size in thumb_sizes:
thumb_file = thumbs_dir.joinpath(f"thumb_{size}.png",)
if thumb_file.exists():
thumb_square_file = thumbs_dir.joinpath(f"thumb_square_{size}.png",)
thumb_square_hashfile = thumbs_dir.joinpath(f"thumb_square_{size}.png.md5",)
image = None
if not thumb_square_file.exists():
square = PIL.Image.new('RGB', (size, size), (0, 0, 0))
image = PIL.Image.open(thumb_file)
img_w, img_h = image.size
offset = ((size - img_w) // 2, (size - img_h) // 2)
square.paste(image, offset)
del img_h
del img_w
del image
del offset
square.save(thumb_square_file, 'png')
image = square
del square
if not thumb_square_hashfile.exists():
m = hashlib.md5()
m.update(thumb_square_file.read_bytes())
thumb_square_hashfile.write_text(m.hexdigest())
thumbs_dict['thumbs'][f'{size}']['square'] = dict()
thumbs_dict['thumbs'][f'{size}']['square']['original'] = thumb_square_hashfile.read_text()
thumbs_dict['thumbs'][f'{size}']['square']['posterized'] = dict()
for pl in range(1,9):
thumb_square_file_posterized = thumbs_dir.joinpath(f"thumb_square_{size}_posterized_{pl}.png",)
thumb_square_hashfile_posterized = thumbs_dir.joinpath(f"thumb_square_{size}_posterized_{pl}.png.md5",)
if not thumb_square_file_posterized.exists():
if image is None:
image = PIL.Image.open(thumb_square_file)
posterized = PIL.ImageOps.posterize(image, pl)
posterized.save(thumb_square_file_posterized, 'png')
del posterized
if not thumb_square_hashfile_posterized.exists():
m = hashlib.md5()
m.update(thumb_square_file_posterized.read_bytes())
thumb_square_hashfile_posterized.write_text(m.hexdigest())
thumbs_dict['thumbs'][f'{size}']['square']['posterized'][f'{pl}'] = thumb_square_hashfile_posterized.read_text()
del image
return thumbs_dict
def gen_thumb(ext, target_file, thumb_file, size):
if ext!='unk':
actualext = 'unk'
with target_file.open('rb') as f:
actualext = filetype.guess_extension(f)
actualext = actualext if actualext else 'unk'
if actualext!='unk':
r = subprocess.run(
['ffmpegthumbnailer', '-i', str(target_file), '-o', '-', '-c', 'png', '-q', '10', '-s', str(size)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
if r.returncode and actualext in ('jpg', 'png', 'gif'):
tmpfile = Path('/tmp').joinpath(f'{uuid.uuid4().hex}.png')
r = subprocess.run(
['gdk-pixbuf-thumbnailer', '-s', str(size), str(target_file), str(tmpfile)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
r.check_returncode()
r = subprocess.run(
['cat', str(tmpfile)],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
tmpfile.unlink()
else:
r.check_returncode()
thumb_file.write_bytes(r.stdout)
if __name__ == "__main__":
main()