diff --git a/core/engine.py b/core/engine.py index 78a7e31..75ae3b6 100644 --- a/core/engine.py +++ b/core/engine.py @@ -58,8 +58,11 @@ class PDFEngine: @staticmethod def compress_pdfa(data: bytes, quality: int = 60) -> bytes: - """Comprime mantendo a estrutura PDF/A.""" - return compress_pdfa(data, quality=quality) + """Comprime mantendo a estrutura PDF/A (protegido contra inflação).""" + result = compress_pdfa(data, quality=quality) + if len(result) >= len(data): + return data + return result @staticmethod def detect_pdfa(data: bytes) -> dict: diff --git a/core/pdfa.py b/core/pdfa.py index 64a5a6d..f3bea32 100644 --- a/core/pdfa.py +++ b/core/pdfa.py @@ -139,14 +139,18 @@ def strip_pdfa(data: bytes) -> bytes: def compress_pdfa(data: bytes, quality: int = 60, max_dim: int = 2000) -> bytes: """ Comprime imagens internas mantendo a estrutura PDF/A. - Usa a mesma lógica de compress_pdf (ImageFile.replace) - mas preserva metadados XMP e OutputIntents. + Usa a atualização incremental (incremental=True) para garantir + que a assinatura estrutural, /ID do trailer, XMP Metadata e + /OutputIntents originais permaneçam 100% intactos e conformes. """ from PIL import Image as PILImage from .compress import _prepare_image - reader = PdfReader(io.BytesIO(data)) - writer = PdfWriter(clone_from=reader) + # A grande sacada: em vez de usar PdfWriter(clone_from=reader) + # que reconstrói a árvore inteira do zero perdendo a conformidade, + # instanciamos um writer que atua sobre um stream aberto no modo incremental. + stream = io.BytesIO(data) + writer = PdfWriter(stream, incremental=True) replaced = 0 for page in writer.pages: