lundi 23 juillet 2018

L'encodage d'objet DICOM - Format Classique (Partie 2)

Ce billet constitue la seconde partie sur la présentation de l'encodage d'objets DICOM avec le format classique (décrit dans la partie PS3.5). Afin de comprendre la suite de cet article, il est préférable d'avoir lu la première partie qui introduit les concepts d'endianisme et du système Implicit VR.

2.2. L'encodage Explicit VR


Le système Explicit VR est très proche du système Implicit VR. Il reprend exactement le même formalisme mais en ajoutant un champ pour stocker le type de l'élément (la VR). Avec ce système, il n'y a plus de risque de non interprétation des données car la VR est incluse dans l'encodage de l'élément. En contrepartie, l'espace utilisé pour représenter un élément est un peu plus conséquent. Suivant la VR, deux codages sont possibles (voir DICOM PS3.5 section 7.1.2):
           
Pour les VR de type OB, OD, OF, OL, OW, SQ, UC, UR, UT ou UN
           
Pour les VR autres que celles listées dans la figure ci-dessus

Exemple 1 : Encodage Explicit avec une VR textuelle de type « DA »
pour encoder l'élément
(0010,0030) DA #8 [20180608] PatientBirthDate
  • Le numéro de groupe du tag est un nombre codé sur 2 octets, il faut donc appliquer l'endianisme. « 00 10 » sera donc encodé « 10 00 » ;
  • La même logique que pour le numéro de groupe s'applique au numéro d'élément. « 00 30 » sera donc encodé « 30 00 » ;
  • La VR est une donnée textuelle, elle n'est donc pas affectée par l'endianisme. Les deux caractères « DA » sont donc codés par « 44 41 » ;
  • La chaîne « 20180608 » est composée de 8 caractères. Cette longueur de 8 est représentée en hexadécimal sur 2 octets par « 00 08 ». Ce nombre étant multi-octets, l'endianisme s'applique. « 00 08 » sera donc encodé « 08 00 » ;
  • Enfin « 20180608 » est une chaîne textuelle, l'endianisme ne s'applique donc pas. La longueur du texte étant paire, il n'est donc pas nécessaire de la compléter par un caractère NULL. La chaîne finale sera donc encodée « 32 30 31 38 30 36 30 38 ».
L'élément Patient's Birth Date sera donc encodé sur 14 octets dont la valeur binaire est : « 10 00 30 00 08 00 32 30 31 38 30 36 30 38 »



Exemple 2 : Encodage Explicit avec une VR binaire de type « OB »
pour encoder l'élément
(7FE0,0010) OB #25 [pixel Value] PixelData
  • Le numéro de groupe du tag est un nombre codé sur 2 octets, il faut donc appliquer l'endianisme. « 7F E0 » sera donc encodé « E0 7F » ;
  • La même logique que pour le numéro de groupe s'applique au numéro d'élément. « 00 10 » sera donc encodé « 10 00 » ;
  • La VR est une données textuelle de type OB, elle est donc codée sur 4 octets et n'est donc pas affectée par l'endianisme. Pour les 4 octets, DICOM indique que les deux octets de poids fort (je rappelle que l'on est en Little Endian) valent « 00 00 ». Les deux caractères « OB » sont donc encodés par « 4F 42 00 00 » ;
  • Nous voulons encoder une image de 5x5 pixels avec une VR de type « OB » (1 octet par pixel), soit 5x5=25 pixels. La chaîne étant de longueur impaire, il faudra ajouter le caractère NULL pour obtenir une longueur de 26. Cette longueur de 26 est représentée en hexadécimal sur 4 octets par « 00 00 00 1A ». Ce nombre étant multi-octets, l'endianisme s'applique. « 00 00 00 1A » sera donc encodé « 1A 00 00 00 » ;
  • Supposons que la valeur des 25 pixels soit « 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 ». La VR « OB » étant codé sur 1 octet, l'endianisme ne s'applique pas. De plus, DICOM impose une longueur paire. On ajoute donc le caractère NULL binaire 0x00. On obtient donc en final la chaîne encodée suivante : « 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13 14 15 16 17 18 00 ».

Remarque : Il n'est pas possible de mélanger des Data Element encodés en Implicit VR et en Explicit VR dans un même objet DICOM.

3. Exemple d'encodage d'un objet DICOM


Nous savons maintenant encoder des Data Element. Essayons d'encoder un objet DICOM composé des deux Data Element suivants.

(0008,0018) UI #6 [1.2.3] SOPInstanceUID
(0010,0040) CS #2 [M] PatientSex

L'encodage d'objet DICOM consiste à enchaîner les différents Data Element. Pour cet exemple, nous allons utiliser l'encodage Implicit VR. Voici le résultat de l'encodage de cet objet:
           
Exemple d'objet DICOM (Cliquer pour agrandir)

4. L'encodage des séquences


Jusqu'à présent, nous avons vu comment encoder des Data Element et des objets DICOM. Mais voilà, il existe dans le standard un type de Data Element particulier qui permet de contenir des objets DICOM, le type SQ.
Pour inclure un objet dans un autre, il faut pouvoir délimiter où commence et où se termine l'objet à imbriquer. DICOM propose deux méthodes pour marquer cette limite : la solution « Explicit Length » et la solution « Undefined Length ».
Quelque soit la méthode choisie, DICOM définit les règles d'encodages suivantes concernant un Data Element de type SQ:
  • Chaque objet DICOM contenu dans une séquence est encodé comme un Item. Une séquence peut avoir plusieurs Items ;
  • Une séquence peut utiliser l'encodage « Explicit Length » ou « Undefined length » ;
  • Un Item peut utiliser l'encodage « Explicit Length » ou « Undefined Length ».
Dans les sections suivantes, nous utiliserons l'encodage Implicit VR pour présenter les méthodes « Explicit Length » et « Undefined Length ». 

4.1. L'encodage d'une séquence en « Undefined Length »


L'encodage « Undefined Length » permet de ne pas connaître la longueur des objets (des items) à intégrer dans la séquence. Pour délimiter un objet, DICOM utilise un marqueur de début et de fin (à la manière de XML qui utilise des balises pour délimiter une valeur).
Il existe en DICOM des « marqueurs » pour délimiter une séquence et des « marqueurs » pour délimiter les /items.
Puisque qu'en DICOM tout est Data Element et que la règle générale d'encodage (Implicit VR ou Explicit VR) est que chaque Data Element est composé d'un Tag, d'une longueur et d'une valeur. Il va falloir jouer avec ces 3 champs pour créer des marqueurs.

4.1.1 Règles d'encodages


Pour représenter les marqueurs, DICOM donne des valeurs particulières aux champs « Tag », « Length » ou « Value ».
Ainsi le marqueur de début d'une séquence est définit par un Data Element qui a les spécificités suivantes :
  • Le champ « Tag » doit avoir une VR SQ ;
  • Le champ « Length » doit avoir la valeur FFFFFFFFH (indique que la taille est inconnue) ;
  • Le champ « Value » contient les différents Item.
Le marqueur de fin de séquence est définit par un Data Element se situant après le dernier item et ayant les caractéristiques suivantes:
  • Le champ « Tag » doit avoir la valeur (FFFE, E0DD) ;
  • Le champ « Length » doit avoir la valeur 00000000H ;
  • Pas de présence du champ « Value ».
           
Marqueurs de séquence (Cliquer pour agrandir)

Le marqueur de début d'item est définit par un Data Element qui a les spécificités suivantes:
  • Le champ « Tag » doit avoir la valeur (FFFE, E000) ;
  • Le champ « Length » doit avoir la valeur FFFFFFFFH ;
  • Le champ « Value » contient l'objet DICOM.

Le marqueur de fin d'item est définit par un Data Element se situant après l'objet DICOM et ayant les caractéristiques suivantes:
  • Le champ « Tag » doit avoir la valeur (FFFE, E00D) ;
  • Le champ « Length » doit avoir la valeur 00000000H ;
  • Pas de présence du champ « Value ».
Marqueur d'Item (Cliquer pour agrandir)

Remarque : Puisque les Data Element (FFFE, E000), (FFFE, E00D) et (FFFE, E0DD) n'ont pas de valeur, il n'ont pas besoin d'avoir une VR (la VR de ces 3 éléments n'existe pas).

4.1.2. Exemple d'encodage d'une séquence en « Undefined Length »


Supposons que l'on dispose de la séquence suivante à encoder en Implicit VR. Cette séquence est composée de deux Items. Le premier contient un objet de deux Data Element; le second contient un objet d'un seul Data Element

(0040,A730) SQ #-1 ContentSequence
> (FFFE,E000) #-1 Item #1
> (0008,0018) UI #6 [1.2.3] SOPInstanceUID
> (0010,0040) CS #2 [M] PatientSex
> (FFFE,E00D) #0 ItemDelimitationItem
> (FFFE,E000) #-1 Item #2
> (0008,0050) SH #4 [AN1] AccessionNumber
> (FFFE,E00D) #0 ItemDelimitationItem
(FFFE,E0DD) #0 SequenceDelimitationItem

En appliquant les règles d'encodage de séquence, d'item et de Data Element, on obtient le résultat suivant:
Exemple d'encodage en Implicit VR d'une séquence en « Undefined Length » (Cliquer pour agrandir)

4.2. L'encodage d'une Séquence en « Explicit Length »


Cette méthode d'encodage permet de savoir la taille exacte de la séquence et de l'objet contenu dans cette dernière. Cette solution est similaire à l'encodage des Data Element de type autre que SQ.

4.2.1. Règles d'encodages


L'encodage d'une séquence en « Explicit Length » se fait de la manière suivante :
  • Le champ « Tag » doit avoir une VR QS ;
  • Le champ « Length » doit avoir la longueur du champ « Value » ;.
  • Le champ « Value » contient les différents Item.
L'encodage d'un item « Explicit Length » se fait de la manière suivante:
  • Le champ « Tag » doit avoir la valeur (FFFE, E000) ;
  • Le champ « Length » doit contenir la longueur de la valeur ;
  • Le champ « Value » contient l'objet DICOM.
           
encodage d'une séquence en « Explicit Length » (Cliquer pour agrandir)

4.2.2. Exemple d'encodage de la séquence


Essayons d'encoder une séquence ayant deux Items. Le premier item contient un objet composé de deux Data Element; le second item contient un objet composé d'un seul Data Element.

(0040,A730) SQ #52 ContentSequence
> (FFFE,E000) #24 Item #1
> (0008,0018) UI #6 [1.2.3] SOPInstanceUID
> (0010,0040) CS #2 [M] PatientSex
> (FFFE,E000) #12 Item #2
> (0008,0050) SH #4 [AN1] AccessionNumber
> (FFFE,E00D) #0 ItemDelimitationItem
(FFFE,E0DD) #0 SequenceDelimitationItem

Exemple d'encodage en Implicit VR en « Explicit Length » (Cliquer pour agrandir)

4.3 « Undefined Length » versus « Explicit Length »


L'utilisation de la méthode « Undefined Length » permet de ne pas connaître la longueur d'une séquence ou d'un item. Ainsi, il n'est pas nécessaire de calculer la longueur d'un item ou d'une séquence. Ce système semble plus fiable que la solution « Explicit Length » car si une erreur est commise sur le calcul de la taille, la séquence devient illisible. D'un autre côté, l'utilisation de la méthode « Explicit Length » permet d'ignorer un Data Element SQ en allant directement au suivant en sautant du nombre d'octets de la longueur de la séquence si l'on n'est pas intéressé par cette dernière.

Nous avons vu deux méthodes pour encoder une séquence, mais rien n'empêche de mélanger les deux méthodes. Par exemple, d'utiliser la méthode « Undefined Length » pour encoder une séquence et d'utiliser la méthode « Explicit Length » pour encoder chacun des items de cette séquence. On pourrait également imaginer que certains items d'une séquence sont en « Undefined Length » et d'autres en « Explicit Length ». En fait, toutes les combinaisons sont possibles, DICOM l'autorise parfaitement.

En pratique, les éditeurs ou constructeurs ne mettent en place qu'une seule méthode pour créer des séquences. Le plus souvent la méthode « Undefined Length » qui est plus facile à implémenter et plus fiable.

Remarque: DICOM impose de savoir lire toutes les méthodes (et combinaisons possibles) pour interpréter correctement un objet. En revanche, le standard n'impose pas de savoir écrire toutes les méthodes.

Aucun commentaire:

Enregistrer un commentaire