2010-03-04 7 views
10

Je voudrais lire un fichier DICOM en C#. Je ne veux pas faire quelque chose de fantaisie, je voudrais juste pour le moment savoir comment lire dans les éléments, mais d'abord je voudrais savoir comment lire l'en-tête pour voir si est un fichier DICOM valide.C#: comment lire des parties d'un fichier? (DICOM)

Il se compose d'éléments de données binaires. Les 128 premiers octets sont inutilisés (mis à zéro), suivis de la chaîne 'DICM'. Ceci est suivi par des informations d'en-tête, qui sont organisées en groupes.

Un en-tête DICOM échantillon

 
First 128 bytes: unused DICOM format. 
Followed by the characters 'D','I','C','M' 
Followed by extra header information such as: 

0002,0000, File Meta Elements Groups Len: 132 
0002,0001, File Meta Info Version: 256 
0002,0010, Transfer Syntax UID: 1.2.840.10008.1.2.1. 
0008,0000, Identifying Group Length: 152 
0008,0060, Modality: MR 
0008,0070, Manufacturer: MRIcro 

Dans l'exemple ci-dessus, l'en-tête est organisé en groupes. Le groupe 0002 hex est le groupe de méta-informations du fichier qui contient 3 éléments: l'un définit la longueur du groupe, l'autre stocke la version du fichier et stocke la syntaxe de transfert.

Questions

  • Comment je lis le fichier d'en-tête et de vérifier si elle est un fichier DICOM en vérifiant le 'D', 'I', 'C', caractères 'M' après la 128 octets préambule?
  • Comment continuer à analyser le fichier en lisant les autres parties des données?
+0

Je pense qu'il sera préférable d'utiliser ReadLine() au lieu de lire l'octet de fichier par octet. Chaque enregistrement semble être sur une ligne différente – A9S6

Répondre

11

Quelque chose comme cela devrait lire le fichier, sa base et ne gère pas tous les cas, mais ce serait un point de départ:


public void ReadFile(string filename) 
{ 
    using (FileStream fs = File.OpenRead(filename)) 
    { 
     fs.Seek(128, SeekOrigin.Begin); 
     if (!(fs.ReadByte() != (byte)'D' || 
       fs.ReadByte() != (byte)'I' || 
       fs.ReadByte() != (byte)'C' || 
       fs.ReadByte() != (byte)'M')) 
     { 
      Console.WriteLine("Not a DCM"); 
      return; 
     } 
     BinaryReader reader = new BinaryReader(fs); 

     ushort g; 
     ushort e; 
     do 
     { 
      g = reader.ReadUInt16(); 
      e = reader.ReadUInt16(); 

      string vr = new string(reader.ReadChars(2)); 
      long length; 
      if (vr.Equals("AE") || vr.Equals("AS") || vr.Equals("AT") 
       || vr.Equals("CS") || vr.Equals("DA") || vr.Equals("DS") 
       || vr.Equals("DT") || vr.Equals("FL") || vr.Equals("FD") 
       || vr.Equals("IS") || vr.Equals("LO") || vr.Equals("PN") 
       || vr.Equals("SH") || vr.Equals("SL") || vr.Equals("SS") 
       || vr.Equals("ST") || vr.Equals("TM") || vr.Equals("UI") 
       || vr.Equals("UL") || vr.Equals("US")) 
       length = reader.ReadUInt16(); 
      else 
      { 
       // Read the reserved byte 
       reader.ReadUInt16(); 
       length = reader.ReadUInt32(); 
      } 

      byte[] val = reader.ReadBytes((int) length); 

     } while (g == 2); 

     fs.Close(); 
    } 

    return ; 
} 

Le code ne cherche pas réellement et prendre en compte que la syntaxe de transfert des données codées peuvent changer après que le groupe 2 éléments, il ne également pas essayer de tout faire avec les valeurs réelles lues.

+0

Merci Steve, j'ai remarqué que vous avez beaucoup écrit sur DICOM en particulier concernant ClearCanvas. Je respecte ta réponse. Merci encore. – Xaisoft

+0

Merci, Xaisoft. Si vous voulez vraiment regarder, j'ai copié une partie de ce code à partir des bibliothèques ClearCanvas, qui sont basées sur une version antérieure de mDCM. Vous pouvez regarder la classe ClearCanvas.Dicom.IO.DicomStreamReader pour voir notre analyseur, qui est évidemment beaucoup plus complexe que juste cet extrait. –

+0

bonjour Steve, pouvez-vous me dire quel est le format de fichier * .dcm. Par exemple, le premier octet de 128 est le préambule, les 4 octets suivants sont préfixés. Où seront les informations sur le nom du patient, l'image réelle, etc. –

4

Un Google search rapide fait monter trois DICOM C# bibliothèques:

+1

Les bibliothèques sont bonnes, mais j'essaie de le faire moi-même juste à des fins d'apprentissage. J'ai juste besoin d'un point de départ sur la façon de lire les fichiers ... Merci pour les liens – Xaisoft

1

Juste quelques pseudologic

Comment je lis le fichier d'en-tête et de vérifier si elle est un fichier DICOM en vérifiant les caractères 'D', 'I', 'C', 'M' après le préambule de 128 octets?

  • Ouvrir comme fichier binaire, en utilisant File.OpenRead
  • Cherchez à la position 128 et lire 4 octets dans le tableau et le comparer againts octet [] valeur pour DICM. Vous pouvez utiliser ASCIIEncoding.GetBytes() pour cela

Comment continuer à analyser le fichier en lisant les autres parties des données?

  • Continuer la lecture du fichier à l'aide de lecture ou ReadByte en utilisant la poignée d'objet FileStream que vous avez précédemment
  • Utilisez la même méthode comme ci-dessus pour faire votre comparaison.

N'oubliez pas de fermer et de disposer du fichier.

+0

Merci pour le Psudocode, cela aide. – Xaisoft

0

vous pouvez également utiliser comme ceci.

FileStream fs = File.OpenRead(path); 

byte[] data = new byte[132]; 
fs.Read(data, 0, data.Length); 

int b0 = data[0] & 255, b1 = data[1] & 255, b2 = data[2] & 255, b3 = data[3] & 255; 

if (data[128] == 68 && data[129] == 73 && data[130] == 67 && data[131] == 77) 
     { 
      //dicom file 
     } 
     else if ((b0 == 8 || b0 == 2) && b1 == 0 && b3 == 0) 
     { 
      //dicom file 
     } 
0

Taken de EvilDicom.Helper.DicomReader de la bibliothèque Evil Dicom:

public static bool IsValidDicom(BinaryReader r) 
    { 
     try 
     { 
      //128 null bytes 
      byte[] nullBytes = new byte[128]; 
      r.Read(nullBytes, 0, 128); 
      foreach (byte b in nullBytes) 
      { 
       if (b != 0x00) 
       { 
        //Not valid 
        Console.WriteLine("Missing 128 null bit preamble. Not a valid DICOM file!"); 
        return false; 
       } 
      } 
     } 
     catch (Exception) 
     { 

      Console.WriteLine("Could not read 128 null bit preamble. Perhaps file is too short"); 
      return false; 
     } 

     try 
     { 
      //4 DICM characters 
      char[] dicm = new char[4]; 
      r.Read(dicm, 0, 4); 
      if (dicm[0] != 'D' || dicm[1] != 'I' || dicm[2] != 'C' || dicm[3] != 'M') 
      { 
       //Not valid 
       Console.WriteLine("Missing characters D I C M in bits 128-131. Not a valid DICOM file!"); 
       return false; 
      } 
      return true; 

     } 
     catch (Exception) 
     { 

      Console.WriteLine("Could not read DICM letters in bits 128-131."); 
      return false; 
     } 

    }