Referencia de la API de Python
PDF Oxide ofrece bindings nativos de Python construidos con PyO3. Hay wheels precompilados para Python 3.8–3.14 en Linux, macOS y Windows (x86_64 y ARM64).
pip install pdf_oxide
Para la API de Rust, consulta la Referencia de la API de Rust. Para la API de JavaScript, consulta la Referencia de la API de Node.js o la Referencia de la API WASM. Para los detalles de tipos, consulta Tipos y enums.
PdfDocument
La clase principal para abrir, extraer, editar y guardar archivos PDF.
from pdf_oxide import PdfDocument
Constructor
PdfDocument(path: str, password: str | None = None)
| Parámetro | Tipo | Descripción |
|---|---|---|
path |
str |
Ruta al archivo PDF |
password |
str | None |
Contraseña opcional para PDFs cifrados (por defecto: None) |
Pasa password= para abrir PDFs cifrados en un solo paso. Como alternativa, también puedes usar doc.authenticate(password) tras abrirlo.
Lanza FileNotFoundError si el archivo no existe. Lanza PdfError si el archivo no es un PDF válido.
Métodos de clase
PdfDocument.from_bytes(data: bytes, password: str | None = None) -> PdfDocument
Abre un PDF a partir de bytes en memoria (p. ej. descargado de S3, recibido por HTTP). Acepta una contraseña opcional para PDFs cifrados.
| Parámetro | Tipo | Descripción |
|---|---|---|
data |
bytes |
Bytes crudos del archivo PDF |
password |
str | None |
Contraseña opcional para PDFs cifrados (por defecto: None) |
from pdf_oxide import PdfDocument
# Open PDF from bytes (e.g., downloaded from S3)
doc = PdfDocument.from_bytes(pdf_bytes)
# Also supports password:
doc = PdfDocument.from_bytes(pdf_bytes, password="secret")
Métodos
Generales
| Método | Tipo de retorno | Descripción |
|---|---|---|
version() |
tuple[int, int] |
Versión del PDF como (major, minor) (p. ej. (1, 7)) |
authenticate(password) |
bool |
Autentica un PDF cifrado con la contraseña de usuario o de propietario |
Información del documento
doc.page_count() -> int
Devuelve el número de páginas del documento.
doc.has_structure_tree() -> bool
Comprueba si el documento es un Tagged PDF con árbol de estructura.
Autenticación
doc.authenticate(password: str) -> bool
Autentica con una contraseña después de abrir. Devuelve True si la autenticación tuvo éxito.
Extracción de texto
doc.extract_text(
page: int,
region: tuple[float, float, float, float] | None = None,
exclude_layers: list[str] | None = None,
exclude_inks: list[str] | None = None,
extract_tables: bool = True
) -> str
Extrae texto plano de una sola página. Las páginas se indexan desde cero. Opcionalmente, recorta a una region, excluye capas de contenido opcional con nombre o nombres de tintas/separaciones, y activa o desactiva la reconstrucción de tablas.
doc.extract_chars(
page: int,
region: tuple[float, float, float, float] | None = None,
exclude_layers: list[str] | None = None,
exclude_inks: list[str] | None = None
) -> list[TextChar]
Extrae el posicionamiento por carácter y los metadatos de fuente. Devuelve una lista de objetos TextChar.
doc.extract_spans(page: int, region: tuple | None = None, reading_order: str | None = None) -> list[TextSpan]
Extrae spans de texto con metadatos de fuente. Cada span es una secuencia de texto con un estilo idéntico. Pasa reading_order="column_aware" para PDFs multicolumna.
doc.extract_words(
page: int,
*,
include_artifacts: bool = True,
region: tuple | None = None,
word_gap_threshold: float | None = None,
profile: ExtractionProfile | None = None
) -> list[TextWord]
Extrae texto agrupado por palabras con cajas delimitadoras. Devuelve una lista de objetos TextWord.
doc.extract_text_lines(
page: int,
*,
include_artifacts: bool = True,
region: tuple | None = None,
word_gap_threshold: float | None = None,
line_gap_threshold: float | None = None,
profile: ExtractionProfile | None = None
) -> list[TextLine]
Extrae texto agrupado por líneas. Devuelve una lista de objetos TextLine.
doc.extract_page_text(page: int, reading_order: str | None = None) -> dict
Extrae spans, caracteres y dimensiones de página en una sola pasada. Devuelve un dict con las claves: spans, chars, page_width, page_height, text. Es más eficiente que llamar a extract_spans() + extract_chars() por separado.
doc.page_layout_params(page: int) -> LayoutParams
Calcula parámetros de maquetación adaptativos (umbrales de separación entre palabras/líneas, métricas medianas, número de columnas) para una página. Consulta LayoutParams.
doc.within(page: int, bbox: tuple[float, float, float, float]) -> PdfPageRegion
Crea un handle de región recortada para extraer texto, palabras, líneas, tablas, imágenes y trazados dentro de bbox. Consulta PdfPageRegion.
Extracción y clasificación automáticas
doc.extract_text_auto(page: int) -> str
Selecciona automáticamente la mejor estrategia de extracción (texto nativo frente a OCR) para una página y devuelve texto plano.
doc.extract_page_auto(page: int, options_json: str | None = None) -> str
Extrae una página de forma automática y devuelve un documento JSON; pasa una cadena JSON options_json para ajustar el pipeline.
doc.classify_page(page: int) -> str
Clasifica una sola página (p. ej. "text", "scanned", "mixed").
doc.classify_document() -> str
Clasifica todo el documento muestreando sus páginas.
doc.has_text_layer(page: int) -> bool
Comprueba si una página ya tiene una capa de texto nativo extraíble (frente a requerir OCR).
Conversión
doc.to_plain_text(
page: int,
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None
) -> str
Convierte una página a texto plano con opciones de maquetación.
doc.to_plain_text_all(
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None
) -> str
Convierte todas las páginas a texto plano.
doc.to_markdown(
page: int,
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None,
embed_images: bool = True,
include_form_fields: bool = True
) -> str
Convierte una página a Markdown.
doc.to_markdown_all(
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None,
embed_images: bool = True,
include_form_fields: bool = True
) -> str
Convierte todas las páginas a Markdown.
doc.to_html(
page: int,
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None,
embed_images: bool = True,
include_form_fields: bool = True
) -> str
Convierte una página a HTML.
doc.to_html_all(
preserve_layout: bool = False,
detect_headings: bool = True,
include_images: bool = True,
image_output_dir: str | None = None,
embed_images: bool = True,
include_form_fields: bool = True
) -> str
Convierte todas las páginas a HTML.
Conversión a Office
| Método | Tipo de retorno | Descripción |
|---|---|---|
to_docx(path) |
– | Convierte el PDF a un archivo de documento de Word |
to_docx_bytes() |
bytes |
Convierte el PDF a bytes DOCX |
to_pptx(path) |
– | Convierte el PDF a un archivo de PowerPoint |
to_pptx_bytes() |
bytes |
Convierte el PDF a bytes PPTX |
to_xlsx(path) |
– | Convierte el PDF a un archivo de libro de Excel |
to_xlsx_bytes() |
bytes |
Convierte el PDF a bytes XLSX |
Extracción de imágenes
doc.extract_images(page: int) -> list[ImageInfo]
Extrae todas las imágenes de una página, incluidas las imágenes en content streams y Form XObjects anidados.
doc.extract_image_bytes(page: int) -> list[dict]
Extrae los bytes crudos de las imágenes de una página. Cada dict contiene width, height, data (bytes) y format.
Búsqueda
doc.search(
pattern: str,
case_insensitive: bool = False,
literal: bool = False,
whole_word: bool = False,
max_results: int = 0
) -> list[SearchResult]
Busca texto en todas las páginas. Usa max_results=0 para resultados ilimitados. Devuelve una lista de coincidencias con número de página, texto y coordenadas.
doc.search_page(
page: int,
pattern: str,
case_insensitive: bool = False,
literal: bool = False,
whole_word: bool = False,
max_results: int = 0
) -> list[SearchResult]
Busca texto en una sola página.
Edición de metadatos
| Método | Parámetros | Descripción |
|---|---|---|
set_title(title) |
str |
Establece el título del documento |
set_author(author) |
str |
Establece el autor del documento |
set_subject(subject) |
str |
Establece el asunto del documento |
set_keywords(keywords) |
str |
Establece las palabras clave del documento |
Rotación de páginas
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
page_rotation(page) |
int |
int |
Obtiene la rotación actual (0, 90, 180, 270) |
set_page_rotation(page, degrees) |
int, int |
– | Establece la rotación absoluta |
rotate_page(page, degrees) |
int, int |
– | Suma a la rotación actual |
rotate_all_pages(degrees) |
int |
– | Rota todas las páginas |
Dimensiones de página
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
page_media_box(page) |
int |
tuple[float, float, float, float] |
Obtiene el MediaBox (llx, lly, urx, ury) |
set_page_media_box(page, llx, lly, urx, ury) |
int, float, float, float, float |
– | Establece el MediaBox |
page_crop_box(page) |
int |
`tuple | None` |
set_page_crop_box(page, llx, lly, urx, ury) |
int, float, float, float, float |
– | Establece el CropBox |
crop_margins(left, right, top, bottom) |
float, float, float, float |
– | Recorta los márgenes de todas las páginas |
Borrar / Whiteout
| Método | Parámetros | Descripción |
|---|---|---|
erase_region(page, llx, lly, urx, ury) |
int, float, float, float, float |
Borra una región rectangular |
erase_regions(page, rects) |
int, list[tuple] |
Borra varias regiones |
clear_erase_regions(page) |
int |
Cancela las operaciones de borrado pendientes |
Anotaciones
doc.get_annotations(page: int) -> list[dict]
Obtiene los metadatos de las anotaciones (tipo, rect, contenido, etc.) de una página.
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
flatten_page_annotations(page) |
int |
– | Aplana las anotaciones de una página |
flatten_all_annotations() |
– | – | Aplana todas las anotaciones |
is_page_marked_for_flatten(page) |
int |
bool |
Comprueba si la página está marcada para aplanar |
unmark_page_for_flatten(page) |
int |
– | Desmarca una página para aplanar |
Redacción (Redaction)
doc.add_redaction(
page: int,
rect: tuple[float, float, float, float],
fill: tuple[float, float, float] | None = None
) -> None
Marca una región rectangular para redacción con un color de relleno RGB opcional.
doc.redaction_count(page: int) -> int
Devuelve el número de redacciones pendientes en una página.
doc.apply_redactions_destructive(
scrub_metadata: bool = True,
remove_javascript: bool = True,
remove_embedded_files: bool = True,
fill: tuple[float, float, float] = (0.0, 0.0, 0.0)
) -> None
Aplica todas las redacciones de forma destructiva, eliminando el contenido subyacente y, opcionalmente, depurando metadatos, JavaScript y archivos embebidos.
doc.sanitize_document(
scrub_metadata: bool = True,
remove_javascript: bool = True,
remove_embedded_files: bool = True
) -> None
Sanea el documento sin redactar regiones: elimina metadatos, JavaScript y/o archivos embebidos.
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
apply_page_redactions(page) |
int |
– | Aplica las redacciones de una página |
apply_all_redactions() |
– | – | Aplica todas las redacciones pendientes |
is_page_marked_for_redaction(page) |
int |
bool |
Comprueba si la página está marcada para redacción |
unmark_page_for_redaction(page) |
int |
– | Desmarca una página para redacción |
Capas y tintas
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
get_layers() |
– | list[str] |
Lista los nombres de las capas de contenido opcional (OCG) |
get_page_inks(page) |
int |
list[str] |
Lista los nombres de colorantes de tinta / separación de una página |
get_page_inks_deep(page) |
int |
list[str] |
Lista las tintas, incluidas las anidadas en Form XObjects |
Limpieza de cabeceras / pies de página
doc.remove_headers(threshold: float = 0.8) -> int
doc.remove_footers(threshold: float = 0.8) -> int
doc.remove_artifacts(threshold: float = 0.8) -> int
Detecta y elimina cabeceras, pies de página o artefactos de página que se repiten a lo largo del documento. threshold es la proporción de repetición entre páginas. Devuelve el número de elementos eliminados.
| Método | Parámetros | Descripción |
|---|---|---|
erase_header(page) |
int |
Borra la región de cabecera detectada en una página |
edit_header(page) |
int |
Marca la región de cabecera para edición |
erase_footer(page) |
int |
Borra la región de pie de página detectada en una página |
edit_footer(page) |
int |
Marca la región de pie de página para edición |
erase_artifacts(page) |
int |
Borra los artefactos detectados en una página |
sync_editor_erasures() |
– | Vuelca al editor los borrados pendientes de cabeceras/pies/artefactos |
Campos de formulario
doc.get_form_fields() -> list[FormField]
Obtiene todos los campos de formulario. Consulta FormField para ver sus propiedades.
doc.get_form_field_value(name: str) -> str | bool | list | None
Obtiene el valor de un campo de formulario por su nombre. Devuelve el tipo de Python adecuado según el tipo de campo.
doc.set_form_field_value(name: str, value: str | bool) -> None
Establece el valor de un campo de formulario por su nombre.
doc.has_xfa() -> bool
Comprueba si el documento contiene formularios XFA.
doc.export_form_data(path: str, format: str = "fdf") -> None
Exporta los datos del formulario a un archivo. Formatos admitidos: "fdf" y "xfdf".
| Método | Parámetros | Descripción |
|---|---|---|
flatten_forms() |
– | Aplana todos los campos de formulario en el contenido de la página |
flatten_forms_on_page(page) |
int |
Aplana los formularios de una página concreta |
Manipulación de imágenes
doc.page_images(page: int) -> list[dict]
Obtiene los nombres y los límites de las imágenes para operaciones de posicionamiento. Cada dict contiene name, bounds [x, y, width, height] y matrix.
| Método | Parámetros | Descripción |
|---|---|---|
reposition_image(page, name, x, y) |
int, str, float, float |
Mueve una imagen |
resize_image(page, name, width, height) |
int, str, float, float |
Cambia el tamaño de una imagen |
set_image_bounds(page, name, x, y, width, height) |
int, str, float, float, float, float |
Establece la posición y el tamaño de una imagen |
clear_image_modifications(page) |
int |
Cancela las modificaciones de imagen pendientes |
has_image_modifications(page) |
int → bool |
Comprueba si hay modificaciones de imagen pendientes |
Operaciones sobre el documento
doc.merge_from(source: str | PdfDocument) -> int
Fusiona las páginas de otro PDF. Acepta una ruta de archivo o una instancia de PdfDocument. Devuelve el número de páginas fusionadas.
doc.embed_file(name: str, data: bytes) -> None
Adjunta un archivo al PDF.
doc.get_outline() -> list[dict] | None
Obtiene los marcadores / índice de contenido del documento. Devuelve None si no existe un esquema.
doc.extract_paths(page: int, region: tuple | None = None) -> list[dict]
Obtiene los trazados vectoriales (líneas, curvas, formas) de una página.
doc.extract_rects(page: int, region: tuple | None = None) -> list[dict]
Obtiene los rectángulos alineados con los ejes (de trazados rellenos/contorneados) de una página.
doc.extract_lines(page: int, region: tuple | None = None) -> list[dict]
Obtiene los segmentos de línea recta de una página.
doc.extract_tables(page: int, region: tuple | None = None, table_settings: dict | None = None) -> list[dict]
Detecta y extrae tablas. Cada tabla es un dict con filas y celdas (texto + cajas delimitadoras). Pasa table_settings para ajustar la estrategia de detección.
doc.extract_structured(page: int) -> str
Extrae la página como un documento JSON estructurado (orden de lectura lógico, bloques y roles).
doc.page_labels() -> list[dict]
Obtiene los rangos de etiquetas de página. Cada dict contiene start_page, style, prefix y start_value.
doc.xmp_metadata() -> dict | None
Obtiene los metadatos XMP como un diccionario con campos como dc_title, dc_creator, xmp_create_date, etc. Devuelve None si no existen metadatos XMP.
OCR
doc.extract_text_ocr(page: int, engine: OcrEngine | None = None) -> str
Extrae texto mediante OCR. Requiere la feature ocr en la compilación de Rust. Pasa un OcrEngine personalizado o None para el motor por defecto.
Extracción y reordenación de páginas
doc.extract_pages(pages: list[int], output: str) -> None
Extrae los índices de página indicados en un nuevo archivo PDF en output.
doc.extract_pages_to_bytes(pages: list[int]) -> bytes
Extrae los índices de página indicados en un nuevo PDF devuelto como bytes.
doc.extract_page_ranges_to_bytes(ranges: list[tuple[int, int]]) -> bytes
Extrae uno o varios rangos de páginas (start, end) en un nuevo PDF devuelto como bytes.
| Método | Parámetros | Descripción |
|---|---|---|
select_pages(pages) |
list[int] |
Conserva solo las páginas indicadas, en el orden dado |
delete_page(index) |
int |
Elimina una sola página |
move_page(from_index, to_index) |
int, int |
Mueve una página a una nueva posición |
Conformidad y validación
doc.validate_pdf_a(level: str = "1b") -> dict
Valida frente a un nivel de conformidad PDF/A (p. ej. "1b", "2b", "3b"). Devuelve un dict de informe.
doc.convert_to_pdf_a(level: str = "2b") -> dict
Convierte el documento a PDF/A y devuelve un dict de informe de conversión.
doc.validate_pdf_ua() -> dict
Valida frente a los requisitos de PDF/UA (accesibilidad).
doc.validate_pdf_x(level: str = "1a_2001") -> dict
Valida frente a un nivel de conformidad PDF/X (producción de impresión).
Permisos y advertencias
doc.permissions() -> dict
Devuelve los flags de permisos de cifrado del documento (imprimir, copiar, modificar, anotar, etc.).
doc.structured_warnings() -> list
Devuelve las advertencias recopiladas durante la extracción de contenido estructurado / etiquetado.
doc.flatten_warnings() -> list[str]
Devuelve las advertencias recopiladas durante el aplanado de formularios/anotaciones.
Firmas y Document Security Store
doc.signatures() -> list[Signature]
Devuelve todas las firmas digitales del documento. Consulta Signature.
doc.signature_count() -> int
Devuelve el número de firmas digitales.
doc.dss() -> Dss | None
Devuelve el Document Security Store (material LTV) analizado del documento, o None. Consulta Dss.
API de páginas (v0.3.34)
PdfDocument es iterable e indexable, y devuelve objetos Page perezosos. Consulta Page.
len(doc) # number of pages
doc[i] # page at index i (negative indexing supported)
doc[-1] # last page
for page in doc: ... # iterate pages
Acceso al DOM
doc.page(index: int) -> PdfPage
Obtiene un handle de página tipo DOM para edición a nivel de elemento. Consulta PdfPage.
doc.save_page(page: PdfPage) -> None
Guarda en el documento una PdfPage modificada.
Renderizado
doc.render_page(
page: int,
dpi: int | None = None,
format: str | None = None,
background: tuple[float, float, float, float] | None = None,
transparent: bool = False,
render_annotations: bool | None = None,
jpeg_quality: int | None = None,
excluded_layers: list[str] | None = None
) -> bytes
Renderiza una página a bytes PNG o JPEG con control sobre el DPI, el fondo, la transparencia, el renderizado de anotaciones, la calidad JPEG y las capas excluidas.
doc.render_pixmap(page: int, dpi: int | None = None) -> RenderedPixmap
Renderiza una página a un RenderedPixmap RGBA crudo (named tuple con width, height, data).
doc.render_separations(page: int, dpi: int | None = None) -> list[SeparationPlate]
Renderiza las planchas de separación por tinta de una página. Devuelve una lista de named tuples SeparationPlate (name, width, height, data).
doc.render_separation(page: int, ink_name: str, dpi: int | None = None) -> SeparationPlate
Renderiza la plancha de separación de una sola tinta con nombre.
| Método | Tipo de retorno | Descripción |
|---|---|---|
render_page_fit(page, fit_width, fit_height, format=0) |
bytes |
Renderiza una página escalada para ajustarse a una caja de píxeles |
flatten_to_images(dpi=150) |
bytes |
Aplana todas las páginas a un PDF basado en imágenes |
Guardado
doc.save(path: str, compress: bool = True, garbage_collect: bool = True, linearize: bool = False) -> None
Guarda el PDF en un archivo. Activa o desactiva la compresión de streams, la recolección de objetos muertos y la linealización (visualización web rápida).
doc.to_bytes(compress: bool = True, garbage_collect: bool = True, linearize: bool = False) -> bytes
Serializa el PDF a bytes con las mismas opciones que save().
doc.save_encrypted(
path: str,
user_password: str,
owner_password: str | None = None,
allow_print: bool = True,
allow_copy: bool = True,
allow_modify: bool = True,
allow_annotate: bool = True
) -> None
Guarda con protección por contraseña AES-256 y controles de permisos. Si owner_password es None, se utiliza la contraseña de usuario.
doc.to_bytes_encrypted(
user_password: str,
owner_password: str | None = None,
allow_print: bool = True,
allow_copy: bool = True,
allow_modify: bool = True,
allow_annotate: bool = True
) -> bytes
Serializa un PDF cifrado con AES-256 a bytes.
Page
Un handle de página perezoso devuelto por doc[i] o al iterar sobre PdfDocument. Todas las propiedades se calculan al acceder a ellas y se delegan al documento padre.
from pdf_oxide import PdfDocument
with PdfDocument("paper.pdf") as doc:
page = doc[0]
text = page.text
md = page.markdown(detect_headings=True)
Propiedades (perezosas)
| Propiedad | Tipo | Descripción |
|---|---|---|
index |
int |
Índice de página basado en cero |
width, height |
float |
Dimensiones de la página en puntos PDF |
bbox |
tuple[float, 4] |
(llx, lly, urx, ury) |
text |
str |
Texto plano extraído |
chars, words, lines, spans |
list[...] |
Texto estructurado |
tables |
list[dict] |
Tablas con filas + celdas (texto + bboxes) |
images, paths, annotations |
list[...] |
Contenido de la página |
Métodos
page.markdown(preserve_layout=False, detect_headings=True,
include_images=False, image_output_dir=None,
embed_images=True, include_form_fields=True) -> str
page.plain_text(...) -> str
page.html(...) -> str
page.render(dpi=None, format=None, background=None, transparent=False,
render_annotations=None, jpeg_quality=None, excluded_layers=None) -> bytes
page.render_pixmap(dpi=None) -> RenderedPixmap
page.search(pattern, case_insensitive=False, literal=False,
whole_word=False, max_results=100) -> list
page.region(x, y, width, height) -> PdfPageRegion
El objeto de página perezoso también se expone como doc.pages() (un iterador equivalente a iterar el documento directamente).
PdfPage
Handle de página tipo DOM para acceso y edición a nivel de elemento. Se obtiene mediante PdfDocument.page().
from pdf_oxide import PdfDocument
doc = PdfDocument("file.pdf")
page = doc.page(0)
Propiedades
| Propiedad | Tipo | Descripción |
|---|---|---|
index |
int |
Índice de página basado en cero |
width |
float |
Ancho de la página en puntos PDF |
height |
float |
Alto de la página en puntos PDF |
Métodos
page.children() -> list[PdfElement]
Obtiene todos los elementos de la página.
page.find_text_containing(needle: str) -> list[PdfText]
Encuentra todos los elementos de texto que contienen la subcadena dada.
page.find_images() -> list[PdfImage]
Encuentra todos los elementos de imagen de la página.
page.get_element(element_id: str) -> PdfElement | None
Obtiene un elemento concreto por su ID.
page.set_text(text_id: PdfTextId, new_text: str) -> None
Reemplaza el contenido de texto de un elemento identificado por su PdfTextId.
page.annotations() -> list[PdfAnnotation]
Obtiene todas las anotaciones de la página.
page.add_link(x: float, y: float, width: float, height: float, url: str) -> str
Añade una anotación de enlace URL. Devuelve el ID de la anotación.
page.add_highlight(x: float, y: float, width: float, height: float, color: tuple[float, float, float]) -> str
Añade una anotación de resaltado con un color RGB. Devuelve el ID de la anotación.
page.add_note(x: float, y: float, text: str) -> str
Añade una anotación de nota adhesiva. Devuelve el ID de la anotación.
page.remove_annotation(index: int) -> bool
Elimina una anotación por su índice. Devuelve True si se eliminó.
page.add_text(text: str, x: float, y: float, font_size: float = 12.0) -> PdfTextId
Añade texto nuevo a la página. Devuelve un PdfTextId para referencia posterior.
page.remove_element(element_id: PdfTextId) -> bool
Elimina un elemento por su ID. Devuelve True si se eliminó.
Ejemplo
from pdf_oxide import PdfDocument
doc = PdfDocument("invoice.pdf")
page = doc.page(0)
# Find and replace text
for text in page.find_text_containing("DRAFT"):
page.set_text(text.id, "FINAL")
# Add a link
page.add_link(100, 700, 200, 20, "https://example.com")
doc.save_page(page)
doc.save("invoice_updated.pdf")
La clase unificada para crear PDFs a partir de distintos formatos de origen.
from pdf_oxide import Pdf
Métodos de fábrica
Pdf.from_markdown(content: str, title: str | None = None, author: str | None = None) -> Pdf
Crea un PDF a partir de contenido Markdown.
Pdf.from_html(content: str, title: str | None = None, author: str | None = None) -> Pdf
Crea un PDF a partir de contenido HTML.
Pdf.from_text(content: str, title: str | None = None, author: str | None = None) -> Pdf
Crea un PDF a partir de texto plano.
Pdf.from_markdown_with_template(content: str, template: str, title: str | None = None, author: str | None = None) -> Pdf
Crea un PDF a partir de Markdown renderizado mediante una plantilla CSS/de maquetación con nombre.
Pdf.from_image(path: str) -> Pdf
Crea un PDF de una sola página a partir de un archivo de imagen (JPEG, PNG).
Pdf.from_bytes(data: bytes) -> Pdf
Abre un PDF existente a partir de bytes en memoria para modificarlo. Útil para cargar PDFs descargados de S3, HTTP o bases de datos.
from pdf_oxide import Pdf
pdf = Pdf.from_bytes(existing_pdf_bytes)
pdf.save("modified.pdf")
Pdf.from_images(paths: list[str]) -> Pdf
Crea un PDF de varias páginas a partir de varios archivos de imagen, una página por imagen.
Pdf.from_image_bytes(data: bytes) -> Pdf
Crea un PDF de una sola página a partir de bytes de imagen.
Pdf.merge(paths: list[str]) -> Pdf
Fusiona varios archivos PDF (por ruta) en un único Pdf.
Métodos
pdf.save(path: str) -> None
Guarda el PDF en un archivo.
pdf.to_bytes() -> bytes
Obtiene el contenido del PDF como bytes.
len(pdf) -> int
Obtiene el tamaño del PDF en bytes (mediante __len__).
PdfText
Representa un elemento de texto en una página. Devuelto por PdfPage.find_text_containing().
| Propiedad | Tipo | Descripción |
|---|---|---|
id |
PdfTextId |
Identificador único del elemento |
value |
str |
Contenido de texto |
text |
str |
Contenido de texto (alias de value) |
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
font_name |
str |
Nombre PostScript de la fuente |
font_size |
float |
Tamaño de fuente en puntos |
is_bold |
bool |
Si el texto está en negrita |
is_italic |
bool |
Si el texto está en cursiva |
Métodos
| Método | Parámetros | Devuelve | Descripción |
|---|---|---|---|
contains(needle) |
str |
bool |
Comprueba si el texto contiene una subcadena |
starts_with(prefix) |
str |
bool |
Comprueba si el texto empieza por un prefijo |
ends_with(suffix) |
str |
bool |
Comprueba si el texto termina en un sufijo |
PdfImage
Representa un elemento de imagen en una página. Devuelto por PdfPage.find_images().
| Propiedad | Tipo | Descripción |
|---|---|---|
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
width |
int |
Ancho de la imagen en píxeles |
height |
int |
Alto de la imagen en píxeles |
aspect_ratio |
float |
Relación ancho / alto |
PdfAnnotation
Representa una anotación en una página. Devuelta por PdfPage.annotations().
| Propiedad | Tipo | Descripción |
|---|---|---|
subtype |
str |
Tipo de anotación (p. ej. "Link", "Highlight", "Text") |
rect |
tuple[float, float, float, float] |
Posición (x0, y0, x1, y1) |
contents |
`str | None` |
color |
`tuple[float, float, float] | None` |
is_modified |
bool |
Si la anotación ha sido modificada |
is_new |
bool |
Si la anotación es de nueva incorporación |
PdfElement
Envoltorio genérico de elemento. Devuelto por PdfPage.children().
| Método | Devuelve | Descripción |
|---|---|---|
is_text() |
bool |
Comprueba si el elemento es texto |
is_image() |
bool |
Comprueba si el elemento es una imagen |
is_path() |
bool |
Comprueba si el elemento es un trazado vectorial |
is_table() |
bool |
Comprueba si el elemento es una tabla |
is_structure() |
bool |
Comprueba si el elemento es un elemento de estructura |
as_text() |
`PdfText | None` |
as_image() |
`PdfImage | None` |
| Propiedad | Tipo | Descripción |
|---|---|---|
bbox |
tuple[float, float, float, float] |
Caja delimitadora |
TextChar
Representa un único carácter con posicionamiento y metadatos de fuente. Devuelto por PdfDocument.extract_chars().
from pdf_oxide import TextChar # or access via PdfDocument
| Atributo | Tipo | Descripción |
|---|---|---|
char |
str |
El carácter Unicode |
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
font_name |
str |
Nombre PostScript de la fuente |
font_size |
float |
Tamaño de fuente en puntos |
font_weight |
str |
Peso ("thin", "light", "normal", "medium", "semi-bold", "bold", "extra-bold", "black") |
is_italic |
bool |
Si el carácter está en cursiva |
color |
tuple[float, float, float] |
Color RGB (r, g, b), valores 0.0–1.0 |
rotation_degrees |
float |
Rotación del carácter en grados |
origin_x |
float |
Posición X del origen del texto |
origin_y |
float |
Posición Y del origen del texto |
advance_width |
float |
Ancho de avance del glifo |
mcid |
`int | None` |
Ejemplo
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
chars = doc.extract_chars(0)
for ch in chars[:5]:
print(f"'{ch.char}' at bbox={ch.bbox} "
f"font={ch.font_name} size={ch.font_size:.1f} "
f"weight={ch.font_weight} italic={ch.is_italic}")
TextSpan
Representa una secuencia de texto que comparte la misma fuente y estilo. Devuelto por PdfDocument.extract_spans().
| Atributo | Tipo | Descripción |
|---|---|---|
text |
str |
El contenido de texto |
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
font_name |
str |
Nombre PostScript de la fuente |
font_size |
float |
Tamaño de fuente en puntos |
is_bold |
bool |
Si el span está en negrita |
is_italic |
bool |
Si el span está en cursiva |
is_monospace |
bool |
Si la fuente es de ancho fijo (Courier, Consolas, etc.) |
char_widths |
list[float] |
Anchos de avance por glifo para cajas delimitadoras precisas |
color |
tuple[float, float, float] |
Color RGB (r, g, b), valores 0.0–1.0 |
Ejemplo
from pdf_oxide import PdfDocument
doc = PdfDocument("paper.pdf")
spans = doc.extract_spans(0)
for span in spans:
print(f"'{span.text}' font={span.font_name} size={span.font_size:.1f} "
f"bold={span.is_bold} italic={span.is_italic} color={span.color}")
Extracción de imágenes
extract_images() devuelve objetos ImageInfo con metadatos de imagen. Usa extract_image_bytes() para obtener los datos crudos de imagen aptos para guardar en disco.
Formato de retorno de extract_image_bytes()
Cada dict devuelto por extract_image_bytes() tiene las siguientes claves:
| Clave | Tipo | Descripción |
|---|---|---|
width |
int |
Ancho de la imagen en píxeles |
height |
int |
Alto de la imagen en píxeles |
data |
bytes |
Datos crudos de la imagen |
format |
str |
Formato de la imagen (p. ej. "png", "jpeg") |
Ejemplo
from pdf_oxide import PdfDocument
doc = PdfDocument("brochure.pdf")
images = doc.extract_image_bytes(0)
for i, img in enumerate(images):
print(f"Image {i}: {img['width']}x{img['height']}")
with open(f"image_{i}.{img['format']}", "wb") as f:
f.write(img["data"])
SearchResult
Representa una coincidencia de búsqueda de texto. Devuelto por search() y search_page().
| Atributo | Tipo | Descripción |
|---|---|---|
page |
int |
Índice de página basado en cero |
text |
str |
Texto coincidente |
x |
float |
Posición X en puntos PDF |
y |
float |
Posición Y en puntos PDF |
FormField
Representa un campo de formulario. Devuelto por PdfDocument.get_form_fields().
| Propiedad | Tipo | Descripción |
|---|---|---|
name |
str |
Nombre completamente cualificado del campo |
field_type |
str |
Tipo de campo: "text", "button", "choice", "signature" o "unknown" |
value |
`str | bool |
tooltip |
`str | None` |
bounds |
`tuple[float, float, float, float] | None` |
flags |
`int | None` |
max_length |
`int | None` |
is_readonly |
bool |
Si el campo es de solo lectura |
is_required |
bool |
Si el campo es obligatorio |
TextWord
Una secuencia de texto agrupada por palabras. Devuelta por PdfDocument.extract_words() y PdfPageRegion.extract_words().
| Propiedad | Tipo | Descripción |
|---|---|---|
text |
str |
El texto de la palabra |
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
font_name |
str |
Nombre PostScript de la fuente |
font_size |
float |
Tamaño de fuente en puntos |
is_bold |
bool |
Si la palabra está en negrita |
is_italic |
bool |
Si la palabra está en cursiva |
chars |
list[TextChar] |
Caracteres que la componen |
TextLine
Una secuencia de texto agrupada por líneas. Devuelta por PdfDocument.extract_text_lines() y PdfPageRegion.extract_text_lines().
| Propiedad | Tipo | Descripción |
|---|---|---|
text |
str |
El texto de la línea |
bbox |
tuple[float, float, float, float] |
Caja delimitadora (x0, y0, x1, y1) |
words |
list[TextWord] |
Palabras de la línea |
chars |
list[TextChar] |
Caracteres de la línea |
PdfPageRegion
Una región recortada de una página. Devuelta por PdfDocument.within() y PdfPage.region().
| Propiedad | Tipo | Descripción |
|---|---|---|
bbox |
tuple[float, float, float, float] |
Los límites de la región |
Métodos
region.extract_text() -> str
region.extract_words() -> list[TextWord]
region.extract_text_lines() -> list[TextLine]
region.extract_tables(table_settings: dict | None = None) -> list[dict]
region.extract_images() -> list
region.extract_paths() -> list
Métodos de extracción acotados a la caja delimitadora de la región.
LayoutParams
Parámetros de maquetación adaptativos calculados para una página. Devueltos por PdfDocument.page_layout_params().
| Propiedad | Tipo | Descripción |
|---|---|---|
word_gap_threshold |
float |
Umbral de separación entre palabras en puntos |
line_gap_threshold |
float |
Umbral de separación entre líneas en puntos |
median_char_width |
float |
Ancho mediano de carácter |
median_font_size |
float |
Tamaño mediano de fuente |
median_line_spacing |
float |
Interlineado mediano |
column_count |
int |
Número de columnas de texto detectadas |
ExtractionProfile
Un perfil de extracción de texto ajustable que se pasa a extract_words() / extract_text_lines().
from pdf_oxide import ExtractionProfile
Constructores estáticos
ExtractionProfile.conservative()
ExtractionProfile.aggressive()
ExtractionProfile.balanced()
ExtractionProfile.academic()
ExtractionProfile.policy()
ExtractionProfile.form()
ExtractionProfile.government()
ExtractionProfile.scanned_ocr()
ExtractionProfile.adaptive()
ExtractionProfile.available() -> list[str] # names of all built-in profiles
Propiedades
| Propiedad | Tipo | Descripción |
|---|---|---|
name |
str |
Nombre del perfil |
tj_offset_threshold |
float |
Umbral de salto de palabra por offset del array TJ |
word_margin_ratio |
float |
Proporción de margen de palabra |
space_threshold_em_ratio |
float |
Umbral de ancho de espacio (proporción em) |
space_char_multiplier |
float |
Multiplicador de carácter de espacio |
use_adaptive_threshold |
bool |
Si los umbrales adaptativos están habilitados |
OfficeConverter
Convierte documentos de Office (DOCX, XLSX, PPTX) a PDF. Requiere la feature office en la compilación de Rust.
from pdf_oxide import OfficeConverter
OfficeConverter() # instances are stateless; the conversion methods are also usable as static methods
Métodos
OfficeConverter.from_docx(path: str) -> Pdf
Convierte un documento de Word a un objeto Pdf.
OfficeConverter.from_docx_bytes(data: bytes) -> Pdf
Convierte bytes de un documento de Word a un objeto Pdf.
OfficeConverter.from_xlsx(path: str) -> Pdf
Convierte una hoja de cálculo de Excel a un objeto Pdf.
OfficeConverter.from_xlsx_bytes(data: bytes) -> Pdf
Convierte bytes de una hoja de cálculo de Excel a un objeto Pdf.
OfficeConverter.from_pptx(path: str) -> Pdf
Convierte una presentación de PowerPoint a un objeto Pdf.
OfficeConverter.from_pptx_bytes(data: bytes) -> Pdf
Convierte bytes de una presentación de PowerPoint a un objeto Pdf.
OfficeConverter.convert(path: str) -> Pdf
Autodetecta el formato y convierte cualquier documento de Office admitido a un objeto Pdf.
Ejemplo
from pdf_oxide import OfficeConverter
pdf = OfficeConverter.from_docx("report.docx")
pdf.save("report.pdf")
# Or use convert() for auto-detection
pdf = OfficeConverter.convert("spreadsheet.xlsx")
pdf.save("spreadsheet.pdf")
Clases de gráficos
Estas clases están disponibles para la creación avanzada de PDFs con gráficos:
Color
from pdf_oxide import Color
Color(r: float, g: float, b: float) # RGB, values 0.0-1.0
Color.from_hex("#ff0000")
Color.black()
Color.white()
Color.red()
Color.green()
Color.blue()
BlendMode
from pdf_oxide import BlendMode
BlendMode.NORMAL()
BlendMode.MULTIPLY()
BlendMode.SCREEN()
BlendMode.OVERLAY()
BlendMode.DARKEN()
BlendMode.LIGHTEN()
BlendMode.COLOR_DODGE()
BlendMode.COLOR_BURN()
BlendMode.HARD_LIGHT()
BlendMode.SOFT_LIGHT()
BlendMode.DIFFERENCE()
BlendMode.EXCLUSION()
ExtGState
from pdf_oxide import ExtGState
gs = ExtGState()
gs = gs.fill_alpha(0.5)
gs = gs.stroke_alpha(0.8)
gs = gs.alpha(0.5) # Set both fill and stroke
gs = gs.blend_mode(BlendMode.MULTIPLY())
gs = ExtGState.semi_transparent() # Preset
LineCap / LineJoin
from pdf_oxide import LineCap, LineJoin
LineCap.BUTT() # Default
LineCap.ROUND()
LineCap.SQUARE()
LineJoin.MITER() # Default
LineJoin.ROUND()
LineJoin.BEVEL()
Gradientes
from pdf_oxide import LinearGradient, RadialGradient, Color
# Linear gradient (fluent API)
grad = (LinearGradient()
.start(0, 0)
.end(100, 0)
.add_stop(0.0, Color.red())
.add_stop(1.0, Color.blue()))
# Convenience constructors
hgrad = LinearGradient.horizontal(200, Color.red(), Color.blue())
vgrad = LinearGradient.vertical(100, Color(1, 1, 0), Color(0, 0, 1))
# Radial gradient
rgrad = RadialGradient.centered(50, 50, 50)
rgrad = rgrad.add_stop(0.0, Color(1, 1, 0))
rgrad = rgrad.add_stop(1.0, Color(1, 0, 0))
PatternPresets
from pdf_oxide import PatternPresets, Color
PatternPresets.horizontal_stripes(width, height, stripe_height, color)
PatternPresets.vertical_stripes(width, height, stripe_width, color)
PatternPresets.checkerboard(size, color1, color2)
PatternPresets.dots(spacing, radius, color)
PatternPresets.diagonal_lines(size, line_width, color)
PatternPresets.crosshatch(size, line_width, color)
Clases de OCR
Requiere la feature ocr en la compilación de Rust.
OcrEngine
from pdf_oxide import OcrEngine, OcrConfig
engine = OcrEngine(
det_model_path: str,
rec_model_path: str,
dict_path: str,
config: OcrConfig | None = None
)
OcrConfig
from pdf_oxide import OcrConfig
config = OcrConfig(
det_threshold: float | None = None,
box_threshold: float | None = None,
rec_threshold: float | None = None,
num_threads: int | None = None,
max_candidates: int | None = None,
use_v5: bool = False
)
DocumentBuilder
Builder fluido para componer PDFs página a página. Consulta el ejemplo de más abajo y Crear desde cero.
from pdf_oxide import DocumentBuilder
Métodos a nivel de documento
| Método | Parámetros | Descripción |
|---|---|---|
DocumentBuilder() |
– | Construye un nuevo builder |
title(title) |
str |
Establece el título del documento |
author(author) |
str |
Establece el autor del documento |
subject(subject) |
str |
Establece el asunto del documento |
keywords(keywords) |
str |
Establece las palabras clave del documento |
creator(creator) |
str |
Establece el nombre de la aplicación productora |
on_open(script) |
str |
Establece una acción JavaScript de apertura a nivel de documento |
tagged_pdf_ua1() |
– | Emite un documento accesible Tagged PDF/UA-1 |
language(lang) |
str |
Establece el idioma del documento (p. ej. "en-US") |
role_map(custom, standard) |
str, str |
Asigna una etiqueta de estructura personalizada a una estándar |
register_embedded_font(name, font) |
str, EmbeddedFont |
Registra una fuente (consume el EmbeddedFont) |
Fábricas de páginas
builder.a4_page() -> FluentPageBuilder # 595 x 842 pt
builder.letter_page() -> FluentPageBuilder # 612 x 792 pt
builder.page(width: float, height: float) -> FluentPageBuilder
Salida
builder.build() -> bytes
builder.save(path: str) -> None
builder.save_encrypted(path: str, user_password: str, owner_password: str) -> None
builder.to_bytes_encrypted(user_password: str, owner_password: str) -> bytes
FluentPageBuilder
Almacena en búfer las operaciones a nivel de página hasta done(). Devuelto por DocumentBuilder.a4_page() / letter_page() / page(). Cada método devuelve self para encadenar; done() confirma la página y devuelve el DocumentBuilder padre.
Texto y maquetación
| Método | Parámetros | Descripción |
|---|---|---|
font(name, size) |
str, float |
Establece la fuente y el tamaño actuales |
at(x, y) |
float, float |
Mueve el cursor a una posición absoluta |
text(text) |
str |
Dibuja texto en el cursor |
heading(level, text) |
int, str |
Dibuja un encabezado (nivel 1–6) |
paragraph(text) |
str |
Dibuja un párrafo con ajuste de línea |
space(points) |
float |
Avanza espacio vertical |
horizontal_rule() |
– | Dibuja un divisor horizontal |
columns(column_count, gap_pt, text) |
int, float, str |
Flujo de texto multicolumna equilibrado |
footnote(ref_mark, note_text) |
str, str |
Marca de referencia en línea + nota al pie de página |
new_page_same_size() |
– | Inicia una nueva página con las mismas dimensiones |
measure(text) -> float |
str |
Mide el ancho del texto renderizado en puntos |
remaining_space() -> float |
– | Espacio vertical restante en la página |
Secuencias en línea
page.inline(text: str)
page.inline_bold(text: str)
page.inline_italic(text: str)
page.inline_color(text: str, r: float, g: float, b: float)
page.newline()
Enlaces y acciones
page.link_url(url: str)
page.link_page(page: int)
page.link_named(name: str)
page.link_javascript(script: str)
page.on_open(script: str)
page.on_close(script: str)
page.field_keystroke(script: str)
page.field_format(script: str)
page.field_validate(script: str)
page.field_calculate(script: str)
Anotaciones de marcado
page.highlight(color: tuple[float, float, float])
page.underline(color: tuple[float, float, float])
page.strikeout(color: tuple[float, float, float])
page.squiggly(color: tuple[float, float, float])
page.sticky_note(text: str)
page.sticky_note_at(x: float, y: float, text: str)
page.watermark(text: str)
page.watermark_confidential()
page.watermark_draft()
page.stamp(name: str)
page.freetext(x: float, y: float, w: float, h: float, text: str)
Widgets de AcroForm
page.text_field(name: str, x: float, y: float, w: float, h: float, default_value: str | None = None)
page.checkbox(name: str, x: float, y: float, w: float, h: float, checked: bool = False)
page.combo_box(name: str, x: float, y: float, w: float, h: float, options: list[str], selected: str | None = None)
page.radio_group(name: str, buttons: list[tuple[str, float, float, float, float]], selected: str | None = None)
page.push_button(name: str, x: float, y: float, w: float, h: float, caption: str)
page.signature_field(name: str, x: float, y: float, w: float, h: float)
Gráficos
page.rect(x: float, y: float, w: float, h: float)
page.filled_rect(x: float, y: float, w: float, h: float, r: float, g: float, b: float)
page.line(x1: float, y1: float, x2: float, y2: float)
page.text_in_rect(x: float, y: float, w: float, h: float, text: str, align: int | None = None)
page.stroke_rect(x, y, w, h, width=1.0, color=(0.0, 0.0, 0.0))
page.stroke_rect_dashed(x, y, w, h, dash, width=1.0, color=(0.0, 0.0, 0.0), phase=0.0)
page.stroke_line(x1, y1, x2, y2, width=1.0, color=(0.0, 0.0, 0.0))
page.stroke_line_dashed(x1, y1, x2, y2, dash, width=1.0, color=(0.0, 0.0, 0.0), phase=0.0)
Imágenes y códigos de barras
page.image_with_alt(bytes: bytes, x: float, y: float, w: float, h: float, alt_text: str)
page.image_artifact(bytes: bytes, x: float, y: float, w: float, h: float)
page.barcode_1d(barcode_type: int, data: str, x: float, y: float, w: float, h: float)
page.barcode_qr(data: str, x: float, y: float, size: float)
barcode_type: 0=Code128, 1=Code39, 2=EAN13, 3=EAN8, 4=UPCA, 5=ITF, 6=Code93, 7=Codabar.
Tablas
page.table(table: Table)
page.streaming_table(
columns: list[Column],
repeat_header: bool = False,
mode: str = "fixed",
sample_rows: int = 50,
min_col_width_pt: float = 20.0,
max_col_width_pt: float = 400.0,
max_rowspan: int = 1,
batch_size: int = 256
) -> StreamingTable
Confirmar
page.done() -> DocumentBuilder
EmbeddedFont
Una fuente TTF/OTF registrada con un DocumentBuilder.
from pdf_oxide import EmbeddedFont
EmbeddedFont.from_file(path: str) -> EmbeddedFont
EmbeddedFont.from_bytes(data: bytes, name: str | None = None) -> EmbeddedFont
| Propiedad | Tipo | Descripción |
|---|---|---|
name |
str |
El nombre registrado de la fuente |
Tablas
Objetos de valor para la API fluida de tablas.
Align
from pdf_oxide import Align
Align.LEFT # 0
Align.CENTER # 1
Align.RIGHT # 2
Column
from pdf_oxide import Column
Column(header: str, width: float = 100.0, align: Align | int | None = None)
| Propiedad | Tipo | Descripción |
|---|---|---|
header |
str |
Texto del encabezado de columna |
width |
float |
Ancho de la columna en puntos |
align |
int |
Alineación de la celda |
Table
from pdf_oxide import Table
Table(columns: list[Column], rows: list[list[str]], has_header: bool = False)
Una tabla con búfer consumida por FluentPageBuilder.table(). Con has_header=True, los encabezados de columna se renderizan como una fila de cabecera con estilo.
StreamingTable
Un handle de tabla con streaming de filas devuelto por FluentPageBuilder.streaming_table(), para tablas demasiado grandes como para materializarse de una vez.
| Método | Parámetros | Descripción |
|---|---|---|
push_row(cells) |
list[str] |
Añade una fila de cadenas de celda |
push_row_span(cells) |
list[tuple[str, int]] |
Añade una fila de celdas (text, colspan) |
flush() |
– | Vuelca el lote actual |
finish() |
– | Finaliza la tabla, devolviendo el FluentPageBuilder |
column_count() |
– → int |
Número de columnas |
pending_row_count() |
– → int |
Filas en búfer pero aún no confirmadas |
batch_count() |
– → int |
Número de lotes completados |
Plantillas de página
Artefactos de cabecera/pie de página repetidos que se aplican a lo largo de las páginas.
Artifact / ArtifactStyle
from pdf_oxide import Artifact, ArtifactStyle
Artifact() # empty artifact
Artifact.center(text: str) # centered artifact text
artifact.with_left(text: str) # add left-aligned text
style = ArtifactStyle()
style = style.font(name: str, size: float)
style = style.bold()
Header / Footer
from pdf_oxide import Header, Footer
Header() # or Header.center(text: str)
Footer() # or Footer.center(text: str)
PageTemplate
from pdf_oxide import PageTemplate, Header, Footer
template = (PageTemplate()
.header(Header.center("Confidential"))
.footer(Footer.center("Page")))
Firmas digitales
Firma, sella temporalmente y verifica PDFs (PAdES / LTV). Requiere las features signatures (y, opcionalmente, tsa-client) en la compilación de Rust.
Certificate
from pdf_oxide import Certificate
Certificate.load(data: bytes) -> Certificate # DER certificate (verify only)
Certificate.load_pem(cert_pem: str, key_pem: str) -> Certificate # signing credential
Certificate.load_pkcs12(data: bytes, password: str) -> Certificate # PKCS#12 / .p12 signing credential
| Método | Devuelve | Descripción |
|---|---|---|
subject() |
str |
DN del sujeto del certificado |
issuer() |
str |
DN del emisor del certificado |
serial() |
str |
Número de serie |
validity() |
tuple[int, int] |
Marcas de tiempo Unix (not_before, not_after) |
is_valid() |
bool |
Si el certificado se encuentra actualmente dentro de su ventana de validez |
Signature
Devuelta por PdfDocument.signatures().
| Propiedad / Método | Tipo | Descripción |
|---|---|---|
signer_name |
`str | None` |
reason |
`str | None` |
location |
`str | None` |
contact_info |
`str | None` |
signing_time |
`int | None` |
covers_whole_document |
bool |
Si la firma cubre todo el archivo |
pades_level |
PadesLevel |
Línea base PAdES detectada (B-B/B-T/B-LT) |
verify() |
bool |
Verifica la firma criptográficamente |
verify_detached(pdf_data) |
bool |
Verifica incluyendo el messageDigest frente a los bytes del archivo |
Timestamp
from pdf_oxide import Timestamp
Timestamp.parse(data: bytes) -> Timestamp
| Propiedad / Método | Tipo | Descripción |
|---|---|---|
time |
int |
Hora del sello temporal (Unix) |
serial |
str |
Número de serie de la respuesta de la TSA |
policy_oid |
str |
OID de política de la TSA |
tsa_name |
str |
Nombre de la TSA |
hash_algorithm |
int |
Código del algoritmo de hash del message-imprint |
message_imprint |
bytes |
El message imprint con hash |
verify() |
bool |
Verifica el token de sello temporal |
TsaClient
from pdf_oxide import TsaClient
client = TsaClient(
url: str,
username: str | None = None,
password: str | None = None,
timeout_seconds: int = 30,
hash_algorithm: int = 2,
use_nonce: bool = True,
cert_req: bool = True
)
client.request_timestamp(data: bytes) -> Timestamp
client.request_timestamp_hash(digest: bytes, algorithm: int = 2) -> Timestamp
PadesLevel
from pdf_oxide import PadesLevel
PadesLevel.B_B # baseline
PadesLevel.B_T # + trusted timestamp
PadesLevel.B_LT # + long-term validation material
PadesLevel.B_LTA # + archival timestamp
RevocationMaterial
from pdf_oxide import RevocationMaterial
RevocationMaterial(
certs: list[bytes] | None = None,
crls: list[bytes] | None = None,
ocsps: list[bytes] | None = None
)
Certificados, CRLs y respuestas OCSP codificados en DER para la firma B-LT.
Dss
Un Document Security Store analizado, devuelto por PdfDocument.dss().
| Propiedad | Tipo | Descripción |
|---|---|---|
certs |
list[bytes] |
Blobs DER de certificados a nivel de documento |
crls |
list[bytes] |
Blobs DER de CRL |
ocsps |
list[bytes] |
Blobs DER de respuestas OCSP |
vri |
list[str] |
Claves VRI por firma (SHA-1 en hex de /Contents) |
Funciones a nivel de módulo
from pdf_oxide import (
sign_pdf_bytes, sign_pdf_bytes_pades, has_document_timestamp,
generate_barcode_svg, generate_qr_svg,
plan_split_by_bookmarks, split_by_bookmarks,
)
Firma
sign_pdf_bytes(pdf_data: bytes, cert: Certificate, reason: str | None = None, location: str | None = None) -> bytes
Firma bytes crudos de PDF con un Certificate de firma cargado y devuelve el PDF firmado.
sign_pdf_bytes_pades(
pdf_data: bytes,
cert: Certificate,
level: PadesLevel,
tsa_url: str | None = None,
reason: str | None = None,
location: str | None = None,
revocation: RevocationMaterial | None = None
) -> bytes
Firma bytes crudos de PDF en un nivel de línea base PAdES. B_T/B_LT requieren un tsa_url.
has_document_timestamp(pdf_data: bytes) -> bool
Si el PDF lleva un sello temporal de archivo RFC 3161 a nivel de documento (PAdES-B-LTA).
Códigos de barras
generate_barcode_svg(barcode_type: int, data: str) -> str
generate_qr_svg(data: str, error_correction: int, size: int) -> str
Genera un código de barras 1D o un código QR como una cadena SVG. Requiere la feature barcodes.
División por marcadores
plan_split_by_bookmarks(src_bytes: bytes, title_prefix: str | None = None, ignore_case: bool = False, level: int = 1, include_front_matter: bool = True) -> list[dict]
split_by_bookmarks(src_bytes: bytes, title_prefix: str | None = None, ignore_case: bool = False, level: int = 1, include_front_matter: bool = True) -> list[tuple[dict, bytes]]
Planifica o realiza la división de un PDF en los límites de los marcadores. plan_* devuelve solo los metadatos de los segmentos; split_* devuelve cada segmento emparejado con sus bytes de PDF.
Aprovisionamiento de modelos de OCR
prefetch_models(languages: list[str]) -> str
model_manifest() -> str
prefetch_available() -> bool
Aprovisiona modelos de OCR para uso sin conexión / en entornos aislados, inspecciona el manifiesto de modelos (JSON) y comprueba si esta compilación puede descargar modelos.
Logging
setup_logging() -> None
set_log_level(level: str) -> None # "off" | "error" | "warn" | "info" | "debug" | "trace"
get_log_level() -> str
disable_logging() -> None
Ajuste del motor
set_max_ops_per_stream(limit: int | None) -> int | None
set_preserve_unmapped_glyphs(preserve: bool) -> bool
Ajusta el límite de operadores por stream (protección frente a entradas adversarias) y la preservación de U+FFFD para glifos sin mapear. Ambos devuelven el valor anterior.
Gobernanza criptográfica
crypto_active_provider() -> str
crypto_available_providers() -> list[str]
crypto_use_fips() -> None # install the FIPS aws-lc-rs provider (requires the fips feature)
crypto_set_policy(spec: str) -> None # e.g. "strict" or "compat;deny:rc4@write"
crypto_policy() -> str
crypto_inventory() -> list[str]
crypto_cbom() -> str # CycloneDX 1.6 CBOM (JSON)
API asíncrona
Envoltorios async/await que ejecutan operaciones bloqueantes en un pool de hilos. Los métodos reflejan sus equivalentes síncronos.
from pdf_oxide import AsyncPdfDocument, AsyncPdf, AsyncOfficeConverter
async def main():
doc = await AsyncPdfDocument.open("input.pdf")
text = await doc.extract_text(0)
await doc.close()
# Or use as an async context manager:
async with await AsyncPdfDocument.from_bytes(pdf_bytes) as doc:
md = await doc.to_markdown_all()
| Clase | Constructores | Notas |
|---|---|---|
AsyncPdfDocument |
await AsyncPdfDocument.open(path, password=None), await AsyncPdfDocument.from_bytes(data, password=None) |
Todos los métodos de PdfDocument están disponibles como awaitables; admite async with y .close() |
AsyncPdf |
envuelve los métodos de fábrica de Pdf |
await pdf.save(path), await pdf.to_bytes() |
AsyncOfficeConverter |
envuelve los métodos estáticos de OfficeConverter |
p. ej. await AsyncOfficeConverter.from_docx(path) |
Manejo de errores
PdfError
Todos los errores específicos del PDF lanzan PdfError:
from pdf_oxide import PdfDocument, PdfError
try:
doc = PdfDocument("file.pdf")
text = doc.extract_text(0)
except PdfError as e:
print(f"PDF error: {e}")
except FileNotFoundError:
print("File not found")
except IndexError:
print("Page index out of range")
Escenarios de error habituales:
| Excepción | Causa |
|---|---|
PdfError |
PDF mal formado, cifrado sin contraseña, fallo de análisis |
FileNotFoundError |
El archivo no existe |
IndexError |
El índice de página supera page_count() |
ValueError |
Argumento no válido (p. ej. índice de página negativo) |
Ejemplo completo
from pdf_oxide import PdfDocument, Pdf
# --- Extraction ---
doc = PdfDocument("input.pdf")
print(f"Pages: {doc.page_count()}")
for i in range(doc.page_count()):
text = doc.extract_text(i)
print(f"Page {i + 1}: {len(text)} characters")
# Character-level analysis
chars = doc.extract_chars(0)
fonts = set(ch.font_name for ch in chars)
print(f"Fonts on page 1: {fonts}")
# Image extraction
images = doc.extract_image_bytes(0)
for i, img in enumerate(images):
with open(f"extracted_{i}.{img['format']}", "wb") as f:
f.write(img["data"])
# --- Creation ---
pdf = Pdf.from_markdown("# Report\n\nGenerated by PDF Oxide.",
title="Report", author="PDF Oxide")
pdf.save("report.pdf")
# --- Editing ---
doc = PdfDocument("document.pdf")
doc.set_title("Updated Title")
doc.set_author("New Author")
doc.rotate_all_pages(90)
# Search and replace via DOM
page = doc.page(0)
for text in page.find_text_containing("DRAFT"):
page.set_text(text.id, "FINAL")
doc.save_page(page)
# Form filling
fields = doc.get_form_fields()
for f in fields:
print(f"{f.name} ({f.field_type}) = {f.value}")
doc.set_form_field_value("name", "John Doe")
# Merge another PDF
merged_count = doc.merge_from("appendix.pdf")
print(f"Merged {merged_count} pages")
doc.save("output.pdf")
# --- Search ---
results = doc.search("configuration", case_insensitive=True)
for r in results:
print(f"Page {r.page + 1}: '{r.text}' at ({r.x:.0f}, {r.y:.0f})")
Novedades de v0.3.38
DocumentBuilder / FluentPageBuilder / EmbeddedFont
from pdf_oxide import DocumentBuilder, EmbeddedFont, StampType
font = EmbeddedFont.from_file("DejaVuSans.ttf")
# Alt: EmbeddedFont.from_bytes(data: bytes, name: str | None = None)
(DocumentBuilder()
.register_embedded_font("DejaVu", font)
.letter_page() # or .a4_page() / .page(size)
.at(72, 720).font("DejaVu", 12).text("Hello")
.heading(1, "Title")
.paragraph("Body text with automatic wrapping")
# Annotations (15 methods)
.link_url("https://example.com")
.link_page(2)
.link_named("glossary")
.highlight((1.0, 1.0, 0.0))
.underline((0.0, 0.0, 1.0))
.strikeout((1.0, 0.0, 0.0))
.squiggly((1.0, 0.5, 0.0))
.sticky_note("Review this")
.stamp(StampType.APPROVED)
.freetext((100, 500, 200, 50), "Comment")
.watermark("DRAFT")
.watermark_confidential()
.watermark_draft()
# AcroForm widgets (5 types)
.text_field("name", 150, 400, 200, 20, "Jane Doe")
.checkbox("agree", 72, 380, 15, 15, True)
.combo_box("country", 150, 360, 200, 20, ["US", "UK"], "US")
.radio_group("tier", [("free", 72, 340, 15, 15), ("pro", 120, 340, 15, 15)], "pro")
.push_button("submit", 72, 300, 80, 25, "Submit")
# Graphics primitives
.rect(50, 270, 500, 2)
.filled_rect(50, 260, 500, 2, (0.9, 0.9, 0.9))
.line(50, 250, 550, 250)
.done()
.save_encrypted("out.pdf", "user-pw", "owner-pw"))
# Alt: .save("out.pdf") / .build() -> bytes
# Alt: .to_bytes_encrypted("user-pw", "owner-pw") -> bytes
Pipeline HTML + CSS
Pdf.from_html_css(html: str, css: str, font_bytes: bytes) -> Pdf
Pdf.from_html_css_with_fonts(html: str, css: str, fonts: list[tuple[str, bytes]]) -> Pdf
Consulta Crear desde HTML.
Verificación de firmas
from pdf_oxide import PdfDocument, Timestamp, TsaClient
doc = PdfDocument("signed.pdf")
doc.signature_count() # int
for sig in doc.signatures():
sig.signer_name # str
sig.reason # str | None
sig.location # str | None
sig.signing_time # datetime | None
sig.verify() # "Valid" | "Invalid" | "Unknown"
sig.verify_detached(pdf_bytes) # adds messageDigest check
# Timestamp
ts = Timestamp.parse(tst_bytes)
ts.time, ts.serial, ts.policy_oid, ts.tsa_name, ts.hash_algorithm, ts.message_imprint
# TSA client (behind `tsa-client` feature)
client = TsaClient(url="https://freetsa.org/tsr",
username=None, password=None,
timeout_seconds=30, hash_algorithm=2,
use_nonce=True, cert_req=True)
ts = client.request_timestamp(pdf_bytes)
ts = client.request_timestamp_hash(digest, algorithm=2)
Consulta Firmas digitales para más detalles.
Renderizado
doc.render_page_region(page: int, x: float, y: float, w: float, h: float, format: int = 0) -> bytes
doc.render_page_fit(page: int, fit_width: int, fit_height: int, format: int = 0) -> bytes
format: 0 = PNG, 1 = JPEG. Coordenadas en puntos PDF desde la esquina inferior izquierda.
Aplanado de Pdf
doc.flatten_to_images(dpi: int = 150) -> bytes
Other Language Bindings
PDF Oxide ofrece bindings nativos para todos los ecosistemas principales: Rust, Node.js, WASM, C#, Golang, Java, PHP, Ruby, C++, Swift, Kotlin, Dart, R, Julia, Zig, Scala, Clojure, Objective-C y Elixir.
Próximos pasos
- Tipos y enums — todos los tipos y enums compartidos
- Referencia de la API Page — iteración de página consistente entre bindings
- Primeros pasos con Python — tutorial