70 lines
2.6 KiB
Python
Executable file
70 lines
2.6 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
# 3rd-party sw: cjxl (libjxl)
|
|
|
|
import itertools
|
|
import subprocess
|
|
import sys
|
|
from pathlib import Path
|
|
from typing import Final
|
|
|
|
source_dir: Final = Path(sys.argv[1])
|
|
if len(sys.argv) > 2:
|
|
backup_dir: Final = Path(sys.argv[2])
|
|
|
|
|
|
def check_source_against_convert(source_dir: Path) -> None:
|
|
for jxl in source_dir.rglob('*.jxl'):
|
|
has_original = jxl.with_suffix('.jpg').exists() or jxl.with_suffix('.JPG').exists()
|
|
if not has_original:
|
|
print(f'Source image for {jxl} has been lost')
|
|
|
|
|
|
def check_source_against_backup(source_dir: Path, backup_dir: Path) -> None:
|
|
pics_src = { p.relative_to(source_dir) for p in source_dir.rglob('*.JPG') }
|
|
pics_src |= { p.relative_to(source_dir) for p in source_dir.rglob('*.jpg') }
|
|
|
|
pics_bak = { p.relative_to(backup_dir) for p in backup_dir.rglob('*.JPG') }
|
|
pics_bak |= { p.relative_to(backup_dir) for p in backup_dir.rglob('*.jpg') }
|
|
|
|
diff = pics_src - pics_bak
|
|
if diff:
|
|
print('Source contains the following additional images:\n', '\n'.join(map(str, diff)))
|
|
diff = pics_bak - pics_src
|
|
if diff:
|
|
print('Backup contains the following additional images:\n', '\n'.join(map(str, diff)))
|
|
|
|
|
|
def check_successful_conversion(source_dir: Path) -> None:
|
|
pics_src = itertools.chain(source_dir.rglob('*.jpg'), source_dir.rglob('*.JPG'))
|
|
|
|
for jpg in pics_src:
|
|
jxl = jpg.with_suffix('.jxl')
|
|
if not jxl.exists():
|
|
print(f'Converted counterpart for {jpg} does not exist')
|
|
|
|
|
|
def convert(source_dir: Path) -> None:
|
|
pics_src_it = itertools.chain(source_dir.rglob('*.jpg'), source_dir.rglob('*.JPG'))
|
|
# set offset to start from image #offset (e.g. in case of a previous error)
|
|
# e.g. offset = 5 will start with converting 5th image
|
|
offset = 0
|
|
pics_src = list(sorted(pics_src_it))[offset:]
|
|
for i, jpg in enumerate(pics_src):
|
|
jxl = jpg.with_suffix('.jxl')
|
|
cmd = ['cjxl', '-v', '--lossless_jpeg=1', '--effort=9', '--brotli_effort=11', jpg, jxl]
|
|
try:
|
|
subprocess.run(cmd, check=True, capture_output=True, encoding='utf-8') # type: ignore[arg-type]
|
|
except subprocess.CalledProcessError as ex:
|
|
print(f'ERR processing file #{i + offset} {jpg}: {ex}')
|
|
print(f'cjxl says: {ex.stderr}\n{ex.stdout}')
|
|
sys.exit(ex.returncode)
|
|
except Exception as ex:
|
|
print(f'ERR unexpected: {ex}')
|
|
sys.exit(1)
|
|
print(f'Converted #{i + offset} {jpg}')
|
|
|
|
# check_source_against_convert(source_dir)
|
|
# check_source_against_backup(source_dir, second_dir)
|
|
convert(source_dir)
|
|
# check_successful_conversion(source_dir)
|