Dicom患者信息获取乱码分析

开发的软件在读取CT机的Dicom文件时,其中的患者信息出现乱码,产生原因是因为Dicom使用了默认的字符集,导致不能正常解析中文。

开发环境

Fo-Dicom

VS2022 

.net6+

问题现象

开发的CT软件,从CT的Dicom文件中读取到的患者姓名、性别出现了乱码。

同时将此Dicom以RadiAnt打开,也是一样的问题。

 

排查过程

开始怀疑是在扫描CT时出现了异常,导致Dicom的PatientName标签中汉字异常。但debug时尝试将PatientName以如下方式读取时:

    var item = dicomDataset.GetDicomItem<DicomElement>(dicomTag);
    if (item == null) return string.Empty;
    byte[] bytes = item.Buffer.Data;
    string txt = Encoding.GetEncoding("GB18030").GetString(bytes).Trim('\0');

发现是能还获取到患者姓名的。于是怀疑是DICOM的字符集可能是有问题。看了Dicom中的Specific Character Set,确认此是有问题的。

原因分析

在 DICOM 文件中,​​Specific Character Set (0008,0005)​​ 的值为 ​​ISO_IR 100​​ 时无法正常解析中文,是因为该字符集实际上是 ​​Latin-1(ISO-8859-1)​​,仅支持西欧语言字符,​​不包含中文字符​​。

以下为Dicom中Specific Character Set截图:

 

(1) ISO_IR 100 的本质​​

  • ​​ISO_IR 100​​ 是 DICOM 标准中定义的字符集标识符,对应 ​​ISO-8859-1(Latin-1)​​。
  • ​​Latin-1 的局限性​​:
    • 仅支持 ​​256 个字符​​(0x00-0xFF),覆盖 ​​西欧字母​​(如 äñé),但​​不包含任何中文字符​​。
    • 中文字符在 Latin-1 编码下会被解析为​​乱码​​(如 张三 → ÕÅСÀÖ)。

​​(2) DICOM 的字符集处理逻辑​​

  • 当 Specific Character Set 被声明为 ISO_IR 100 时,解析器会强制使用 Latin-1 解码所有字符串标签(如 PatientName)。
  • 如果实际数据是中文(如 GB18030/UTF-8 编码),则必然解析失败。

 

解决方案

(1) 修改 Specific Character Set 为中文编码​​

在写入或修改 DICOM 文件时,显式声明支持中文的字符集:

// 使用 fo-dicom 库示例
var dataset = new DicomDataset();

// 关键步骤:声明为 GB18030 或 UTF-8
dataset.AddOrUpdate(DicomTag.SpecificCharacterSet, "GB18030"); // 或 "ISO_IR 192"(UTF-8)

// 添加中文数据
dataset.AddOrUpdate(DicomTag.PatientName, "张三");
dataset.AddOrUpdate(DicomTag.StudyDescription, "胸部CT");

// 保存文件
new DicomFile(dataset).Save("output.dcm");

 

若不想操作DICOM,仅是想在读取相应文件时,不出现乱码,那么在读取字符串时,以中文编码读取也是可行的。

如下为参考代码:

private static string GetChineseString(DicomDataset dicomDataset, DicomTag dicomTag)
{

    var item = dicomDataset.GetDicomItem<DicomElement>(dicomTag);
    if (item == null) return string.Empty;
    byte[] bytes = item.Buffer.Data;
    string txt = Encoding.GetEncoding("GB18030").GetString(bytes).Trim('\0');
    Debug.WriteLine(txt);
    return txt;
}

注意:GetDicomItem方法是可能返回null值的,一定不要忘了处理。

 

​​(2) 支持的 DICOM 中文编码标识符​​

​​字符集​​​​DICOM 标识符​​​​适用范围​​
GB18030 "GB18030" 中国国家标准(全覆盖)
GBK "GBK" 兼容 GB2312(较旧系统)
UTF-8 "ISO_IR 192" 国际通用(推荐)

  建议使用GB18030,其它字符集不能完全覆盖,一些人的人名中有生僻字的话又会出现乱码。

​​(3) 修复已存在的文件​​

若文件已错误写入 ISO_IR 100,需重新编码数据:

var dicomFile = await DicomFile.OpenAsync("corrupted.dcm");

// 1. 修正字符集声明
dicomFile.Dataset.AddOrUpdate(DicomTag.SpecificCharacterSet, "GB18030");

// 2. 重新解码原始字节(假设原始数据是 GB18030)
var nameBytes = dicomFile.Dataset.GetDicomItem<DicomElement>(DicomTag.PatientName).Buffer.Data;
string correctName = Encoding.GetEncoding("GB18030").GetString(nameBytes).Trim('\0');

// 3. 更新数据
dicomFile.Dataset.AddOrUpdate(DicomTag.PatientName, correctName);
dicomFile.Save("fixed.dcm");

 

为什么会出现 ISO_IR 100?​​

  • ​​默认行为​​:某些 DICOM 生成工具(如老旧设备)未正确配置字符集,默认使用 ISO_IR 100
  • ​​错误转换​​:中文数据被错误地用 Latin-1 编码后写入文件。

建议

在国内DICOM字符集建议使用GB18030,其它字符集不能完全覆盖,一些人的人名中有生僻字的话又会出现乱码。

 

posted @ 2025-07-03 17:59  盛沧海  阅读(73)  评论(0)    收藏  举报