DICOM:Transfer Syntax传输语义之奇葩GE Private TS
背景:
专栏之前对Transfer Syntax(暂定中文翻译为传输语义,8月初博客中提到的DICOM3.0标准中文版开源书籍计划顺利启动。兴许会面临诸多专有名词的翻译工作,欢迎广大博友提意见)进行过多次的介绍。在DICOM医学图像处理:DICOM网络传输中差别过Abstract Syntax与Transfer Syntax,在DICOM:dcmqrscp.exe与storescu.exe中C-STORE服务的差别中介绍过在网络服务中Transfer Syntax的作用。以及上一篇DICOM:dcm4che工具包怎样压缩dcm文件探讨(续篇)中介绍对dcm文件进行压缩时提到的JPEG LossLess压缩语义以及Implicit VR Little Endian。
Transfer Sytanx在DICOM标准中占有重要的一席之地,既作为必要元素写入到DCM文件元信息(MetaInformation)中,又是DICOM网络服务中两方传输数据的前提(如博文DICOM医学图像处理:DICOM网络传输描写叙述TransferSyntaxx是PresentationContext必备元素)。
题记:
最近收到了GE一款设备的数据,使用dcm4che3提供的StoreSCP服务起初无法识别,在开启“–accept-known”后顺利完毕接收,但数据打开后图像“失真”——与原始图像全然不同。因此特意研究了一下GE私有的Transfer Syntax。即1.2.840.113619.5.2。以下让我们看看这奇葩的私有协议。
dcm4che3的StoreSCP:
dcm4che3提供的StoreSCP服务在未开启“–accept-known”选项时,仅仅支持sop-classes.properties文件里的标准,开启后能够接受其它未知协议。
通过查看StoreSCP.java源代码能够看到对未知协议相同採用直接将数据流存储到文件里。
private void storeTo(Association as, Attributes fmi,
PDVInputStream data, File file) throws IOException {
LOG.info("{}: M-WRITE {}", as, file);
file.getParentFile().mkdirs();
DicomOutputStream out = new DicomOutputStream(file);
try {
out.writeFileMetaInformation(fmi);
data.copyTo(out);
} finally {
SafeClose.close(out);
}
}
将StoreSCP的“–accept-known”选项开启后。在本地顺利接收到了GE设备的数据。依照上述代码所看到的直接存储到了文件里。可是图像显示结果失真。
图像失真:
使用DICOM Viewer打开数据。结果例如以下所看到的:
即使调节窗宽窗位,也无法顺利显示各种组织。通过查看DICOM相关信息并未找出问题。
相同採用直接查看二进制的方法。定位到PixelData元素能够看到真实像素数据数值为FA 24。依照GE Private TransferSyntax=1.2.840.113619.5.2的说明,该私有语义是Implicit VR - Big Endian (G.E Private)假设依照Big Endian来解析像素数据为0xFA24=-1500,假设依照Little Endian像素数据为0x24FA=9466.在Sante Editor查看背景数据显示为9466.由此能够推測问题出如今PixelData数据读取有误。即Sante Editor对GE Private TransferSyntax=1.2.840.113619.5.2理解有误。
奇葩之GE Private TS:
利用Wireshark抓取GE设备发送到StoreSCP的数据包。依据Wireshark中对DICOM协议数据包的提示。发现GE Private TransferSyntax的确非常奇葩,例如以下所看到的:
言外之意,GE Private TransferSyntax私有传输语义仅仅对PixelData元素採用Big Endian进行处理。对于其它非PxielData元素依旧採用Implicit VR Little Endian,即GE Private TransferSyntax对标准Implicit VR Little Endian语义所做的改动仅限于PixelData数据。
结合之前StoreSCP.java中的源代码可知。dcm4che3的StoreSCP通过开启“–accept-known”选项尽管能够接受GE Private TransferSyntax私有语义。可是并未真正理解当中的含义。而是简单的将1.2.840.113619.5.2写入到MetaInformation元信息中。而将PixelData直接复制到文件流中。加之多数DICOM Viewer无法顺利理解GE Private TransferSyntax。因此导致在解析PixelData时依照之前大多数元素的方式直接以Implicit VR Little Endian语义读。导致图像失真。
解决方式:
參照GE的说明文档,了解GE Private TransferSyntax私有语义后可知,除了PixelData的存储顺序是Big Endian以外,其它元素GE私有语义与Implicit VR Little Endian标准默认语义没有差别。
因此考虑到DICOM Viewer的兼容性问题。在StoreSCP.java的storeTo函数中对GE Private TransferSyntax私有语义进行单独处理,对PixelData进行转序处理就可以。在完毕PixelData的Big Endian到Little Endian转序后。也就能够将Transfer Syntax直接由GE Private TransferSyntax改成Implicit VR Little Endian。
示范代码例如以下所看到的:
private void storeTo(Association as, Attributes fmi, PDVInputStream data,
File file) throws IOException {
LOG.info("{}: M-WRITE {}", as, file);
file.getParentFile().mkdirs();
boolean bExchange=false;
// TransferSyntax=1.2.840.113619.5.2,is GE Private TS,
// Implicit VR Little Endian for all elements except pixel Data, which is Big Endian
if(fmi.getString(Tag.TransferSyntaxUID)=="1.2.840.113619.5.2")
{
fmi.setString(Tag.TransferSyntaxUID, VR.UI, "1.2.840.10008.1.2");
bExchange=true;
}
DicomOutputStream out = new DicomOutputStream(file);
try {
out.writeFileMetaInformation(fmi);
data.copyTo(out);
} finally {
SafeClose.close(out);
if(bExchange)
{
//这里应该对于GE Private进行单独推断。将Pixel Data数据由Big Endian转换成Little Endian
try {
DicomInputStream input=new DicomInputStream(file);
Attributes attrs=input.readDataset(-1, -1);
byte[] bytes=attrs.getBytes(2145386512);
byte[] newBytes=new byte[bytes.length];
for(int i=0;i<bytes.length/2;++i)
{
newBytes[2*i]=bytes[2*i+1];
newBytes[2*i+1]=bytes[2*i];
}
// //或者直接交换
// for(int i=0;i<bytes.length;i+=2)
// {
// byte swap=bytes[i];
// bytes[i]=bytes[i+1];
// bytes[i+1]=swap;
// }
attrs.setBytes(2145386512, VR.OW, newBytes);
File file2=new File("c:\\GE2.dcm");
DicomOutputStream out2=new DicomOutputStream(file2);
out2.writeDataset(input.getFileMetaInformation(), attrs);
input.close();
out2.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
改动后又一次打开新接收的数据,能够看到正确的图像例如以下所看到的:
至此,GE Private TransferSyntax私有语义的奇葩问题就攻克了。
作者:zssure@163.com
时间:2015/08/03
DICOM:Transfer Syntax传输语义之奇葩GE Private TS的更多相关文章
- DICOM:DICOM标准学习路线图(初稿)
题记: DICOM医学图像处理专栏撰写已有两个年头,积累了近百篇文章.起初只是用于记录自己科研.工作中遇到的疑难问题,专注于图像处理(主要是医学图像,这也正是专栏名称最初的由来):后来逐渐延伸到了DI ...
- Dicom格式文件解析器
转自:http://www.cnblogs.com/assassinx/archive/2013/01/09/dicomViewer.html Dicom全称是医学数字图像与通讯,这里讲的暂不涉及通讯 ...
- Dicom格式文件解析器[转]
Dicom格式文件解析器 Dicom全称是医学数字图像与通讯,这里讲的暂不涉及通讯那方面的问题 只讲*.dcm 也就是diocm格式文件的读取,读取本身是没啥难度的 无非就是字节码数据流处理.只不 ...
- Dicom Conformance
Platform Compatibility of DICOM Transfer Syntax 1.2.840.10008.1.2 Implicit VR - Little Endian yes ...
- DICOM:DICOM3.0网络通信协议
转载:http://blog.csdn.net/zssureqh/article/details/41016091 背景: 专栏取名为DICOM医学图像处理原因是:博主是从医学图像处理算法研究时开始接 ...
- DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM
背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO.C-FIND.C-STORE.C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只 ...
- DICOM医学图像处理:开源库mDCM与DCMTK的比較分析(一),JPEG无损压缩DCM图像
背景介绍: 近期项目需求,须要使用C#进行最新的UI和相关DICOM3.0医学图像模块的开发.在C++语言下,我使用的是应用最广泛的DCMTK开源库,在本专栏的起初阶段的大多数博文都是对DCMTK开源 ...
- DICOM简介
背景: DICOM分为两大类(这里只是从DICOM相关从业者日常工作角度出发来分类的):1)DICOM医学图像处理,即DCM文件中具体数据的处理,说图像可能有些狭隘,广义上还包括波形(心电).视频(超 ...
- 闲话Dicom
最近在准备一场有关DICOM应用的讲座,整理了一下思路.想了几个问题,发现挺有意思的,想与大家共同分享.接触过DICOM,应该了解普通DICOM 文件包含的四级属性,病人,检查,序列,影像.每一级别需 ...
随机推荐
- HDU 1548 A strange lift【BFS】
题意:给出一个电梯,给出它的层数f,给出起点s,终点g,以及在每一层能够上或者下w[i]层,问至少需要按多少次按钮到达终点. 和POJ catch that cow一样,直接用了那一题的代码,发现一直 ...
- js邮箱,汉字,数字 表单验证
//电子邮箱验证 function isEmail(str) { var myreg = /^([a-zA-Z0-9]+[_|\_|\.]?)*[a-zA-Z0-9]+@([a-zA-Z0-9]+[_ ...
- 路飞学城Python-Day15
模拟实现一个ATM + 购物商城程序 额度 15000或自定义 实现购物商城,买东西加入 购物车,调用信用卡接口结账 可以提现,手续费5% 支持多账户登录 支持账户间转账 记录每月日常消费流水 提供还 ...
- pycharm修改提示
- CDQ分治笔记
以前一直不会CDQ……然后经常听到dalao们说“这题直接CDQ啊”“CDQ不就秒了吗”的时候我只能瑟瑟发抖QAQ CDQ分治 其实CDQ分治就是二分分治,每次将$[l,r]$的问题划分为$[l,mi ...
- luogu P3765 总统选举(线段树维护摩尔投票+平衡树)
这题需要一个黑科技--摩尔投票.这是一个什么东西?一个神奇的方法求一个序列中出现次数大于长度一半的数. 简而言之就是同加异减: 比如有一个代表投票结果的序列. \[[1,2,1,1,2,1,1]\] ...
- POJ 3093 Margaritas on the River Walk(背包)
题意 n个有体积的物品,问选取一些物品,且不能再继续选有多少方法? n<=1000 题解 以前的考试题.当时是A了,但发现是数据水,POJ上WA了. 把体积从小到大排序枚举没选的物品中体积最小的 ...
- [洛谷P3948]数据结构
题目大意:有n个数,opt个操作,并给你md.min.max. 每种操作有以下两种:1.给一段区间加一个固定值.2.询问一段区间内满足$min\leq T*i\ mod\ md\leq max$(T是 ...
- yii框架原生代码
http://www.cnblogs.com/duanxz/p/3480254.htm
- 入门python:《Python编程快速上手让繁琐工作自动化》中英文PDF+代码
入门推荐学习<python编程快速上手>前6章是python的基础知识,通俗易懂地讲解基础,初学者容易犯错的地方,都会指出来.从第三章开始,每章都有一个实践项目,用来巩固前面所学的知识. ...