Metadata-Version: 2.4
Name: bgustreadimg
Version: 0.3.0
Classifier: Programming Language :: Rust
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Topic :: Scientific/Engineering :: Image Processing
License-File: LICENSE
License-File: LICENSE-MIT
License-File: NOTICE
Summary: Adaptive image preprocessing engine for OCR pipelines — Sauvola binarization in O(N) with Rust
Home-Page: https://github.com/B-GUST/bgustreadimg
Author: B-GUST
License: MIT
Requires-Python: >=3.7
Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM

# bgustreadimg 🖼️

<p align="center">
  <b>Motor de Preprocesamiento de Imágenes Adaptativo de Alto Rendimiento para Pipelines de OCR.</b><br>
  <i>Elimina sombras, arrugas y variaciones de luz no uniformes en milisegundos — 100% Rust nativo.</i>
</p>

<p align="center">
  <a href="https://crates.io/crates/bgustreadimg"><img src="https://img.shields.io/crates/v/bgustreadimg.svg?style=flat-square" alt="Crates Version"></a>
  <a href="https://www.npmjs.com/package/bgustreadimg"><img src="https://img.shields.io/npm/v/bgustreadimg.svg?style=flat-square" alt="NPM Version"></a>
  <img src="https://img.shields.io/badge/version-0.3.0-orange.svg?style=flat-square" alt="Stable Version">
  <a href="https://github.com/B-GUST/bgustreadimg"><img src="https://img.shields.io/badge/license-MIT-blue.svg?style=flat-square" alt="License"></a>
</p>

---

## 💡 La Visión

`bgustreadimg` es un motor de preprocesamiento de imágenes de nivel industrial construido desde cero en **Rust**. Está diseñado para eliminar el ruido visual en fotografías de documentos —facturas, contratos, capturas de cámara— antes de ser enviadas a motores de OCR. A diferencia de los convertidores de formato convencionales, su núcleo implementa **Binarización Adaptativa de Sauvola** con **Imágenes Integrales (SAT)** para lograr una limpieza uniforme en tiempo lineal O(N), independientemente del tamaño de la ventana de análisis local.

---

## 🎯 Alcance

> **Estado:** este proyecto es un motor de **preprocesamiento + OCR**. El núcleo es preprocesamiento (binarización Sauvola + resize Lanczos3), y desde la **v0.3.0** incluye **OCR de transcripción de texto real** (PP-OCRv5) como feature **opcional** `ocr`.

| Funcionalidad | Estado | Disponible en |
|---|---|---|
| Binarización adaptativa Sauvola (O(N)) | ✅ Estable | v0.1+ — core |
| Resize inteligente Lanczos3 | ✅ Estable | v0.1+ — core |
| Detección de líneas de texto (PP-OCRv5 det) | ✅ Estable | v0.3.0 (feature `ocr`) |
| Reconocimiento de texto (PP-OCRv5 rec) | ✅ Estable | v0.3.0 (feature `ocr`) |
| OCR en navegador (WASM) | 🚧 En desarrollo | v0.3.0+ (paquete `bgustreadimg-wasm`) |

> **Nota sobre los modelos:** los modelos de OCR **no** se empaquetan dentro de npm/cargo ni se descargan de Hugging Face en tiempo de ejecución. Se distribuyen como **assets del release `v0.3.0` en GitHub** y se descargan bajo confirmación al primer uso de OCR (con verificación SHA256). Ver [Distribución de modelos](#-distribución-de-modelos).

---

## 🌟 Características Clave

*   **Binarización Adaptativa Sauvola O(N):** Umbral de contraste local dinámico usando Summed Area Tables. Elimina sombras, arrugas y fondos no uniformes sin distorsionar los caracteres.
*   **Redimensionamiento Inteligente con Lanczos3:** Escalado de alta calidad que conserva la nitidez del texto. Selección automática del ancho objetivo basada en la memoria RAM disponible.
*   **Bindings NAPI-RS Nativos:** Extensión dinámica `.node` cargada directamente por Node.js sin sobrecoste de IPC ni dependencias Python.
*   **Doble Canal de Distribución:** Biblioteca estática (`rlib`) para Rust en crates.io y bindings dinámicos (`cdylib`) para npm.
*   **Multiplataforma:** Bindings para Node.js (NAPI-RS), Python (PyO3) y WebAssembly (wasm-bindgen) desde el mismo núcleo Rust.

---

## 🏗️ Arquitectura del Pipeline

```
                    ┌─────────────────────┐
                    │   Input Image       │
                    │  (JPEG, PNG, ...)   │
                    └─────────┬───────────┘
                              │
                    ┌─────────▼───────────┐
                    │  Metadata Probe     │
                    │  (formato, dims)    │  ── sin decodificar a RAM
                    └─────────┬───────────┘
                              │
                    ┌─────────▼───────────┐
                    │  Decode & Resize    │
                    │  Lanczos3, auto-RAM │
                    └─────────┬───────────┘
                              │
                    ┌─────────▼───────────┐
                    │  Sauvola Adaptive   │
                    │  Binarization (SAT) │
                    │  O(N), window_size  │
                    └─────────┬───────────┘
                              │
                    ┌─────────▼───────────┐
                    │  Clean Output PNG   │
                    │  (sin pérdidas)     │
                    └─────────────────────┘
```

---

## 📦 Canales de Distribución

### 1. Canal Rust (Crates.io) 🦀
*   **Tipo:** Biblioteca estática (`rlib`).
*   **Uso:**
    ```toml
    [dependencies]
    bgustreadimg = "0.3.0"
    ```

### 2. Canal Node.js & NPM (Backend) 🟢
*   **Tipo:** Extensión nativa (`cdylib` mediante NAPI-RS).
*   **Instalación:**
    ```bash
    npm install bgustreadimg
    ```

### 3. Canal Python & Pip (Maturin) 🐍
*   **Tipo:** Módulo nativo compilado (PyO3).
*   **Instalación:**
    ```bash
    pip install bgustreadimg
    ```

### 4. Canal Frontend & NPM (WebAssembly) 🌐
*   **Tipo:** Paquete JS/WASM para navegador (`wasm-bindgen`).
*   **Instalación:**
    ```bash
    npm install bgustreadimg-wasm
    ```

---

## 📥 Distribución de Modelos

Los modelos de OCR (PP-OCRv5) **no** viajan dentro de los paquetes npm/cargo (crates.io limita archivos a 10MB y el modelo de reconocimiento pesa ~16.5MB). En su lugar:

*   Se distribuyen como **assets del GitHub Release `v0.3.0`** de este repositorio.
*   Se descargan **bajo confirmación** al primer uso de OCR, mediante `scripts/download_models.sh`, con verificación **SHA256**.
*   Nunca se descargan de Hugging Face en tiempo de ejecución.

| Asset | Tamaño | Descripción |
|---|---|---|
| `det.onnx` | ~4.75 MB | PP-OCRv5 mobile_det — detección de líneas de texto |
| `rec.onnx` | ~16.5 MB | PP-OCRv5 mobile_rec — reconocimiento de texto (multilingual) |
| `ppocrv5_dict.txt` | ~92 KB | Diccionario de caracteres para decodificación |

**Flujo de confirmación (primer uso de OCR):**

```
La función OCR requiere los modelos PP-OCRv5 (~21 MB).
¿Descargar ahora desde el release v0.3.0 de GitHub? [Sí/Después]
```

*   `Sí` → descarga a `models/` con barra de progreso + verificación SHA256.
*   `Después` → el OCR devuelve `BGUST_MODELS_MISSING` con instrucciones para instalar.

**Descarga manual:**

```bash
bash scripts/download_models.sh            # descarga desde GitHub Release
bash scripts/download_models.sh --force    # re-descarga forzada
```

Los modelos se almacenan en `models/` (gitignored). Licencias: ver [Licencias y Atribuciones](#-licencias-y-atribuciones).

---

## 🛠️ Instalación y Compilación de Desarrollo

1.  **Clonar el repositorio:**
    ```bash
    git clone https://github.com/B-GUST/bgustreadimg.git
    cd bgustreadimg
    ```

2.  **Compilar para Node.js (NAPI-RS):**
    ```bash
    npm install
    npm run build
    ```

3.  **Compilar para Python (Maturin):**
    ```bash
    # Requiere instalar maturin
    pip install maturin
    PYO3_USE_ABI3_FORWARD_COMPATIBILITY=1 maturin build --release
    ```

4.  **Compilar para Frontend/Navegador (WASM):**
    ```bash
    # Compila a WASM y prepara el paquete listo para npm en pkg-wasm/
    npm run build:wasm
    ```

---

## 🚀 Primeros Pasos

### Rust
```rust
use bgustreadimg::preprocess_image_rs;

let image_data = std::fs::read("input.jpg").unwrap();
let result = preprocess_image_rs(image_data, Some(
    bgustreadimg::PreprocessConfigRs {
        window_size: Some(25),
        k: Some(0.2),
        target_width: Some(1920),
    }
)).await.unwrap();

std::fs::write("output.png", result).unwrap();
```

### Node.js (Backend)
```javascript
const { preprocessImage } = require('bgustreadimg');
const fs = require('fs');

const clean = await preprocessImage(fs.readFileSync('input.jpg'), {
    windowSize: 25,
    k: 0.2,
    targetWidth: 1920,
});
fs.writeFileSync('output.png', clean);
```

### Python
```python
import bgustreadimg

with open("input.jpg", "rb") as f:
    data = f.read()

config = bgustreadimg.PreprocessConfigPy(window_size=25, k=0.2, target_width=1920)
clean = bgustreadimg.preprocess_image(data, config)

with open("output.png", "wb") as f:
    f.write(clean)
```

### Frontend (Navegador/WASM)
```javascript
import init, { preprocessImage } from 'bgustreadimg-wasm';

await init(); // Inicializar módulo WASM

const fileBuffer = await file.arrayBuffer();
const cleanBuffer = preprocessImage(new Uint8Array(fileBuffer), 25, 0.2, 1280);
```

---

## ⚙️ Configuración

| Parámetro     | Default | Descripción |
|---------------|---------|-------------|
| `windowSize`  | `25`    | Tamaño de la ventana local de análisis (impar, ≥3) |
| `k`           | `0.2`   | Sensibilidad al contraste (menor = más agresivo con sombras) |
| `targetWidth` | auto    | Ancho máximo de salida; auto-selecciona 1920 o 1280 según RAM libre |

---

## 🧩 Estructura del Proyecto

```
├── Cargo.toml          # Manifiesto Rust (publicable en crates.io)
├── pyproject.toml      # Manifiesto Python (publicable con maturin)
├── package.json        # Manifiesto npm
├── build.rs            # Script de compilación condicional
├── scripts/
│   └── prepare-wasm-pkg.js # Script de post-procesamiento para WASM
├── docs/
│   ├── README_WASM.md  # README del paquete frontend/WASM
│   ├── updated_multi_platform_plan.md # Plan de arquitectura multi-plataforma
│   └── implementation_report.md # Reporte de cambios realizados
├── src/
│   ├── lib.rs          # Núcleo: Sauvola threshold, preprocess_image_sync
│   ├── bindings_napi.rs # Bindings específicos para Node.js
│   ├── bindings_pyo3.rs # Bindings específicos para Python
│   └── bindings_wasm.rs # Bindings específicos para WebAssembly
├── index.js            # Binding NAPI-RS para Node.js (auto-generado)
├── index.d.ts          # Declaraciones de tipos TypeScript para Node.js
└── LICENSE             # Licencia MIT
```

---

## 📜 Licencia y Atribuciones

Este proyecto se distribuye bajo la **Business Source License 1.1 (BUSL-1.1)**. Consulta el archivo [`CREDITS.md`](./CREDITS.md) para las atribuciones completas.

**Licencias de componentes de terceros (importante para uso legal):**

| Componente | Licencia | Archivo |
|---|---|---|
| Modelos PP-OCRv5 (PaddlePaddle) | Apache-2.0 | [`LICENSES/PP-OCRv5.txt`](./LICENSES/PP-OCRv5.txt) |
| Código PaddleOCR (export/ref) | Apache-2.0 | [`LICENSES/PP-OCRv5.txt`](./LICENSES/PP-OCRv5.txt) |
| ONNX Runtime (inferencia) | MIT | [`LICENSES/ONNX-Runtime.txt`](./LICENSES/ONNX-Runtime.txt) |
| Crate `ort` (pykeio) | MIT / Apache-2.0 | [`NOTICE`](./NOTICE) |
| Algoritmo Sauvola | Atribución académica | [`CREDITS.md`](./CREDITS.md) |

> ⚠️ El uso de los **modelos PP-OCRv5** está cubierto por **Apache-2.0**, lo que permite uso comercial. Aun así, es obligatorio mantener la atribución a **PaddlePaddle/PaddleOCR** en los artefactos que redistribuyas. Ver [`LICENSES/PP-OCRv5.txt`](./LICENSES/PP-OCRv5.txt).

