背景:

上一篇博文对DICOM中的网络传输进行了介绍。主要參照DCMTK Wiki中的英文原文。通过对照DCMTK与fo-dicom两个开源库对DICOM标准的详细实现,对理解DICOM标准有一个更直观的认识。此篇博文是对上一篇博文的补充。由于专栏前面的演示样例大多是利用DCMTK工具包来进行的,此次借着分析fo-dicom源代码结构的机会,參照fo-dicom的README.md,给出C-ECHO 和C-STORE服务的详细实现。在实现的同一时候给出DICOM3.0标准中的相关介绍,帮助我们理解。

C-ECHO的fo-dicom实现:

1)C-ECHO參数说明:

C-ECHO又叫验证服务(即Verification),是用来验证DICOM服务两端的交流是否畅通。DICOM3.0的第7部分给出了C-ECHO服务的參数。例如以下图1所看到的:

【注意】:这里解说一下DICOM3.0标准的阅读方法。

以DICOM3.0标准的第7、8部分为例,【第7部分】中第9章開始解说DIMSE-C的各种服务。依次为C-STORE、C-FIND、C-GET、C-MOVE、C-ECHO(上图1就是我在该部分的C-ECHO小节中截取的),当中前半部分主要给出了DIMSE-C各种服务的參数。这里不过罗列出DICOM3.0标准的要求,目的是让你明确各个服务參数是否是必要的(分别用M、U、=表示);后半部分開始解说DIMSE-C各种服务的协议及实现流程(即Protocol和Procedures)。在PROTOCOL中给出的是详细的DIMSE-C服务的各种指令在传输过程中的格式,该部分也就是你利用抓包工具可以直接抓取的真实数据流;在Procedures中给出的是SCU和SCP之间的交互流程。通常为了说明服务是由谁发起的,由谁响应。在介绍Protocol的时候对于比較复杂的、可变的区域(Variables
Fields)一般会放在附录中。比如第7部分的附录C和E等。【第8部分】与【第7部分】类似,从第7章開始介绍ACSE的各种服务的參数(例如以下图2所看到的),依次为A-ASSOCIATE、A-RELEASE、A-ABORT、A-P-ABORT、P-DATA;第9章给出的是ACSE中各种服务的结构,即STRUCTURE。该部分与【第7部分】中的PROTOCOL相同,给出的是详细ACSE PDU在传输时刻的数据格式,该部分也是能够通过抓包工具直接获得的;相同对于比較复杂的STRUCTURE介绍也会单独放到附录中,比如第8部分的附录E。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

fo-dicom对于DIMSE消息的实现基类是DicomMessage。针对请求和响应分别派生出了DicomRequest和DicomResponse。最后依据不同的DIMSE服务派生对应的类。C-ECHO是当中最简单的,fo-dicom已经给出了SCP和SCU的详细实现。

參照fo-dicom中的README.md文件,给出C-ECHO SCP和SCU的代码,详情例如以下:

2)C-ECHO代码实例:

C-ECHO SCP的代码是直接利用了fo-dicom给出的DicomCEchoProvider类,通过创建DicomServer<DicomCEchoProvider>(12345)对象,开启C-ECHO SCP服务,当中參数12345表示C-ECHO服务的port号。C-ECHO SCU和C-ECHO SCP的代码分别例如以下所看到的:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Dicom;
using Dicom.Network; namespace CEchoSCU
{
class Program
{
static void Main(string[] args)
{
var client = new DicomClient();
client.NegotiateAsyncOps();
client.AddRequest(new DicomCEchoRequest());
client.Send("127.0.0.1", 12345, false, "SCU", "ANY-SCP");
Console.ReadLine(); }
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using Dicom;
using Dicom.Network;
namespace CEchoSCP
{
class Program
{
static void Main(string[] args)
{
var server = new DicomServer<DicomCEchoProvider>(12345);
Console.ReadLine(); }
}
}

实际执行结果例如以下:

C-STORE的fo-dicom实现:

1)C-STORE參数说明:

C-STORE就是存储服务。在医疗信息系统中最常见的服务之中的一个。尤其是PACS系统中。与C-ECHO服务同样,DICOM3.0标准第7部分也给出了C-STORE服务的參数列表,例如以下图4所看到的:

该參数列表的目的相同是为了介绍C-STORE服务中各參数的必要性。真正的參数消息格式在兴许的C-STORE PROTOCOL中介绍,例如以下图5所看到的:

图5中给出的不过C-STORE RQ的实际消息格式,该消息由C-STORE服务的SCU(client)流向C-SOTRE服务的SCP(服务端);与之相相应的C-STORE-RSP消息是从SCP流向SCU。DICOM3.0标准中也有C-STORE-RSP的具体介绍,例如以下图6所看到的。

2)C-STORE代码实例:

在fo-dicom的说明文档README.md中仅仅给出了C-STORE的SCU演示样例,例如以下图7所看到的:

上一篇博文对fo-dicom源代码结构分析的基础上可知。实现DIMSE众多服务的SCU端非常easy,首先创建DicomClient实体类,代表一个client。然后通过AddRequest加入不同的请求就可以实现各种DIMSE的client,如图7中C-STORE SCU的实现为:

client.AddRequest(new DicomCStoreRequest(@"test.dcm"));

DicomCStoreRequest类是DicomRequest的派生类,上述代码通过制定DCM文件路径来构建了一个DicomCStoreRequest对象,在DicomCStoreRequest内部通过打开指定的DCM文件提取获得上述參数中的Affected SOP Instance UID等參数。

既然fo-dicom中没有提供线程的C-STORE SCP实现,我们先利用DCMTK的storescp.exe工具来验证一下fo-dicom给出的C-STORE SCU的正确性,測试代码例如以下:

  • SCP端利用storescp.exe,在控制台下输入:storescp.exe –d –od c:\ 12345
  • SCU端利用fo-dicom中的C-STORE SCU。详细代码如上图7所看到的。然后双击生成后的storescu.exe。

最后能够得到例如以下结果,如图8所看到的:

同一时候在C盘根文件夹下能够看到被重命名的test.dcm文件,例如以下图9所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

之所以被重命名我们在之前分析DCMTK开源库源代码时提到过,通常DCMTK会依据SOP Instance UID(-uf,默认的)对接收到的DCM文件进行重命名,当然也能够通过选项设置重命名的方式。比如依照时间(-tn)、特定前缀(-fe)等等,例如以下图10所看到的。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

由此说明fo-dicom中给出的C-STORE SCU功能正常。接下来我们尝试利用fo-dicom构建C-STORE SCP。

3)构建C-STORE SCP

打开C-ECHO SCP的实现DicomCEchoProvider.cs文件,我们看到DicomCEchoProvider类通过派生DicomService服务类来实现了Dicom服务的基本框架。然后通过实现IDicomServiceProvider和IDicomCEchoProvider接口,完毕了C-ECHO 的服务端。细致查看DicomCEchoProvider的代码能够发现,事实上就是在接收到A-ASSOCIATE-RQ消息后。判别Presentation Context中的Abstract Syntax。依据实际请求消息来决定是否建立连接,另外当接收到C-ECHO
SCU发起的C-ECHO Request时,向其会送DicomCEchoResponse确认信息就可以。

既然通过实现两个接口函数就能够完毕C-ECHO SCP的构建,那么我们就自己尝试来完毕C-STORE SCP的搭建,仿照DicomCEchoProvider的方式,DicomCStoreProvider的代码例如以下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dicom;
using Dicom.Log;
using Dicom.Network;
using System.Threading;
using System.IO;
namespace CStoreSCP
{
class CStoreSCPProvider : DicomService, IDicomServiceProvider, IDicomCStoreProvider
{
public CStoreSCPProvider(Stream stream, Logger log) : base(stream, log) { } public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
{
return new DicomCStoreResponse(request,DicomStatus.Success);
}
public void OnCStoreRequestException(string tempFileName, Exception e)
{ }
public void OnReceiveAssociationRequest(DicomAssociation association)
{
foreach (var pc in association.PresentationContexts)
{
if (pc.AbstractSyntax == DicomUID.Verification)
pc.SetResult(DicomPresentationContextResult.Accept);
else
{
//pc.SetResult(DicomPresentationContextResult.RejectAbstractSyntaxNotSupported);
}
if (pc.AbstractSyntax == DicomUID.CTImageStorage)
{
pc.SetResult(DicomPresentationContextResult.Accept);
}
}
SendAssociationAccept(association); }
public void OnReceiveAssociationReleaseRequest()
{
SendAssociationReleaseResponse(); }
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
{ }
public void OnConnectionClosed(int errorCode)
{ } }
}

然后通过var server = new DicomServer<CStoreSCPProvider>(12345);Console.ReadLine(); 来构建一个C-STORE SCP应用。

下图11是先执行CStoreSCP.exe,然后执行CStoreSCU.exe得到的结果:

从图11的输出结果能够看出。此次C-STORE SCP和SCU两端的通讯顺利完毕,那么我们发送的C:\test.dcm文件会被CStoreSCP.exe存储到那里呢?由上一篇博文分析我们知道fo-dicom库中将DICOM的服务基本框架放在了DicomService类中。查看当中处理P-DATA服务的核心函数ProcessPDataTF,能够看到例如以下代码:

var file = new DicomFile();
file.FileMetaInfo.MediaStorageSOPClassUID = pc.AbstractSyntax;
file.FileMetaInfo.MediaStorageSOPInstanceUID = _dimse.Command.Get<DicomUID>(DicomTag.AffectedSOPInstanceUID);
file.FileMetaInfo.TransferSyntax = pc.AcceptedTransferSyntax;
file.FileMetaInfo.ImplementationClassUID = Association.RemoteImplemetationClassUID;
file.FileMetaInfo.ImplementationVersionName = Association.RemoteImplementationVersion;
file.FileMetaInfo.SourceApplicationEntityTitle = Association.CallingAE;
_dimseStream = CreateCStoreReceiveStream(file);

转到CreateCStoreReceiveStream函数内部,通过函数的说明就能够知道fo-dicom对C-STORE服务默认情况下是在系统中创建了一个暂时文件,用来接收C-STORE SCU的数据。因此能够判断我们的test.dcm文件应该也在暂时目录中,打开我本机的temp目录。能够看到有一个后缀为tmp的暂时文件。例如以下图12所看到的。

文件大小与我们測试用的test.dcm同样。尝试改动.tmp的扩展名,改动后能够使用DICOM Viewer软件正常打开。因此说明我们的C-STORE SCP顺利成功。

DICOM数据流分析:

C-ECHO服务数据流分析:

1)工具:

在本地測试。为了抓取127.0.0.1回路数据包,须要使用RawCap.exe工具包。

RawCap.exe是控制台程序,在抓取本地回路数据包时非常便捷。

当抓取完毕后我们须要借助于WireShark的强大分析功能,来实现C-ECHO数据流的具体分析。WireShark能够直接打开RawCap.exe抓取的.pcap数据包。

WireShark是功能强大的数据包统计分析工具。当然本身也能够抓取网络数据包(本地回路数据包不方便)。WireShark支持众多协议,当中包含DICOM协议。以下以C-ECHO的数据包为例,简介一下怎样使用WireShark来自己主动识别并解析DICOM数据包。首先打开抓取的本地C-ECHO数据包cecho.pcap。如图13,在Protocol中右键选择"Protocol Preferences “中的"Data Preferences…”,会弹出一个协议设置窗体如图13。在左側列表中找到DICOM协议,勾选图14中红色部分。该部分的意思是除了检測DICOM协议默认port104的数据包的同一时候也检測其它port的数据包。之所以须要选择此项是由于非常多DICOM服务并未使用协议默认的104port。设置完毕后,又一次查看Protocol列,能够看到出现了DICOM字样。如图15所看到的。最上方的带DICOM字样的数据包就是我们抓取到的C-ECHO服务的本地回路数据包。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

2)C-ECHO数据流分析:

利用RawCap.exe和WireShark两大强大的工具,我们已经能够直观的看到抓取的DICOM数据包了。接下来我就依照DICOM标准第7部分和第8部分中的内容,逐个数据包来分析一下,通过观察真实的数据包来加深一下对DICOM协议的理解。

从图15中能够看到。最顶部DICOM协议包括6个数据包,各自是连接建立(A-ASSOCIATE RQ/A-ASSOCIATE AC)、数据交互(P-DATA-TF)、连接释放(A-RELEASE RQ/A-RELEASE RP),这与DICOM协议第8部分中介绍的ACSE控制流程相符。

A-ASSOCIATE RQ/A-ASSOCATE AC分析:

双击第一个DICOM数据包,该数据包是A-ASSOCIATE RQ的真实数据流,如图16所看到的:

依照DICOM协议第8部分中第9章对A-ASSOCIATE RQ PDU的描写叙述。我们来逐项对照(DICOM协议可參照图17):第一项1个字节的PDU-type,图中为01H,说明该数据包代表的是A-ASSOCIATE RQ;第二项一个字节的保留,数据流为00H;第三项是四个字节的PDU-length,图中为00 00 00 ff,转换为无符号整数正好为255。这也是整个图中蓝色部分兴许的数据包长度;第四项是两个字节的Protocol-Version,图中为00
01。相应版本号为1;第五项为两字节保留;第六项和第七项是我们熟悉的AE Title,从WireShark的数据流中也能够看出各自是ANY-SCP和ECHOSCU;第8项又是一堆保留字节。用00H填充;第9项是一个可变区域(Variable Fields),该项是复合项。内部包括多个独立的子项。由图16能够看出该复合项内部含有Application ContextPresentation
Context
(2个,ID各自是1、3)、UserInfo三个子项;而UserInfo又是一个复合项,其内部又包括了Max PDU LengthImplentationUIDImplentationVersion三个子项。从WireShark的分析来看,Application Context子项类型为10H、Presentation Context子项类型为20H、UserInfo子项为50H(其内部的嵌套子项的类型分别为,Max
PDU Length-51H、Implentation UID-52H、Implentation Version-55H
)。各个子项的类型与DICOM协议第7、8两部分中的附录D相相应。比如图19中我截取的是Max PDU Length子项的格式。A-ASSOCIATE AC的数据包分析与A-ASSOCIATE RQ类似,仅仅是A-ASSOCIATE AC的数据流更简单一些,这里就不做具体介绍了。(终于数据域DICOM协议的相应结果如图18)。

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

A-RELEASE RQ/A-RELEASE RP分析:

连接释放的数据包格式简单,以下图20和图21各自是DICOM协议第8部分中给出的连接释放请求和应答数据包的格式:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvenNzdXJlcWg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

双击WireShark中的连接释放数据包,能够看到两者的数据包类型分别为05H和06H,这与上图中DICOM协议的规定全然一致。

P-DATA-TF:

在上一篇博文中(http://blog.csdn.net/zssureqh/article/details/41016091)我已经分析了。DICOM协议第7部分中规定的DIMSE消息(Command和Dataset)是通过第8部分中ACSE协议中的P-DATA-TF服务以PDV的形式来传输的

以下就让我们来分析一下DIMSE消息中C-ECHO
RQ 和C-ECHO RSP的格式:

双击WireShark数据包中间两个,从数据流向能够断定一个是C-ECHO RQ消息。一个是C-ECHO RSP消息。

先打开第一个。依照上一篇博文的分析。首先该数据包是一个P-DATA-TF PDU,因此须要符合下图23中的格式。

通过分析最外层的是代表P-DATA-TF类型的04H。然后是由DIMSE消息填充的PDV区域,该项是复合项,第一子项是Item-length,此处为46H;第二子项为Presentation-context-ID,此处为01H;第三子项又是一个复合项。是DICOM标准第4部分中给出的DIMSE消息结构。包含Message Control Header、Command和DataSet三部分。此处的MessageControlHeader为03H,即表示是Command数据而不是DataSet,且是最后一个PDV,即Last
Fragment。详细的相应关系如图24所看到的:

C-STORE服务数据流分析:

1)工具:

依旧使用RawCap.exe+WireShark来解决。

2)C-STORE数据流分析:

依照C-ECHO中的分析方式,相同能够看到DICOM数据包,如图25所看到的:

A-ASSOCIATE RQ/A-ASSOCIATE AC:

对于A-ASSOCIATE RQ/A-ASSOCIATE AC的分析与C-ECHO中基本类似,唯一不同的就是对于C-STORE服务须要不同的Presentation Context描写叙述上下文,如图26所看到的,此处C-STORE须要的是CT Image Storage服务,其SOP Class UID为1.2.840.10008.5.1.4.1.1.2。

A-RELEASE RQ/A-RELEASE RP:

与C-ECHO中的同样,这也说明了博文中的C-ECHO 和C-STORE服务实现成功。连接可以正常释放。

P-DATA-TF:

此处着重分析一下C-STORE服务中的P-DATA-TF数据包,由于传输一个DCM文件须要多个PDU,自然也须要多个PDV。

所以我们通过分析C-STORE的P-DATA-TF数据包能够更形象的学习Message Control Header和DIMSE的知识

相同传输的每一个数据包首先符合P-DATA-TF的格式要求。第一项是PDU类型,即04H。随后是保留项、PDU-length、PDV复合项……,这与C-ECHO中的分析相同。依照上一篇博文的分析,C-STORE PROTOCOL的流程是CSTORE SCU向SCP发送C-STORE RQ消息。可是打开图中的第一个P-DATA数据包时我们看到的却不是C-STORE RQ,而是当中的一个数据片段,例如以下图27所看到的。

依次查看后面的几个P-DATA数据包,都是类似的情况。最后倒数两个各自是C-STORE RQ中DCM文件数据的最后一个数据包(Last Fragment)和SCP向SCU发送的C-STORE RSP,详细分析如图28所看到的:

从最后数据包Command中的(0000,0100)的值域8001H可知该指令就是C-STORE RSP。

看到这里你也许会非常兴奋,由于我们最终也看到了C-STORE服务的真实数据流。可是在上图中的全部DICOM相应的数据包中我们并未找到C-STORE SCU发起的C-STORE RQ数据包,那么C-STORE RQ数据包在哪里呢

让我们将cstore.pcap的全部数据包依照时间排序,出现了大量标记为[TCP segment of a reassembled PDU]的TCP数据包。

打开第一个标记为[TCP segment of a reassembled PDU]的TCP数据包。其内部的真实数据分析例如以下图30所看到的:

至此我们顺利找到了C-STORE SCU端发送的C-STORE RQ消息,之所以没有在WireShark中以DICOM协议显示,可能是因为WireShark在识别多个连续分片的数据时不够智能。博文中的演示样例图和文字较多,细致阅读后应该对DICOM3.0中的协议会有更进一步的了解。通过分析数据包的方式在更直观的学习和掌握DICOM3.0标准的同一时候,对后期排查DICOM网络传输相关错误也会有帮助。

备注:

再次说明一下阅读DICOM3.0标准的方式:

以DICOM3.0标准的第7、8部分为例,【第7部分】中第9章開始解说DIMSE-C的各种服务,依次为C-STORE、C-FIND、C-GET、C-MOVE、C-ECHO(上图1就是我在该部分的C-ECHO小节中截取的),当中前半部分主要给出了DIMSE-C各种服务的參数,这里不过罗列出DICOM3.0标准的要求。目的是让你明确各个服务參数是否是必要的(分别用M、U、=表示);后半部分開始解说DIMSE-C各种服务的协议及实现流程(即Protocol和Procedures)。在PROTOCOL中给出的是详细的DIMSE-C服务的各种指令在传输过程中的格式,该部分也就是你利用抓包工具可以直接抓取的真实数据流;在Procedures中给出的是SCU和SCP之间的交互流程。通常为了说明服务是由谁发起的。由谁响应。在介绍Protocol的时候对于比較复杂的、可变的区域(Variables
Fields)一般会放在附录中。比如第7部分的附录C和E等;【第8部分】与【第7部分】类似。从第7章開始介绍ACSE的各种服务的參数(如图2所看到的),依次为A-ASSOCIATE、A-RELEASE、A-ABORT、A-P-ABORT、P-DATA;第9章给出的是ACSE中各种服务的结构,即STRUCTURE,该部分与【第7部分】中的PROTOCOL相同,给出的是详细ACSE PDU在传输时刻的数据格式,该部分也是能够通过抓包工具直接获得的。相同对于比較复杂的STRUCTURE介绍也会单独放到附录中。比如第8部分的附录E。

实例project及抓取的数据包:

代码:搜索我上传的资源

数据包:搜索我上传的资源

兴许专栏博文介绍:

利用PHP Skel结合DCMTK开发WEB PACS应用

利用oracle直接操作DICOM数据

C#的异步编程模式在fo-dicom中的应用

VMWare三种网络连接模式的实际測试





作者:zssure@163.com

时间:2014-11-18

DICOM医学图像处理:fo-dicom网络传输之 C-Echo and C-Store的更多相关文章

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

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

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

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

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

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

  4. DICOM医学图像处理:Orthanc Plugin SDK实现WADO服务

    背景: Orthanc是博主发现的一个很完美的DICOM和HTTP服务端开源软件,前几篇分别介绍了Orthanc的基本使用.Orthanc从0.8.0版本之后给出了Plugin SDK,通过该SDK可 ...

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

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

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

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

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

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

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

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

  9. DICOM医学图像处理:WEB PACS初谈

    背景: 周末看到了一篇原公司同事的文章,讲的是关于新的互联网形势下的PACS系统.正好上一篇专栏文章也提到了有想搭建一个worklist服务器的冲动,所以就翻箱倒柜将原本学生时代做课题时搭建的简易We ...

随机推荐

  1. 金蝶KIS标准版与金蝶K3的差别

    一.数据库  金蝶KIS标准版使用MS Access数据库.该数据库适用于小规模的数据处理,是比較经济的数据库解决方式,但当单个表的数据记录超过5万条时.执行的速度和稳定性都将受到一定程序的影响. K ...

  2. Adding Kentico controls to the Visual Studio toolbox

    https://docs.kentico.com/k10/references/kentico-controls https://docs.kentico.com/k10/references/ken ...

  3. 2016 提高组c++ 错题

    需重做 树的重心 链表 计算机基础知识 无线通讯技术: 蓝牙,wifi,GPRS 现在常用的无线通信技术:FM调频广播(用于收音机): 2G.3G移动通信技术(中国移动.中国联通.中国电信正在运营的网 ...

  4. ROS-package.xml文件标签解读

    前言:package.xml是一个XML文件名为package.xml中必须包括与任何兼容包的根文件夹.此文件定义有关包的属性,例如包名称,版本号,作者,维护者以及其他catkin包的依赖关系. 标签 ...

  5. hdu 1394 Minimum Inversion Number 【线段树求逆序数】

    之前写过树状数组的,再用线段树写一下--- #include<cstdio> #include<cstring> #include<iostream> #inclu ...

  6. Hihocoder1350-Binary Watch

    时间限制:10000ms单点时限:1000ms内存限制:256MB 描述 Consider a binary watch with 5 binary digits to display hours ( ...

  7. WiFi相关基础概念

    转自:https://blog.csdn.net/lbaihao/article/details/73250798 一.WiFi相关基础概念 1.什么是wifi 我们看一下百度百科是如何定义的: Wi ...

  8. 使用ECharts制作图形时,如何设置指定图形颜色?

    使用ECharts制作图形时,图形颜色是默认的颜色,有时需求需要指定图形颜色,这就需要自己去设置. 在option下的series属性中设置itemStyle,如下所示: itemStyle: { n ...

  9. Someing-About-Work

    投料分拨次评估1.调试线投料分波次:(由调试厂录入生产计划:按照实际装机计划做二次分拣)1)计划组必须改两次工单:因为使用的是不同的任务号,一次一次分拣,一次二次分拣,2)计划核对数量困难,不能按照制 ...

  10. js单体内置对象

    js单体内置对象:js的内置对象,是ECMAScritp提供的.不依赖于宿主环境的对象,我的理解就是在我们开发之前js里面就已经存在的对象.单体内置对象就是是不需要通过new来实例化的,例如我们的st ...