rewrite jxl-restore -> jxl-convert
Signed-off-by: Martin Matous <m@matous.dev>
This commit is contained in:
parent
acd336e659
commit
70b69e1f8c
3 changed files with 75 additions and 46 deletions
13
README.md
13
README.md
|
|
@ -90,17 +90,14 @@ Dependencies: openssl
|
|||
Usage: ???
|
||||
|
||||
|
||||
## jxl-restore.py
|
||||
Check whether JPEG version of .jxl exists, remove .jxl if does.
|
||||
Attempt at rescuing collection where conversion got messed up.
|
||||
## jxl-convert.py
|
||||
Recursively convert jpgs to jxls with additional checks.
|
||||
|
||||
Will fix one day. Maybe.
|
||||
Status: one-off
|
||||
|
||||
Status: ancient one-off, broken
|
||||
Dependencies: libjxl
|
||||
|
||||
Dependencies: None
|
||||
|
||||
Usage: None
|
||||
Usage: `./jxl-convert.py /path/to/pics`
|
||||
|
||||
|
||||
## invoke-magic.bat
|
||||
|
|
|
|||
70
jxl-convert.py
Executable file
70
jxl-convert.py
Executable file
|
|
@ -0,0 +1,70 @@
|
|||
#!/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)
|
||||
|
|
@ -1,38 +0,0 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import Final
|
||||
|
||||
source: Final = Path(sys.argv[1])
|
||||
dest: Final = Path(sys.argv[2])
|
||||
|
||||
def find_source_jpg(dest_name: Path) -> Path:
|
||||
ext_list = ['.jpg', '.jpeg', '.JPG', '.JPEG']
|
||||
for ext in ext_list:
|
||||
res = (Path(source) / relative_path / (dest_name + ext))
|
||||
if os.path.exists(dest_file_path):
|
||||
return res
|
||||
raise RuntimeError('No original found', dest_name)
|
||||
|
||||
for dest_root, dirs, files in os.walk(dest):
|
||||
for name in files:
|
||||
dest_name, dest_ext = os.path.splitext(name)
|
||||
if dest_ext.lower() != '.jxl':
|
||||
continue
|
||||
dest_file_path = (Path(dest_root) / (dest_name + '.jpg'))
|
||||
print('scanning for ', dest_file_path, '\n')
|
||||
if os.path.exists(dest_file_path): # both .jxl and jpg exist
|
||||
print(dest_file_path, ' already exists\n')
|
||||
continue
|
||||
relative_path = os.path.relpath(dest_root, dest)
|
||||
print('relapath ', relative_path, '\n')
|
||||
src_file_path = find_source_jpg(dest_name)
|
||||
shutil.copy2(src_file_path, dest_file_path)
|
||||
print('restored ', dest_file_path, ' from ', src_file_path, '\n')
|
||||
#dest_jxl = (Path(dest_root) / (dest_name + '.jxl'))
|
||||
#os.remove(dest_jxl)
|
||||
#print('deleted ', dest_jxl, '\n')
|
||||
Loading…
Add table
Add a link
Reference in a new issue