dicom 0.9.6 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,122 +1,122 @@
1
- module DICOM
2
-
3
- # This class handles DICOM files that have been received through network communication.
4
- #
5
- # === Notes
6
- #
7
- # The purpose of this class is to make it as easy as possible for users to customize the way
8
- # DICOM files are handled when they are received through the network.
9
- #
10
- # The default behaviour is to save the files to disk using a folder structure determined by a few select tags of the DICOM file.
11
- #
12
- # Some suggested alternatives for user customization:
13
- # * Analyzing tags and/or image data to determine further actions.
14
- # * Modify the DICOM object before it is saved to disk.
15
- # * Modify the folder structure in which DICOM files are saved to disk.
16
- # * Store DICOM contents in a database (highly relevant if you are building a Ruby on Rails DICOM application).
17
- # * Retransmit the DICOM object to another network destination using the DClient class.
18
- # * Write information to a log file.
19
- #
20
- class FileHandler
21
-
22
- # Saves a single DICOM object to file.
23
- # Returns a status message stating where the file has been saved.
24
- #
25
- # Modify this method if you want to change the way your server saves incoming files.
26
- #
27
- # === Notes
28
- #
29
- # As default, files will be saved with the following path:
30
- # <tt> path_prefix/<PatientID>/<StudyDate>/<Modality>/ </tt>
31
- #
32
- # === Parameters
33
- #
34
- # * <tt>path_prefix</tt> -- String. Specifies the root path of the DICOM storage.
35
- # * <tt>dcm</tt> -- A DObject instance which will be written to file.
36
- # * <tt>transfer_syntax</tt> -- String. Specifies the transfer syntax that will be used to write the DICOM file.
37
- #
38
- def self.save_file(path_prefix, dcm, transfer_syntax)
39
- # File name is set using the SOP Instance UID:
40
- file_name = dcm.value("0008,0018") || "missing_SOP_UID"
41
- extension = ".dcm"
42
- folders = Array.new(3)
43
- folders[0] = dcm.value("0010,0020") || "PatientID"
44
- folders[1] = dcm.value("0008,0020") || "StudyDate"
45
- folders[2] = dcm.value("0008,0060") || "Modality"
46
- local_path = folders.join(File::SEPARATOR) + File::SEPARATOR + file_name
47
- full_path = path_prefix + local_path + extension
48
- # Save the DICOM object to disk:
49
- dcm.write(full_path, :transfer_syntax => transfer_syntax)
50
- message = [:info, "DICOM file saved to: #{full_path}"]
51
- return message
52
- end
53
-
54
- # Handles the reception of a series of DICOM objects which are received in a single association.
55
- #
56
- # Modify this method if you want to change the way your server handles incoming file series.
57
- #
58
- # === Notes
59
- #
60
- # Default action: Pass each file to the class method which saves files to disk.
61
- #
62
- # === Parameters
63
- #
64
- # * <tt>path</tt> -- String. Specifies the root path of the DICOM storage.
65
- # * <tt>objects</tt> -- An array containing the DObject instances which were received.
66
- # * <tt>transfer_syntaxes</tt> -- An array containing the transfer syntaxes belonging to the received objects.
67
- #
68
- def self.receive_files(path, objects, transfer_syntaxes)
69
- all_success = true
70
- successful, too_short, parse_fail, handle_fail = 0, 0, 0, 0
71
- total = objects.length
72
- message = nil
73
- messages = Array.new
74
- # Process each DICOM object:
75
- objects.each_index do |i|
76
- if objects[i].length > 8
77
- # Temporarily increase the log threshold to suppress messages from the DObject class:
78
- server_level = DICOM.logger.level
79
- DICOM.logger.level = Logger::FATAL
80
- # Parse the received data string and load it to a DICOM object:
81
- dcm = DObject.parse(objects[i], :no_meta => true, :syntax => transfer_syntaxes[i])
82
- # Reset the logg threshold:
83
- DICOM.logger.level = server_level
84
- if dcm.read?
85
- begin
86
- message = self.save_file(path, dcm, transfer_syntaxes[i])
87
- successful += 1
88
- rescue
89
- handle_fail += 1
90
- all_success = false
91
- messages << [:error, "Saving file failed!"]
92
- end
93
- else
94
- parse_fail += 1
95
- all_success = false
96
- messages << [:error, "Invalid DICOM data encountered: The received string was not parsed successfully."]
97
- end
98
- else
99
- too_short += 1
100
- all_success = false
101
- messages << [:error, "Invalid data encountered: The received string was too small to contain any DICOM data."]
102
- end
103
- end
104
- # Create a summary status message, when multiple files have been received:
105
- if total > 1
106
- if successful == total
107
- messages << [:info, "All #{total} DICOM files received successfully."]
108
- else
109
- if successful == 0
110
- messages << [:warn, "All #{total} received DICOM files failed!"]
111
- else
112
- messages << [:warn, "Only #{successful} of #{total} DICOM files received successfully!"]
113
- end
114
- end
115
- else
116
- messages = [message] if all_success
117
- end
118
- return all_success, messages
119
- end
120
-
121
- end
1
+ module DICOM
2
+
3
+ # This class handles DICOM files that have been received through network communication.
4
+ #
5
+ # === Notes
6
+ #
7
+ # The purpose of this class is to make it as easy as possible for users to customize the way
8
+ # DICOM files are handled when they are received through the network.
9
+ #
10
+ # The default behaviour is to save the files to disk using a folder structure determined by a few select tags of the DICOM file.
11
+ #
12
+ # Some suggested alternatives for user customization:
13
+ # * Analyzing tags and/or image data to determine further actions.
14
+ # * Modify the DICOM object before it is saved to disk.
15
+ # * Modify the folder structure in which DICOM files are saved to disk.
16
+ # * Store DICOM contents in a database (highly relevant if you are building a Ruby on Rails DICOM application).
17
+ # * Retransmit the DICOM object to another network destination using the DClient class.
18
+ # * Write information to a log file.
19
+ #
20
+ class FileHandler
21
+
22
+ # Saves a single DICOM object to file.
23
+ # Returns a status message stating where the file has been saved.
24
+ #
25
+ # Modify this method if you want to change the way your server saves incoming files.
26
+ #
27
+ # === Notes
28
+ #
29
+ # As default, files will be saved with the following path:
30
+ # <tt> path_prefix/<PatientID>/<StudyDate>/<Modality>/ </tt>
31
+ #
32
+ # === Parameters
33
+ #
34
+ # * <tt>path_prefix</tt> -- String. Specifies the root path of the DICOM storage.
35
+ # * <tt>dcm</tt> -- A DObject instance which will be written to file.
36
+ # * <tt>transfer_syntax</tt> -- String. Specifies the transfer syntax that will be used to write the DICOM file.
37
+ #
38
+ def self.save_file(path_prefix, dcm, transfer_syntax)
39
+ # File name is set using the SOP Instance UID:
40
+ file_name = dcm.value("0008,0018") || "missing_SOP_UID"
41
+ extension = ".dcm"
42
+ folders = Array.new(3)
43
+ folders[0] = dcm.value("0010,0020") || "PatientID"
44
+ folders[1] = dcm.value("0008,0020") || "StudyDate"
45
+ folders[2] = dcm.value("0008,0060") || "Modality"
46
+ local_path = folders.join(File::SEPARATOR) + File::SEPARATOR + file_name
47
+ full_path = path_prefix + local_path + extension
48
+ # Save the DICOM object to disk:
49
+ dcm.write(full_path, :transfer_syntax => transfer_syntax)
50
+ message = [:info, "DICOM file saved to: #{full_path}"]
51
+ return message
52
+ end
53
+
54
+ # Handles the reception of a series of DICOM objects which are received in a single association.
55
+ #
56
+ # Modify this method if you want to change the way your server handles incoming file series.
57
+ #
58
+ # === Notes
59
+ #
60
+ # Default action: Pass each file to the class method which saves files to disk.
61
+ #
62
+ # === Parameters
63
+ #
64
+ # * <tt>path</tt> -- String. Specifies the root path of the DICOM storage.
65
+ # * <tt>objects</tt> -- An array containing the DObject instances which were received.
66
+ # * <tt>transfer_syntaxes</tt> -- An array containing the transfer syntaxes belonging to the received objects.
67
+ #
68
+ def self.receive_files(path, objects, transfer_syntaxes)
69
+ all_success = true
70
+ successful, too_short, parse_fail, handle_fail = 0, 0, 0, 0
71
+ total = objects.length
72
+ message = nil
73
+ messages = Array.new
74
+ # Process each DICOM object:
75
+ objects.each_index do |i|
76
+ if objects[i].length > 8
77
+ # Temporarily increase the log threshold to suppress messages from the DObject class:
78
+ server_level = DICOM.logger.level
79
+ DICOM.logger.level = Logger::FATAL
80
+ # Parse the received data string and load it to a DICOM object:
81
+ dcm = DObject.parse(objects[i], :no_meta => true, :syntax => transfer_syntaxes[i])
82
+ # Reset the logg threshold:
83
+ DICOM.logger.level = server_level
84
+ if dcm.read?
85
+ begin
86
+ message = self.save_file(path, dcm, transfer_syntaxes[i])
87
+ successful += 1
88
+ rescue
89
+ handle_fail += 1
90
+ all_success = false
91
+ messages << [:error, "Saving file failed!"]
92
+ end
93
+ else
94
+ parse_fail += 1
95
+ all_success = false
96
+ messages << [:error, "Invalid DICOM data encountered: The received string was not parsed successfully."]
97
+ end
98
+ else
99
+ too_short += 1
100
+ all_success = false
101
+ messages << [:error, "Invalid data encountered: The received string was too small to contain any DICOM data."]
102
+ end
103
+ end
104
+ # Create a summary status message, when multiple files have been received:
105
+ if total > 1
106
+ if successful == total
107
+ messages << [:info, "All #{total} DICOM files received successfully."]
108
+ else
109
+ if successful == 0
110
+ messages << [:warn, "All #{total} received DICOM files failed!"]
111
+ else
112
+ messages << [:warn, "Only #{successful} of #{total} DICOM files received successfully!"]
113
+ end
114
+ end
115
+ else
116
+ messages = [message] if all_success
117
+ end
118
+ return all_success, messages
119
+ end
120
+
121
+ end
122
122
  end
@@ -1,210 +1,210 @@
1
- module DICOM
2
-
3
- # Ruby DICOM's registered DICOM UID root (Implementation Class UID).
4
- UID_ROOT = "1.2.826.0.1.3680043.8.641"
5
- # Ruby DICOM name & version (max 16 characters).
6
- NAME = "RUBY-DCM_" + DICOM::VERSION
7
-
8
- # Item tag.
9
- ITEM_TAG = "FFFE,E000"
10
- # All Item related tags (includes both types of delimitation items).
11
- ITEM_TAGS = ["FFFE,E000", "FFFE,E00D", "FFFE,E0DD"]
12
- # Item delimiter tag.
13
- ITEM_DELIMITER = "FFFE,E00D"
14
- # Sequence delimiter tag.
15
- SEQUENCE_DELIMITER = "FFFE,E0DD"
16
- # All delimiter tags.
17
- DELIMITER_TAGS = ["FFFE,E00D", "FFFE,E0DD"]
18
-
19
- # The VR used for the item elements.
20
- ITEM_VR = " "
21
-
22
- # Pixel tag.
23
- PIXEL_TAG = "7FE0,0010"
24
- # Name of the pixel tag when holding encapsulated data.
25
- ENCAPSULATED_PIXEL_NAME = "Encapsulated Pixel Data"
26
- # Name of encapsulated items.
27
- PIXEL_ITEM_NAME = "Pixel Data Item"
28
-
29
- # File meta group.
30
- META_GROUP = "0002"
31
-
32
- # Group length element.
33
- GROUP_LENGTH = "0000"
34
-
35
- # Implicit, little endian (the default transfer syntax).
36
- IMPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2"
37
- # Explicit, little endian transfer syntax.
38
- EXPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2.1"
39
- # Explicit, big endian transfer syntax.
40
- EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2"
41
-
42
- # Verification SOP class UID.
43
- VERIFICATION_SOP = "1.2.840.10008.1.1"
44
- # Application context SOP class UID.
45
- APPLICATION_CONTEXT = "1.2.840.10008.3.1.1.1"
46
-
47
- # Network transmission successful.
48
- SUCCESS = 0
49
- # Network proposition accepted.
50
- ACCEPTANCE = 0
51
- # Presentation context rejected by abstract syntax.
52
- ABSTRACT_SYNTAX_REJECTED = 3
53
- # Presentation context rejected by transfer syntax.
54
- TRANSFER_SYNTAX_REJECTED = 4
55
-
56
- # Some network command element codes:
57
- C_STORE_RQ = 1 # (encodes to 0001H as US)
58
- C_GET_RQ = 16 # (encodes to 0010H as US)
59
- C_FIND_RQ = 32 # (encodes to 0020H as US)
60
- C_MOVE_RQ = 33 # (encodes to 0021H as US)
61
- C_ECHO_RQ = 48 # (encodes to 0030 as US)
62
- C_CANCEL_RQ = 4095 # (encodes to 0FFFH as US)
63
- C_STORE_RSP = 32769 # (encodes to 8001H as US)
64
- C_GET_RSP = 32784 # (encodes to 8010H as US)
65
- C_FIND_RSP = 32800 # (encodes to 8020H as US)
66
- C_MOVE_RSP = 32801 # (encodes to 8021H as US)
67
- C_ECHO_RSP = 32816 # (encodes to 8030H as US)
68
- NO_DATA_SET_PRESENT = 257 # (encodes to 0101H as US)
69
- DATA_SET_PRESENT = 1
70
- DEFAULT_MESSAGE_ID = 1
71
-
72
- # The network communication flags:
73
- DATA_MORE_FRAGMENTS = "00"
74
- COMMAND_MORE_FRAGMENTS = "01"
75
- DATA_LAST_FRAGMENT = "02"
76
- COMMAND_LAST_FRAGMENT = "03"
77
-
78
- # Network communication PDU types:
79
- PDU_ASSOCIATION_REQUEST = "01"
80
- PDU_ASSOCIATION_ACCEPT = "02"
81
- PDU_ASSOCIATION_REJECT = "03"
82
- PDU_DATA = "04"
83
- PDU_RELEASE_REQUEST = "05"
84
- PDU_RELEASE_RESPONSE = "06"
85
- PDU_ABORT = "07"
86
-
87
- # Network communication item types:
88
- ITEM_APPLICATION_CONTEXT = "10"
89
- ITEM_PRESENTATION_CONTEXT_REQUEST = "20"
90
- ITEM_PRESENTATION_CONTEXT_RESPONSE = "21"
91
- ITEM_ABSTRACT_SYNTAX = "30"
92
- ITEM_TRANSFER_SYNTAX = "40"
93
- ITEM_USER_INFORMATION = "50"
94
- ITEM_MAX_LENGTH = "51"
95
- ITEM_IMPLEMENTATION_UID = "52"
96
- ITEM_MAX_OPERATIONS_INVOKED = "53"
97
- ITEM_ROLE_NEGOTIATION = "54"
98
- ITEM_IMPLEMENTATION_VERSION = "55"
99
-
100
- # Varaibles used to determine endianness.
101
- x = 0xdeadbeef
102
- endian_type = {
103
- Array(x).pack("V*") => false, # Little
104
- Array(x).pack("N*") => true # Big
105
- }
106
- # System (CPU) Endianness.
107
- CPU_ENDIAN = endian_type[Array(x).pack("L*")]
108
-
109
- # Transfer Syntaxes (taken from the DICOM Specification PS 3.5, Chapter 10).
110
-
111
- # General
112
- TXS_IMPLICIT_LITTLE_ENDIAN = '1.2.840.10008.1.2' # also defined as IMPLICIT_LITTLE_ENDIAN, default transfer syntax
113
- TXS_EXPLICIT_LITTLE_ENDIAN = '1.2.840.10008.1.2.1' # also defined as EXPLICIT_LITTLE_ENDIAN
114
- TXS_EXPLICIT_BIG_ENDIAN = '1.2.840.10008.1.2.2' # also defined as EXPLICIT_BIG_ENDIAN
115
-
116
- # TRANSFER SYNTAXES FOR ENCAPSULATION OF ENCODED PIXEL DATA
117
- TXS_JPEG_BASELINE = '1.2.840.10008.1.2.4.50'
118
- TXS_JPEG_EXTENDED = '1.2.840.10008.1.2.4.51'
119
- TXS_JPEG_LOSSLESS_NH = '1.2.840.10008.1.2.4.57' # NH: non-hirarchical
120
- TXS_JPEG_LOSSLESS_NH_FOP = '1.2.840.10008.1.2.4.70' # NH: non-hirarchical, FOP: first-order prediction
121
-
122
- TXS_JPEG_LS_LOSSLESS = '1.2.840.10008.1.2.4.80'
123
- TXS_JPEG_LS_NEAR_LOSSLESS = '1.2.840.10008.1.2.4.81'
124
-
125
- TXS_JPEG_2000_PART1_LOSSLESS = '1.2.840.10008.1.2.4.90'
126
- TXS_JPEG_2000_PART1_LOSSLESS_OR_LOSSY = '1.2.840.10008.1.2.4.91'
127
- TXS_JPEG_2000_PART2_LOSSLESS = '1.2.840.10008.1.2.4.92'
128
- TXS_JPEG_2000_PART2_LOSSLESS_OR_LOSSY = '1.2.840.10008.1.2.4.93'
129
-
130
- TXS_MPEG2_MP_ML = '1.2.840.10008.1.2.4.100'
131
- TXS_MPEG2_MP_HL = '1.2.840.10008.1.2.4.101'
132
-
133
- TXS_DEFLATED_LITTLE_ENDIAN = '1.2.840.10008.1.2.1.99' # ZIP Compression
134
-
135
- TXS_JPIP = '1.2.840.10008.1.2.4.94'
136
- TXS_JPIP_DEFLATE = '1.2.840.10008.1.2.4.95'
137
-
138
- TXS_RLE = '1.2.840.10008.1.2.5'
139
-
140
-
141
- # Photometric Interpretations
142
- # Taken from DICOM Specification PS 3.3 C.7.6.3.1.2 Photometric Interpretation
143
-
144
- PI_MONOCHROME1 = 'MONOCHROME1'
145
- PI_MONOCHROME2 = 'MONOCHROME2'
146
- PI_PALETTE_COLOR = 'PALETTE COLOR'
147
- PI_RGB = 'RGB'
148
- PI_YBR_FULL = 'YBR_FULL'
149
- PI_YBR_FULL_422 = 'YBR_FULL_422 '
150
- PI_YBR_PARTIAL_422 = 'YBR_PARTIAL_422'
151
- PI_YBR_PARTIAL_420 = 'YBR_PARTIAL_420'
152
- PI_YBR_ICT = 'YBR_ICT'
153
- PI_YBR_RCT = 'YBR_RCT'
154
-
155
- # Retired Photometric Interpretations, are those needed to be supported?
156
- PI_HSV = 'HSV'
157
- PI_ARGB = 'ARGB'
158
- PI_CMYK = 'CMYK'
159
-
160
- # The relationship between DICOM Character Set and Encoding name.
161
- ENCODING_NAME = {
162
- 'ISO_IR 100' => 'ISO-8859-1',
163
- 'ISO_IR 101' => 'ISO-8859-2',
164
- 'ISO_IR 109' => 'ISO-8859-3',
165
- 'ISO_IR 110' => 'ISO-8859-4',
166
- 'ISO_IR 144' => 'ISO-8859-5',
167
- 'ISO_IR 127' => 'ISO-8859-6',
168
- 'ISO_IR 126' => 'ISO-8859-7',
169
- 'ISO_IR 138' => 'ISO-8859-8',
170
- 'ISO_IR 148' => 'ISO-8859-9',
171
- 'ISO_IR 13' => 'JIS_X0201',
172
- 'ISO_IR 166' => 'ISO-8859-11',
173
- 'GB18030' => 'GB18030',
174
- 'ISO_IR 192' => 'UTF-8'
175
- }
176
- ENCODING_NAME.default = 'ASCII-8BIT'
177
-
178
- # The type conversion (method) used for the various value representations.
179
- VALUE_CONVERSION = {
180
- 'BY' => :to_i,
181
- 'US' => :to_i,
182
- 'SS' => :to_i,
183
- 'UL' => :to_i,
184
- 'SL' => :to_i,
185
- 'OB' => :to_i,
186
- 'OW' => :to_i,
187
- 'OF' => :to_f,
188
- 'FL' => :to_f,
189
- 'FD' => :to_f,
190
- 'AT' => :to_s,
191
- 'AE' => :to_s,
192
- 'AS' => :to_s,
193
- 'CS' => :to_s,
194
- 'DA' => :to_s,
195
- 'DS' => :to_s,
196
- 'DT' => :to_s,
197
- 'IS' => :to_s,
198
- 'LO' => :to_s,
199
- 'LT' => :to_s,
200
- 'PN' => :to_s,
201
- 'SH' => :to_s,
202
- 'ST' => :to_s,
203
- 'TM' => :to_s,
204
- 'UI' => :to_s,
205
- 'UT' => :to_s
206
- }
207
- VALUE_CONVERSION.default = :to_s
208
-
209
- end
210
-
1
+ module DICOM
2
+
3
+ # Ruby DICOM's registered DICOM UID root (Implementation Class UID).
4
+ UID_ROOT = "1.2.826.0.1.3680043.8.641"
5
+ # Ruby DICOM name & version (max 16 characters).
6
+ NAME = "RUBY-DCM_" + DICOM::VERSION
7
+
8
+ # Item tag.
9
+ ITEM_TAG = "FFFE,E000"
10
+ # All Item related tags (includes both types of delimitation items).
11
+ ITEM_TAGS = ["FFFE,E000", "FFFE,E00D", "FFFE,E0DD"]
12
+ # Item delimiter tag.
13
+ ITEM_DELIMITER = "FFFE,E00D"
14
+ # Sequence delimiter tag.
15
+ SEQUENCE_DELIMITER = "FFFE,E0DD"
16
+ # All delimiter tags.
17
+ DELIMITER_TAGS = ["FFFE,E00D", "FFFE,E0DD"]
18
+
19
+ # The VR used for the item elements.
20
+ ITEM_VR = " "
21
+
22
+ # Pixel tag.
23
+ PIXEL_TAG = "7FE0,0010"
24
+ # Name of the pixel tag when holding encapsulated data.
25
+ ENCAPSULATED_PIXEL_NAME = "Encapsulated Pixel Data"
26
+ # Name of encapsulated items.
27
+ PIXEL_ITEM_NAME = "Pixel Data Item"
28
+
29
+ # File meta group.
30
+ META_GROUP = "0002"
31
+
32
+ # Group length element.
33
+ GROUP_LENGTH = "0000"
34
+
35
+ # Implicit, little endian (the default transfer syntax).
36
+ IMPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2"
37
+ # Explicit, little endian transfer syntax.
38
+ EXPLICIT_LITTLE_ENDIAN = "1.2.840.10008.1.2.1"
39
+ # Explicit, big endian transfer syntax.
40
+ EXPLICIT_BIG_ENDIAN = "1.2.840.10008.1.2.2"
41
+
42
+ # Verification SOP class UID.
43
+ VERIFICATION_SOP = "1.2.840.10008.1.1"
44
+ # Application context SOP class UID.
45
+ APPLICATION_CONTEXT = "1.2.840.10008.3.1.1.1"
46
+
47
+ # Network transmission successful.
48
+ SUCCESS = 0
49
+ # Network proposition accepted.
50
+ ACCEPTANCE = 0
51
+ # Presentation context rejected by abstract syntax.
52
+ ABSTRACT_SYNTAX_REJECTED = 3
53
+ # Presentation context rejected by transfer syntax.
54
+ TRANSFER_SYNTAX_REJECTED = 4
55
+
56
+ # Some network command element codes:
57
+ C_STORE_RQ = 1 # (encodes to 0001H as US)
58
+ C_GET_RQ = 16 # (encodes to 0010H as US)
59
+ C_FIND_RQ = 32 # (encodes to 0020H as US)
60
+ C_MOVE_RQ = 33 # (encodes to 0021H as US)
61
+ C_ECHO_RQ = 48 # (encodes to 0030 as US)
62
+ C_CANCEL_RQ = 4095 # (encodes to 0FFFH as US)
63
+ C_STORE_RSP = 32769 # (encodes to 8001H as US)
64
+ C_GET_RSP = 32784 # (encodes to 8010H as US)
65
+ C_FIND_RSP = 32800 # (encodes to 8020H as US)
66
+ C_MOVE_RSP = 32801 # (encodes to 8021H as US)
67
+ C_ECHO_RSP = 32816 # (encodes to 8030H as US)
68
+ NO_DATA_SET_PRESENT = 257 # (encodes to 0101H as US)
69
+ DATA_SET_PRESENT = 1
70
+ DEFAULT_MESSAGE_ID = 1
71
+
72
+ # The network communication flags:
73
+ DATA_MORE_FRAGMENTS = "00"
74
+ COMMAND_MORE_FRAGMENTS = "01"
75
+ DATA_LAST_FRAGMENT = "02"
76
+ COMMAND_LAST_FRAGMENT = "03"
77
+
78
+ # Network communication PDU types:
79
+ PDU_ASSOCIATION_REQUEST = "01"
80
+ PDU_ASSOCIATION_ACCEPT = "02"
81
+ PDU_ASSOCIATION_REJECT = "03"
82
+ PDU_DATA = "04"
83
+ PDU_RELEASE_REQUEST = "05"
84
+ PDU_RELEASE_RESPONSE = "06"
85
+ PDU_ABORT = "07"
86
+
87
+ # Network communication item types:
88
+ ITEM_APPLICATION_CONTEXT = "10"
89
+ ITEM_PRESENTATION_CONTEXT_REQUEST = "20"
90
+ ITEM_PRESENTATION_CONTEXT_RESPONSE = "21"
91
+ ITEM_ABSTRACT_SYNTAX = "30"
92
+ ITEM_TRANSFER_SYNTAX = "40"
93
+ ITEM_USER_INFORMATION = "50"
94
+ ITEM_MAX_LENGTH = "51"
95
+ ITEM_IMPLEMENTATION_UID = "52"
96
+ ITEM_MAX_OPERATIONS_INVOKED = "53"
97
+ ITEM_ROLE_NEGOTIATION = "54"
98
+ ITEM_IMPLEMENTATION_VERSION = "55"
99
+
100
+ # Varaibles used to determine endianness.
101
+ x = 0xdeadbeef
102
+ endian_type = {
103
+ Array(x).pack("V*") => false, # Little
104
+ Array(x).pack("N*") => true # Big
105
+ }
106
+ # System (CPU) Endianness.
107
+ CPU_ENDIAN = endian_type[Array(x).pack("L*")]
108
+
109
+ # Transfer Syntaxes (taken from the DICOM Specification PS 3.5, Chapter 10).
110
+
111
+ # General
112
+ TXS_IMPLICIT_LITTLE_ENDIAN = '1.2.840.10008.1.2' # also defined as IMPLICIT_LITTLE_ENDIAN, default transfer syntax
113
+ TXS_EXPLICIT_LITTLE_ENDIAN = '1.2.840.10008.1.2.1' # also defined as EXPLICIT_LITTLE_ENDIAN
114
+ TXS_EXPLICIT_BIG_ENDIAN = '1.2.840.10008.1.2.2' # also defined as EXPLICIT_BIG_ENDIAN
115
+
116
+ # TRANSFER SYNTAXES FOR ENCAPSULATION OF ENCODED PIXEL DATA
117
+ TXS_JPEG_BASELINE = '1.2.840.10008.1.2.4.50'
118
+ TXS_JPEG_EXTENDED = '1.2.840.10008.1.2.4.51'
119
+ TXS_JPEG_LOSSLESS_NH = '1.2.840.10008.1.2.4.57' # NH: non-hirarchical
120
+ TXS_JPEG_LOSSLESS_NH_FOP = '1.2.840.10008.1.2.4.70' # NH: non-hirarchical, FOP: first-order prediction
121
+
122
+ TXS_JPEG_LS_LOSSLESS = '1.2.840.10008.1.2.4.80'
123
+ TXS_JPEG_LS_NEAR_LOSSLESS = '1.2.840.10008.1.2.4.81'
124
+
125
+ TXS_JPEG_2000_PART1_LOSSLESS = '1.2.840.10008.1.2.4.90'
126
+ TXS_JPEG_2000_PART1_LOSSLESS_OR_LOSSY = '1.2.840.10008.1.2.4.91'
127
+ TXS_JPEG_2000_PART2_LOSSLESS = '1.2.840.10008.1.2.4.92'
128
+ TXS_JPEG_2000_PART2_LOSSLESS_OR_LOSSY = '1.2.840.10008.1.2.4.93'
129
+
130
+ TXS_MPEG2_MP_ML = '1.2.840.10008.1.2.4.100'
131
+ TXS_MPEG2_MP_HL = '1.2.840.10008.1.2.4.101'
132
+
133
+ TXS_DEFLATED_LITTLE_ENDIAN = '1.2.840.10008.1.2.1.99' # ZIP Compression
134
+
135
+ TXS_JPIP = '1.2.840.10008.1.2.4.94'
136
+ TXS_JPIP_DEFLATE = '1.2.840.10008.1.2.4.95'
137
+
138
+ TXS_RLE = '1.2.840.10008.1.2.5'
139
+
140
+
141
+ # Photometric Interpretations
142
+ # Taken from DICOM Specification PS 3.3 C.7.6.3.1.2 Photometric Interpretation
143
+
144
+ PI_MONOCHROME1 = 'MONOCHROME1'
145
+ PI_MONOCHROME2 = 'MONOCHROME2'
146
+ PI_PALETTE_COLOR = 'PALETTE COLOR'
147
+ PI_RGB = 'RGB'
148
+ PI_YBR_FULL = 'YBR_FULL'
149
+ PI_YBR_FULL_422 = 'YBR_FULL_422 '
150
+ PI_YBR_PARTIAL_422 = 'YBR_PARTIAL_422'
151
+ PI_YBR_PARTIAL_420 = 'YBR_PARTIAL_420'
152
+ PI_YBR_ICT = 'YBR_ICT'
153
+ PI_YBR_RCT = 'YBR_RCT'
154
+
155
+ # Retired Photometric Interpretations, are those needed to be supported?
156
+ PI_HSV = 'HSV'
157
+ PI_ARGB = 'ARGB'
158
+ PI_CMYK = 'CMYK'
159
+
160
+ # The relationship between DICOM Character Set and Encoding name.
161
+ ENCODING_NAME = {
162
+ 'ISO_IR 100' => 'ISO-8859-1',
163
+ 'ISO_IR 101' => 'ISO-8859-2',
164
+ 'ISO_IR 109' => 'ISO-8859-3',
165
+ 'ISO_IR 110' => 'ISO-8859-4',
166
+ 'ISO_IR 144' => 'ISO-8859-5',
167
+ 'ISO_IR 127' => 'ISO-8859-6',
168
+ 'ISO_IR 126' => 'ISO-8859-7',
169
+ 'ISO_IR 138' => 'ISO-8859-8',
170
+ 'ISO_IR 148' => 'ISO-8859-9',
171
+ 'ISO_IR 13' => 'JIS_X0201',
172
+ 'ISO_IR 166' => 'ISO-8859-11',
173
+ 'GB18030' => 'GB18030',
174
+ 'ISO_IR 192' => 'UTF-8'
175
+ }
176
+ ENCODING_NAME.default = 'ASCII-8BIT'
177
+
178
+ # The type conversion (method) used for the various value representations.
179
+ VALUE_CONVERSION = {
180
+ 'BY' => :to_i,
181
+ 'US' => :to_i,
182
+ 'SS' => :to_i,
183
+ 'UL' => :to_i,
184
+ 'SL' => :to_i,
185
+ 'OB' => :to_i,
186
+ 'OW' => :to_i,
187
+ 'OF' => :to_f,
188
+ 'FL' => :to_f,
189
+ 'FD' => :to_f,
190
+ 'AT' => :to_s,
191
+ 'AE' => :to_s,
192
+ 'AS' => :to_s,
193
+ 'CS' => :to_s,
194
+ 'DA' => :to_s,
195
+ 'DS' => :to_s,
196
+ 'DT' => :to_s,
197
+ 'IS' => :to_s,
198
+ 'LO' => :to_s,
199
+ 'LT' => :to_s,
200
+ 'PN' => :to_s,
201
+ 'SH' => :to_s,
202
+ 'ST' => :to_s,
203
+ 'TM' => :to_s,
204
+ 'UI' => :to_s,
205
+ 'UT' => :to_s
206
+ }
207
+ VALUE_CONVERSION.default = :to_s
208
+
209
+ end
210
+