Skip to content

Commit 8cf5a3d

Browse files
committed
Add override engine
1 parent 24e7911 commit 8cf5a3d

5 files changed

+86
-10
lines changed

add_panel_override.py

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
#!/usr/bin/env python3
2+
import hashlib
3+
import json
4+
from pathlib import Path
5+
6+
import typer
7+
from PIL import Image
8+
9+
app = typer.Typer()
10+
11+
12+
def add_panel_override(image_path: Path, panel_no: list[int]) -> None:
13+
overrides = json.load(open('parse_qwantz/data/panel_overrides.json'))
14+
md5 = hashlib.md5(Image.open(image_path).tobytes()).hexdigest()
15+
if md5 not in overrides:
16+
comic_id, file_name = image_path.name.split(' - ')
17+
overrides[md5] = {"comic_id": int(comic_id), "file_name": file_name, "panels": {}}
18+
for n in panel_no:
19+
overrides[md5]["panels"][n] = ["", ""]
20+
json.dump(overrides, open('parse_qwantz/data/panel_overrides.json', 'w'), indent=2, ensure_ascii=False)
21+
22+
23+
if __name__ == '__main__':
24+
typer.run(add_panel_override)

parse_qwantz/main.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hashlib
12
import logging
23
import sys
34
from dataclasses import dataclass
@@ -11,6 +12,7 @@
1112
from parse_qwantz.color_logs import set_logging_formatter, ColorFormatter
1213
from parse_qwantz.colors import Color
1314
from parse_qwantz.lines import Line
15+
from parse_qwantz.panel_overrides import get_panel_overrides
1416
from parse_qwantz.text_blocks import get_text_blocks, TextBlock
1517
from parse_qwantz.elements import get_elements
1618
from parse_qwantz.match_blocks import match_blocks
@@ -74,8 +76,16 @@ def __bool__(self):
7476

7577

7678
def parse_qwantz(image: Image, debug: bool, log_to_file: bool) -> Iterable[list[str]]:
77-
masked = prepare_image(image)
79+
md5 = hashlib.md5(image.tobytes()).hexdigest()
80+
panel_overrides = get_panel_overrides().get(md5, {})
81+
masked, good_panels = prepare_image(image)
7882
for i, (panel, characters) in enumerate(zip(PANELS, CHARACTERS), start=1):
83+
if str(i) in panel_overrides:
84+
yield panel_overrides[str(i)]
85+
continue
86+
if i not in good_panels:
87+
logger.warning("Non-standard panel without an override")
88+
continue
7989
set_current_panel(i, log_to_file)
8090
(width, height), (x, y) = panel
8191
cropped = masked.crop((x, y, x + width, y + height))

parse_qwantz/panel_overrides.py

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import json
2+
from dataclasses import dataclass
3+
from functools import cache
4+
from importlib.resources import files, as_file
5+
6+
import parse_qwantz
7+
8+
OVERRIDE_FILE_PATH = files(parse_qwantz).joinpath('data/panel_overrides.json')
9+
10+
11+
@cache
12+
def get_panel_overrides() -> dict[str, dict[int, list[str]]]:
13+
with as_file(OVERRIDE_FILE_PATH) as override_path:
14+
return {
15+
key: value["panels"]
16+
for key, value in json.load(open(override_path)).items()
17+
}

parse_qwantz/prepare_image.py

+15-9
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616

1717
SAMPLE = [
1818
((113, 183), (128, 255, 64)),
19+
((290, 160), (255, 128, 161)),
1920
((704, 183), (255, 242, 179)),
21+
((143, 375), (255, 191, 82)),
2022
((452, 405), (255, 191, 82)),
21-
((290, 160), (255, 128, 161)),
22-
((372, 484), (0, 0, 0)),
23+
((585, 386), (69, 196, 5)),
2324
]
2425

2526

@@ -28,22 +29,27 @@ class ImageError(Exception):
2829

2930

3031
@cache
31-
def get_mask_image():
32+
def get_mask_image() -> Image:
3233
with as_file(MASK_FILE_PATH) as image_path:
3334
return Image.open(image_path)
3435

3536

36-
def prepare_image(image: Image):
37+
def prepare_image(image: Image) -> tuple[Image, list[int]]:
3738
if image.size != DIM:
3839
logger.error(f"Wrong image dimensions: {image.size}, only {DIM} is valid")
3940
raise ImageError(f"Wrong image dimensions: {image.size}, only {DIM} is valid")
4041
palette = image.getpalette()
4142
palette = tuple(palette) if palette else None
42-
for pixel, expected_color in SAMPLE:
43+
good_panels: list[int] = []
44+
for panel_no, (pixel, expected_color) in enumerate(SAMPLE, start=1):
4345
color = image.getpixel(pixel)
4446
color = normalize_color(color, palette)
45-
if square_distance(color, expected_color) > COLOR_THRESHOLD:
46-
logger.error(f"Invalid template: expected {expected_color} at {pixel}; found {color}")
47-
raise ImageError(f"Invalid template: expected {expected_color} at {pixel}; found {color}")
47+
if square_distance(color, expected_color) <= COLOR_THRESHOLD:
48+
good_panels.append(panel_no)
49+
else:
50+
logger.warning(f"Invalid template: expected {expected_color} at {pixel}; found {color}")
51+
if not good_panels:
52+
logger.error("Invalid template")
53+
raise ImageError(f"Invalid template")
4854
all_white = Image.new(mode='RGB', size=DIM, color=(255, 255, 255))
49-
return Image.composite(image, all_white, get_mask_image())
55+
return Image.composite(image, all_white, get_mask_image()), good_panels

sort_panel_overrides.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/usr/bin/env python3
2+
import hashlib
3+
import json
4+
from pathlib import Path
5+
6+
import typer
7+
from PIL import Image
8+
9+
app = typer.Typer()
10+
11+
12+
def sort_panel_overrides() -> None:
13+
overrides = json.load(open('parse_qwantz/data/panel_overrides.json'))
14+
sorted_overrides = {key: value for key, value in sorted(overrides.items(), key=lambda r: r[1]["comic_id"])}
15+
json.dump(sorted_overrides, open('parse_qwantz/data/panel_overrides.json', 'w'), indent=2, ensure_ascii=False)
16+
17+
18+
if __name__ == '__main__':
19+
typer.run(sort_panel_overrides)

0 commit comments

Comments
 (0)