一个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[]{// LosslessDicomTransferSyntax.JPEGLSLossless,DicomTransferSyntax.JPEG2000Lossless,DicomTransferSyntax.JPEGProcess14SV1,DicomTransferSyntax.JPEGProcess14,DicomTransferSyntax.RLELossless,// LossyDicomTransferSyntax.JPEGLSNearLossless,DicomTransferSyntax.JPEG2000Lossy,DicomTransferSyntax.JPEGProcess1,DicomTransferSyntax.JPEGProcess2_4,// UncompressedDicomTransferSyntax.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;}}
}