背景:

周末看到了一篇原公司同事的文章,讲的是关于新的互联网形势下的PACS系统。正好上一篇专栏文章也提到了有想搭建一个worklist服务器的冲动,所以就翻箱倒柜将原本学生时代做课题时搭建的简易Web PACS找了出来,借着再次搭建的机会学习一下Web PACS相关的技术,例如WADO标准、CGI或者FastCGI等技术。

WEB PACS技术浅谈:

WEB PACS是一种利用互联网技术,跨越了医院和地域限制的,可随意查询和获取DICOM对象的PACS系统。目前常见的方式有两种:第一种是通过Web服务器提供查询定位,将对应DICOM影像存储服务器(通常为FTP)的地址与路径返回,客户端再向DICOM影像存储服务器请求对象;第二种是通过Web服务器统一提供查询及返回请求对象。两者各有利弊,第一种通过分别部署Web服务器和FTP文件服务器,减轻了Web服务器的负担,加快了响应时间,但是该方案也存在着诸多缺点,例如获取图像需要发送两次请求,FTP服务器安全性维护代价高,要求在浏览器下载能够解析DICOM图像的插件等等;第二种Web服务器整合了查询与返回,去除了FTP服务器,部署方便,它的缺点是由于Web服务器返回的数据是真实DCM转换过来的BMP或JPEG文件,因此某些依赖于DICOM文件其他信息的操作(例如窗宽窗位调整)需要重新请求服务端,要求更新数据,因此对服务器的处理能力消耗较大,对带宽也有一定要求。

两种方式的示意图如下:

(摘自文献《DICOM WADO原理及应用研究》)

1)WADO

WADO(Web Access to DICOM Persistent Object),是DICOM标准中的一部分,提供了一种通过HTTP或HTTPS协议并利用DICOM的标识符从HTML页或XML文档中存取与重现DICOM对象的机制,用于解决在互联网环境下访问DICOM对象——这也可以认为是Web PACS的终极目标。与标准的基于HTTP或HTTPS的网络访问方式相同,用户在浏览器地址栏中输入URL,向服务器发送WEB请求,服务器接收到请求后根据URL中提供的参数,在服务端定位要求的图像或报告回送给浏览器,示意图如下(摘自DICOM标准第18章),

其实WADO标准就是定义了客户端和服务端之间交互的规则,可以简单的理解为双向交互时的参数约定,即服务端可以根据浏览器端发送参数的不同来实现常见的单机版PACS的C-FIND、C-MOVE、C-STORE等功能。DICOM标准中关于WADO部分的介绍也主要是各种参数规则的说明,以及部分URL实例,这里截取一个来简单的说明一下:

如上图所示,URL采用常见的GET方式,将传统的PACS系统客户端发送查询时的参数发送给服务端,例如studyUID、seriesUID和objectUID(其实就是DICOM图像中的SOP Instance UID)。

2)CGI

CGI(Common Gateway Interface),是WWW技术中最重要的技术之一,有着不可取代的重要地位。CGI定义了外部应用程序(CGI程序)与Web服务器之间的接口标准,独立于开发语言,给用户提供了一种从网页浏览器向执行在服务器上的程序请求数据的方式——为Web PACS的实现提供了一种途径。

为了理解CGI的含义,必须要搞清楚WEB开发中常见的前端和后端。前端就是Web应用中用户可以看得见碰的着的东西,服务端接收到请求后大多直接将数据传输到浏览器;后端更多的是用户看不到的(这里指的看不到不是操作后的结果看不到,而是操作的流程看不到),接收到请求后需要服务端进一步操作的,例如查询数据库、算法运算等等。而CGI就是实现这种由浏览器的输入触发在WEB服务器上运行的程序的标准。

实际环境搭建:

正如博文第一部分所述,由于第一类Web PACS需要浏览器安装第三方插件,需要单独部署FTP服务器,因此在课题起初没有采用该方案。第二种Web PACS服务端在接受请求后会再向影像服务器发送请求,这正是上文中提到的CGI技术的一种很好的应用场景。下面就具体介绍一下如何搭建CGI应用环境:

1)WampServer+FastCGI

Web服务器搭建:

WampServer安装包下载http://www.wampserver.com/en/#wampserver-64-bits-php-5-5

安装过程中有可能会遇到“缺少msvcr110.dll,程序无法启动”错误,可以参照http://jingyan.baidu.com/article/ed2a5d1f3303d709f7be1776.html中给出的方法解决,需要提醒的是下载的Visual C++ Redistributable for VisualStudio 2012 Update 4版本不是由电脑的操作系统类型(32位or64位)来决定,而是应该根据WampServer安装包的类型来选择。安装完Visual C++ Redistributable for VisualStudio 2012 Update 4后需要重新安装WampServer。

配置FastCGI环境:

参考http://www.admin10000.com/Document/53.htmlhttp://my.oschina.net/Twitter/blog/210044对Apache服务器进行配置。在配置完成后重启WampServer竟然失败,出现如下错误:

更悲剧的是查看Apache的ErrorLog竟然没有提示,所以只能对修改的httpd.conf配置文件逐行排查,通过逐行注释的本方法最后找到了问题所在,由于修改DirectoryIndex引发的错误,恢复到原本的顺序后,重启WampServer竟然奇迹般的成功了,小有成就感啊,至于具体的原因后续在慢慢查找,确定了再补充上来。

2)C语言CGI实例

配置完开发环境后,给出一个简单的测试,由于电脑中没有安装PHP,所以这里就讨巧一下,直接利用Apache自带的cgi来调用一下C语言开发的程序,关于C语言CGI的配置比较简单,在Apache目录下的modules中已经包含了cgi模块,只需要在httpd.conf配置文件中指定c-cgi运行的目录即可,添加如下代码:

ScriptAlias /cgi-bin/"C:/wamp/www/c-cgi/"
AddHandler cgi-script .exe .pl .cgi
<Directory"C:/wamp/www/c-cgi/">
Options Indexes FollowSymLinks ExecCGI
AllowOverride all
Order allow,deny
Allow from all
Require local
</Directory>

具体的配置可参考http://blog.sina.com.cn/s/blog_66ec4d660100rd2h.html,实例的话就不要用该博文中的了,用我下面给出的完整示例。

GET方法实例源码

#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char *data;
char a[10],b[10];
printf("Content-Type:text/html\n\n");
printf("<HTML>\n");
printf("<HEAD>\n<TITLE >Get Method</TITLE>\n</HEAD>\n");
printf("<BODY>\n");
printf("<div style=\"font-size:12px\">\n");
data = getenv("QUERY_STRING");
if(data==NULL)
return 1;
if(sscanf(data,"a=%[^&]&b=%s",a,b)!=2){
printf("<DIV STYLE=\"COLOR:RED\">Error parameters should be entered!</DIV>\n");
}
else{
printf("<DIV STYLE=\"COLOR:GREEN; font-size:15px;font-weight:bold\">a + b = %d</DIV>\n",atoi(a)+atoi(b));
}
printf("<HR COLOR=\"blue\" align=\"left\" width=\"100\">");
printf("<input type=\"button\" value=\"Back CGI\" onclick=\"javascript:window.location='../cgitest-c.html'\">");
printf("</div>\n");
printf("</BODY>\n");
printf("</HTML>\n");
return 0;
}

利用VS编译后的可执行文件为gettest.exe,放到/www/cgitest-c目录下。

POST方法实例源码

#include <stdio.h>
#include <stdlib.h>
int main(void){
int len;
char *lenstr,poststr[20];
char m[10],n[10];
printf("Content-Type:text/html\n\n");
printf("<HTML>\n");
printf("<HEAD>\n<TITLE >post Method</TITLE>\n</HEAD>\n");
printf("<BODY>\n");
printf("<div style=\"font-size:12px\">\n");
lenstr=getenv("CONTENT_LENGTH");
if(lenstr == NULL)
printf("<DIV STYLE=\"COLOR:RED\">Error parameters should be entered!</DIV>\n");
else{
len=atoi(lenstr);
fgets(poststr,len+1,stdin);
if(sscanf(poststr,"m=%[^&]&n=%s",m,n)!=2){
printf("<DIV STYLE=\"COLOR:RED\">Error: Parameters are not right!</DIV>\n");
}
else{
printf("<DIV STYLE=\"COLOR:GREEN; font-size:15px;font-weight:bold\">m * n = %d</DIV>\n",atoi(m)*atoi(n));
}
}
printf("<HR COLOR=\"blue\" align=\"left\" width=\"100\">");
printf("<input type=\"button\" value=\"Back CGI\" onclick=\"javascript:window.location='../cgitest-c.html'\">");
printf("</div>\n");
printf("</BODY>\n");
printf("</HTML>\n");
fflush(stdout);
return 0;
}

利用VS编译后的可执行文件为posttest.exe,同样放到/www/cgitest-c目录下。

测试网页源码

<html>
<head>
<title>CGI Testing</title>
</head>
<body>
<table width="200" height="180" border="0" style="font-size:12px">
<tr><td>
<div style="font-weight:bold; font-size:15px">Method: GET</div>
<div>please input two number:<div>
<form method="get" action="./c-cgi/gettest.exe">
<input type="txt" size="3" name="a">+
<input type="txt" size="3" name="b">=
<input type="submit" value="sum">
</form>
</td></tr>
<tr><td>
<div style="font-weight:bold; font-size:15px">Method: POST</div>
<div>please input two number:<div>
<form method="post" action="./c-cgi/posttest.exe">
<input type="txt" size="3" name="m">*
<input type="txt" size="3" name="n">=
<input type="submit" value="resu">
</form>
</td></tr>
<tr><td><input type="button" value="Back Home" onclick='javascript:window.location="./index.php"'></td></tr>
</table>
</body>
</html>

放到Apache服务器根目录下,在浏览器中通过localhost/cgitest-c.html可以访问到。

实际运行结果

上述通过一个简单的计算来演示了CGI技术的实现和开发流程,当然对于简单的数字计算WEB前端自己就搞定了,此处只是为了说明CGI流程。至此整个Web PACS的Web服务端就已经搭建的差不多了,利用CGI或FastCGI我们可以使用服务端的其他语言开发的程序来实现我们想要的功能,那么后续的工作就跟开发C/S模式的PACS一样了,用C/C++、C#或JAVA等高级语言开发PACS服务相关的程序供Web服务器调用即可。本博文中演示的是调用exe可执行文件,这种方式有风险,后续我会介绍在FastCGI模式下的利用PHP调用C++或C#或JAVA动态库的更安全的实现方式。

DICOM医学图像处理:WEB PACS初谈的更多相关文章

  1. DICOM医学图像处理:WEB PACS初谈四,PHP DICOM Class

    背景: 预告了好久的几篇专栏博文一直没有整理好,主要原因是早前希望搭建的WML服务器计划遇到了问题.起初以为参照DCMTK的官方文档wwwapp.txt结合前两天搭建的WAMP服务器可以顺利的实现WM ...

  2. DICOM医学图像处理:WEB PACS初谈二,图像的传输

    背景: 如前一篇专栏博文所述,借助于CGI或FastCGI技术转发浏览器发送过来的用户请求,启动本地的DCMTK和CxImage库响应.然后将处理结果转换成常规图像返回到浏览器来实现Web PACS. ...

  3. DICOM医学图像处理:DIMSE消息发送与接收“大同小异”之DCMTK fo-dicom mDCM

    背景: 从DICOM网络传输一文开始,相继介绍了C-ECHO.C-FIND.C-STORE.C-MOVE等DIMSE-C服务的简单实现,博文中的代码给出的实例都是基于fo-dicom库来实现的,原因只 ...

  4. DICOM医学图像处理:storescp.exe与storescu.exe源码剖析,学习C-STORE请求

    转载:http://blog.csdn.net/zssureqh/article/details/39213817 背景: 上一篇专栏博文中针对PACS终端(或设备终端,如CT设备)与RIS系统之间w ...

  5. [转]DICOM医学图像处理:Deconstructed PACS之Orthanc

    转载:http://blog.csdn.net/zssureqh/article/details/41424027 背景: 此篇博文介绍一个开源的.基于WEB的DICOM Server软件.该开源软件 ...

  6. DICOM医学图像处理:Deconstructed PACS之Orthanc

    背景: 此篇博文介绍一个开源的.基于WEB的DICOM Server软件.该开源软件完全使用C++编写,不依赖于第三方数据库(内置了SQLite数据库)或其他框架,支持RESTful API设计模式. ...

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

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

  8. DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store

    背景: 上一篇博文对DICOM中的网络传输进行了介绍.主要參照DCMTK Wiki中的英文原文.通过对照DCMTK与fo-dicom两个开源库对DICOM标准的详细实现,对理解DICOM标准有一个更直 ...

  9. DICOM医学图像处理:Deconstructed PACS之Orthanc,Modification & Anonymization

    背景: 上篇博文为引子,介绍了一款神奇的开源PACS系统——Orthanc.本篇开始解读官方Cookbook中的相关内容,对于简单的浏览.访问和上传请阅读前篇博文.在常规的PACS系统中还未出现对于D ...

随机推荐

  1. 【LOJ】#2888. 「APIO2015」巴邻旁之桥 Palembang Bridges

    题解 发现我们选择一座桥会选择力\(\frac{s + t}{2}\)较近的一座桥 然后我们只需要按照\(s + t\)排序,然后枚举断点,左边取所有s和t的中位数,右边同理 动态求中位数用平衡树维护 ...

  2. PHP字符串指定位置插入字符串

    1.substr_replace(string,replacement,start,length);需插入时设置length为0即可 string 必需.规定要检查的字符串. replacement ...

  3. Jmeter脚本录制方法(一)分别使用Badboy录制和Jmeter自带的代理服务器录制

    Jmeter录制方式分三种,分别是:使用Badboy录制.Jmeter自带的代理服务器录制和手工录制,今天先介绍前两种录制方法. Badboy录制 Badboy是用C++开发的动态应用测试工具, 其拥 ...

  4. Codeforces Round 542 (Div. 2)

    layout: post title: Codeforces Round 542 (Div. 2) author: "luowentaoaa" catalog: true tags ...

  5. CSS3选择器02—CSS3部分选择器

    该部分主要为CSS3新增的选择器 接上一篇 CSS(CSS3)选择器(1) 一.通用兄弟选择器: 24:E ~ F,匹配任何E元素之后的同级F元素. div ~ p{ background-color ...

  6. Xamarin iOS教程之显示和编辑文本

    Xamarin iOS教程之显示和编辑文本 Xamarin iOS显示和编辑文本 在一个应用程序中,文字是非常重要的.它就是这些不会说话的设备的嘴巴.通过这些文字,可以很清楚的指定这些应用程序要表达的 ...

  7. [ 转载 ] Java中成员变量 和局部变量

    java语言支持的变量类型 类变量:独立于方法之外的变量,用 static 修饰. 局部变量:类的方法中的变量. 实例变量(全局变量):独立于方法之外的变量,不过没有 static 修饰. publi ...

  8. [USACO06JAN]Redundant Paths

    OJ题号:洛谷2860.POJ3177 题目大意: 给定一个无向图,试添加最少的边使得原图中没有桥. 思路: Tarjan缩点,然后统计度为$1$的连通分量的个数(找出原图中所有的桥). 考虑给它们每 ...

  9. 解决浏览器抛出乱码,(HTML、PHP等的乱码问题)

    在Windows上编写html或php代码的时候,本地编辑器设置的文件编码格式是utf-8保存,但是浏览器打开页面的时候经常出现乱码,而且浏览器自动检测到的页面编码为GBK格式,这时候我就开始纳闷了? ...

  10. 喵哈哈村的魔法考试 Round #6 (Div.3) 题解

    有任何问题 直接联系QQ:475517977 喵哈哈村的代码传说 第一章 冒泡排序 第一题就是排序嘛,在ACM/OI竞赛中,我只推崇一种排序方法,就是直接调用algorithm里面的sort函数. # ...