jiapeng лет назад: 5
Родитель
Сommit
50777537e9

+ 20 - 0
pom.xml

@ -65,6 +65,26 @@
65 65
            <artifactId>mail</artifactId>
66 66
            <version>1.4</version>
67 67
        </dependency>
68
        		<dependency>
69
			<groupId>org.dcm4che</groupId>
70
			<artifactId>dcm4che-core</artifactId>
71
			<version>5.16.0</version>
72
		</dependency>
73
		<dependency>
74
			<groupId>org.dcm4che</groupId>
75
			<artifactId>dcm4che-net</artifactId>
76
			<version>5.16.0</version>
77
		</dependency>
78
		<dependency>
79
			<groupId>org.dcm4che</groupId>
80
			<artifactId>dcm4che-dict</artifactId>
81
			<version>5.16.0</version>
82
		</dependency>
83
		<dependency>
84
			<groupId>org.dcm4che.tool</groupId>
85
			<artifactId>dcm4che-tool-common</artifactId>
86
			<version>5.16.0</version>
87
		</dependency>
68 88
<!-- 		<dependency>
69 89
			<groupId>org.apache.hadoop</groupId>
70 90
			<artifactId>hadoop-hdfs</artifactId>

+ 118 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomBase.java

@ -0,0 +1,118 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.util.concurrent.atomic.AtomicInteger;
4

5
import org.dcm4che3.data.Attributes;
6
import org.dcm4che3.data.ElementDictionary;
7
import org.dcm4che3.data.Tag;
8
import org.dcm4che3.data.UID;
9
import org.dcm4che3.data.VR;
10
import org.dcm4che3.net.ApplicationEntity;
11
import org.dcm4che3.net.Association;
12
import org.dcm4che3.net.Connection;
13
import org.dcm4che3.net.Device;
14
import org.dcm4che3.net.pdu.AAssociateRQ;
15
import org.dcm4che3.net.pdu.PresentationContext;
16

17

18
public class DicomBase {
19
	
20
    protected static String[] IVR_LE_FIRST = {
21
            UID.ImplicitVRLittleEndian,
22
            UID.ExplicitVRLittleEndian,
23
            UID.ExplicitVRBigEndianRetired
24
        };
25

26
    protected final Device device;
27
    protected final ApplicationEntity ae;
28
    protected final Connection conn;
29
    protected final Connection remote;
30
    protected final AAssociateRQ rq;
31
    protected Attributes keys = new Attributes();
32
    protected Association as;
33
    protected AtomicInteger totNumMatches = new AtomicInteger();
34

35
	protected DicomBase(String title) {
36
		device = new Device(title);
37
		ae = new ApplicationEntity(title);
38
		conn = new Connection();
39
		remote = new Connection();
40
		rq = new AAssociateRQ();
41
        device.addConnection(conn);
42
        device.addApplicationEntity(ae);
43
        ae.addConnection(conn);
44
	}
45
	
46
	
47
	public void setRemote(String title,String hostname,int port){
48
        rq.setCalledAET(title);
49
        remote.setHostname(hostname);
50
        remote.setPort(port);
51
        conn.setReceivePDULength(Connection.DEF_MAX_PDU_LENGTH);
52
        conn.setSendPDULength(Connection.DEF_MAX_PDU_LENGTH);
53
        conn.setMaxOpsInvoked(0);
54
        conn.setMaxOpsPerformed(0);
55
        
56
        conn.setPackPDV(true);
57
        conn.setConnectTimeout( 0);
58
        conn.setRequestTimeout(0);
59
        conn.setAcceptTimeout(0);
60
        conn.setReleaseTimeout(0);
61
        conn.setResponseTimeout(0);
62

63
        conn.setIdleTimeout(0);
64
        conn.setSocketCloseDelay(Connection.DEF_SOCKETDELAY);
65
        conn.setSendBufferSize( 0);
66
        conn.setReceiveBufferSize( 0);
67
        conn.setTcpNoDelay(true);
68
	}
69
	
70
	public String getLevel(){
71
		return "STUDY";
72
	}
73
	
74

75
	
76
	public void addAttribute(int tag, String value) {
77
		VR vr = ElementDictionary.vrOf(tag, keys.getPrivateCreator(tag));
78
		if (value == null) {
79

80
			if (vr == VR.SQ)
81
				keys.newSequence(tag, 1).add(new Attributes(0));
82
			else
83
				keys.setNull(tag, vr);
84
		} else {
85
			keys.setString(tag, vr, value);
86
		}
87
	}
88
	
89
    public void configureServiceClass()  {
90
    	rq.addPresentationContext(new PresentationContext(1,UID.StudyRootQueryRetrieveInformationModelFIND, IVR_LE_FIRST));
91
    	keys.setString(Tag.QueryRetrieveLevel, VR.CS, "STUDY");
92
    	
93

94
    	
95
//    	this.addAttribute(PatientID, null);
96
//    	
97
//
98
//    	
99
//		 "PatientID",
100
//         "IssuerOfPatientID",
101
//         "PatientSex", 
102
//         "PatientBirthDate",
103
//         "StudyInstanceUID",
104
//         "StudyInstanceUID",
105
//         "SeriesInstanceUID",
106
//         "StudyID",
107
//         "AccessionNumber",
108
//         "StudyDate",
109
//         "StudyTime",
110
//         "StudyDescription",
111
//         "NumberOfStudyRelatedSeries",
112
//         "NumberOfStudyRelatedInstances"
113
    }
114

115
	
116
	
117

118
}

+ 190 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomGetImage.java

@ -0,0 +1,190 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.io.File;
4
import java.io.IOException;
5
import java.security.GeneralSecurityException;
6
import java.util.LinkedList;
7
import java.util.List;
8
import java.util.concurrent.ExecutorService;
9
import java.util.concurrent.Executors;
10
import java.util.concurrent.ScheduledExecutorService;
11

12
import org.dcm4che3.data.Attributes;
13
import org.dcm4che3.data.Tag;
14
import org.dcm4che3.data.UID;
15
import org.dcm4che3.data.VR;
16
import org.dcm4che3.io.DicomOutputStream;
17
import org.dcm4che3.net.Association;
18
import org.dcm4che3.net.DimseRSPHandler;
19
import org.dcm4che3.net.IncompatibleConnectionException;
20
import org.dcm4che3.net.PDVInputStream;
21
import org.dcm4che3.net.Priority;
22
import org.dcm4che3.net.Status;
23
import org.dcm4che3.net.pdu.PresentationContext;
24
import org.dcm4che3.net.pdu.RoleSelection;
25
import org.dcm4che3.net.service.BasicCStoreSCP;
26
import org.dcm4che3.net.service.DicomServiceException;
27
import org.dcm4che3.net.service.DicomServiceRegistry;
28
import org.dcm4che3.util.SafeClose;
29

30
public class DicomGetImage extends DicomBase {
31
	private File storageDir;
32
	private String fn;
33
	private File dstFile;
34

35
	private BasicCStoreSCP storageSCP = new BasicCStoreSCP("*") {
36

37
		@Override
38
		protected void store(Association as, PresentationContext pc, Attributes rq, PDVInputStream data, Attributes rsp)
39
				throws IOException {
40
			if (storageDir == null)
41
				return;
42
			if(dstFile != null){
43
				return;
44
			}
45

46
			String iuid = rq.getString(Tag.AffectedSOPInstanceUID);
47
			String cuid = rq.getString(Tag.AffectedSOPClassUID);
48
			String tsuid = pc.getTransferSyntax();
49
			File file = new File(storageDir, fn);
50
			try {
51
				storeTo(as, as.createFileMetaInformation(iuid, cuid, tsuid), data, file);
52
				dstFile = file;
53
			} catch (Exception e) {
54
				throw new DicomServiceException(Status.ProcessingFailure, e);
55
			}
56

57
		}
58

59
	};
60

61
	private void storeTo(Association as, Attributes fmi, PDVInputStream data, File file) throws IOException {
62
		file.getParentFile().mkdirs();
63
		DicomOutputStream out = new DicomOutputStream(file);
64
		try {
65
			out.writeFileMetaInformation(fmi);
66
			data.copyTo(out);
67
		} finally {
68
			SafeClose.close(out);
69
		}
70
	}
71

72
	protected DicomGetImage(String title) {
73
		super(title);
74
		DicomServiceRegistry serviceRegistry = new DicomServiceRegistry();
75
		serviceRegistry.addDicomService(storageSCP);
76
		device.setDimseRQHandler(serviceRegistry);
77
	}
78

79
	private void download() throws IOException, InterruptedException {
80

81
		DimseRSPHandler rspHandler = new DimseRSPHandler(as.nextMessageID()) {
82

83
			@Override
84
			public void onDimseRSP(Association as, Attributes cmd, Attributes data) {
85
				super.onDimseRSP(as, cmd, data);
86
			}
87
		};
88
		as.cget(UID.StudyRootQueryRetrieveInformationModelGET, Priority.NORMAL, keys, null, rspHandler);
89
	}
90

91
	public static String toUID(String uid) {
92
		uid = uid.trim();
93
		return (uid.equals("*") || Character.isDigit(uid.charAt(0))) ? uid : UID.forName(uid);
94
	}
95

96
	private void configureStorageSOPClass(String cuid, String tsuid) {
97
		if (!rq.containsPresentationContextFor(cuid))
98
			rq.addRoleSelection(new RoleSelection(cuid, false, true));
99
		rq.addPresentationContext(new PresentationContext(2 * rq.getNumberOfPresentationContexts() + 1, cuid, tsuid));
100

101
	}
102

103
	public File download(String title, String hostname, int port, String imageId, File path, String fn)
104
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
105
		this.setRemote(title, hostname, port);
106
		this.rq.addPresentationContext(
107
				new PresentationContext(1, UID.StudyRootQueryRetrieveInformationModelGET, IVR_LE_FIRST));
108
		configureStorageSOPClass(UID.GrayscaleSoftcopyPresentationStateStorage, UID.ImplicitVRLittleEndian);
109
		configureStorageSOPClass(UID.GrayscaleSoftcopyPresentationStateStorage, UID.ExplicitVRLittleEndian);
110
		configureStorageSOPClass(UID.SecondaryCaptureImageStorage, UID.ImplicitVRLittleEndian);
111
		configureStorageSOPClass(UID.SecondaryCaptureImageStorage, UID.ExplicitVRLittleEndian);
112
		configureStorageSOPClass(UID.EncapsulatedPDFStorage, UID.ImplicitVRLittleEndian);
113
		configureStorageSOPClass(UID.EncapsulatedPDFStorage, UID.ExplicitVRLittleEndian);
114
		configureStorageSOPClass(UID.UltrasoundMultiFrameImageStorage, UID.ImplicitVRLittleEndian);
115
		configureStorageSOPClass(UID.UltrasoundMultiFrameImageStorage, UID.ExplicitVRLittleEndian);
116
		configureStorageSOPClass(UID.DigitalXRayImageStorageForPresentation, UID.ImplicitVRLittleEndian);
117
		configureStorageSOPClass(UID.DigitalXRayImageStorageForPresentation, UID.ExplicitVRLittleEndian);
118
		configureStorageSOPClass(UID.BasicTextSRStorage, UID.ImplicitVRLittleEndian);
119
		configureStorageSOPClass(UID.BasicTextSRStorage, UID.ExplicitVRLittleEndian);
120
		configureStorageSOPClass(UID.CTImageStorage, UID.ImplicitVRLittleEndian);
121
		configureStorageSOPClass(UID.CTImageStorage, UID.ExplicitVRLittleEndian);
122
		configureStorageSOPClass(UID.ComputedRadiographyImageStorage, UID.ImplicitVRLittleEndian);
123
		configureStorageSOPClass(UID.ComputedRadiographyImageStorage, UID.ExplicitVRLittleEndian);
124
		configureStorageSOPClass(UID.EnhancedSRStorage, UID.ImplicitVRLittleEndian);
125
		configureStorageSOPClass(UID.EnhancedSRStorage, UID.ExplicitVRLittleEndian);
126
		configureStorageSOPClass(UID.XRayRadiofluoroscopicImageStorage, UID.ImplicitVRLittleEndian);
127
		configureStorageSOPClass(UID.XRayRadiofluoroscopicImageStorage, UID.ExplicitVRLittleEndian);
128
		configureStorageSOPClass(UID.DigitalXRayImageStorageForProcessing, UID.ImplicitVRLittleEndian);
129
		configureStorageSOPClass(UID.DigitalXRayImageStorageForProcessing, UID.ExplicitVRLittleEndian);
130
		configureStorageSOPClass(UID.VLPhotographicImageStorage, UID.ImplicitVRLittleEndian);
131
		configureStorageSOPClass(UID.VLPhotographicImageStorage, UID.ExplicitVRLittleEndian);
132
		configureStorageSOPClass(UID.VLPhotographicImageStorage, UID.JPEGBaseline1);
133
		configureStorageSOPClass(UID.KeyObjectSelectionDocumentStorage, UID.ImplicitVRLittleEndian);
134
		configureStorageSOPClass(UID.KeyObjectSelectionDocumentStorage, UID.ExplicitVRLittleEndian);
135
		configureStorageSOPClass(UID.UltrasoundImageStorage, UID.ImplicitVRLittleEndian);
136
		configureStorageSOPClass(UID.KeyObjectSelectionDocumentStorage, UID.ExplicitVRLittleEndian);
137
		configureStorageSOPClass(UID.VideoPhotographicImageStorage, UID.JPEGBaseline1);
138
		configureStorageSOPClass(UID.VideoPhotographicImageStorage, UID.MPEG2);
139
		configureStorageSOPClass(UID.PositronEmissionTomographyImageStorage, UID.ImplicitVRLittleEndian);
140
		configureStorageSOPClass(UID.PositronEmissionTomographyImageStorage, UID.ExplicitVRLittleEndian);
141
		configureStorageSOPClass(UID.XRayAngiographicImageStorage, UID.ImplicitVRLittleEndian);
142
		configureStorageSOPClass(UID.XRayAngiographicImageStorage, UID.ExplicitVRLittleEndian);
143
		configureStorageSOPClass(UID.DigitalMammographyXRayImageStorageForProcessing, UID.ImplicitVRLittleEndian);
144
		configureStorageSOPClass(UID.DigitalMammographyXRayImageStorageForProcessing, UID.ExplicitVRLittleEndian);
145
		configureStorageSOPClass(UID.XRayRadiationDoseSRStorage, UID.ImplicitVRLittleEndian);
146
		configureStorageSOPClass(UID.XRayRadiationDoseSRStorage, UID.ExplicitVRLittleEndian);
147
		configureStorageSOPClass(UID.NuclearMedicineImageStorage, UID.ImplicitVRLittleEndian);
148
		configureStorageSOPClass(UID.NuclearMedicineImageStorage, UID.ExplicitVRLittleEndian);
149
		configureStorageSOPClass(UID.VLWholeSlideMicroscopyImageStorage, UID.JPEGBaseline1);
150
		configureStorageSOPClass(UID.VLWholeSlideMicroscopyImageStorage, UID.JPEG2000LosslessOnly);
151
		configureStorageSOPClass(UID.VLWholeSlideMicroscopyImageStorage, UID.JPEG2000);
152
		configureStorageSOPClass(UID.MRImageStorage, UID.ImplicitVRLittleEndian);
153
		configureStorageSOPClass(UID.MRImageStorage, UID.ExplicitVRLittleEndian);
154
		configureStorageSOPClass(UID.DigitalMammographyXRayImageStorageForPresentation, UID.ImplicitVRLittleEndian);
155
		configureStorageSOPClass(UID.DigitalMammographyXRayImageStorageForPresentation, UID.ExplicitVRLittleEndian);
156
		this.keys.setString(Tag.QueryRetrieveLevel, VR.CS, "IMAGE");
157

158
		this.addAttribute(Tag.SOPInstanceUID, imageId);
159

160
		this.storageDir = path;
161
		this.fn = fn;
162

163
		ExecutorService executorService = Executors.newSingleThreadExecutor();
164
		ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
165
		this.device.setExecutor(executorService);
166
		this.device.setScheduledExecutor(scheduledExecutorService);
167

168
		try {
169
			as = ae.connect(conn, remote, rq);
170
			download();
171
		} finally {
172
			if (as != null && as.isReadyForDataTransfer()) {
173
				as.waitForOutstandingRSP();
174
				as.release();
175
			}
176
			executorService.shutdown();
177
			scheduledExecutorService.shutdown();
178
		}
179
		return this.dstFile;
180
	}
181

182
	public static void main(String args[])
183
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
184
		DicomGetImage q = new DicomGetImage("GETSCU");
185
		q.download("DCM4CHEE", "192.168.3.97", 11112, "1.2.840.113663.1500.1.434945515.3.6.20180902.100711.313",
186
				new File("D:\\test\\GETSCU"), "2.dcm");
187

188
	}
189

190
}

+ 115 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomQueryImage.java

@ -0,0 +1,115 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.io.IOException;
4
import java.security.GeneralSecurityException;
5
import java.util.LinkedList;
6
import java.util.List;
7
import java.util.concurrent.ExecutorService;
8
import java.util.concurrent.Executors;
9
import java.util.concurrent.ScheduledExecutorService;
10

11
import org.dcm4che3.data.Attributes;
12
import org.dcm4che3.data.Tag;
13
import org.dcm4che3.data.UID;
14
import org.dcm4che3.data.VR;
15
import org.dcm4che3.net.Association;
16
import org.dcm4che3.net.DimseRSPHandler;
17
import org.dcm4che3.net.IncompatibleConnectionException;
18
import org.dcm4che3.net.Priority;
19
import org.dcm4che3.net.Status;
20
import org.dcm4che3.net.pdu.PresentationContext;
21
import org.jfw.util.json.JsonService;
22

23
public class DicomQueryImage extends DicomBase {
24
	private List<SeriesImage> result = new LinkedList<SeriesImage>();
25
	private SeriesImage image;
26
	private StringBuilder sb = new StringBuilder();
27

28

29
	private Attributes.Visitor visitor = new Attributes.Visitor() {
30

31
		public boolean visit(Attributes attrs, int tag, VR vr, Object value) throws Exception {
32
			if (value != null) {
33
				sb.setLength(0);
34
				if(vr.prompt(value, attrs.bigEndian(), attrs.getSpecificCharacterSet(vr),
35
		               100000, sb)){
36
					if(sb.length()<1){
37
						return true;
38
					}
39
					
40
					if(tag == Tag.SOPInstanceUID){
41
						image.setId(sb.toString());
42
					}else if(tag == Tag.InstanceNumber){
43
						image.setNum(sb.toString());
44
					}
45
				}
46
			}
47
			return true;
48
		}
49
	};
50

51
	protected DicomQueryImage(String title) {
52
		super(title);
53
	}
54

55
	private void query() throws IOException, InterruptedException {
56
		DimseRSPHandler rspHandler = new DimseRSPHandler(as.nextMessageID()) {
57
			@Override
58
			public void onDimseRSP(Association as, Attributes cmd, Attributes data) {
59
				super.onDimseRSP(as, cmd, data);
60
				int status = cmd.getInt(Tag.Status, -1);
61
				if (Status.isPending(status)) {
62
					image = new SeriesImage();
63
					result.add(image);
64
					try {
65
						data.accept(visitor, false);
66
					} catch (Exception e) {
67
					}
68
				}
69
			}
70
		};
71
		as.cfind(UID.StudyRootQueryRetrieveInformationModelFIND, Priority.NORMAL, keys, null, rspHandler);
72
	}
73

74
	public List<SeriesImage> query(String title, String hostname, int port, String studyUid,String seriesUid)
75
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
76
		this.setRemote(title, hostname, port);
77
		this.rq.addPresentationContext(
78
				new PresentationContext(1, UID.StudyRootQueryRetrieveInformationModelFIND, IVR_LE_FIRST));
79
		this.keys.setString(Tag.QueryRetrieveLevel, VR.CS, "IMAGE");
80
		
81
		
82
		this.addAttribute(Tag.StudyInstanceUID, studyUid);
83
		this.addAttribute(Tag.SeriesInstanceUID, seriesUid);
84
		this.addAttribute(Tag.SOPInstanceUID,null);
85
		this.addAttribute(Tag.InstanceNumber,null);
86
		ExecutorService executorService = Executors.newSingleThreadExecutor();
87
		ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
88
		this.device.setExecutor(executorService);
89
		this.device.setScheduledExecutor(scheduledExecutorService);
90

91
		try {
92
			as = ae.connect(conn, remote, rq);
93
			query();
94
		} finally {
95
			if (as != null && as.isReadyForDataTransfer()) {
96
				as.waitForOutstandingRSP();
97
				as.release();
98
			}
99
			executorService.shutdown();
100
			scheduledExecutorService.shutdown();
101
		}
102
		return this.result;
103
	}
104

105
	public static void main(String args[])
106
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
107
		DicomQueryImage q = new DicomQueryImage("findscu");
108
		q.query("DCM4CHEE", "192.168.3.97", 11112, "1.2.840.113663.1500.1.434945515.1.1.20180902.100500.537","1.2.840.113663.1500.1.434945515.2.1.20180902.100500.539");
109
		
110
		for(SeriesImage s:q.result){
111
			System.out.println(JsonService.toJson(s));
112
		}
113

114
	}
115
}

+ 130 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomQuerySeries.java

@ -0,0 +1,130 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.io.IOException;
4
import java.security.GeneralSecurityException;
5
import java.util.LinkedList;
6
import java.util.List;
7
import java.util.concurrent.ExecutorService;
8
import java.util.concurrent.Executors;
9
import java.util.concurrent.ScheduledExecutorService;
10

11
import org.dcm4che3.data.Attributes;
12
import org.dcm4che3.data.Tag;
13
import org.dcm4che3.data.UID;
14
import org.dcm4che3.data.VR;
15
import org.dcm4che3.net.Association;
16
import org.dcm4che3.net.DimseRSPHandler;
17
import org.dcm4che3.net.IncompatibleConnectionException;
18
import org.dcm4che3.net.Priority;
19
import org.dcm4che3.net.Status;
20
import org.dcm4che3.net.pdu.PresentationContext;
21
import org.jfw.util.json.JsonService;
22

23
public class DicomQuerySeries extends DicomBase {
24
	private List<StudySeries> result = new LinkedList<StudySeries>();
25
	private StudySeries series;
26
	private StringBuilder sb = new StringBuilder();
27

28

29
	private Attributes.Visitor visitor = new Attributes.Visitor() {
30

31
		public boolean visit(Attributes attrs, int tag, VR vr, Object value) throws Exception {
32
			if (value != null) {
33
				sb.setLength(0);
34
				if(vr.prompt(value, attrs.bigEndian(), attrs.getSpecificCharacterSet(vr),
35
		               100000, sb)){
36
					if(sb.length()<1){
37
						return true;
38
					}
39
					
40
					if(tag == Tag.SeriesDate){
41
						series.setSeriesDate(sb.toString());
42
					}else if(tag == Tag.SeriesTime){
43
						series.setSeriesTime(sb.toString());
44
					}else if(tag == Tag.Modality){
45
						series.setSeriesType(sb.toString());
46
					}else if(tag == Tag.SeriesDescription){
47
						series.setSeriesDescription(sb.toString());
48
					}else if(tag == Tag.SeriesInstanceUID){
49
						series.setId(sb.toString());
50
					}else if(tag == Tag.SeriesNumber){
51
						series.setNumOfStudy(sb.toString());
52
					}else if(tag == Tag.NumberOfStudyRelatedInstances){
53
						series.setNumberOfSeriesRelatedInstances(sb.toString());
54
					}
55
				}
56
			}
57
			return true;
58
		}
59
	};
60

61
	protected DicomQuerySeries(String title) {
62
		super(title);
63
	}
64

65
	private void query() throws IOException, InterruptedException {
66
		DimseRSPHandler rspHandler = new DimseRSPHandler(as.nextMessageID()) {
67
			@Override
68
			public void onDimseRSP(Association as, Attributes cmd, Attributes data) {
69
				super.onDimseRSP(as, cmd, data);
70
				int status = cmd.getInt(Tag.Status, -1);
71
				if (Status.isPending(status)) {
72
					series = new StudySeries();
73
					result.add(series);
74
					try {
75
						data.accept(visitor, false);
76
					} catch (Exception e) {
77
					}
78
				}
79
			}
80
		};
81
		as.cfind(UID.StudyRootQueryRetrieveInformationModelFIND, Priority.NORMAL, keys, null, rspHandler);
82
	}
83

84
	public List<StudySeries> query(String title, String hostname, int port, String studyUid)
85
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
86
		this.setRemote(title, hostname, port);
87
		this.rq.addPresentationContext(
88
				new PresentationContext(1, UID.StudyRootQueryRetrieveInformationModelFIND, IVR_LE_FIRST));
89
		this.keys.setString(Tag.QueryRetrieveLevel, VR.CS, "SERIES");
90
		
91
		
92
		this.addAttribute(Tag.StudyInstanceUID, studyUid);
93
		
94
		this.addAttribute(Tag.SeriesDate,null);
95
		this.addAttribute(Tag.SeriesTime,null);
96
		this.addAttribute(Tag.Modality,null);
97
		this.addAttribute(Tag.SeriesDescription,null);
98
		this.addAttribute(Tag.SeriesInstanceUID,null);
99
	    this.addAttribute(Tag.SeriesNumber,null);
100
		this.addAttribute(Tag.NumberOfStudyRelatedInstances,null);
101
		ExecutorService executorService = Executors.newSingleThreadExecutor();
102
		ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
103
		this.device.setExecutor(executorService);
104
		this.device.setScheduledExecutor(scheduledExecutorService);
105

106
		try {
107
			as = ae.connect(conn, remote, rq);
108
			query();
109
		} finally {
110
			if (as != null && as.isReadyForDataTransfer()) {
111
				as.waitForOutstandingRSP();
112
				as.release();
113
			}
114
			executorService.shutdown();
115
			scheduledExecutorService.shutdown();
116
		}
117
		return this.result;
118
	}
119

120
	public static void main(String args[])
121
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
122
		DicomQuerySeries q = new DicomQuerySeries("findscu");
123
		q.query("DCM4CHEE", "192.168.3.97", 11112, "1.2.840.113663.1500.1.434945515.1.1.20180902.100500.537");
124
		
125
		for(StudySeries s:q.result){
126
			System.out.println(JsonService.toJson(s));
127
		}
128

129
	}
130
}

+ 143 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomQueryStudy.java

@ -0,0 +1,143 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.io.IOException;
4
import java.security.GeneralSecurityException;
5
import java.util.LinkedList;
6
import java.util.List;
7
import java.util.concurrent.ExecutorService;
8
import java.util.concurrent.Executors;
9
import java.util.concurrent.ScheduledExecutorService;
10

11
import org.dcm4che3.data.Attributes;
12
import org.dcm4che3.data.ElementDictionary;
13
import org.dcm4che3.data.Tag;
14
import org.dcm4che3.data.UID;
15
import org.dcm4che3.data.VR;
16
import org.dcm4che3.net.Association;
17
import org.dcm4che3.net.DimseRSPHandler;
18
import org.dcm4che3.net.IncompatibleConnectionException;
19
import org.dcm4che3.net.Priority;
20
import org.dcm4che3.net.Status;
21
import org.dcm4che3.net.pdu.PresentationContext;
22
import org.jfw.util.json.JsonService;
23

24
public class DicomQueryStudy extends DicomBase {
25

26
	private List<PatientStudy> result = new LinkedList<PatientStudy>();
27
	private PatientStudy study;
28
	private StringBuilder sb = new StringBuilder();
29

30

31
	private Attributes.Visitor visitor = new Attributes.Visitor() {
32

33
		public boolean visit(Attributes attrs, int tag, VR vr, Object value) throws Exception {
34
			if (value != null) {
35
				sb.setLength(0);
36
				if(vr.prompt(value, attrs.bigEndian(), attrs.getSpecificCharacterSet(vr),
37
		               100000, sb)){
38
					if(sb.length()<1){
39
						return true;
40
					}
41
					if(tag == Tag.PatientName){
42
						study.setPatientName(sb.toString());
43
					}else if(tag == Tag.PatientID){
44
						study.setPatientId(sb.toString());
45
					}else if(tag == Tag.PatientSex){
46
						study.setSex(sb.toString());
47
					}else if(tag == Tag.PatientBirthDate){
48
						study.setBirth(sb.toString());
49
					}else if(tag == Tag.StudyInstanceUID){
50
						study.setStudyUid(sb.toString());
51
					}else if(tag == Tag.StudyID){
52
						study.setStudyId(sb.toString());
53
					}else if(tag == Tag.StudyDate){
54
						study.setStudyDate(sb.toString());
55
					}else if(tag == Tag.StudyTime){
56
						study.setStudyTime(sb.toString());
57
					}else if(tag == Tag.StudyDescription){
58
						study.setDescription(sb.toString());
59
					}else if(tag == Tag.NumberOfStudyRelatedSeries){
60
						study.setNumOfStudyRelatedSeries(sb.toString());
61
					}else if(tag == Tag.NumberOfStudyRelatedInstances){
62
						study.setNumOfstudyRelatedInstances(sb.toString());
63
					}
64
				}
65
			}
66
			return true;
67
		}
68
	};
69

70
	protected DicomQueryStudy(String title) {
71
		super(title);
72
	}
73

74
	private void query() throws IOException, InterruptedException {
75
		DimseRSPHandler rspHandler = new DimseRSPHandler(as.nextMessageID()) {
76
			@Override
77
			public void onDimseRSP(Association as, Attributes cmd, Attributes data) {
78
				super.onDimseRSP(as, cmd, data);
79
				int status = cmd.getInt(Tag.Status, -1);
80
				if (Status.isPending(status)) {
81
					study = new PatientStudy();
82
					result.add(study);
83
					try {
84
						data.accept(visitor, false);
85
					} catch (Exception e) {
86
					}
87
				}
88
			}
89
		};
90
		as.cfind(UID.StudyRootQueryRetrieveInformationModelFIND, Priority.NORMAL, keys, null, rspHandler);
91
	}
92

93
	public List<PatientStudy> query(String title, String hostname, int port, String patientName, String patientId)
94
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
95
		this.setRemote(title, hostname, port);
96
		this.rq.addPresentationContext(
97
				new PresentationContext(1, UID.StudyRootQueryRetrieveInformationModelFIND, IVR_LE_FIRST));
98
		this.keys.setString(Tag.QueryRetrieveLevel, VR.CS, "STUDY");
99
		this.addAttribute(Tag.PatientID, patientId);
100
		this.addAttribute(Tag.PatientName, patientName);
101
		this.addAttribute(Tag.IssuerOfPatientID, null);
102
		this.addAttribute(Tag.PatientSex, null);
103
		this.addAttribute(Tag.PatientBirthDate, null);
104
		this.addAttribute(Tag.StudyInstanceUID, null);
105
		this.addAttribute(Tag.StudyInstanceUID, null);
106
		this.addAttribute(Tag.SeriesInstanceUID, null);
107
		this.addAttribute(Tag.StudyID, null);
108
		this.addAttribute(Tag.AccessionNumber, null);
109
		this.addAttribute(Tag.StudyDate, null);
110
		this.addAttribute(Tag.StudyTime, null);
111
		this.addAttribute(Tag.StudyDescription, null);
112
		this.addAttribute(Tag.NumberOfStudyRelatedSeries, null);
113
		this.addAttribute(Tag.NumberOfStudyRelatedInstances, null);
114
		ExecutorService executorService = Executors.newSingleThreadExecutor();
115
		ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
116
		this.device.setExecutor(executorService);
117
		this.device.setScheduledExecutor(scheduledExecutorService);
118

119
		try {
120
			as = ae.connect(conn, remote, rq);
121
			query();
122
		} finally {
123
			if (as != null && as.isReadyForDataTransfer()) {
124
				as.waitForOutstandingRSP();
125
				as.release();
126
			}
127
			executorService.shutdown();
128
			scheduledExecutorService.shutdown();
129
		}
130
		return this.result;
131
	}
132

133
	public static void main(String args[])
134
			throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException {
135
		DicomQueryStudy q = new DicomQueryStudy("findscu");
136
		q.query("DCM4CHEE", "192.168.3.97", 11112, "759417ASD", null);
137
		
138
		for(PatientStudy s:q.result){
139
			System.out.println(JsonService.toJson(s));
140
		}
141

142
	}
143
}

+ 94 - 0
src/main/java/com/ekexiu/project/storage/dicom/DicomService.java

@ -0,0 +1,94 @@
1
package com.ekexiu.project.storage.dicom;
2

3
import java.io.File;
4
import java.io.IOException;
5
import java.security.GeneralSecurityException;
6
import java.util.Collections;
7
import java.util.List;
8

9
import org.dcm4che3.net.IncompatibleConnectionException;
10
import org.jfw.apt.annotation.Nullable;
11
import org.jfw.apt.web.annotation.Path;
12
import org.jfw.apt.web.annotation.operate.Get;
13

14
@Path("/dicom")
15
public class DicomService {
16
	private String localTitle="AIADS";
17
	private String remoteTitle="STPACS";
18
	private String remoteHostName ="133.0.14.150";
19
	private int remotePort = 104;
20
	private File storagePath = new File("/ekexiu/storage_asd/download");
21
	
22
	
23
	public String getLocalTitle() {
24
		return localTitle;
25
	}
26
	public void setLocalTitle(String localTitle) {
27
		this.localTitle = localTitle;
28
	}
29
	public String getRemoteTitle() {
30
		return remoteTitle;
31
	}
32
	public void setRemoteTitle(String remoteTitle) {
33
		this.remoteTitle = remoteTitle;
34
	}
35
	public String getRemoteHostName() {
36
		return remoteHostName;
37
	}
38
	public void setRemoteHostName(String remoteHostName) {
39
		this.remoteHostName = remoteHostName;
40
	}
41
	public int getRemotePort() {
42
		return remotePort;
43
	}
44
	public void setRemotePort(int remotePort) {
45
		this.remotePort = remotePort;
46
	}
47
	public File getStoragePath() {
48
		return storagePath;
49
	}
50
	public void setStoragePath(File storagePath) {
51
		this.storagePath = storagePath;
52
	}
53
	
54
	@Get
55
	@Path("/study")
56
	public List<PatientStudy> queryStudy(@Nullable String name,@Nullable String id) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException{
57
		if(name != null || id !=null){
58
			DicomQueryStudy query = new DicomQueryStudy(this.localTitle);
59
			return query.query(this.remoteTitle, remoteHostName, remotePort,name,id);
60
		}else{
61
			return Collections.emptyList();
62
		}
63
	} 
64
	@Get
65
	@Path("/series")
66
	public List<StudySeries> querySeries(String id) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException{
67
			DicomQuerySeries query = new DicomQuerySeries(this.localTitle);
68
			return query.query(this.remoteTitle, remoteHostName, remotePort,id);
69
	} 
70
	
71
	@Get
72
	@Path("/image")
73
	public List<SeriesImage> queryImage(String study,String series) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException{
74
			DicomQueryImage query = new DicomQueryImage(this.localTitle);
75
			return query.query(this.remoteTitle, remoteHostName, remotePort,study,series);
76
	} 
77
	
78
	@Get
79
	@Path("/download")
80
	public boolean download(String id) throws IOException, InterruptedException, IncompatibleConnectionException, GeneralSecurityException{
81
		DicomGetImage q = new DicomGetImage(this.localTitle);
82
		return null !=q.download(this.remoteTitle, remoteHostName, remotePort,id,this.storagePath,id+".dcm");
83
	}
84
	
85
	
86
	
87
	
88
	
89
	
90
	
91
	
92
	
93

94
}

+ 87 - 0
src/main/java/com/ekexiu/project/storage/dicom/PatientStudy.java

@ -0,0 +1,87 @@
1
package com.ekexiu.project.storage.dicom;
2

3
public class PatientStudy {
4
	
5
	private String	 patientName;
6
	private String   patientId;
7
	private String   sex;
8
	private String   birth;
9
	private String   studyUid;
10
	private String   studyId;
11
	private String 	 studyDate;
12
	private String   studyTime;
13
	private String   description;
14
	private String 	 numOfStudyRelatedSeries;
15
	private String	 numOfstudyRelatedInstances;
16
	
17
	
18
	public String getPatientName() {
19
		return patientName;
20
	}
21
	public void setPatientName(String patientName) {
22
		this.patientName = patientName;
23
	}
24
	public String getPatientId() {
25
		return patientId;
26
	}
27
	public void setPatientId(String patientId) {
28
		this.patientId = patientId;
29
	}
30
	public String getSex() {
31
		return sex;
32
	}
33
	public void setSex(String sex) {
34
		this.sex = sex;
35
	}
36
	public String getBirth() {
37
		return birth;
38
	}
39
	public void setBirth(String birth) {
40
		this.birth = birth;
41
	}
42
	public String getStudyUid() {
43
		return studyUid;
44
	}
45
	public void setStudyUid(String studyUid) {
46
		this.studyUid = studyUid;
47
	}
48
	public String getStudyId() {
49
		return studyId;
50
	}
51
	public void setStudyId(String studyId) {
52
		this.studyId = studyId;
53
	}
54
	public String getStudyDate() {
55
		return studyDate;
56
	}
57
	public void setStudyDate(String studyDate) {
58
		this.studyDate = studyDate;
59
	}
60
	public String getStudyTime() {
61
		return studyTime;
62
	}
63
	public void setStudyTime(String studyTime) {
64
		this.studyTime = studyTime;
65
	}
66
	public String getDescription() {
67
		return description;
68
	}
69
	public void setDescription(String description) {
70
		this.description = description;
71
	}
72
	public String getNumOfStudyRelatedSeries() {
73
		return numOfStudyRelatedSeries;
74
	}
75
	public void setNumOfStudyRelatedSeries(String numOfStudyRelatedSeries) {
76
		this.numOfStudyRelatedSeries = numOfStudyRelatedSeries;
77
	}
78
	public String getNumOfstudyRelatedInstances() {
79
		return numOfstudyRelatedInstances;
80
	}
81
	public void setNumOfstudyRelatedInstances(String numOfstudyRelatedInstances) {
82
		this.numOfstudyRelatedInstances = numOfstudyRelatedInstances;
83
	}
84

85
	
86
	
87
}

+ 20 - 0
src/main/java/com/ekexiu/project/storage/dicom/SeriesImage.java

@ -0,0 +1,20 @@
1
package com.ekexiu.project.storage.dicom;
2

3
public class SeriesImage {
4

5
	private String id;
6
	private String num;
7
	public String getId() {
8
		return id;
9
	}
10
	public void setId(String id) {
11
		this.id = id;
12
	}
13
	public String getNum() {
14
		return num;
15
	}
16
	public void setNum(String num) {
17
		this.num = num;
18
	}
19
	
20
}

+ 57 - 0
src/main/java/com/ekexiu/project/storage/dicom/StudySeries.java

@ -0,0 +1,57 @@
1
package com.ekexiu.project.storage.dicom;
2

3
public class StudySeries {
4
	private String seriesDate;
5
	private String seriesTime;
6
	private String seriesType;
7
	private String seriesDescription;
8
	private String id;
9
	private String numOfStudy;
10
	private String numberOfSeriesRelatedInstances;
11
	
12
	
13
	public String getSeriesDate() {
14
		return seriesDate;
15
	}
16
	public void setSeriesDate(String seriesDate) {
17
		this.seriesDate = seriesDate;
18
	}
19
	public String getSeriesTime() {
20
		return seriesTime;
21
	}
22
	public void setSeriesTime(String seriesTime) {
23
		this.seriesTime = seriesTime;
24
	}
25
	public String getSeriesType() {
26
		return seriesType;
27
	}
28
	public void setSeriesType(String seriesType) {
29
		this.seriesType = seriesType;
30
	}
31
	public String getSeriesDescription() {
32
		return seriesDescription;
33
	}
34
	public void setSeriesDescription(String seriesDescription) {
35
		this.seriesDescription = seriesDescription;
36
	}
37
	public String getId() {
38
		return id;
39
	}
40
	public void setId(String id) {
41
		this.id = id;
42
	}
43
	public String getNumOfStudy() {
44
		return numOfStudy;
45
	}
46
	public void setNumOfStudy(String numOfStudy) {
47
		this.numOfStudy = numOfStudy;
48
	}
49
	public String getNumberOfSeriesRelatedInstances() {
50
		return numberOfSeriesRelatedInstances;
51
	}
52
	public void setNumberOfSeriesRelatedInstances(String numberOfSeriesRelatedInstances) {
53
		this.numberOfSeriesRelatedInstances = numberOfSeriesRelatedInstances;
54
	}
55
	
56
	
57
}