¿Cómo se guardan las imágenes en un PDF? XObject, filtros y máscaras
9 min de lectura
Cuando abres un PDF, la fotografía que ves ¿cómo está guardada dentro del archivo? La respuesta es más compleja de lo que parece a primera vista: los datos de imagen, la información de color, la máscara de transparencia y la información de colocación se guardan en sitios distintos. En este artículo explicamos la arquitectura de almacenamiento de imágenes del PDF y cómo se refleja eso en la extracción.
Image XObject: la estructura básica
En un PDF, una imagen se guarda como un objeto llamado Image XObject. Ese objeto consta de un diccionario y un flujo de datos:
<< /Type /XObject
/Subtype /Image
/Width 2400
/Height 1800
/ColorSpace /DeviceRGB
/BitsPerComponent 8
/Filter /DCTDecode
/Length 458392
>>
stream
...(datos JPEG)...
endstream
El significado de las claves:
| Clave | Significado |
|---|---|
| /Width, /Height | Dimensiones en píxeles |
| /ColorSpace | Espacio de color (DeviceRGB, DeviceCMYK, DeviceGray, Indexed) |
| /BitsPerComponent | Bits por canal (normalmente 8) |
| /Filter | Cómo están codificados los datos |
| /SMask | Si existe, referencia al objeto de máscara de transparencia |
| /Decode | Si los valores de color deben invertirse o no |
El punto clave: este diccionario no dice dónde está la imagen en la página. La información de posición y escala está en el flujo de contenido de la página:
q
400 0 0 300 100 500 cm % matriz de escala y posición
/Im1 Do % dibuja la imagen Im1
Q
Esa matriz significa "dibuja esta imagen con 400 puntos de ancho y 300 de alto, en la posición (100,500)".
Esta separación explica el comportamiento de la extracción en bruto: la extracción toma el objeto de imagen, no su colocación en la página. Una imagen que en la página aparece girada, recortada o reducida sale en la extracción en su estado original.
Filtros: cómo están codificados los datos
La clave /Filter indica con qué compresión están codificados los datos del flujo. Los más habituales:
/DCTDecode — compresión JPEG. Los datos del flujo son un archivo JPEG real. Es una decisión de diseño inteligente del PDF: al añadir un JPEG a un PDF, en lugar de decodificarlo y volver a comprimirlo lo guarda tal cual. Resultado: el archivo se mantiene pequeño y no hay pérdida de calidad adicional.
En la extracción en bruto puedes guardar esos datos directamente como .jpg: no hace falta ninguna conversión.
/FlateDecode — compresión zlib/deflate sin pérdidas. Al descomprimir los datos del flujo sale una secuencia de píxeles en bruto. En la extracción hay que envolver esos datos en un formato usable (normalmente PNG), porque una secuencia de píxeles en bruto no es por sí sola un archivo de imagen.
/JPXDecode — JPEG 2000. Es raro, pero se usa en algunos sistemas de escaneo. Se puede extraer directamente como .jp2, aunque muchos programas no abren ese formato.
/CCITTFaxDecode — compresión de fax, para documentos escaneados en blanco y negro. Es muy eficiente; el escaneo de una página A4 puede ocupar unas decenas de kilobytes. En la extracción es habitual envolverla en TIFF.
/JBIG2Decode — compresión avanzada para blanco y negro. Es más eficiente que CCITT pero tiene menos soporte.
/LZWDecode — una compresión sin pérdidas antigua, que también se usa en TIFF y GIF.
El formato de salida de la herramienta de extracción depende de ese filtro: DCTDecode → JPEG, FlateDecode → PNG, CCITTFaxDecode → TIFF. Por eso de un mismo PDF pueden salir archivos en formatos distintos.
Espacios de color y problemas de extracción
La clave /ColorSpace determina cómo se interpreta el color de la imagen:
/DeviceRGB — colores estándar de pantalla. Sale sin problemas.
/DeviceGray — escala de grises. Sin problemas.
/DeviceCMYK — colores de impresión. Aquí empiezan los problemas: muchos visores y navegadores no abren bien los JPEG CMYK o muestran los colores invertidos. Además, algunos JPEG CMYK usan la convención de codificación invertida de Adobe y se marcan con la secuencia /Decode [1 0 1 0 1 0 1 0]; esa información está en el objeto de imagen, no en el archivo JPEG extraído. Resultado: el archivo resultante puede verse en negativo.
/Indexed — color basado en paleta. Los datos de imagen contienen índices de paleta y los colores reales se guardan en un array de paleta aparte. Si durante la extracción no se aplica la paleta, la imagen sale con colores sin sentido.
/ICCBased — perfil de color incrustado. Para obtener el color correcto hay que trasladar también el perfil.
Por eso, en la extracción en bruto, los colores de algunas imágenes pueden verse "mal". No es un error; es la consecuencia de que la información de interpretación de color esté fuera del archivo de imagen.
Transparencia: el mecanismo SMask
En un PDF, la transparencia de una imagen no está incrustada en la propia imagen. Se guarda en un objeto de máscara suave (soft mask) aparte:
/SMask 15 0 R
El objeto número 15 es una imagen en escala de grises de las mismas dimensiones que la imagen principal. El valor de cada píxel indica la opacidad en ese punto: 0 es totalmente transparente, 255 totalmente opaco.
En la extracción en bruto, esos dos objetos se encuentran por separado y salen como archivos distintos. Resultado:
- La imagen principal sale sin información de transparencia, opaca. Un fondo que en el PDF se veía transparente puede aparecer ahora negro o blanco.
- El archivo de máscara, por sí solo, se ve como una silueta en blanco y negro. No es un archivo corrupto; es la máscara en sí.
Para recuperar la transparencia hay que combinar los dos en un editor de imagen: abre la imagen principal, aplica la máscara como canal alfa y guárdala como PNG.
También existe la clave /Mask, que se usa para máscaras de esténcil binarias (1 bit) o enmascarado por clave de color; funciona de otra manera que SMask pero genera un problema de separación parecido.
Por qué se trocean las imágenes
Una situación frecuente en la extracción en bruto: en la página hay una fotografía pero salen diez archivos en forma de franjas.
La causa es la gestión de memoria del generador de PDF. En lugar de procesar una imagen muy grande de una pieza, la lee en franjas horizontales y así la escribe en el archivo. Cada franja se convierte en un Image XObject independiente.
En la página se ven unidas porque el flujo de contenido coloca cada franja en una posición exactamente contigua:
q 612 80 0 0 0 712 cm /Im1 Do Q
q 612 80 0 0 0 632 cm /Im2 Do Q
q 612 80 0 0 0 552 cm /Im3 Do Q
Este comportamiento se ve sobre todo en los programas de escáner y en las salidas PDF de algunos programas de ofimática.
Para unirlas hay que juntar las piezas en un editor. Puedes deducir el orden por los números de los nombres de archivo, pero no es garantía; emparejarlas visualmente es más fiable.
El concepto de resolución efectiva
En un PDF, la "resolución" de una imagen no es una propiedad fija. Se calcula a partir de la relación entre dos valores:
PPP efectivos = ancho en píxeles / ancho físico en la página (en pulgadas)
Una imagen de 2400 píxeles dibujada con 8 pulgadas de ancho en la página está a 300 PPP. Esa misma imagen encajada en 4 pulgadas está a 600 PPP.
Esto explica por qué la extracción en bruto a veces da imágenes de calidad sorprendente: una fotografía que en la página se ve pequeña puede tener en su origen una resolución muy alta. Al generar el PDF la imagen no se redujo, solo se colocó en un área pequeña.
Lo contrario también es cierto: si el PDF ha pasado por una compresión, las imágenes pueden haberse reducido de verdad a baja resolución y la extracción en bruto dará esa baja resolución. Los píxeles perdidos no vuelven.
Imágenes invisibles
La extracción en bruto a veces devuelve imágenes que no has visto en ninguna página. Los motivos:
- Zonas que quedan fuera del trazado de recorte. Puede que solo se muestre una parte de una imagen; el objeto lleva la imagen entera.
- Imágenes tapadas. Un elemento dibujado después puede haber ocultado el que estaba debajo.
- Elementos colocados fuera de la página. El contenido que queda fuera del MediaBox sigue en el archivo.
- Objetos sin usar. Tras una edición, pueden quedar en el archivo imágenes a las que ya no hace referencia ninguna página.
El último punto es importante en términos de privacidad: para "borrar" una imagen de un PDF no basta con poner algo encima; el objeto sigue en el archivo y la extracción en bruto lo encuentra.
Por qué no se pueden extraer los gráficos vectoriales
La extracción en bruto solo encuentra objetos Image XObject. Los logotipos, esquemas y gráficos de un PDF suelen ser vectoriales: están definidos por instrucciones de dibujo en el flujo de contenido de la página, no son un objeto aparte.
Para "extraer" un logotipo vectorial hace falta otro enfoque: convertir la página a SVG y aislar ahí el logotipo.
Una prueba sencilla para distinguirlos: amplía mucho el elemento en el PDF. Si se pixela es ráster (extraíble); si se mantiene nítido es vectorial (no extraíble).
En resumen
En un PDF, cada imagen es un objeto Image XObject con su propio diccionario y su flujo de datos; la información de posición y escala, en cambio, está en el flujo de contenido de la página. Esa separación es la razón de que la extracción en bruto entregue la imagen original y no su estado en la página. Los datos se guardan, según el filtro, como JPEG real (DCTDecode) o como píxeles en bruto (FlateDecode), y de eso depende el formato de extracción. Como la transparencia vive en un objeto SMask aparte, se pierde en la extracción y salen dos archivos. Y como algunos generadores trocean las imágenes grandes en franjas, una sola fotografía puede salir como muchos archivos. Los gráficos vectoriales quedan fuera de este mecanismo; para ellos hace falta una conversión a SVG.
Preguntas frecuentes
¿El JPEG que hay dentro de un PDF es realmente un JPEG?
Sí; las imágenes codificadas con el filtro DCTDecode son datos JPEG reales y, al extraerlas del archivo, se pueden usar directamente como .jpg. Es una decisión de diseño inteligente del PDF: en lugar de decodificar el JPEG y volver a comprimirlo, lo guarda tal cual, así que el archivo se mantiene pequeño y no hay pérdida de calidad adicional. Las imágenes guardadas con FlateDecode, en cambio, son datos de píxel en bruto y al extraerlas hay que envolverlas en un formato como PNG.
¿Cómo se determina la resolución de una imagen en un PDF?
Se calcula a partir de la relación entre las dimensiones en píxeles del objeto de imagen (Width/Height) y el espacio físico que ocupa en la página. Si una imagen de 2400 píxeles de ancho se dibuja con 8 pulgadas de ancho en la página, su resolución efectiva es de 300 PPP. Si esa misma imagen se encaja en 4 pulgadas, pasa a ser de 600 PPP. Es decir, en un PDF la 'resolución' de una imagen no es una propiedad fija, sino un resultado que depende de la escala de colocación.
¿Por qué algunas imágenes salen partidas en franjas horizontales?
Normalmente por eficiencia de memoria. Los programas de escáner y algunos generadores de PDF, al procesar imágenes muy grandes, en lugar de cargarlas enteras en memoria las procesan por franjas y así las escriben en el archivo. En la página se ven unidas porque las franjas se colocan en posiciones exactamente contiguas. La extracción en bruto encuentra cada franja como objeto independiente y la entrega como archivo aparte.
¿Qué es un SMask y por qué sale como archivo aparte?
Un SMask (máscara suave) es una imagen en escala de grises independiente que lleva la información de transparencia de otra imagen. Indica con un valor de 0 a 255 cuánta transparencia tiene cada píxel. Como en el PDF la transparencia no está incrustada en la propia imagen sino en ese objeto aparte, la extracción en bruto entrega los dos como archivos separados y la transparencia se pierde. Para recuperarla hay que combinarlos en un editor.
Pruébalo ahora mismo con PDF'ten Görsel Çıkar (Ham).
Probar PDF'ten Görsel Çıkar (Ham)