Archivos PNM: La Familia de Formatos de Mapa de Bits Portables (PBM, PGM, PPM, PNM)
La familia de formatos Netpbm — PBM (Portable BitMap), PGM (Portable GrayMap), PPM (Portable PixMap) y el término colectivo PNM (Portable aNyMap) — se encuentran entre los formatos de imagen más simples jamás diseñados. Creados por Jef Poskanzer en 1988 y desarrollados a través del toolkit Netpbm, estos formatos priorizan la simplicidad y la portabilidad sobre la eficiencia. Cada formato es texto ASCII plano o datos binarios con una cabecera ASCII mínima, lo que los hace trivialmente analizables en cualquier lenguaje de programación sin bibliotecas. A pesar de su antigüedad, siguen en uso activo en computación científica, investigación de procesamiento de imágenes y pipelines de herramientas Unix.
Los Cuatro Formatos
PBM — Portable BitMap (blanco y negro de 1 bit)
PBM almacena imágenes biniveles — cada píxel es blanco (0) o negro (1). Usado para texto escaneado, códigos QR, códigos de barras y cualquier imagen puramente binaria.
Formato ASCII (P1):
P1
# Creado por GIMP
4 4
0 0 0 0
0 1 1 0
0 1 1 0
0 0 0 0
Formato binario (P4): Misma cabecera, datos de píxeles empaquetados 8 píxeles por byte.
PGM — Portable GrayMap (escala de grises de 8 o 16 bits)
PGM almacena imágenes en escala de grises donde cada píxel es un valor de 0 (negro) a MAXVAL (blanco). MAXVAL se especifica en la cabecera y puede ser hasta 65.535.
Formato binario (P5): Cabecera ASCII, datos de píxeles binarios crudos (1 byte/píxel para MAXVAL ≤ 255, 2 bytes big-endian para MAXVAL > 255).
PPM — Portable PixMap (RGB de 24 bits)
PPM almacena imágenes a todo color con tres canales de color (R, G, B), cada uno de 0 a MAXVAL (típicamente 255).
Formato ASCII (P3):
P3
# 2x2 píxeles rojos y azules
2 2
255
255 0 0 0 0 255
255 0 0 0 0 255
Formato binario (P6): Misma cabecera, datos de píxeles binarios crudos (3 bytes por píxel para color de 8 bits).
PNM — Nombre Colectivo
PNM no es un formato separado — es el término colectivo para toda la familia. Un archivo .pnm puede contener datos PBM, PGM o PPM. La mayoría de las herramientas detectan automáticamente qué subformato contiene el archivo basándose en el número mágico de la cabecera.
Números Mágicos
| Mágico | Formato | Variante |
|---|---|---|
| P1 | PBM | ASCII |
| P2 | PGM | ASCII |
| P3 | PPM | ASCII |
| P4 | PBM | Binario |
| P5 | PGM | Binario |
| P6 | PPM | Binario |
| P7 | PAM | Binario |
Por Qué Estos Formatos Siguen Siendo Relevantes
Cero complejidad de parser: Leer un archivo PPM binario solo requiere:
- Leer líneas hasta encontrar ancho, alto y maxval en la cabecera
- Leer
ancho × alto × 3bytes crudos para los datos de píxeles
Compatibilidad con pipelines: Los flujos de trabajo de tuberías Unix pueden encadenar herramientas que generan y consumen PNM:
# Capturar pantalla → convertir a escala de grises → umbral → contar píxeles negros
scrot - | pngtopnm | ppmtopgm | pgmthresh 128 | ...
Toolkit Netpbm: El paquete Netpbm incluye más de 300 programas para convertir entre formatos de imagen y realizar operaciones básicas de imagen.
Sin restricciones de patentes: PNM es completamente libre de patentes o restricciones de licencias.
Conversión A y Desde PNM
PNG a PPM (para obtener píxeles crudos para procesamiento):
convert entrada.png salida.ppm
# O usando Netpbm:
pngtopnm entrada.png > salida.pnm
PPM a PNG (tras el procesamiento, volver a un formato útil):
convert salida.ppm resultado.png
# O:
pnmtopng salida.ppm > resultado.png
JPEG a PGM (escala de grises para visión por computador):
convert entrada.jpg -colorspace Gray salida.pgm
Cualquier formato a PBM (umbralización binivel):
convert entrada.png -threshold 50% salida.pbm
PNM en Programación
Python (sin PIL/Pillow)
Lectura de un archivo PPM binario desde cero:
def leer_ppm(nombre_archivo):
with open(nombre_archivo, 'rb') as f:
assert f.readline().strip() == b'P6'
linea = f.readline()
while linea.startswith(b'#'):
linea = f.readline()
ancho, alto = map(int, linea.split())
maxval = int(f.readline().strip())
datos = f.read()
pixeles = []
for i in range(0, ancho * alto * 3, 3):
r, g, b = datos[i], datos[i+1], datos[i+2]
pixeles.append((r, g, b))
return ancho, alto, maxval, pixeles
Consideraciones de Rendimiento
Los formatos PNM binarios son sin comprimir — un archivo PPM de 1920×1080 es exactamente 1920 × 1080 × 3 = 6.220.800 bytes (~6 MB). Para flujos de trabajo donde el espacio en disco importa, PNG o TIFF son mejores opciones.
Las variantes ASCII (P1, P2, P3) son aún más grandes y lentas de analizar. Usa variantes binarias (P4, P5, P6) para cualquier trabajo sensible al rendimiento.
Herramientas que Generan o Aceptan PNM
- SANE (Linux scanner driver) — genera PNM
- dcraw — convertidor de RAW de cámara, puede generar PPM
- GraphicsMagick / ImageMagick — soporte PNM completo
- GIMP — lee y escribe PNM de forma nativa
- OpenCV — lee PNM mediante
cv2.imread() - Netpbm toolkit — más de 300 herramientas especializadas
- ImageJ / Fiji — herramienta de bioimagen, lee PNM