一个DICOM测试工具。
引用了 fo-dicom 。fo-dicom 算是比较好用的,我的另外一个项目也是用了它。
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Dicom;
using Dicom.Log;
using Dicom.Network;
using Dicom.Serialization;
using Newtonsoft.Json;
namespace DicomUtils
{
public delegate void CStoreRequestHandler(TDicomServer Server, TDicomService service, string studyuid, string instuid, string tag, ref string fileid, ref string filename);
public delegate void CStoreFileSavedHandler(TDicomServer Server, TDicomService service, string studyuid, string instuid, string tag, string fileid, string filename);
public delegate void CFindHandler(TDicomServer Server, TDicomService service, string json,ref DataTable dt);
public class TDicomServer
{
public IDicomServer Server = null;
public ServerConfig Config = null;
public List<TLogItem> Log = new List<TLogItem>();
public void Start()
{
wirtelog("Server "+ "Start");
Server = DicomServer.Create<TDicomService>(Config.Port, userState: this);
}
public void Stop()
{
if (Server != null)
{
wirtelog("Server " + "Stop");
Server.Stop();
Server.Dispose();
Server = null;
}
}
public event CStoreRequestHandler EventCStoreRequest;
public virtual void OnCStoreRequest(TDicomService service,string studyuid, string instuid, string tag, ref string fileid, ref string filename)
{
if (filename == "")
{
string dir =get_storge_dir();
string fn = System.IO.Path.Combine(dir, studyuid, instuid + ".dcm");
filename = fn;
}
wirtelog("OnCStoreRequest " + filename);
if (EventCStoreRequest != null)
{
EventCStoreRequest(this, service, studyuid, instuid, tag, ref fileid, ref filename);
}
}
public event CStoreFileSavedHandler EventCStoreFileSaved;
public virtual void OnCStoreFileSaved(TDicomService service, string studyuid, string instuid, string tag, string fileid, string filename)
{
wirtelog("OnCStoreFileSaved " + filename);
string fn_json = System.IO.Path.ChangeExtension(filename,".json");
System.IO.File.WriteAllText(fn_json, tag);
if (EventCStoreFileSaved != null)
{
EventCStoreFileSaved(this, service, studyuid, instuid, tag, fileid, filename);
}
}
public event CFindHandler EventCFind;
public virtual void OnCFindRequest(TDicomService service, DicomDataset request, string json, List<DicomDataset> list)
{
wirtelog("OnCFindRequest " + json);
if (EventCFind != null)
{
DataTable dt = null;
EventCFind(this, service, json,ref dt);
if (dt != null)
{
List<WorklistItem> worklists = WorklistHandler.dt2worklists(dt);
List<DicomDataset> data= WorklistHandler.Worklist2DataSet(request,worklists);
list.AddRange(data);
}
}
}
public void wirtelog(string msg)
{
lock (Log)
try
{
if (Log.Count > 1000)
{
Log.RemoveRange(0,500);
}
Log.Add(TLogItem.new_item(msg));
}
catch
{
}
}
public string get_storge_dir()
{
return Config.get_storge_dir();
}
}
public class TDicomService : DicomService, IDicomServiceProvider, IDicomCStoreProvider, IDicomCFindProvider, IDicomCMoveProvider, IDicomCGetProvider, IDicomCEchoProvider
{
private static readonly DicomTransferSyntax[] AcceptedTransferSyntaxes = new DicomTransferSyntax[]
{
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
private static readonly DicomTransferSyntax[] AcceptedImageTransferSyntaxes = new DicomTransferSyntax[]
{
// Lossless
DicomTransferSyntax.JPEGLSLossless,
DicomTransferSyntax.JPEG2000Lossless,
DicomTransferSyntax.JPEGProcess14SV1,
DicomTransferSyntax.JPEGProcess14,
DicomTransferSyntax.RLELossless,
// Lossy
DicomTransferSyntax.JPEGLSNearLossless,
DicomTransferSyntax.JPEG2000Lossy,
DicomTransferSyntax.JPEGProcess1,
DicomTransferSyntax.JPEGProcess2_4,
// Uncompressed
DicomTransferSyntax.ExplicitVRLittleEndian,
DicomTransferSyntax.ExplicitVRBigEndian,
DicomTransferSyntax.ImplicitVRLittleEndian
};
public TDicomService(INetworkStream stream, Encoding fallbackEncoding, Logger log)
: base(stream, fallbackEncoding, log)
{
}
public TDicomServer GetSCPServer()
{
return (TDicomServer)UserState;
}
public void wirtelog(string msg)
{
TDicomServer Server = GetSCPServer();
Server.wirtelog(msg);
}
public Task OnReceiveAssociationRequestAsync(DicomAssociation association)
{
wirtelog("OnReceiveAssociationRequestAsync IP:" + association.RemoteHost + " PORT:" + association.RemotePort.ToString() + " AE:" + association.CalledAE);
TDicomServer Server = GetSCPServer();
if (!Server.Config.isAllowAE(association.CalledAE))
{
wirtelog("SendAssociationRejectAsync IP:" + association.RemoteHost + " PORT:" + association.RemotePort.ToString() + " AE:" + association.CalledAE);
return SendAssociationRejectAsync(
DicomRejectResult.Permanent,
DicomRejectSource.ServiceUser,
DicomRejectReason.CalledAENotRecognized);
}
foreach (var pc in association.PresentationContexts)
{
if (pc.AbstractSyntax == DicomUID.Verification
|| pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelFind
|| pc.AbstractSyntax == DicomUID.PatientRootQueryRetrieveInformationModelMove
|| pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelFind
|| pc.AbstractSyntax == DicomUID.StudyRootQueryRetrieveInformationModelMove
|| pc.AbstractSyntax == DicomUID.ModalityWorklistInformationModelFind
|| pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStep
|| pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStepNotification
|| pc.AbstractSyntax == DicomUID.ModalityPerformedProcedureStepRetrieve
)
{
pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
}
if (pc.AbstractSyntax == DicomUID.Verification) pc.AcceptTransferSyntaxes(AcceptedTransferSyntaxes);
else if (pc.AbstractSyntax.StorageCategory != DicomStorageCategory.None) pc.AcceptTransferSyntaxes(AcceptedImageTransferSyntaxes);
}
return SendAssociationAcceptAsync(association);
}
public Task OnReceiveAssociationReleaseRequestAsync()
{
wirtelog("OnReceiveAssociationReleaseRequestAsync");
return SendAssociationReleaseResponseAsync();
}
public void OnReceiveAbort(DicomAbortSource source, DicomAbortReason reason)
{
wirtelog("OnReceiveAbort IP:" + source.ToString() + " reason:" + reason.ToString());
}
public void OnConnectionClosed(Exception exception)
{
if (exception != null)
{
wirtelog("OnConnectionClosed exception:" + exception.ToString());
}
else
{
wirtelog("OnConnectionClosed");
}
}
public DicomCStoreResponse OnCStoreRequest(DicomCStoreRequest request)
{
TDicomServer Server = GetSCPServer();
string studyUid = request.Dataset.GetSingleValue<string>(DicomTag.StudyInstanceUID);
string instUid = request.SOPInstanceUID.UID;
wirtelog("OnCStoreRequest studyUid:" + studyUid + " instUid:" + instUid);
string tag = "";
if (request.HasDataset)
tag=Pub.DicomDataset2json(request.Dataset);
string filename = "";
string fileid = "";
Server.OnCStoreRequest(this, studyUid, instUid, tag, ref fileid, ref filename);
string dir = System.IO.Path.GetDirectoryName(filename);
if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
request.File.Save(filename);
Server.OnCStoreFileSaved(this, studyUid, instUid, tag, fileid, filename);
return new DicomCStoreResponse(request, DicomStatus.Success);
}
public void OnCStoreRequestException(string tempFileName, Exception e)
{
wirtelog("OnCStoreRequest tempFileName:" + tempFileName + " exception:" + e.Message);
}
public DicomCEchoResponse OnCEchoRequest(DicomCEchoRequest request)
{
wirtelog("OnCEchoRequest MessageID:" + request.MessageID);
return new DicomCEchoResponse(request, DicomStatus.Success);
}
public IEnumerable<DicomCFindResponse> OnCFindRequest(DicomCFindRequest request)
{
wirtelog("OnCFindRequest request:" + request.Type.ToString());
string json = "";
if (request.HasDataset)
json =Pub.DicomDataset2json(request.Dataset);
TDicomServer Server = GetSCPServer();
List<DicomCFindResponse> responses = new List<DicomCFindResponse>();
List<DicomDataset> list = new List<DicomDataset>();
Server.OnCFindRequest(this, request.Dataset,json, list);
foreach (DicomDataset result in list)
{
responses.Add(new DicomCFindResponse(request, DicomStatus.Pending) { Dataset = result });
}
responses.Add(new DicomCFindResponse(request, DicomStatus.Success));
return responses;
}
public IEnumerable<DicomCMoveResponse> OnCMoveRequest(DicomCMoveRequest request)
{
wirtelog("OnCMoveRequest request:" + request.Type.ToString());
throw new NotImplementedException();
}
public IEnumerable<DicomCGetResponse> OnCGetRequest(DicomCGetRequest request)
{
wirtelog("OnCGetRequest request:" + request.Type.ToString());
throw new NotImplementedException();
}
}
public class TLogItem
{
public Int64 id = get_new_id();
public DateTime time = DateTime.Now;
public string msg = "";
public static Int64 last_id = 0;
public static Int64 get_new_id()
{
last_id = last_id + 1;
return last_id;
}
public static TLogItem new_item(string msg)
{
TLogItem i = new TLogItem();
i.msg = msg;
return i;
}
}
}