dcm4che3读取含反斜杠LO类型DICOM值及addAll丢失多值问题
解决dcm4che3中
Attributes.addAll丢失LO类型多值的问题 我太懂你这种兼容性头疼了——ITK的固有设定搞出了一个不符合DICOM标准的LO多值存储,偏偏dcm4che3严格按协议办事,addAll直接把第二个值截掉,可大部分DICOM查看器又能正常显示,简直是个矛盾的小坑。
问题根源
DICOM标准里明确规定LO(Long String)是单值类型,不允许用反斜杠做多值分隔符。dcm4che3的Attributes.addAll方法在复制属性时,会严格遵循这个规则:碰到LO类型的属性,只会保留数组第一个值,直接丢弃反斜杠后面的内容。而你用getStrings能拿到完整多值,是因为dcm4che3解析文件时,只是按分隔符拆分了字符串,没严格校验VR和值数量的匹配关系。
解决方案:手动处理私有标签,绕过addAll的自动限制
既然addAll会自动“修正”LO类型的属性,那我们就把这个特殊的私有标签单独拎出来处理,再执行批量复制:
方法1:还原成带反斜杠的原始字符串写入
如果你想完全保留ITK写入时的格式(带反斜杠的单字符串),可以这么写:
// 替换成你实际的私有标签Tag Tag privateTag = new Tag(0x00XX, 0xXXXX); // 从dataSet中取出完整的多值数组 String[] values = dataSet.getStrings(privateTag); if (values != null && values.length > 0) { // 合并成带反斜杠的原始字符串 String combinedValue = String.join("\\", values); // 手动写入到fmi,指定VR为LO fmi.putString(privateTag, VR.LO, combinedValue); // 从dataSet中移除该标签,避免addAll时被覆盖 dataSet.remove(privateTag); } // 再复制剩下的常规属性 fmi.addAll(dataSet);
方法2:强制按多值写入(忽略VR规范)
如果你想保留多值数组的形式(虽然不符合标准,但能保证后续用getStrings直接拿到完整值),可以强制写入多值:
Tag privateTag = new Tag(0x00XX, 0xXXXX); String[] values = dataSet.getStrings(privateTag); if (values != null && values.length > 0) { // 强制写入多值,忽略LO的单值限制 fmi.putStrings(privateTag, VR.LO, values); dataSet.remove(privateTag); } fmi.addAll(dataSet);
长期建议:规范VR使用
上面的方法能解决当下的问题,但本质是绕过了DICOM标准。从长期兼容性考虑,建议和ITK开发方沟通,改用**DS(Decimal String)**这类允许多值的VR来存储这两个十进制数值。DS是专门为存储十进制数字设计的多值类型,完全符合DICOM规范,这样不管是dcm4che3还是其他工具,都能正常处理,不会再出现这类奇怪的兼容性问题。
内容的提问来源于stack exchange,提问作者MilacH
相关产品推荐
相关产品推荐

