转载http://blog.sina.com.cn/s/blog_4bce5f4b01019ix5.html

DICOM 文件内容在 Part 3 DICOM IOD 里定义。CT, MR, CR, DR, US, NM, PET, XA 等各有自己的内容定义,由共同的专有的部分 (IE 和 Modules) 组成。

DICOMDIR 由 Part 10 定义。是一种 mini 可变长度数据库文件结构。

过去我手下一个学计算机的非常聪明的印度人问我:图像文件格式不是有 BMP, GIF, TIF 和 JPEG 等等吗,为什么还要定义 DICOM 呢? 我向他解释了好几次最后还是放弃了。 任何图像文件格式无非是由两个部分组成:存参数的 header 和图点数据 (pixel data)。 BMP, JPEG, TIFF 之类的格式的 header 只描述图像的基本参数:如几行、几烈、每点用了几位、有没有压缩、调色板等等。Header 往往是固定长度的。 而医疗影像还要许多其它参数,如病人基本资料、检验基本资料、系列资料、位置资料等等。而且每种 Modality 和每种 image 所需要的内容不一样。因此,一般的图像格式不能用。

DICOM 的 4 个内容层次:

1. Patient (病人)

2. Study (检验)

3. Series (系列)

4. Image (图像)

尽管头几层的内容在很多图像里是相同的,它们在每个图像文件里都要有。 每一层叫一个 Information Entity,或 IE (从 relational database schema 设计引用而来)。每一层又细分成 Module。每个 Module 里面的最小单元叫做一个 attribute 或 element。

现在举个例子:

CR 图像

DICOM Part 3, A.2.3, Table A.2-1

1. Patient IE: a. Patient Module (参考 C.7.1.1)

2. Study IE: a. Study Module (参考 C.7.2.1) b. Patient Study Module (参考 C.7.2.2)

3. Series IE: a. General Series (参考 C.7.3.1) b. CR Series (参考 C.8.1..1) c. General Equipment (参考 C.7.5.1)

4. Image IE: a. Genrral Image (C.7.6.1) b. Image Pixel (C.7.6.3) c. Contrast/bolus (C.7.6.4) d. CR Image (C.8.1.2)

...

i. SOP Common (C.12.1)

将这些 modules (tables) 里的所有 elements 都找出来就做成了一个 CR 图像的架构。 要注意的是这些 module 有些是一定要的 (modatory) 有些是用户选用的 (user)。 到了每个 module 里 attribute/element 表又有分五类 Type 1, 1C, 2, 2C 和 3。 Type 1 是一定要的,2 也是一定要的但是内容可以是空的。Type 3 则可要可不要。 所以浓缩一下,一个 CR 图像里的元素 (elements) 也不是太多。

把这些表格展开后,这些 elements 组成一个 dataset。 那么写到一个文件里或通过网路传送又是个什么格式呢?这就要看 Part 5。

一个元素 (element) 的结构是:

1. group tag: 16-bit

2. element tag: 16-bit

3. length (or VR/length): 32-bit

4. data (bytes of length)

对应每一个用到的 element DICOM 标准 Part 6 都定义了一个 group tag 和 element tag。

比如说: patient name: 0x0010, 0x0010 patient ID: 0x0010, 0x0020 ...

VR 说的是 element 格式,比如说 patinet name 的 VR 是 PN。格式是 last_name^first_name^middle_name^prefix^surfix。那么我的英文名字就是: Wang^JB^^Dr.^

往外写时要做几个事情:

1. 要把所有元素按 group tage 和 element tag 理一遍 (sort)。从小排到大。

2. 如果是写 DICOM 介质的 DICOM file 还先写 128 bytes preamble (一般是空白),加 "DICM", 加 group 2 Meta header。(讲到 Part 10 时再细说)

3. 如果 dataset 里面含有 Sequence elements, sequence 里面每一个 Item 又是一个 dataset。

作业: 有了这些知识,你就可以开始写一个小小的 BMP 到 DICOM 的转化程序。

关键资料:

Modality (0008, 0060): SC

Photometric Interpretation (0028, 0004): RGB

SOP Class UID: 1.2.840.10008.1.5.4.1.1.7

最简单的办法是写一个 structure,然后一个

array. typedef struct DicomElem(short int group_tag, short int element_tag, char VR[4], int length, char data[128]) DicomElem;

DicomElem CRDataSet [] = ( ( 0x0008, 0x0005, "CS", 10, "ISO_IR 100"), ( 0x0008, 0x0008, "CS", 16, "ORIGINAL\\PRIMARY"), ... (0x0010, 0x0010, "PN", 16, "My^Test^Image^^ "),

(0x0010, 0x0020, "SH", 6, "123456"),

...

(0,0,"",0,"")

);

void WriteCDImage(FILE *fp)

{

DicomElem elem = CRDataSet[0];

unsigned long int lComboTag;

int nCols, nRows;

unsigned char *pPixelData unsigned long int lPixelLength;

pPixelData = LoadBMPImgeData("MyImage.bmp", nCols, nRows, lPixelLength);

while(CRDataSet.group_tag)

{

lComboTag = (CRDataSet.group_tag << 16) | CRDataSet.element_tag;

switch(lComboTag)

{

case 0x00280010: *((short int *)CRDataSet.data) = nCols;

break;

case 0x00280011: *((short int *)CRDataSet.data) = nRows;

break;

...

}

// Write group and element tag

fwrite(&lComboTag, 1, sizeof(long), fp);

// Write VR

fwrite(CRDataSet.VR, 1, 2, fp);

if (lComboTag != 0x7fe00010)

{

fwrite(CRDataSet.length, 1, sizeof(short), fp);

fwrite(CRDataSet.data, 1, CRDataSet.length, fp);

}

else

{

fwrite("\0\0", 1, 2, fp);

// Two blank bytes after VR

fwrite(&lPixelLength, 1, sizeof(long), fp);

// Length

fwrite(pPixelData, 1, lPixelLength, fp);

}

i++;

}

}

unsigned char *LoadBMPImgeData(char *fileName, int &nCols, int &nRows, unsigned long &lPixelLength) ( .... )

细节自己去写。

更上一层楼: DICOM 文件读写最难的是两个东西:

o DICOM Sequence

o DICOM Pixel Data

刚刚让大家做的作业里没有 Sequence,pixel data 也很简单。 Sequence 在 C 里的类比是一个 structure 的 array。 是结构套结构。 所以读起来难。更讨厌的是 Sequence 还可以不定义长度, 即长度是 -1。要靠你自己去找 (FFFE, E0DD) 来决定 Sequence 是否结束。 Array 里面的每个 structure 单元就是 DICOM Sequence 里的一个 Item。Item 的开头是一个特定 element (FFFE, E000)。 如果 Item 的长度是 -1, 要靠找到 (FFFE, E00D) 来决定 Item 的结束。 Pixel Data (7fe0, 0010) 是一个特殊的 DICOM element。总是在所有元素的最后面。它个 Sequence 有两个相似的地方: o 长度区总是 32-位 (即 explicit VR 的情况下要在 VR 区后面填两个 bytes,然后再加 4-bytes 的长度。 o 如图像是压缩的,每幅图用一个 item 来存。 第一个 item 是个 offset table。每幅图的 offset 是一个 dword (4 bytes),第一幅图的 offset 是 0。

DICOM 介质与 DICOMDIR:

DICOM 图像通过 Store SCU/SCP 来传的时候最小的组是 (0008, xxxx),一般头一个 element 是 (0008, 0000) 或 (0008, 0005)。 而存在介质上 (如光盘,硬盘和 MOD),则要加两套东西:

1. Preamble 和 DICOM signature: 128 bytes (一般是空的) 后面跟 DICM。

2. Meta header: group (0002, xxxx) 的十几个 elements. 看 DICOM Part 10。 DICOMDIR 是一个可变长度 迷你 database 文件。由 group (0002, xxxx) 和 group (0004, xxxx) 为主题。描述的是一个 4 层的树状结构 (tree structure)。 1. Patient 2. Study

3. Series 4. Image 除了用 DICOM 惯用的 Sequene 外还用了 offset 来做 linked list。所以读写起来比较麻烦。请看 DICOM Part 10。

DICOM 的中文支持: DICOM 本身可以支持任何文字。应用程序则可能无法破译。 DICOM 图像用中文是可以通过下列方法实现: (0008,0005)设 "GB2312" 或 “Big5"。 所有文字用双字节 GB 或 Big 5 码。 大部分的 DICOM 控件用起来都会有问题。国标用的是 8-bit bytes 而非 7-bit printable ASCII。 ANSI 字串函数如 sprintf, sscanf 会将最高一个 bit 削掉。要改写成支持 wide character 的才行。

dicom和dicomdir的更多相关文章

  1. DICOM医学图像处理:开源库mDCM与DCMTK的比較分析(一),JPEG无损压缩DCM图像

    背景介绍: 近期项目需求,须要使用C#进行最新的UI和相关DICOM3.0医学图像模块的开发.在C++语言下,我使用的是应用最广泛的DCMTK开源库,在本专栏的起初阶段的大多数博文都是对DCMTK开源 ...

  2. 大型三甲医院管理系统源码PACS超声科室源码DICOM影像工作站

    详情点击查看 开发环境 :VS2008 + C# + SQL2000 功能简介 1.患者登记工作站 集中登记患者基本信息和检查信息,包括就诊方式.患者来源.检查类型.检查部位.申请科室.申请医生等.可 ...

  3. DICOMDIR

    DICOMDIR 是一个可变长度 迷你 database 文件.由 group (0002, xxxx) 和 group (0004, xxxx) 为主题.描述的是一个 4 层的树状结构 (tree ...

  4. DICOMDIR结构

    DICOMDIR文件结构: 格式: DICOMDIR文件遵照DICOM文件的存储格式,需要有128个无意义字节的前言(假如没有特殊要求,这些字节都为00H),紧接着是DICOM前缀(长度为4字节的“D ...

  5. dcm4che tools 之dicomdir

    1.在dcm4che-3.3.7目录下的bin文件夹下运行命令行窗口 运行以下命令: dcmdir -c E:\TEMP\DICOMDIR E:\TEMP\04E439CE 为E:\TEMP\04E4 ...

  6. C#开发PACS医学影像处理系统(六):加载Dicom影像

    对于一款软件的扩展性和维护性来说,上层业务逻辑和UI表现一定要自己开发才有控制权,否则项目上线之后容易被掣肘, 而底层图像处理,我们不需要重复造轮子,这里推荐使用fo-dicom,同样基于Dicom3 ...

  7. dicom网络通讯入门(3)

    接下来可以进行消息传递了 ,也就是dimse ,再来复习下 什么是dimse .n-set  n-create c-echo 这些都是dimse  他们都是属于一种结构的pdu 那就是tf-pdu(传 ...

  8. dicom网络通讯入门(2)

    第二篇,前面都是闲扯 其实正文现在才开始,这次是把压箱底的东西都拿出来了. 首先我们今天要干的事是实现一个echo响应测试工具 也就是echo 的scu,不是实现打印作业管理么.同学我告诉你还早着呢. ...

  9. dicom网络通讯入门(1)

    看标准 越看越糊,根本原因:dicom抽象得非常严重,是“专家”弄的.没办法. 又是什么服务类 又是什么sop,相信你把dicom标准看到头大 都不知如何下手. 不就是 socket么 这有何难. 首 ...

随机推荐

  1. (转)AIX 5.3 安装中文语言包

    AIX 5.3 安装中文语言包 原文:http://blog.51cto.com/lubby/571648 在AIX操作系统安装国内软件厂商使用的一些应用软件中,会涉及到一些中文乱码问题(我就是在部署 ...

  2. Python3实现计算BMI指数,跟我一起来计算你的BMI吧

    废话不多说,直接上程序哈: name=input('Name:') height=input('Height(m):') weight=input('Weight(kg):') BMI=float(f ...

  3. Beam概念学习系列之PCollection数据集

    不多说,直接上干货! PCollection数据集  PCollection是Apache Beam中数据的不可变集合,可以是有限的数据集合也可以是无限的数据集合. 有限数据集,这种一般对应的是批处理 ...

  4. IAR6.1的工程迁移到IAR6.5不能用的解决方法

    1.重命名过时的CMSIS头文件 "... \ CMSIS \ CM3 \ CoreSupport \ core_cm3.h  比如:core_cm3.h.old 2.启用CMSIS:项目- ...

  5. pat1041. Be Unique (20)

    1041. Be Unique (20) 时间限制 100 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yue Being uniqu ...

  6. pat1094. The Largest Generation (25)

    1094. The Largest Generation (25) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CHEN, Yu ...

  7. react做股票、期货交易遇到的问题(不完全是react)及解决方法。

    公司项目主要是做股票及期货行情展示及交易,h5相应的做了一些功能---可以看行情图及模拟交易,实盘交易存在一定的风险,老板希望做自己的产品,这样h5就尴尬了,不过没关系,项目里还是有一定技术含量的-- ...

  8. MVC在页面View上获取当前控制器名称、Action名称以及路由参数

    有时候在封装MVC通用控件时需要在页面上获取这些数据. 用以下方法即可: //获取控制器名称: ViewContext.RouteData.Values["controller"] ...

  9. 【转】大数据批处理框架 Spring Batch全面解析

    如今微服务架构讨论的如火如荼.但在企业架构里除了大量的OLTP交易外,还存在海量的批处理交易.在诸如银行的金融机构中,每天有3-4万笔的批处理作业需要处理.针对OLTP,业界有大量的开源框架.优秀的架 ...

  10. 1.字符串池化(intern)机制及拓展学习

    1.字符串intern机制 用了这么久的python,时刻和字符串打交道,直到遇到下面的情况: a = "hello" b = "hello" print(a ...