ClearCanvas源码解析2:读取dcm文件

一、基础知识:

  1、数据集和元素结构

    一个数据集由多个数据元素组成

    数据元素可以嵌套为多级(分组)

    一个数据元素分:标记、值类型、长度、和值四部分。

    传输语法为隐式VR的,没有值类型。

    一个标记分:组和组元素,如(0010,0010)

    显示VR数据结构:

 tag  vr  value length  value filed
 标记  值类型  长度  值

    隐式VR数据结构: 

 

 tag  value length  value filed
 标记  长度  值

   

    数据意义:0002组存储通讯描述;0008组检查特征; 0010组病人信息组; 0028 图像信息;

    

  2、数据元素长度定义:

    显示VR,值类型为 OB,OW,OF,OD,SQ,UC,UR,UT,UN

 

  显示VR,其它类型

  隐式VRml数据长度:

  

 

 二、DCM文件结构

  用二进制查看文件,可以明显看到文件内容结构:

  

 

 

有了上面的简单知识,下面就可以了解源码是怎么解析DCM文件的。

 

三、源码内容:

    clearcnavas读取文件类ClearCanvas.Dicom.IO.DicomStreamReader

    实现函数:public DicomReadStatus Read(DicomTag stopAtTag, DicomReadOptions options)

    

    从第132个字节开始读取内容----》128+4

    先读取MetaInfo信息,这个信息不受传输语法影响,,直接按ExplicitVrLittleEndian语法来解析就行,读取结束到0x0002FFFF

     

    MetaInfo信息读取完后,可以确定DCM的传输语法,,后面信息就根据DCM文件的传输语法做解析。。

 

    

      读取4个字节,得到VR的TAG值。

      如果参数e为0x0000,则为标识为Group Length,VR类型为UL,(参照DICOM3.0标准,第3单和第6单);

      其它值则先标识为未知,待后面解析。。。。。

      

      

      这三个TAG是没有VR值的。。。

 

      本人电脑单步调试太慢,,先写到这里,,,未完待续

 

 

       下面写一个自己的简单小例子,实现简单的显示VR,DCM文件的读写。。

    

  1   static void Main(string[] args)
  2         {   
  3             string filename = @"E:\work\dcm\1.2.840.10008.1.2.4.50.dcm";
  4 
  5             BinaryReader dcmfile = new BinaryReader(File.OpenRead(filename));
  6             dcmfile.BaseStream.Seek(132, 0);
  7             while (true)
  8             {
  9                 var g1 = dcmfile.ReadUInt16();
 10                 var g2 = dcmfile.ReadUInt16();
 11 
 12 
 13                 string vr = Encoding.Default.GetString(dcmfile.ReadBytes(2));
 14                 int nRead = Read2Byte(vr) ? 2 : 6;
 15                 byte[] bRead = dcmfile.ReadBytes(nRead);
 16                 int nLen = 0;
 17                 foreach (byte b in bRead)
 18                 {
 19                     nLen += b;
 20                 }
 21 
 22                 bRead = dcmfile.ReadBytes(nLen);
 23                 string val = getVF(vr, bRead);
 24                 Console.WriteLine(string.Format("({0} ,{1})   {2}    {3}     {4}",
 25                                     g1.ToString("X").PadLeft(4, '0'),
 26                                     g2.ToString("X").PadLeft(4, '0'),
 27                                     vr, nLen, val));
 28 
 29                 if (g1 == 0x7FE0 && g2 == 0x0010)
 30                     break;
 31             }
 32 
 33 
 34             Console.ReadKey();
 35         }
 36 
 37 
 38         private static bool Read2Byte(string vrNmae)
 39         {
 40             switch (vrNmae)
 41             {
 42                 case "OB":
 43                 case "OW":
 44                 case "OF":
 45                 case "OD":
 46                 case "SQ":
 47                 case "UC":
 48                 case "UT":
 49                 case "UN":
 50                     return false;
 51                 default:
 52                     break;
 53             }
 54             return true;
 55         }
 56 
 57         private static string getVF(string VR, byte[] VF)
 58         {
 59             string VFStr = string.Empty;
 60             switch (VR)
 61             {
 62                 case "SS":
 63                     VFStr = BitConverter.ToInt16(VF, 0).ToString();
 64                     break;
 65                 case "US":
 66                     VFStr = BitConverter.ToUInt16(VF, 0).ToString();
 67 
 68                     break;
 69                 case "SL":
 70                     VFStr = BitConverter.ToInt32(VF, 0).ToString();
 71 
 72                     break;
 73                 case "UL":
 74                     VFStr = BitConverter.ToUInt32(VF, 0).ToString();
 75                     break;
 76                 case "AT":
 77                     VFStr = BitConverter.ToUInt16(VF, 0).ToString();
 78 
 79                     break;
 80                 case "FL":
 81                     VFStr = BitConverter.ToSingle(VF, 0).ToString();
 82 
 83                     break;
 84                 case "FD":
 85                     VFStr = BitConverter.ToDouble(VF, 0).ToString();
 86 
 87                     break;
 88                 case "OB":
 89                     VFStr = BitConverter.ToString(VF, 0);
 90                     break;
 91                 case "OW":
 92                     VFStr = BitConverter.ToString(VF, 0);
 93                     break;
 94                 case "SQ":
 95                     VFStr = BitConverter.ToString(VF, 0);
 96                     break;
 97                 case "OF":
 98                     VFStr = BitConverter.ToString(VF, 0);
 99                     break;
100                 case "UT":
101                     VFStr = BitConverter.ToString(VF, 0);
102                     break;
103                 case "UN":
104                     VFStr = Encoding.Default.GetString(VF);
105                     break;
106                 default:
107                     VFStr = Encoding.Default.GetString(VF);
108                     break;
109             }
110             return VFStr;
111         }
112     }

结果对比::

    

 

 

得到的数据,一模一样。。。

 

  对于图像解析部分,不太建议用clearCanvas,c#对图像操作不如C++。。还是建议用DCMTK来处理图像压缩和解压缩。。

  具体实现方法,后面再写。。

 

posted @ 2017-03-15 13:07  走楼梯  阅读(3044)  评论(0编辑  收藏  举报