Introducción: Qué Sucede Bajo el Capó Cuando Se Escribe un Archivo DICOM
Cada archivo DICOM es, en última instancia, una secuencia de bytes en disco. Sobre esa secuencia de bytes, el estándar superpone una estructura de tags, longitudes, value representations y valores que permite a sistemas de imagen diversos intercambiar estudios de forma fiable. Pero las reglas para cómo se serializan esas estructuras — el orden de bytes, la ubicación de la VR, el tamaño del campo de longitud — las gobierna un pequeño conjunto de transfer syntaxes. Para los ingenieros TI radiológica que depuran migraciones, construyen herramientas de integración o analizan por qué un PACS rechaza un estudio, entender cómo se codifican los tags DICOM en disco es invaluable.
Este artículo recorre la anatomía binaria de un tag DICOM, explica la diferencia entre orden little-endian y big-endian, contrasta las codificaciones VR implícita y explícita, y muestra cómo se ven el preámbulo del archivo y el marcador DICM. Al final podrás mirar un volcado hex de un archivo DICOM e identificar cada tag, longitud y valor. Para inspeccionar un archivo DICOM a nivel de metadatos (sin ir a hex), usa nuestro Visor de Tags DICOM o explora el data dictionary en el Explorador de Tags DICOM.
Para una referencia de mayor nivel sobre grupos y significados de tags, ver Entendiendo los Tags DICOM. Para el tema relacionado del sistema de tipos de datos, lee referencia de tipos VR DICOM. Y para el ángulo de de-identificación sobre tags específicos del fabricante, mira tags privados DICOM explicados.
El Preámbulo del Archivo DICOM y el Magic Number DICM
Un archivo DICOM Part 10 estándar empieza con una estructura fija:
- 128 bytes de preámbulo a cero. Originalmente pensado para permitir que el archivo empiece con datos arbitrarios específicos de la aplicación; en la práctica casi siempre todo a cero.
- 4 bytes de magic number:
DICMen ASCII. Es como los lectores confirman que un archivo está en formato DICOM Part 10. - El grupo File Meta Information (grupo 0002), que siempre está codificado en Explicit VR Little Endian independientemente del transfer syntax del resto del archivo.
- El dataset, codificado según el transfer syntax declarado en
(0002,0010)Transfer Syntax UID.
El preámbulo de 128 bytes existe por razones históricas. El magic DICM en el offset 128 es la forma universal en que los lectores detectan DICOM. Algunas herramientas se saltan la comprobación del preámbulo; algunos sistemas intermedios lo eliminan, llevando a archivos que técnicamente son datasets válidos pero no Part 10 conformantes.
Orden de Bytes: Little Endian Domina
Los ordenadores pueden almacenar números multi-byte en dos órdenes:
- Little-endian: El byte menos significativo viene primero. El número de 16 bits
0x0010se almacena como10 00en disco. - Big-endian: El byte más significativo viene primero. El mismo número se almacena como
00 10.
DICOM define transfer syntaxes para ambos órdenes de bytes, pero en la práctica little-endian domina. El transfer syntax por defecto en DICOM es 1.2.840.10008.1.2, que es Implicit VR Little Endian. El syntax explícito más usado es 1.2.840.10008.1.2.1, Explicit VR Little Endian. Existen transfer syntaxes big-endian pero son raros y se retiraron de uso nuevo en 2006.
Así que cuando lees un tag DICOM (0010,0010) en disco, los bytes que ves son 10 00 10 00: grupo 0010 en little-endian (10 00) seguido del elemento 0010 en little-endian (10 00). Reconocer este patrón es la primera habilidad para leer DICOM en un editor hex.
Implicit VR Little Endian: el Formato Compacto
En Implicit VR Little Endian (transfer syntax UID 1.2.840.10008.1.2), cada elemento de datos se codifica como:
[grupo: 2 bytes LE] [elemento: 2 bytes LE] [longitud: 4 bytes LE] [valor: bytes]
La VR no se almacena en el archivo. Para saber si el valor es texto, un entero o una secuencia, el lector debe buscar el tag en el data dictionary público de DICOM.
Por ejemplo, el tag (0010,0010) Patient’s Name con el valor “DOE^JUAN^A” (10 caracteres) se codifica como:
10 00 10 00 <- tag (0010,0010) little-endian
0A 00 00 00 <- longitud 10 little-endian
44 4F 45 5E 4A 55 41 4E 5E 41 <- "DOE^JUAN^A" en ASCII
Implicit VR es compacto (sin dos bytes extra por elemento para la VR) pero no puede describir tags privados cuya VR es desconocida para el lector. Es la principal debilidad del formato y causa frecuente de fallos cuando elementos privados viajan entre sistemas.
Explicit VR Little Endian: el Default Moderno
En Explicit VR Little Endian (transfer syntax UID 1.2.840.10008.1.2.1), cada elemento coloca la VR de dos letras después del tag, antes de la longitud. El tamaño del campo de longitud depende de la VR:
- VRs de forma corta (la mayoría de tipos string y numéricos pequeños — LO, SH, CS, UI, PN, DA, TM, US, UL, FL, FD, IS, DS, AS, AE, AT, etc.) usan una longitud de 2 bytes:
[grupo: 2] [elemento: 2] [VR: 2] [longitud: 2] [valor:] - VRs de forma larga (OB, OW, OF, OD, OL, SQ, UT, UC, UR, UN) usan 2 bytes reservados seguidos de una longitud de 4 bytes:
[grupo: 2] [elemento: 2] [VR: 2] [reservado: 2] [longitud: 4] [valor:]
El mismo Patient’s Name codificado en Explicit VR Little Endian se convierte en:
10 00 10 00 <- tag (0010,0010)
50 4E <- VR "PN" en ASCII
0A 00 <- longitud 10 (forma 2 bytes)
44 4F 45 5E 4A 55 41 4E 5E 41 <- "DOE^JUAN^A"
Explicit VR es dos bytes más grande por elemento pero soluciona el problema de tags privados: cualquier lector puede determinar el tipo de dato sin necesitar el diccionario del sistema origen. Por eso Explicit VR Little Endian se recomienda para cualquier DICOM que se compartirá entre fabricantes.
El Grupo File Meta Information: Siempre Explicit VR Little Endian
El grupo 0002 — el File Meta Information — es especial. Independientemente de qué transfer syntax use el resto del archivo, el grupo 0002 está siempre codificado en Explicit VR Little Endian. Esto es para que cualquier lector pueda encontrar (0002,0010) Transfer Syntax UID al inicio del archivo y determinar cómo decodificar el resto.
El grupo 0002 contiene metadatos esenciales:
(0002,0001)File Meta Information Version (OB, fijo a00 01)(0002,0002)Media Storage SOP Class UID (UI)(0002,0003)Media Storage SOP Instance UID (UI)(0002,0010)Transfer Syntax UID (UI)(0002,0012)Implementation Class UID (UI)(0002,0013)Implementation Version Name (SH)
Si alguna vez ves un archivo que viola esta regla — grupo 0002 no en Explicit VR Little Endian — es no conformante y muchos lectores se negarán a parsearlo.
Campos de Longitud: Definida, Indefinida y Secuencias
El campo de longitud le dice al lector cuántos bytes ocupa el valor. La mayoría de elementos usan longitudes definidas: una cuenta exacta de bytes.
Algunos casos especiales usan longitud indefinida, codificada como FFFFFFFF:
- Secuencias (SQ): Una secuencia puede tener longitud indefinida, en cuyo caso se termina con un tag Sequence Delimitation Item
(FFFE,E0DD). - Items dentro de una secuencia: Cada item empieza con
(FFFE,E000). Los items pueden ser de longitud definida o indefinida (terminados por(FFFE,E00D)). - Encapsulated Pixel Data: Pixel Data
(7FE0,0010)en transfer syntaxes comprimidos usa longitud indefinida y va seguido de Basic Offset Table y fragmentos individuales, terminado por Sequence Delimitation Item.
Mal interpretar estos marcadores especiales es causa común de fallos de parser. (FFFE,E000), (FFFE,E00D) y (FFFE,E0DD) no son elementos regulares — son estructuras de control dentro de secuencias y datos encapsulados.
Transfer Syntaxes Comprimidos
Para imágenes, DICOM define transfer syntaxes que comprimen el pixel data manteniendo los metadatos en Explicit VR Little Endian:
- JPEG Baseline (
1.2.840.10008.1.2.4.50): JPEG con pérdida de 8 bits. Común en archivos antiguos. - JPEG Lossless (
1.2.840.10008.1.2.4.70): JPEG matemáticamente sin pérdida. Común en radiografía. - JPEG 2000 Lossless (
1.2.840.10008.1.2.4.90): JPEG 2000 en modo sin pérdida. - RLE Lossless (
1.2.840.10008.1.2.5): Run-length encoding, muy ligero. - HTJ2K (
1.2.840.10008.1.2.4.201): High-Throughput JPEG 2000, cada vez más común.
En todos estos, solo el elemento Pixel Data está comprimido; todo lo demás es Explicit VR Little Endian plano. Así que si puedes leer los metadatos de un archivo no comprimido, puedes leer los metadatos de un archivo comprimido también.
Leer un Archivo DICOM en un Editor Hex: Ejemplo Trabajado
Supón que abres un archivo DICOM en un editor hex y ves (después del preámbulo de 128 bytes y DICM en offset 128):
0000 0080: 44 49 43 4D DICM
0000 0084: 02 00 00 00 55 4C 04 00 BC 00 00 00 ..UL.....
0000 0090: 02 00 02 00 55 49 1A 00 31 2E 32 2E 38 34 30 ....UI..1.2.840
0000 009F: 2E 31 30 30 30 38 2E 35 2E 31 2E 34 2E 31 2E 32 .10008.5.1.4.1.2
Leyendo byte a byte:
- Offset 0x84:
02 00 00 00= tag (0002, 0000) (longitud de grupo). - Luego VR
UL, longitud 4, valorBC 00 00 00= siguen 188 bytes del grupo 0002. - Offset 0x90:
02 00 02 00= tag (0002, 0002) Media Storage SOP Class UID. - VR
UI, longitud1A 00= 26 bytes. - Valor:
1.2.840.10008.5.1.4.1.2— truncado aquí pero ya puedes ver el UID en notación punto-decimal.
Con esta habilidad puedes verificar la estructura del archivo DICOM cuando un visor falla, identificar dónde se rompe el parseo y confirmar si un archivo está corrupto a nivel de byte o solo a nivel de metadatos.
Pitfalls de Codificación en la Práctica
- Los valores string de longitud impar deben rellenarse. DICOM exige que cada campo de valor tenga longitud par. Las VRs de cadena rellenan con un espacio final (
0x20) o, para UI, un null final (0x00). Las herramientas que olvidan esto producen archivos no conformantes. - VR equivocada para un tag. Si un escritor codifica Patient’s Name con VR
LOen lugar dePNen Explicit VR, los lectores estrictos lo rechazarán. - Grupo 0002 en VR implícita. Los lectores esperan grupo 0002 en Explicit VR Little Endian y pueden fallar antes de llegar al resto del archivo.
- Transfer syntax mixto en un mismo archivo. El dataset debe ser uniforme tras el grupo 0002. Concatenar fragmentos de transfer syntaxes distintos produce un archivo corrupto.
- Delimitadores de item mal interpretados. Las herramientas que tratan
(FFFE,E000)como tag regular intentan buscarlo en el diccionario público y fallan. - Asunción de endianness equivocada. Si una herramienta lee un archivo Little Endian como Big Endian, cada valor multi-byte queda byte-swapped y los tags son irreconocibles.
Mejores Prácticas para TI Radiológica
- Usa Explicit VR Little Endian como transfer syntax por defecto para cualquier exportación o migración que cruce fronteras de fabricante.
- Verifica los 128 bytes de preámbulo + DICM en cada archivo ingestado. Rechaza o repara archivos sin la cabecera Part 10.
- Al depurar, mira primero el grupo 0002. La mayoría de problemas de codificación cascadean desde un File Meta Information malformado.
- Rellena valores de longitud impar correctamente. Valida la conformidad antes de transmitir.
- Preserva el ancho del campo de longitud para VRs de forma larga. Errores off-by-two aquí corrompen cada elemento siguiente.
- Lleva un registro de qué transfer syntaxes soporta cada sistema de tu entorno. Planifica pasos de re-codificación cuando origen y destino difieran.
Conclusión
La codificación on-disk de DICOM está bien definida pero es implacable. Orden de bytes little-endian, la distinción VR implícita/explícita, el rol especial del grupo 0002 y la estructura cuidadosa de campos de longitud y delimitadores de item merecen interiorizarse para cualquier ingeniero TI radiológica que trabaja con datos de imagen a nivel de byte. Una vez puedas leer un archivo DICOM en un editor hex, puedes depurar casi cualquier problema de workflow de imagen con confianza. Continúa tu lectura con nuestros artículos compañeros sobre tags privados DICOM, tipos VR DICOM y la referencia de campos de tag más amplia.