Spaces:
Sleeping
Sleeping
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() | |