dicom 0.9.3 → 0.9.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +312 -290
- data/COPYING +674 -674
- data/Gemfile +3 -0
- data/dicom.gemspec +31 -0
- data/lib/dicom.rb +53 -51
- data/lib/dicom/anonymizer.rb +98 -123
- data/lib/dicom/audit_trail.rb +104 -116
- data/lib/dicom/constants.rb +219 -170
- data/lib/dicom/d_client.rb +122 -150
- data/lib/dicom/d_library.rb +219 -287
- data/lib/dicom/d_object.rb +451 -539
- data/lib/dicom/d_read.rb +151 -245
- data/lib/dicom/d_server.rb +329 -359
- data/lib/dicom/d_write.rb +327 -395
- data/lib/dicom/deprecated.rb +1 -72
- data/lib/dicom/dictionary/elements.txt +3646 -0
- data/lib/dicom/dictionary/uids.txt +334 -0
- data/lib/dicom/dictionary_element.rb +61 -0
- data/lib/dicom/element.rb +278 -218
- data/lib/dicom/elemental.rb +21 -27
- data/lib/dicom/file_handler.rb +121 -121
- data/lib/dicom/image_item.rb +819 -861
- data/lib/dicom/image_processor.rb +24 -15
- data/lib/dicom/image_processor_mini_magick.rb +21 -23
- data/lib/dicom/image_processor_r_magick.rb +39 -34
- data/lib/dicom/item.rb +133 -120
- data/lib/dicom/link.rb +1531 -1532
- data/lib/dicom/logging.rb +155 -158
- data/lib/dicom/parent.rb +782 -847
- data/lib/dicom/ruby_extensions.rb +248 -229
- data/lib/dicom/sequence.rb +109 -92
- data/lib/dicom/stream.rb +480 -511
- data/lib/dicom/uid.rb +82 -0
- data/lib/dicom/variables.rb +9 -9
- data/lib/dicom/version.rb +5 -5
- data/rakefile.rb +29 -0
- metadata +130 -76
- data/lib/dicom/dictionary.rb +0 -3280
data/lib/dicom/d_read.rb
CHANGED
@@ -1,121 +1,20 @@
|
|
1
1
|
module DICOM
|
2
2
|
|
3
|
-
|
4
|
-
#
|
5
|
-
# The source of this binary string is typically either a DICOM file or a DICOM network transmission.
|
6
|
-
#
|
7
|
-
# === Notes
|
8
|
-
#
|
9
|
-
# In addition to reading files that are compliant to DICOM 3 Part 10, the philosophy of the
|
10
|
-
# Ruby DICOM library is to feature maximum compatibility, and as such it will also
|
11
|
-
# successfully read many types of 'DICOM' files that deviate in some way from the standard.
|
12
|
-
#
|
13
|
-
class DRead
|
3
|
+
class Parent
|
14
4
|
|
15
|
-
# A boolean which reports the explicitness of the DICOM string, true if explicit and false if implicit.
|
16
|
-
attr_reader :explicit
|
17
|
-
# A boolean which reports the endianness of the post-meta group part of the DICOM string (true for big endian, false for little endian).
|
18
|
-
attr_reader :file_endian
|
19
|
-
# An array which records any status messages that are generated while parsing the DICOM string.
|
20
|
-
attr_reader :msg
|
21
|
-
# A DObject instance which the parsed data elements will be connected to.
|
22
|
-
attr_reader :dcm
|
23
|
-
# A boolean which records whether the DICOM string contained the proper DICOM header signature of 128 bytes + 'DICM'.
|
24
|
-
attr_reader :signature
|
25
|
-
# A boolean which reports whether the DICOM string was parsed successfully (true) or not (false).
|
26
|
-
attr_reader :success
|
27
|
-
|
28
|
-
# Creates a DRead instance.
|
29
|
-
# Parses the DICOM string, builds data element objects and connects these with the DObject instance.
|
30
|
-
#
|
31
|
-
# === Parameters
|
32
|
-
#
|
33
|
-
# * <tt>dcm</tt> -- A DObject instance which the parsed data elements will be connected to.
|
34
|
-
# * <tt>string</tt> -- A string which specifies either the path of a DICOM file to be loaded, or a binary DICOM string to be parsed.
|
35
|
-
# * <tt>options</tt> -- A hash of parameters.
|
36
|
-
#
|
37
|
-
# === Options
|
38
|
-
#
|
39
|
-
# * <tt>:bin</tt> -- Boolean. If true, the string parameter will be interpreted as a binary DICOM string instead of a path string.
|
40
|
-
# * <tt>:no_meta</tt> -- Boolean. If true, the parsing algorithm is instructed that the binary DICOM string contains no meta header.
|
41
|
-
# * <tt>:syntax</tt> -- String. If specified, the decoding of the DICOM string will be forced to use this transfer syntax.
|
42
|
-
#
|
43
|
-
def initialize(dcm, string=nil, options={})
|
44
|
-
# Set the DICOM object as an instance variable:
|
45
|
-
@dcm = dcm
|
46
|
-
# If a transfer syntax has been specified as an option for a DICOM object, make sure that it makes it into the object:
|
47
|
-
if options[:syntax]
|
48
|
-
@transfer_syntax = options[:syntax]
|
49
|
-
dcm.add(Element.new("0002,0010", options[:syntax])) if dcm.is_a?(DObject)
|
50
|
-
end
|
51
|
-
# Initiate the variables that are used during file reading:
|
52
|
-
init_variables
|
53
|
-
# Are we going to read from a file, or read from a binary string?
|
54
|
-
if options[:bin]
|
55
|
-
# Read from the provided binary string:
|
56
|
-
@str = string
|
57
|
-
else
|
58
|
-
# Read from file:
|
59
|
-
open_file(string)
|
60
|
-
# Read the initial header of the file:
|
61
|
-
if @file == nil
|
62
|
-
# File is not readable, so we return:
|
63
|
-
@success = false
|
64
|
-
return
|
65
|
-
else
|
66
|
-
# Extract the content of the file to a binary string:
|
67
|
-
@str = @file.read
|
68
|
-
@file.close
|
69
|
-
end
|
70
|
-
end
|
71
|
-
# Create a Stream instance to handle the decoding of content from this binary string:
|
72
|
-
@stream = Stream.new(@str, @file_endian)
|
73
|
-
# Do not check for header information if we've been told there is none (typically for (network) binary strings):
|
74
|
-
unless options[:no_meta]
|
75
|
-
# Read and verify the DICOM header:
|
76
|
-
header = check_header
|
77
|
-
# If the file didnt have the expected header, we will attempt to read
|
78
|
-
# data elements from the very start of the file:
|
79
|
-
if header == false
|
80
|
-
@stream.skip(-132)
|
81
|
-
elsif header == nil
|
82
|
-
# Not a valid DICOM file, return:
|
83
|
-
@success = false
|
84
|
-
return
|
85
|
-
end
|
86
|
-
end
|
87
|
-
# Run a loop which parses Data Elements, one by one, until the end of the data string is reached:
|
88
|
-
data_element = true
|
89
|
-
while data_element do
|
90
|
-
# Using a rescue clause since processing Data Elements can cause errors when parsing an invalid DICOM string.
|
91
|
-
begin
|
92
|
-
# Extracting Data element information (nil is returned if end of file is encountered in a normal way).
|
93
|
-
data_element = process_data_element
|
94
|
-
rescue Exception => msg
|
95
|
-
# The parse algorithm crashed. Set data_element to false to break the loop and toggle the success boolean to indicate failure.
|
96
|
-
@msg << [:error, msg]
|
97
|
-
@msg << [:warn, "Parsing a Data Element has failed. This was probably caused by an invalidly encoded (or corrupted) DICOM file."]
|
98
|
-
@success = false
|
99
|
-
data_element = false
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
|
105
|
-
# Following methods are private:
|
106
5
|
private
|
107
6
|
|
108
7
|
|
109
8
|
# Checks for the official DICOM header signature.
|
110
|
-
#
|
111
|
-
# and nil if
|
9
|
+
#
|
10
|
+
# @return [Boolean] true if the proper signature is present, false if not, and nil if the string was shorter then the length of the DICOM signature
|
112
11
|
#
|
113
12
|
def check_header
|
114
13
|
# According to the official DICOM standard, a DICOM file shall contain 128 consequtive (zero) bytes,
|
115
14
|
# followed by 4 bytes that spell the string 'DICM'. Apparently, some providers seems to skip this in their DICOM files.
|
116
|
-
# Check that the
|
15
|
+
# Check that the string is long enough to contain a valid header:
|
117
16
|
if @str.length < 132
|
118
|
-
# This does not seem to be a valid DICOM
|
17
|
+
# This does not seem to be a valid DICOM string and so we return.
|
119
18
|
return nil
|
120
19
|
else
|
121
20
|
@stream.skip(128)
|
@@ -123,9 +22,9 @@ module DICOM
|
|
123
22
|
identifier = @stream.decode(4, "STR")
|
124
23
|
@header_length += 132
|
125
24
|
if identifier != "DICM" then
|
126
|
-
# Header signature is not valid (we will still try to
|
127
|
-
|
128
|
-
# As the
|
25
|
+
# Header signature is not valid (we will still try to parse it is a DICOM string though):
|
26
|
+
logger.warn("This string does not contain the expected DICOM header. Will try to parse the string anyway (assuming a missing header).")
|
27
|
+
# As the string is not conforming to the DICOM standard, it is possible that it does not contain a
|
129
28
|
# transfer syntax element, and as such, we attempt to choose the most probable encoding values here:
|
130
29
|
@explicit = false
|
131
30
|
return false
|
@@ -137,13 +36,13 @@ module DICOM
|
|
137
36
|
end
|
138
37
|
end
|
139
38
|
|
140
|
-
# Handles the process of reading a data element from the DICOM string, and
|
141
|
-
#
|
39
|
+
# Handles the process of reading a data element from the DICOM string, and
|
40
|
+
# creating an element object from the parsed data.
|
142
41
|
#
|
143
|
-
|
144
|
-
# FIXME: This method has grown a bit messy and isn't very easy to follow. It would be nice if it could be cleaned up somewhat.
|
42
|
+
# @return [Boolean] nil if end of string has been reached (in an expected way), false if the element parse failed, and true if an element was parsed successfully
|
145
43
|
#
|
146
44
|
def process_data_element
|
45
|
+
# FIXME: This method has grown a bit messy and isn't very pleasant to read. Cleanup possible?
|
147
46
|
# STEP 1:
|
148
47
|
# Attempt to read data element tag:
|
149
48
|
tag = read_tag
|
@@ -151,8 +50,8 @@ module DICOM
|
|
151
50
|
return nil unless tag
|
152
51
|
# STEP 2:
|
153
52
|
# Access library to retrieve the data element name and VR from the tag we just read:
|
154
|
-
# (Note: VR will be overwritten in the next step if the DICOM
|
155
|
-
name, vr = LIBRARY.
|
53
|
+
# (Note: VR will be overwritten in the next step if the DICOM string contains VR (explicit encoding))
|
54
|
+
name, vr = LIBRARY.name_and_vr(tag)
|
156
55
|
# STEP 3:
|
157
56
|
# Read VR (if it exists) and the length value:
|
158
57
|
vr, length = read_vr_length(vr,tag)
|
@@ -210,11 +109,9 @@ module DICOM
|
|
210
109
|
# If length is specified (no delimitation items), load a new DRead instance to read these child elements
|
211
110
|
# and load them into the current sequence. The exception is when we have a pixel data item.
|
212
111
|
if length > 0 and not @enc_image
|
213
|
-
|
112
|
+
@current_element.parse(bin, @transfer_syntax)
|
214
113
|
@current_parent = @current_parent.parent
|
215
|
-
|
216
|
-
@success = child_reader.success
|
217
|
-
return false unless @success
|
114
|
+
return false unless @read_success
|
218
115
|
end
|
219
116
|
elsif DELIMITER_TAGS.include?(tag)
|
220
117
|
# We do not create an element for the delimiter items.
|
@@ -230,15 +127,103 @@ module DICOM
|
|
230
127
|
return true
|
231
128
|
end
|
232
129
|
|
233
|
-
#
|
234
|
-
#
|
130
|
+
# Builds a DICOM object by parsing an encoded DICOM string.
|
131
|
+
#
|
132
|
+
# @param [String] string a binary DICOM string to be parsed
|
133
|
+
# @param [Boolean] signature if true (default), the parsing algorithm will look for the DICOM header signature
|
134
|
+
# @param [Hash] options the options to use for parsing the DICOM string
|
135
|
+
# @option options [String] :syntax if a syntax string is specified, the parsing algorithm is forced to use this transfer syntax when decoding the string
|
136
|
+
#
|
137
|
+
def read(string, signature=true, options={})
|
138
|
+
# (Re)Set variables:
|
139
|
+
@str = string
|
140
|
+
# Presence of the official DICOM signature:
|
141
|
+
@signature = false
|
142
|
+
# Default explicitness of start of DICOM string:
|
143
|
+
@explicit = true
|
144
|
+
# Default endianness of start of DICOM string is little endian:
|
145
|
+
@str_endian = false
|
146
|
+
# A switch of endianness may occur after the initial meta group, an this needs to be monitored:
|
147
|
+
@switched_endian = false
|
148
|
+
# Explicitness of the remaining groups after the initial 0002 group:
|
149
|
+
@rest_explicit = false
|
150
|
+
# Endianness of the remaining groups after the first group:
|
151
|
+
@rest_endian = false
|
152
|
+
# When the string switch from group 0002 to a later group we will update encoding values, and this switch will keep track of that:
|
153
|
+
@switched = false
|
154
|
+
# Keeping track of the data element parent status while parsing the DICOM string:
|
155
|
+
@current_parent = self
|
156
|
+
# Keeping track of what is the current data element:
|
157
|
+
@current_element = self
|
158
|
+
# Items contained under the pixel data element may contain data directly, so we need a variable to keep track of this:
|
159
|
+
@enc_image = false
|
160
|
+
# Assume header size is zero bytes until otherwise is determined:
|
161
|
+
@header_length = 0
|
162
|
+
# Assume string will be read successfully and toggle it later if we experience otherwise:
|
163
|
+
@read_success = true
|
164
|
+
# Our encoding instance:
|
165
|
+
@stream = Stream.new(@str, @str_endian)
|
166
|
+
# If a transfer syntax has been specified as an option for a DICOM object,
|
167
|
+
# make sure that it makes it into the object:
|
168
|
+
if options[:syntax]
|
169
|
+
@transfer_syntax = options[:syntax]
|
170
|
+
Element.new("0002,0010", options[:syntax], :parent => self) if self.is_a?(DObject)
|
171
|
+
end
|
172
|
+
# Check for header information if indicated:
|
173
|
+
if signature
|
174
|
+
# Read and verify the DICOM header:
|
175
|
+
header = check_header
|
176
|
+
# If the string is without the expected header, we will attempt
|
177
|
+
# to read data elements from the very start of the string:
|
178
|
+
if header == false
|
179
|
+
@stream.skip(-132)
|
180
|
+
elsif header.nil?
|
181
|
+
# Not a valid DICOM string, return:
|
182
|
+
@read_success = false
|
183
|
+
return
|
184
|
+
end
|
185
|
+
end
|
186
|
+
# Run a loop which parses Data Elements, one by one, until the end of the data string is reached:
|
187
|
+
data_element = true
|
188
|
+
while data_element do
|
189
|
+
# Using a rescue clause since processing Data Elements can cause errors when parsing an invalid DICOM string.
|
190
|
+
begin
|
191
|
+
# Extracting Data element information (nil is returned if end of the string is encountered in a normal way).
|
192
|
+
data_element = process_data_element
|
193
|
+
rescue Exception => msg
|
194
|
+
# The parse algorithm crashed. Set data_element as false to break
|
195
|
+
# the loop and toggle the success boolean to indicate failure.
|
196
|
+
@read_success = false
|
197
|
+
data_element = false
|
198
|
+
# Output the raised message as a warning:
|
199
|
+
logger.warn(msg.to_s)
|
200
|
+
# Ouput the backtrace as debug information:
|
201
|
+
logger.debug(msg.backtrace)
|
202
|
+
# Explain the failure as an error:
|
203
|
+
logger.error("Parsing a Data Element has failed. This is likely caused by an invalid DICOM encoding.")
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# Reads the data element's binary value string (varying length).
|
209
|
+
#
|
210
|
+
# @param [Integer] length the length of the binary string to be extracted
|
211
|
+
# @return [String] the element value
|
212
|
+
#
|
213
|
+
def read_bin(length)
|
214
|
+
return @stream.extract(length)
|
215
|
+
end
|
216
|
+
|
217
|
+
# Reads the data element's tag (the 4 first bytes of a data element).
|
218
|
+
#
|
219
|
+
# @return [String, NilClass] the element tag, or nil (if end of string reached)
|
235
220
|
#
|
236
221
|
def read_tag
|
237
222
|
tag = @stream.decode_tag
|
238
223
|
if tag
|
239
224
|
# When we shift from group 0002 to another group we need to update our endian/explicitness variables:
|
240
225
|
if tag.group != META_GROUP and @switched == false
|
241
|
-
|
226
|
+
switch_syntax_on_read
|
242
227
|
# We may need to read our tag again if endian has switched (in which case it has been misread):
|
243
228
|
if @switched_endian
|
244
229
|
@stream.skip(-4)
|
@@ -249,14 +234,40 @@ module DICOM
|
|
249
234
|
return tag
|
250
235
|
end
|
251
236
|
|
252
|
-
#
|
253
|
-
# The decoding scheme to be applied depends on explicitness, data element type and vr.
|
254
|
-
# Returns vr and length.
|
237
|
+
# Decodes the data element's value (varying length).
|
255
238
|
#
|
256
|
-
#
|
239
|
+
# * Data elements which have multiple numbers as value, will have these numbers joined to a string, separated by the \ character.
|
240
|
+
# * For some value representations (OW, OB, OF, UN), a value is not processed, and nil is returned.
|
257
241
|
#
|
258
|
-
#
|
259
|
-
#
|
242
|
+
# This means that for data like pixel data, compressed data, unknown data, a value is not
|
243
|
+
# available in the data element, and must be processed from the data element's binary variable.
|
244
|
+
#
|
245
|
+
# @param [String] vr the value representation of the data element which the value to be decoded belongs to
|
246
|
+
# @param [Integer] length the length of the binary string to be extracted
|
247
|
+
# @return [String, NilClass] the data element value
|
248
|
+
#
|
249
|
+
def read_value(vr, length)
|
250
|
+
unless vr == "OW" or vr == "OB" or vr == "OF" or vr == "UN"
|
251
|
+
# Since the binary string has already been extracted for this data element, we must first "rewind":
|
252
|
+
@stream.skip(-length)
|
253
|
+
# Decode data:
|
254
|
+
value = @stream.decode(length, vr)
|
255
|
+
# If the returned value is an array of multiple values, we will join these values to a string with the separator "\":
|
256
|
+
value = value.join("\\") if value.is_a?(Array)
|
257
|
+
else
|
258
|
+
# No decoded value:
|
259
|
+
value = nil
|
260
|
+
end
|
261
|
+
return value
|
262
|
+
end
|
263
|
+
|
264
|
+
# Reads the data element's value representation (2 bytes), as well as the
|
265
|
+
# data element's length (varying length: 2-6 bytes). The decoding scheme
|
266
|
+
# to be applied depends on explicitness, data element type and vr.
|
267
|
+
#
|
268
|
+
# @param [String] vr the value representation that was retrieved from the dictionary for the tag of this data element
|
269
|
+
# @param [String] tag the tag of this data element
|
270
|
+
# @return [Array<String, Integer>] the value representation and length of the element
|
260
271
|
#
|
261
272
|
def read_vr_length(vr, tag)
|
262
273
|
# Structure will differ, dependent on whether we have explicit or implicit encoding:
|
@@ -296,131 +307,26 @@ module DICOM
|
|
296
307
|
return vr, length
|
297
308
|
end
|
298
309
|
|
299
|
-
#
|
300
|
-
#
|
301
|
-
# === Parameters
|
302
|
-
#
|
303
|
-
# * <tt>length</tt> -- Fixnum. The length of the binary string that will be extracted.
|
304
|
-
#
|
305
|
-
def read_bin(length)
|
306
|
-
return @stream.extract(length)
|
307
|
-
end
|
308
|
-
|
309
|
-
# Decodes and returns the data element's value (varying length).
|
310
|
-
#
|
311
|
-
# === Notes
|
310
|
+
# Changes encoding variables as the parsing proceeds past the initial meta
|
311
|
+
# group part (0002,xxxx) of the DICOM string.
|
312
312
|
#
|
313
|
-
|
314
|
-
# * For some value representations (OW, OB, OF, UN), a value is not processed, and nil is returned.
|
315
|
-
# This means that for data like pixel data, compressed data, unknown data, a value is not available in the data element,
|
316
|
-
# and must be processed from the data element's binary variable.
|
317
|
-
#
|
318
|
-
# === Parameters
|
319
|
-
#
|
320
|
-
# * <tt>vr</tt> -- String. The value representation of the data element which the value to be decoded belongs to.
|
321
|
-
# * <tt>length</tt> -- Fixnum. The length of the binary string that will be extracted.
|
322
|
-
#
|
323
|
-
def read_value(vr, length)
|
324
|
-
unless vr == "OW" or vr == "OB" or vr == "OF" or vr == "UN"
|
325
|
-
# Since the binary string has already been extracted for this data element, we must first "rewind":
|
326
|
-
@stream.skip(-length)
|
327
|
-
# Decode data:
|
328
|
-
value = @stream.decode(length, vr)
|
329
|
-
# If the returned value is an array of multiple values, we will join these values to a string with the separator "\":
|
330
|
-
value = value.join("\\") if value.is_a?(Array)
|
331
|
-
else
|
332
|
-
# No decoded value:
|
333
|
-
value = nil
|
334
|
-
end
|
335
|
-
return value
|
336
|
-
end
|
337
|
-
|
338
|
-
# Tests if a file is readable, and if so, opens it.
|
339
|
-
#
|
340
|
-
# === Parameters
|
341
|
-
#
|
342
|
-
# * <tt>file</tt> -- A path/file string.
|
343
|
-
#
|
344
|
-
def open_file(file)
|
345
|
-
if File.exist?(file)
|
346
|
-
if File.readable?(file)
|
347
|
-
if !File.directory?(file)
|
348
|
-
if File.size(file) > 8
|
349
|
-
@file = File.new(file, "rb")
|
350
|
-
else
|
351
|
-
@msg << [:error, "This file is too small to contain valid DICOM information: #{file}."]
|
352
|
-
end
|
353
|
-
else
|
354
|
-
@msg << [:error, "Expected a file, got a directory: #{file}"]
|
355
|
-
end
|
356
|
-
else
|
357
|
-
@msg << [:error, "File exists but I don't have permission to read it: #{file}"]
|
358
|
-
end
|
359
|
-
else
|
360
|
-
@msg << [:error, "Invalid (non-existing) file: #{file}"]
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
# Changes encoding variables as the file reading proceeds past the initial meta group part (0002,xxxx) of the DICOM file.
|
365
|
-
#
|
366
|
-
def switch_syntax
|
313
|
+
def switch_syntax_on_read
|
367
314
|
# Get the transfer syntax string, unless it has already been provided by keyword:
|
368
|
-
unless @transfer_syntax
|
369
|
-
ts_element = @dcm["0002,0010"]
|
370
|
-
if ts_element
|
371
|
-
@transfer_syntax = ts_element.value
|
372
|
-
else
|
373
|
-
@transfer_syntax = IMPLICIT_LITTLE_ENDIAN
|
374
|
-
end
|
375
|
-
end
|
315
|
+
@transfer_syntax = (self["0002,0010"] ? self["0002,0010"].value : IMPLICIT_LITTLE_ENDIAN) unless @transfer_syntax
|
376
316
|
# Query the library with our particular transfer syntax string:
|
377
|
-
|
378
|
-
unless
|
379
|
-
|
380
|
-
|
381
|
-
#
|
317
|
+
ts = LIBRARY.uid(@transfer_syntax)
|
318
|
+
logger.warn("Invalid/unknown transfer syntax: #{@transfer_syntax} Will try parsing the string, but errors may occur.") unless ts && ts.transfer_syntax?
|
319
|
+
@rest_explicit = ts ? ts.explicit? : true
|
320
|
+
@rest_endian = ts ? ts.big_endian? : false
|
321
|
+
# Make sure we only run this method once:
|
382
322
|
@switched = true
|
383
323
|
# Update endian, explicitness and unpack variables:
|
384
|
-
@switched_endian = true if @rest_endian != @
|
385
|
-
@
|
324
|
+
@switched_endian = true if @rest_endian != @str_endian
|
325
|
+
@str_endian = @rest_endian
|
386
326
|
@stream.endian = @rest_endian
|
387
327
|
@explicit = @rest_explicit
|
388
328
|
end
|
389
329
|
|
390
|
-
|
391
|
-
# Creates various instance variables that are used when parsing the DICOM string.
|
392
|
-
#
|
393
|
-
def init_variables
|
394
|
-
# Array for storing any messages that is generated while reading the DICOM file.
|
395
|
-
# The messages shall be of the format: [:type, "message"]
|
396
|
-
# (Because of the possibility of multi-pass file reading, the DRead instance does not access
|
397
|
-
# the Logging module directly; it lets the DObject instance pass along the messages instead)
|
398
|
-
@msg = Array.new
|
399
|
-
# Presence of the official DICOM signature:
|
400
|
-
@signature = false
|
401
|
-
# Default explicitness of start of DICOM file:
|
402
|
-
@explicit = true
|
403
|
-
# Default endianness of start of DICOM files is little endian:
|
404
|
-
@file_endian = false
|
405
|
-
# A switch of endianness may occur after the initial meta group, an this needs to be monitored:
|
406
|
-
@switched_endian = false
|
407
|
-
# Explicitness of the remaining groups after the initial 0002 group:
|
408
|
-
@rest_explicit = false
|
409
|
-
# Endianness of the remaining groups after the first group:
|
410
|
-
@rest_endian = false
|
411
|
-
# When the file switch from group 0002 to a later group we will update encoding values, and this switch will keep track of that:
|
412
|
-
@switched = false
|
413
|
-
# Keeping track of the data element parent status while parsing the DICOM string:
|
414
|
-
@current_parent = @dcm
|
415
|
-
# Keeping track of what is the current data element:
|
416
|
-
@current_element = @dcm
|
417
|
-
# Items contained under the pixel data element may contain data directly, so we need a variable to keep track of this:
|
418
|
-
@enc_image = false
|
419
|
-
# Assume header size is zero bytes until otherwise is determined:
|
420
|
-
@header_length = 0
|
421
|
-
# Assume file will be read successfully and toggle it later if we experience otherwise:
|
422
|
-
@success = true
|
423
|
-
end
|
424
|
-
|
425
330
|
end
|
331
|
+
|
426
332
|
end
|