Spaces:
Running on Zero
Running on Zero
File size: 4,995 Bytes
b411c37 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | from __future__ import annotations
import sys
import urllib.request
from pathlib import Path
from arabic_reshaper import reshape
from bidi.algorithm import get_display
from PIL import Image, ImageDraw, ImageFont
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
from ocr_studio.config import ARABIC_FONT_PATH, EXAMPLES_DIR, FONTS_DIR, LATIN_FONT_PATH
FONT_SOURCES = {
LATIN_FONT_PATH: (
"https://cdn.jsdelivr.net/gh/googlefonts/noto-fonts@main/hinted/ttf/NotoSans/NotoSans-Regular.ttf",
"https://github.com/notofonts/latin-greek-cyrillic/raw/main/fonts/NotoSans/hinted/ttf/NotoSans-Regular.ttf",
),
ARABIC_FONT_PATH: (
"https://cdn.jsdelivr.net/gh/googlefonts/noto-fonts@main/hinted/ttf/NotoNaskhArabic/NotoNaskhArabic-Regular.ttf",
"https://github.com/notofonts/notonaskharabic/raw/main/fonts/NotoNaskhArabic/hinted/ttf/NotoNaskhArabic-Regular.ttf",
),
}
def _download(path: Path, urls: tuple[str, ...]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
last_error: Exception | None = None
for url in urls:
try:
with urllib.request.urlopen(url, timeout=60) as response:
data = response.read()
if len(data) < 10_000:
continue
path.write_bytes(data)
return
except Exception as exc: # noqa: BLE001
last_error = exc
if last_error:
raise last_error
def _font(path: Path, size: int) -> ImageFont.FreeTypeFont | ImageFont.ImageFont:
if path.exists():
return ImageFont.truetype(str(path), size=size)
return ImageFont.load_default()
def _shape(text: str) -> str:
if any("\u0600" <= char <= "\u06ff" for char in text):
return get_display(reshape(text))
return text
def _render(path: Path, lines: list[list[tuple[str, Path, int]]], align: str = "left") -> None:
width, height = 1280, 760
image = Image.new("RGB", (width, height), "#f7f3ea")
draw = ImageDraw.Draw(image)
draw.rectangle((36, 36, width - 36, height - 36), outline="#1f4f4a", width=3)
y = 88
for segments in lines:
x = 80 if align == "left" else width - 80
if align == "right":
for text, font_path, size in reversed(segments):
font = _font(font_path, size)
shaped = _shape(text)
bbox = draw.textbbox((0, 0), shaped, font=font)
text_w = bbox[2] - bbox[0]
x -= text_w
draw.text((x, y), shaped, fill="#1c1915", font=font)
x -= 12
else:
for text, font_path, size in segments:
font = _font(font_path, size)
shaped = _shape(text)
draw.text((x, y), shaped, fill="#1c1915", font=font)
bbox = draw.textbbox((0, 0), shaped, font=font)
x += bbox[2] - bbox[0] + 10
y += max(size for _, _, size in segments) + 28
path.parent.mkdir(parents=True, exist_ok=True)
image.save(path, format="PNG")
def main() -> None:
FONTS_DIR.mkdir(parents=True, exist_ok=True)
EXAMPLES_DIR.mkdir(parents=True, exist_ok=True)
for destination, urls in FONT_SOURCES.items():
if destination.exists():
continue
try:
_download(destination, urls)
except Exception as exc: # noqa: BLE001
print(f"Font download skipped for {destination.name}: {exc}")
_render(
EXAMPLES_DIR / "english-print.png",
[
[("INVOICE 1048", LATIN_FONT_PATH, 42)],
[("Customer: Jane Walton", LATIN_FONT_PATH, 32)],
[("Amount due: 128.40 USD", LATIN_FONT_PATH, 32)],
[("Due date: 24 August 2026", LATIN_FONT_PATH, 32)],
],
)
_render(
EXAMPLES_DIR / "persian-print.png",
[
[("فاکتور ۱۰۴۸", ARABIC_FONT_PATH, 44)],
[("خریدار: سارا محمدی", ARABIC_FONT_PATH, 34)],
[("مبلغ قابل پرداخت: ۱۲۸۴۰۰۰ تومان", ARABIC_FONT_PATH, 34)],
[("تاریخ سررسید: ۳ شهریور ۱۴۰۵", ARABIC_FONT_PATH, 34)],
],
align="right",
)
_render(
EXAMPLES_DIR / "mixed-print.png",
[
[("BOARDING PASS / ", LATIN_FONT_PATH, 36), ("کارت پرواز", ARABIC_FONT_PATH, 36)],
[("Passenger / ", LATIN_FONT_PATH, 30), ("مسافر: ", ARABIC_FONT_PATH, 30), ("Ali Rezaei", LATIN_FONT_PATH, 30)],
[("Flight / ", LATIN_FONT_PATH, 30), ("پرواز: ", ARABIC_FONT_PATH, 30), ("W5 1084", LATIN_FONT_PATH, 30)],
[("Seat / ", LATIN_FONT_PATH, 30), ("صندلی: ", ARABIC_FONT_PATH, 30), ("14A", LATIN_FONT_PATH, 30)],
],
)
if __name__ == "__main__":
main()
|