背景:
上一篇博文简单翻译了Orthanc官网给出的CodeProject上“利用Orthanc Plugin SDK开发WADO插件”的博文,其中提到了Orthanc从0.8.0版本之后支持快速查询,而原本的WADO请求需要是直接借助于Orthanc内部的REST API逐级定位。那么为什么之前的Orthanc必须要逐级来定位WADO请求的Instance呢?新版本中又是如何进行改进的呢?此篇博文通过分析Orthanc内嵌的SQLite数据库,来剖析Orthanc的RESTful API机制,以及WADO服务的实现。
Orthanc UUID与DICOM UID:
1)Orthanc Plugin SDK模拟实现WADO Server
上一篇博文中提到的LocateStudy、LocateSeries、LocateInstanc函数都不是直接查询WADO请求传入的各级UID(StudyUID、SeriesUID、InstanceUID),而是通过内部构建出等同的RESTful API来实现。举个例子,测试DCM文件名为test1.dcm,其对应的三级UID分别是:
StudyUID=1.3.6.1.4.1.30071.6.176694098609799.4240639413125000,
SeriesUID=1.3.6.1.4.1.30071.6.176694098609799.4240639413125000.1,
InstanceUID(即SOP Instance UID)=2.16.840.114421.81623.9430067258.9493139258,正常的WADO协议规定的请求连接为:
seriesUID=1.3.6.1.4.1.30071.6.176694098609799.4240639413125000.1&
objectUID=2.16.840.114421.81623.9430067258.9493139258
按照常规方式来实现的话,应该是直接利用SQL语句在指定的数据库中直接搜索WADO Request中的三级UID,而在Orthanc Plugin SDK实现的WADO插件中,却是分级进行,详细流程如下:
Study级别:第一,LocateStudy函数中构建http://localhost:8042/studies请求,利用内置的REST API服务获得当前数据中所有的studies的UUID(后面会讲到该UUID与DICOM UID之间的转换关系);第二,LocateStudy中的每一个studyUUID,构造http://localhost:8042/studies/XXXX-XXXX-XXXX-XXXX,通过对比返回JSON数据中study["MainDicomTags"]["StudyInstanceUID"]标签值与WADO中的studyUID,实现定位Study的功能;
Series级别:与Study相同,先构造http://localhost:8042/series获取全部seriesUUID,然后针对每个seriesUUID构造http://localhost:8042/series/XXXX-XXXX-XXXX-XXXX,对比返回值中的series["MainDicomTags"]["SeriesInstanceUID"]与seriesUID,实现定位Series的功能;
Instance级别:先构造http://localhost:8042/instances获取全部instanceUUID,然后对每个instanceUUID构造http://localhost:8042/instances/XXXX-XXXX-XXXX-XXXX对比返回值中的instance["MainDicomTags"]["SOPInstanceUID"]与WADO请求中的objectUID,实现最终定位图像的目的。
2)Orthanc UUID与DICOM UID
上面的实现是不是很繁琐啊,哈哈。好在官方Plugin SDK说明博文中给出了最新版的定位方式,具体的实现可参见我上一篇博文(http://blog.csdn.net/zssureqh/article/details/41836885)。那么为何Orthanc起初需要如此繁琐的定位图像呢?这里我们先简单的分析一下Orthanc内部是如何来标记文件的唯一性的,后续章节再详细分析之前Orthanc模拟WADO服务为何如此繁琐。
在Orthanc源码中有这样一个类DicomInstanceHasher(定义在DicomInstanceHasher.h,实现在DicomInstanceHasher.cpp),其注释中如此描述:
/**
* This class implements the hashing mechanism that is used to
* convert DICOM unique identifiers to Orthanc identifiers. Any
* Orthanc identifier for a DICOM resource corresponds to the SHA-1
* hash of the DICOM identifiers.
* \note SHA-1 hash is used because it is less sensitive to
* collision attacks than MD5. <a
* href="http://en.wikipedia.org/wiki/SHA-256#Comparison_of_SHA_functions">[Reference]</a>
**/