Spaces:
Sleeping
Sleeping
Download app/services/image_processing/documents.py from Zeyadmohamed21/OCR: direct link, hf CLI and curl.
- Browser
- Download file 3.68 kB
-
https://huggingface.co/spaces/Zeyadmohamed21/OCR/resolve/main/app/services/image_processing/documents.py
- Command line
-
hf download hf://spaces/Zeyadmohamed21/OCR/app/services/image_processing/documents.py
-
curl -L -o documents.py https://huggingface.co/spaces/Zeyadmohamed21/OCR/resolve/main/app/services/image_processing/documents.py
3.68 kB
| """Sequential bounded PDF/TIFF/image page decoding. No external OCR service.""" | |
| import io | |
| import math | |
| import threading | |
| import warnings | |
| from PIL import Image, UnidentifiedImageError | |
| from app.core.config import settings | |
| from app.core.exceptions import InvalidImageError, PayloadTooLargeError, ConfigurationError | |
| from app.services.image_processing.loader import pil_to_bgr, check_dimensions | |
| # PDFium is not thread safe, including calls on different documents. | |
| _pdf_lock = threading.Lock() | |
| MAX_DOCUMENT_PIXELS = 100_000_000 | |
| MAX_PDF_PAGE_PIXELS = 12_000_000 | |
| def _check_pages(count): | |
| if count < 1: | |
| raise InvalidImageError("Document has no pages.") | |
| if count > settings.DOCUMENT_MAX_PAGES: | |
| raise PayloadTooLargeError(f"Document exceeds {settings.DOCUMENT_MAX_PAGES} page limit.") | |
| def document_pages(contents, mime): | |
| if mime == "application/pdf": | |
| yield from _pdf_pages(contents) | |
| return | |
| try: | |
| with warnings.catch_warnings(): | |
| warnings.simplefilter("error", Image.DecompressionBombWarning) | |
| with Image.open(io.BytesIO(contents)) as document: | |
| count = getattr(document, "n_frames", 1) | |
| _check_pages(count) | |
| pixels = 0 | |
| for index in range(count): | |
| document.seek(index) | |
| check_dimensions(*document.size) | |
| pixels += document.width * document.height | |
| if pixels > MAX_DOCUMENT_PIXELS: | |
| raise PayloadTooLargeError("Document exceeds total pixel limit.") | |
| yield pil_to_bgr(document) | |
| except (Image.DecompressionBombWarning, Image.DecompressionBombError, UnidentifiedImageError, OSError, ValueError) as exc: | |
| raise InvalidImageError("Image document is corrupted or exceeds safe decoding limits.") from exc | |
| def _pdf_pages(contents): | |
| try: | |
| import pypdfium2 as pdfium | |
| except ImportError as exc: | |
| raise ConfigurationError("PDF support requires pypdfium2; install project requirements.") from exc | |
| with _pdf_lock: | |
| try: | |
| with pdfium.PdfDocument(contents) as document: | |
| _check_pages(len(document)) | |
| total_pixels = 0 | |
| for index in range(len(document)): | |
| page = document[index] | |
| try: | |
| width, height = page.get_size() | |
| if not all(math.isfinite(n) and n > 0 for n in (width, height)): | |
| raise InvalidImageError("PDF has invalid page dimensions.") | |
| scale = min(settings.DOCUMENT_DPI / 72, settings.OCR_CANVAS_SIZE / max(width, height), | |
| math.sqrt(MAX_PDF_PAGE_PIXELS / (width * height))) | |
| total_pixels += math.ceil(width * scale) * math.ceil(height * scale) | |
| if total_pixels > MAX_DOCUMENT_PIXELS: | |
| raise PayloadTooLargeError("PDF exceeds total rendered pixel limit.") | |
| bitmap = page.render(scale=scale) | |
| try: | |
| pil_image = bitmap.to_pil() | |
| try: | |
| image = pil_to_bgr(pil_image) | |
| finally: | |
| pil_image.close() | |
| finally: | |
| bitmap.close() | |
| finally: | |
| page.close() | |
| yield image | |
| except pdfium.PdfiumError as exc: | |
| raise InvalidImageError("PDF is corrupted, encrypted or cannot be rendered.") from exc | |