张元鲁+王超
摘要:DICOM(Digital Imaging and Communications in Medicine)即醫学数字成像和通信,是医学图像和相关信息的国际标准(ISO 12052)。它定义了质量能满足临床需要的可用于数据交换的医学图像格式。对DICOM文件进行解析显示并对结果进行发送接收,之后结合到移动端实现,可对医疗信息传输提供极大便利。
关键词:DICOM;医疗;消息解析;文件传输
中图分类号:TP391 文献标识码:A 文章编号:1009-3044(2018)02-0017-02
1 背景
DICOM[1]标准涵盖了医学数字图像的采集、归档、通信、显示及查询等几乎所有信息交换的协议;其推出与实现,大大简化了医学影像信息交换的实现,推动了远程放射学系统、图像管理与通信系统(PACS)的研究与发展,并且由于DICOM的开放性与互联性,使得与其他医学应用系统(HIS、RIS等)的集成成为可能[2]。目前大多数医院使用这种协议进行数据传输主要是在电脑端,这在便捷性和时效性上可能会有所欠缺。
本文将对 DICOM 消息构造进行分析,通过编程语言实现对 DICOM文件的解析,并对解析完成的结果进行发送接收。通过本文中的过程方法可以对DICOM文件实现记录信息和图像的显示和解析传输,基于此可进行移动端应用的开发,凭借移动端便捷,及时的特点,使医疗信息传输更加有效率[3]。
2 DICOM消息构造
DICOM主要的消息构造可分为记录信息和图像数据这两个部分,各类信息的开头通过tag声明。
整体构造如下图所示,先是128字节的导言部分,这里绝大多数的DICOM文件都为空。然后是4字节的前缀‘DICM。之后就是文件元dataelement。
Tag:DICOM中的数据字典。Tag由4字节的16进制数表示,前2个字节为组号,后2个字节为偏移地址,即为元素号。
VR:分为显式VR和隐式VR。组号是0002的元素都是显式的。
3 DICOM文件解析与信息显示
对于DICOM文件的解析与信息显示大致上可分为四步,前三步是根据DICOM消息构造对DICOM文件进行解析,最后一步是对得到的信息进行显示。
第一步:跳过128字节的导言部分,并读取前缀是否为“DICM”这4个字符,若不是则返回文件格式错误,若是则进行文件解析。
dicomFile.BaseStream.Seek(128, SeekOrigin.Begin); //跳过128字节导言部分
if (new string(dicomFile.ReadChars(4)) != "DICM")
{
MessageBox.Show("没有dicom标识头,文件格式错误");
return;
}
第二步:读取文件元dataelement 。读取所有0002开头的tag 并根据(0002,0010)的值确定传输语法。文件元tag部分的数据元素都是以显示VR的方式表示的,它的值是字节码处理传输语法。主要是确定字节序和VR类型。这些在DICOM标准的第六章[4]中有说明。
switch (VFStr)
{
case "1.2.840.10008.1.2.1\0"://显示little
isLitteEndian = true;
isExplicitVR = true;
break;
case "1.2.840.10008.1.2.2\0"://显示big
isLitteEndian = false;
isExplicitVR = true;
break;
case "1.2.840.10008.1.2\0"://隐式little
isLitteEndian = true;
isExplicitVR = false;
break;
default:
break;
}
第三步:读取普通tag根据tag值输出对应记录信息, 直到7fe0,0010 这个存储图像数据的 dataelement。在前一步已经确定了VR是显示还是隐式。显示情况下根据VR 和Len 确定数据类型跟数据长度直接读取就可以了。隐式情况下,则需要根据tag 字典确定它是什么VR再才能读取。关于这个字典也在DICOM标准的第六章。
图2 DICOM文件元部分tag对应信息
if (tag.Substring(0, 4) == "0002")//文件头 特殊情况
{
VR = new string(dicomFile.ReadChars(2));
if (VR == "OB" || VR == "OW" || VR == "SQ" || VR == "OF" || VR == "UT" || VR == "UN")
{
dicomFile.BaseStream.Seek(2, SeekOrigin.Current);
Len = dicomFile.ReadUInt32();
}
else
Len = dicomFile.ReadUInt16();
}
else if (tag == "fffe,e000" || tag == "fffe,e00d" || tag == "fffe,e0dd")//文件夹标签
{
VR = "**";
Len = dicomFile.ReadUInt32();
}
else if (isExplicitVR == true)//有无VR的情况
{
………………………….
else if (isExplicitVR == false)
{
VR = getVR(tag);//无显示VR时根据tag判断
Len = dicomFile.ReadUInt32();
}
//判断是否应该读取VF 以何种方式读取VF
………………………………
第四步:读取灰度像素数据并调窗以GDI的方式显示出来。直接按像素从左到右从上到下逐行依次扫描。两个字节表示1个像素普通DICOM格式存储的是16位的灰度图像,其实有效数据只有12位,除去0 所以最高值是2047。比如CT值从-1000到+1000,空气的密度为-1000水的密度为0 金属的密度为+1000总共的值为2000
4 文件发送接收
解析出来的结果可通过socket通信进行发送接收,这里把解析出来的结果分为记录文件信息和图像信息分别进行传输。发送端创建一个socket。之后把解析出来的文件读入内存并通过socket传输到接收端。接收端监听这个socket,当发送端发送数据时接收,接收完毕后返回接收成功。
5 实验结果
实验环境:windows10 x64,服务器为本地模拟。
DICOM文件解析結果:左侧为解析出来的记录信息,右侧为解析出来的图像信息。
可以看到成功解析出了DICOM文件的记录信息和图像信息,并将其分别显示出来。
对比log日志后发现接收的信息与解析出来的信息一致,发送接收成功。
6 结束语
DICOM这个传输协议是在医疗领域被广泛应用的,现在这个解析系统已经基本上实现了这个协议的解析和发送接收,接下来需要做得到就是移动端的嵌套,相信这个系统的完整版会对各大医院医疗信息的交换带来巨大的便利。
参考文献:
[1] Dicom Standard,Introduction and Overview[EB/OL][2017-09-20]. http://dicom.nema.org/medical/dicom/current/output/html/part01.html.
[2] 尤超. DICOM 文件头信息读取及解析[J]. 微型电脑应用, 2012, 28(9):39-44.
[3] 蒋君, 庞树茂, 冯前进. 医学影像系统的互联网应用[J]. 中国数字医学, 2016, 11(7):17-19.
[4] Dicom Standard,Data Dictionary[EB/OL][2017-10-02]. http://dicom.nema.org/medical/dicom/current/output/html/part06.html.endprint