2010-03-04 67 views
10

我想在C#中读取DICOM文件。我不想做任何事情,我只是为了现在想知道如何阅读元素,但首先我真的很想知道如何阅读标题,看看是否是有效的DICOM文件c#:如何阅读文件的一部分? (DICOM)

它由二进制数据元素组成。前128个字节未使用(设置为零),后面跟着字符串'DICM'。接下来是标题信息,它被组织成组。

样品DICOM标题

 
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 

在上面的例子中,首部被组织成组。组0002十六进制是文件元信息组,其中包含3个元素:一个定义组长度,一个存储文件版本并存储传输语法。后

问题

  • 如何我读的头文件,并验证它是否是通过检查“d” DICOM文件,“我”,“C”,“M”字128字节的前导码?
  • 如何继续解析读取数据其他部分的文件?
+0

我认为这将是更好地使用的ReadLine(),而不是按字节读取文件的字节。每条记录似乎都在不同的路线上 – A9S6 2010-03-05 15:44:43

回答

11

像这样的东西应该读取文件,其基本的,不能处理所有的情况,但是这将是一个起点:


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 ; 
} 

的代码实际上并没有试图考虑到传输语法的编码数据可以在组后更改2组的元素,它也不会尝试这样做,在读的实际值什么。

+0

谢谢史蒂夫,我注意到你在很多关于DICOM的文章中,特别是关于ClearCanvas的文章。我尊重你的答案。再次感谢。 – Xaisoft 2010-03-05 14:03:45

+0

谢谢,Xaisoft。如果你真的想看看,我从基于mDCM早期版本的ClearCanvas库中复制了一些代码。您可以查看ClearCanvas.Dicom.IO.DicomStreamReader类来查看我们的解析器,这显然比这个片段复杂得多。 – 2010-03-05 15:37:15

+0

你好史提夫,你能告诉我什么是* .dcm文件格式。例如,第一个128字节是前导码,接下来的4个字节是前缀。哪里会有关于患者姓名,真实图像等的信息。 – 2011-05-10 14:55:11

4

快速Google search带来了三个DICOM C#库:

+1

图书馆很好,但我只是为了学习目的而自己去做。我只需要一个关于如何阅读文件的起点...感谢您的链接 – Xaisoft 2010-03-04 19:50:40

1

只是一些pseudologic

如何我读的头文件,并验证它是否是一个DICOM文件,通过检查128字节前导后的'D','I','C','M'字符?

  • 打开为二进制文件,使用File.OpenRead
  • 寻求到位置128和读4个字节到阵列,并比较它反对票为DICM字节[]值。您可以使用ASCIIEncoding.GetBytes()

如何继续解析读取数据其他部分的文件?

  • 继续阅读使用Read或ReadByte使用您以前
  • 使用像上面同样的方法做你的比较FileStream对象句柄的文件。

不要忘了关闭和处理文件。

+0

感谢Psudocode,这有助于。 – Xaisoft 2010-03-05 14:05:53

0

你也可以这样使用。

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

从EvilDicom.Helper.DicomReader取自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; 
     } 

    }