File size: 1,392 Bytes
2edb151
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

import io
from pathlib import Path

from PIL import Image

from app.config import Settings

try:
    from pillow_heif import register_heif_opener

    register_heif_opener()
except ImportError:
    pass


def _load_heif() -> None:
    try:
        from pillow_heif import register_heif_opener

        register_heif_opener()
    except ImportError:
        return


def pdf_first_page_jpeg(path: Path, max_edge: int) -> bytes:
    import pypdfium2 as pdfium

    pdf = pdfium.PdfDocument(str(path))
    try:
        page = pdf[0]
        bitmap = page.render(scale=150 / 72)
        image = bitmap.to_pil().convert("RGB")
    finally:
        pdf.close()
    return _pil_to_jpeg(image, max_edge)


def _pil_to_jpeg(image: Image.Image, max_edge: int) -> bytes:
    rgb = image.convert("RGB")
    rgb.thumbnail((max_edge, max_edge), Image.Resampling.LANCZOS)
    buf = io.BytesIO()
    rgb.save(buf, format="JPEG", quality=85, optimize=True)
    return buf.getvalue()


def to_jpeg_bytes(path: Path, settings: Settings) -> bytes | None:
    suffix = path.suffix.lower()
    if suffix == ".txt":
        return None
    if suffix == ".pdf":
        return pdf_first_page_jpeg(path, settings.jpeg_max_edge)
    if suffix in {".heic", ".heif"}:
        _load_heif()
    with Image.open(path) as image:
        return _pil_to_jpeg(image, settings.jpeg_max_edge)