File size: 2,105 Bytes
8839278
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from __future__ import annotations

import base64
import io
from pathlib import Path

import fitz
from PIL import Image, ImageOps

from backend.config import MAX_PDF_PAGES, PDF_RENDER_SCALE


def document_info(path: str) -> tuple[str, int]:
    suffix = Path(path).suffix.lower()
    try:
        with Path(path).open("rb") as file:
            header = file.read(5)
    except OSError as error:
        raise ValueError("The uploaded document could not be read.") from error

    if suffix == ".pdf" or header == b"%PDF-":
        with fitz.open(path) as document:
            total_pages = document.page_count
        if total_pages < 1:
            raise ValueError("The uploaded PDF has no pages.")
        if total_pages > MAX_PDF_PAGES:
            raise ValueError(
                f"This demo accepts up to {MAX_PDF_PAGES} PDF pages; received {total_pages}."
            )
        return "pdf", total_pages

    try:
        with Image.open(path) as source:
            source.verify()
    except Exception as error:
        raise ValueError("Please upload a valid PNG, JPEG, WebP, or PDF file.") from error
    return "image", 1


def load_document_page(path: str, document_type: str, page_index: int) -> Image.Image:
    if document_type == "pdf":
        with fitz.open(path) as document:
            page = document.load_page(page_index)
            pixmap = page.get_pixmap(
                matrix=fitz.Matrix(PDF_RENDER_SCALE, PDF_RENDER_SCALE),
                colorspace=fitz.csRGB,
                alpha=False,
            )
        return Image.frombytes("RGB", (pixmap.width, pixmap.height), pixmap.samples)

    with Image.open(path) as source:
        return ImageOps.exif_transpose(source).convert("RGB")


def page_preview_data_uri(page_image: Image.Image) -> str:
    preview = page_image.copy().convert("RGB")
    preview.thumbnail((1400, 1800), Image.Resampling.BILINEAR)
    buffer = io.BytesIO()
    preview.save(buffer, format="JPEG", quality=82, optimize=False)
    payload = base64.b64encode(buffer.getvalue()).decode("ascii")
    return f"data:image/jpeg;base64,{payload}"