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來處理圖像壓縮和解壓縮。。

  具體實現方法,后面再寫。。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM