File size: 4,918 Bytes
4466e02
 
 
 
 
 
 
0ea50a7
 
4466e02
 
 
 
 
0ea50a7
 
 
 
 
 
 
 
4466e02
 
 
 
 
 
 
 
 
 
 
0ea50a7
 
 
 
 
 
 
 
 
 
 
 
4466e02
 
0ea50a7
50737ce
15a9057
4466e02
 
0ea50a7
4466e02
 
 
5b8b49d
0ea50a7
 
50737ce
4466e02
 
0ea50a7
 
 
 
 
 
4466e02
0ea50a7
 
 
4466e02
 
 
0ea50a7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4888232
0ea50a7
 
 
 
 
 
 
 
 
15a9057
 
 
 
0ea50a7
15a9057
 
 
 
4466e02
 
15611f3
4466e02
 
0ea50a7
4466e02
 
 
 
4888232
 
bc69584
 
4888232
 
 
4466e02
 
4888232
bc69584
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
131
import gradio as gr
import subprocess
import logging
from PyPDF2 import PdfReader
import tempfile
import os
import shlex
from gradio_pdf import PDF
from pdf2image import convert_from_path  # Importar para la funci贸n de mostrar_paginas

# Configuraci贸n de logs
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(levelname)s - %(message)s")

def verificar_comando(comando):
    """Verifica si un comando est谩 disponible en el sistema."""
    try:
        subprocess.run(f"which {comando}", shell=True, check=True, capture_output=True)
        logger.info(f"Comando encontrado: {comando}")
    except subprocess.CalledProcessError:
        raise gr.Error(f"El comando '{comando}' no est谩 disponible. Por favor, inst谩lalo antes de continuar.")

def ejecutar_comando(comando):
    """Ejecuta un comando de shell y maneja errores."""
    try:
        resultado = subprocess.run(comando, shell=True, check=True, capture_output=True, text=True)
        logger.info(f"Comando ejecutado: {comando}\nSalida:\n{resultado.stdout}")
        return resultado.stdout
    except subprocess.CalledProcessError as e:
        error_message = f"Error al ejecutar el comando: {comando}\nError: {e}\nSalida de error:\n{e.stderr}"
        logger.error(error_message)
        raise RuntimeError(error_message)

def reparar_pdf(input_pdf, output_pdf):
    """Repara un PDF usando qpdf."""
    verificar_comando("qpdf")
    comando = f"qpdf --linearize {shlex.quote(input_pdf)} {shlex.quote(output_pdf)}"
    ejecutar_comando(comando)

def simplificar_pdf(input_pdf, output_pdf):
    """Simplifica un PDF usando Ghostscript."""
    verificar_comando("gs")
    comando = f"gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen -dNOPAUSE -dBATCH -sOutputFile={shlex.quote(output_pdf)} {shlex.quote(input_pdf)}"
    ejecutar_comando(comando)

def crear_pdf_con_texto_incrustado(pdf_original, archivo_salida, idioma="spa"):
    """Procesa un PDF con OCR usando OCRmyPDF."""
    verificar_comando("ocrmypdf")
    comando = f"ocrmypdf -l {idioma} --force-ocr --deskew --output-type pdf {shlex.quote(pdf_original)} {shlex.quote(archivo_salida)}"
    ejecutar_comando(comando)

def flujo_principal(pdf_file, idioma="spa"):
    """Procesa un PDF subido con reparaci贸n, simplificaci贸n y OCR."""
    if not pdf_file:
        raise gr.Error("No se subi贸 ning煤n archivo.")

    input_pdf = pdf_file
    reparado_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name
    simplificado_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name
    output_pdf = tempfile.NamedTemporaryFile(delete=False, suffix=".pdf").name

    try:
        # Reparar el PDF
        reparar_pdf(input_pdf, reparado_pdf)

        # Simplificar el PDF
        simplificar_pdf(reparado_pdf, simplificado_pdf)

        # Procesar con OCR
        crear_pdf_con_texto_incrustado(simplificado_pdf, output_pdf, idioma)

        return input_pdf, output_pdf
    except gr.Error as e:
        logger.error("Error durante el procesamiento del PDF.")
        raise e
    finally:
        # Limpiar archivos temporales
        for temp_file in [reparado_pdf, simplificado_pdf]:
            if os.path.exists(temp_file):
                os.remove(temp_file)

def mostrar_pdf_zoom(pdf_path):
    return f"""
    <iframe
        src='viewer.html?file={pdf_path}#zoom=100'
        width='100%'
        height='800px'
        style='border: none;'
    ></iframe>
    """

def mostrar_pdf(pdf_path):
    return f"""
    <iframe
        src='viewer.html?file={pdf_path}'
        width='100%'
        height='800px'
        style='border: none;'
    ></iframe>
    """

def mostrar_paginas(pdf_path):
    pages = convert_from_path(pdf_path, dpi=150)
    temp_images = []
    for i, page in enumerate(pages):
        temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".png")
        page.save(temp_file.name, "PNG")
        temp_images.append(temp_file.name)
    return temp_images

with gr.Blocks() as interfaz:
    gr.Markdown("## Visualizador de PDFs con OCR")

    with gr.Row():
        archivo_pdf = PDF(label="Sube tu archivo PDF")
        idioma_ocr = gr.Dropdown(["spa", "eng", "fra", "deu"], label="Idioma OCR", value="spa")
        boton_procesar = gr.Button("Procesar OCR")

    with gr.Row():
        pdf_original_vista = gr.HTML(label="PDF Original")
        pdf_ocr_vista = gr.HTML(label="PDF con OCR")
        # Eliminamos el m茅todo `style` y configuramos las columnas y altura mediante atributos predefinidos
        imagenes = gr.Gallery(label="P谩ginas del PDF", show_label=True, elem_id="gallery-container")

    boton_procesar.click(fn=flujo_principal, inputs=[archivo_pdf, idioma_ocr], outputs=[pdf_original_vista, pdf_ocr_vista])
    boton_procesar.click(fn=mostrar_paginas, inputs=[archivo_pdf], outputs=[imagenes])

if __name__ == "__main__":
    interfaz.launch()