Class: DICOM::Stream
- Inherits:
-
Object
- Object
- DICOM::Stream
- Defined in:
- lib/dicom/stream.rb
Overview
In practice, this class is for internal library use. It is typically not accessed by the user, and can thus be considered a ‘private’ class.
The Stream class handles string operations (encoding to and decoding from binary strings). It is used by the various classes of ruby-dicom for tasks such as reading and writing from/to files or network packets.
Instance Attribute Summary collapse
-
#equal_endian ⇒ Object
readonly
A boolean which reports the relationship between the endianness of the system and the instance string.
-
#errors ⇒ Object
readonly
An array of warning/error messages that (may) have been accumulated.
-
#index ⇒ Object
Our current position in the instance string (used only for decoding).
-
#pad_byte ⇒ Object
readonly
A hash with vr as key and its corresponding pad byte as value.
-
#str_endian ⇒ Object
readonly
The endianness of the instance string.
-
#string ⇒ Object
The instance string.
Instance Method Summary collapse
-
#add_first(binary) ⇒ Object
Prepends a pre-encoded string to the instance string (inserts at the beginning).
-
#add_last(binary) ⇒ Object
Appends a pre-encoded string to the instance string (inserts at the end).
-
#decode(length, type) ⇒ String, ...
Decodes a section of the instance string.
-
#decode_all(type) ⇒ String, ...
Decodes the entire instance string (typically used for decoding image data).
-
#decode_tag ⇒ String, NilClass
Decodes 4 bytes of the instance string and formats it as a ruby-dicom tag string.
-
#encode(value, type) ⇒ String
Encodes a given value to a binary string.
-
#encode_first(value, type) ⇒ Object
Encodes a value to a binary string and prepends it to the instance string.
-
#encode_last(value, type) ⇒ Object
Encodes a value to a binary string and appends it to the instance string.
-
#encode_string_with_trailing_spaces(string, target_length) ⇒ String
Appends a string with trailling spaces to achieve a target length, and encodes it to a binary string.
-
#encode_tag(tag) ⇒ String
Encodes a tag from the ruby-dicom format (‘GGGG,EEEE’) to a proper binary string.
-
#encode_value(value, vr) ⇒ String
Encodes a value, and if the the resulting binary string has an odd length, appends a proper padding byte to make it even length.
-
#endian=(string_endian) ⇒ Object
Sets the endianness of the instance string.
-
#export(length = nil) ⇒ String
Extracts the entire instance string, or optionally, just the first part of it if a length is specified.
-
#extract(length) ⇒ String
Extracts and returns a binary string of the given length, starting at the index position.
-
#initialize(binary, string_endian, options = {}) ⇒ Stream
constructor
Creates a Stream instance.
-
#length ⇒ Integer
Gives the length of the instance string.
-
#reset ⇒ Object
Resets the instance string and index.
-
#reset_index ⇒ Object
Resets the instance index.
-
#rest_length ⇒ Integer
Calculates the remaining length of the instance string (from the index position).
-
#rest_string ⇒ String
Extracts the remaining part of the instance string (from the index position to the end of the string).
-
#set_file(file) ⇒ Object
Sets the instance file variable.
-
#set_string(binary) ⇒ Object
Sets a new instance string, and resets the index variable.
-
#skip(offset) ⇒ Object
Applies an offset (positive or negative) to the instance index.
-
#write(binary) ⇒ Object
Writes a binary string to the File object of this instance.
Constructor Details
Instance Attribute Details
#equal_endian ⇒ Object (readonly)
A boolean which reports the relationship between the endianness of the system and the instance string.
13 14 15 |
# File 'lib/dicom/stream.rb', line 13 def equal_endian @equal_endian end |
#errors ⇒ Object (readonly)
An array of warning/error messages that (may) have been accumulated.
21 22 23 |
# File 'lib/dicom/stream.rb', line 21 def errors @errors end |
#index ⇒ Object
Our current position in the instance string (used only for decoding).
15 16 17 |
# File 'lib/dicom/stream.rb', line 15 def index @index end |
#pad_byte ⇒ Object (readonly)
A hash with vr as key and its corresponding pad byte as value.
23 24 25 |
# File 'lib/dicom/stream.rb', line 23 def pad_byte @pad_byte end |
#str_endian ⇒ Object (readonly)
The endianness of the instance string.
19 20 21 |
# File 'lib/dicom/stream.rb', line 19 def str_endian @str_endian end |
#string ⇒ Object
The instance string.
17 18 19 |
# File 'lib/dicom/stream.rb', line 17 def string @string end |
Instance Method Details
#add_first(binary) ⇒ Object
Prepends a pre-encoded string to the instance string (inserts at the beginning).
43 44 45 |
# File 'lib/dicom/stream.rb', line 43 def add_first(binary) @string = binary + @string if binary end |
#add_last(binary) ⇒ Object
Appends a pre-encoded string to the instance string (inserts at the end).
51 52 53 |
# File 'lib/dicom/stream.rb', line 51 def add_last(binary) @string = @string + binary if binary end |
#decode(length, type) ⇒ String, ...
If multiple numbers are decoded, these are returned in an array.
Decodes a section of the instance string. The instance index is offset in accordance with the length read.
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/dicom/stream.rb', line 63 def decode(length, type) raise ArgumentError, "Invalid argument length. Expected Fixnum, got #{length.class}" unless length.is_a?(Fixnum) raise ArgumentError, "Invalid argument type. Expected string, got #{type.class}" unless type.is_a?(String) # Check if values are valid: if (@index + length) > @string.length # The index number is bigger then the length of the binary string. # We have reached the end and will return nil. value = nil else if type == 'AT' # We need to guard ourselves against the case where a string contains an invalid 'AT' value: if length == 4 value = decode_tag else # Invalid. Just return nil. skip(length) value = nil end else # Decode the binary string and return value: value = @string.slice(@index, length).unpack(vr_to_str(type)) # If the result is an array of one element, return the element instead of the array. # If result is contained in a multi-element array, the original array is returned. if value.length == 1 value = value[0] # If value is a string, strip away possible trailing whitespace: value = value.rstrip if value.is_a?(String) end # Update our position in the string: skip(length) end end return value end |
#decode_all(type) ⇒ String, ...
If multiple numbers are decoded, these are returned in an array.
Decodes the entire instance string (typically used for decoding image data).
104 105 106 107 108 109 |
# File 'lib/dicom/stream.rb', line 104 def decode_all(type) length = @string.length value = @string.slice(@index, length).unpack(vr_to_str(type)) skip(length) return value end |
#decode_tag ⇒ String, NilClass
Decodes 4 bytes of the instance string and formats it as a ruby-dicom tag string.
115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'lib/dicom/stream.rb', line 115 def decode_tag length = 4 # Check if values are valid: if (@index + length) > @string.length # The index number is bigger then the length of the binary string. # We have reached the end and will return nil. tag = nil else # Decode and process: string = @string.slice(@index, length).unpack(@hex)[0].upcase if @equal_endian tag = string[2..3] + string[0..1] + ',' + string[6..7] + string[4..5] else tag = string[0..3] + ',' + string[4..7] end # Update our position in the string: skip(length) end return tag end |
#encode(value, type) ⇒ String
Encodes a given value to a binary string.
142 143 144 145 146 |
# File 'lib/dicom/stream.rb', line 142 def encode(value, type) raise ArgumentError, "Invalid argument type. Expected string, got #{type.class}" unless type.is_a?(String) value = [value] unless value.is_a?(Array) return value.pack(vr_to_str(type)) end |
#encode_first(value, type) ⇒ Object
Encodes a value to a binary string and prepends it to the instance string.
153 154 155 156 157 |
# File 'lib/dicom/stream.rb', line 153 def encode_first(value, type) value = [value] unless value.is_a?(Array) bin = value.pack(vr_to_str(type)) @string = bin + @string end |
#encode_last(value, type) ⇒ Object
Encodes a value to a binary string and appends it to the instance string.
164 165 166 167 168 |
# File 'lib/dicom/stream.rb', line 164 def encode_last(value, type) value = [value] unless value.is_a?(Array) bin = value.pack(vr_to_str(type)) @string = @string + bin end |
#encode_string_with_trailing_spaces(string, target_length) ⇒ String
Appends a string with trailling spaces to achieve a target length, and encodes it to a binary string.
176 177 178 179 180 181 182 183 184 185 |
# File 'lib/dicom/stream.rb', line 176 def encode_string_with_trailing_spaces(string, target_length) length = string.length if length < target_length return [string].pack(@str)+['20'*(target_length-length)].pack(@hex) elsif length == target_length return [string].pack(@str) else raise "The specified string is longer than the allowed maximum length (String: #{string}, Target length: #{target_length})." end end |
#encode_tag(tag) ⇒ String
Encodes a tag from the ruby-dicom format (‘GGGG,EEEE’) to a proper binary string.
192 193 194 195 196 197 198 199 |
# File 'lib/dicom/stream.rb', line 192 def encode_tag(tag) if @equal_endian clean_tag = tag[2..3] + tag[0..1] + tag[7..8] + tag[5..6] else clean_tag = tag[0..3] + tag[5..8] end return [clean_tag].pack(@hex) end |
#encode_value(value, vr) ⇒ String
Encodes a value, and if the the resulting binary string has an odd length, appends a proper padding byte to make it even length.
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 |
# File 'lib/dicom/stream.rb', line 208 def encode_value(value, vr) if vr == 'AT' bin = encode_tag(value) else # Make sure the value is in an array: value = [value] unless value.is_a?(Array) # Get the proper pack string: type = vr_to_str(vr) # Encode: bin = value.pack(type) # Add an empty byte if the resulting binary has an odd length: bin = bin + @pad_byte[vr] if bin.length.odd? end return bin end |
#endian=(string_endian) ⇒ Object
Sets the endianness of the instance string. The relationship between the string endianness and the system endianness determines which encoding/decoding flags to use.
229 230 231 232 233 234 235 |
# File 'lib/dicom/stream.rb', line 229 def endian=(string_endian) @str_endian = string_endian configure_endian set_pad_byte set_string_formats set_format_hash end |
#export(length = nil) ⇒ String
The exported string is removed from the instance string.
Extracts the entire instance string, or optionally, just the first part of it if a length is specified.
244 245 246 247 248 249 250 251 252 |
# File 'lib/dicom/stream.rb', line 244 def export(length=nil) if length string = @string.slice!(0, length) else string = @string reset end return string end |
#extract(length) ⇒ String
Extracts and returns a binary string of the given length, starting at the index position. The instance index is then offset in accordance with the length read.
260 261 262 263 264 |
# File 'lib/dicom/stream.rb', line 260 def extract(length) str = @string.slice(@index, length) skip(length) return str end |
#length ⇒ Integer
Gives the length of the instance string.
270 271 272 |
# File 'lib/dicom/stream.rb', line 270 def length return @string.length end |
#reset ⇒ Object
Resets the instance string and index.
294 295 296 297 |
# File 'lib/dicom/stream.rb', line 294 def reset @string = '' @index = 0 end |
#reset_index ⇒ Object
Resets the instance index.
301 302 303 |
# File 'lib/dicom/stream.rb', line 301 def reset_index @index = 0 end |
#rest_length ⇒ Integer
Calculates the remaining length of the instance string (from the index position).
278 279 280 281 |
# File 'lib/dicom/stream.rb', line 278 def rest_length length = @string.length - @index return length end |
#rest_string ⇒ String
Extracts the remaining part of the instance string (from the index position to the end of the string).
287 288 289 290 |
# File 'lib/dicom/stream.rb', line 287 def rest_string str = @string[@index..(@string.length-1)] return str end |
#set_file(file) ⇒ Object
For performance reasons, we enable the Stream instance to write directly to file, to avoid expensive string operations which will otherwise slow down the write performance.
Sets the instance file variable.
312 313 314 |
# File 'lib/dicom/stream.rb', line 312 def set_file(file) @file = file end |
#set_string(binary) ⇒ Object
Sets a new instance string, and resets the index variable.
320 321 322 323 324 |
# File 'lib/dicom/stream.rb', line 320 def set_string(binary) binary = binary[0] if binary.is_a?(Array) @string = binary @index = 0 end |
#skip(offset) ⇒ Object
Applies an offset (positive or negative) to the instance index.
330 331 332 |
# File 'lib/dicom/stream.rb', line 330 def skip(offset) @index += offset end |
#write(binary) ⇒ Object
Writes a binary string to the File object of this instance.
338 339 340 |
# File 'lib/dicom/stream.rb', line 338 def write(binary) @file.write(binary) end |