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 |
# File 'lib/dicom/stream.rb', line 63 def decode(length, type) raise ArgumentError, "Invalid argument length. Expected Integer, got #{length.class}" unless length.is_a?(Integer) raise ArgumentError, "Invalid argument type. Expected string, got #{type.class}" unless type.is_a?(String) value = nil if (@index + length) <= @string.length # There are sufficient bytes remaining to extract the value: 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) 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 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).
100 101 102 103 104 105 |
# File 'lib/dicom/stream.rb', line 100 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.
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/dicom/stream.rb', line 111 def decode_tag length = 4 tag = nil if (@index + length) <= @string.length # There are sufficient bytes remaining to extract a full tag: str = @string.slice(@index, length).unpack(@hex)[0].upcase if @equal_endian tag = "#{str[2..3]}#{str[0..1]},#{str[6..7]}#{str[4..5]}" else tag = "#{str[0..3]},#{str[4..7]}" end # Update our position in the string: skip(length) end tag end |
#encode(value, type) ⇒ String
Encodes a given value to a binary string.
134 135 136 137 138 |
# File 'lib/dicom/stream.rb', line 134 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.
145 146 147 148 |
# File 'lib/dicom/stream.rb', line 145 def encode_first(value, type) value = [value] unless value.is_a?(Array) @string = "#{value.pack(vr_to_str(type))}#{@string}" end |
#encode_last(value, type) ⇒ Object
Encodes a value to a binary string and appends it to the instance string.
155 156 157 158 |
# File 'lib/dicom/stream.rb', line 155 def encode_last(value, type) value = [value] unless value.is_a?(Array) @string = "#{@string}#{value.pack(vr_to_str(type))}" 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.
166 167 168 169 170 171 172 173 174 175 |
# File 'lib/dicom/stream.rb', line 166 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.
182 183 184 185 186 |
# File 'lib/dicom/stream.rb', line 182 def encode_tag(tag) [ @equal_endian ? "#{tag[2..3]}#{tag[0..1]}#{tag[7..8]}#{tag[5..6]}" : "#{tag[0..3]}#{tag[5..8]}" ].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.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/dicom/stream.rb', line 195 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.
216 217 218 219 220 221 222 |
# File 'lib/dicom/stream.rb', line 216 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.
231 232 233 234 235 236 237 238 239 |
# File 'lib/dicom/stream.rb', line 231 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.
247 248 249 250 251 |
# File 'lib/dicom/stream.rb', line 247 def extract(length) str = @string.slice(@index, length) skip(length) return str end |
#length ⇒ Integer
Gives the length of the instance string.
257 258 259 |
# File 'lib/dicom/stream.rb', line 257 def length return @string.length end |
#reset ⇒ Object
Resets the instance string and index.
281 282 283 284 |
# File 'lib/dicom/stream.rb', line 281 def reset @string = '' @index = 0 end |
#reset_index ⇒ Object
Resets the instance index.
288 289 290 |
# File 'lib/dicom/stream.rb', line 288 def reset_index @index = 0 end |
#rest_length ⇒ Integer
Calculates the remaining length of the instance string (from the index position).
265 266 267 268 |
# File 'lib/dicom/stream.rb', line 265 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).
274 275 276 277 |
# File 'lib/dicom/stream.rb', line 274 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.
299 300 301 |
# File 'lib/dicom/stream.rb', line 299 def set_file(file) @file = file end |
#set_string(binary) ⇒ Object
Sets a new instance string, and resets the index variable.
307 308 309 310 311 |
# File 'lib/dicom/stream.rb', line 307 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.
317 318 319 |
# File 'lib/dicom/stream.rb', line 317 def skip(offset) @index += offset end |
#write(binary) ⇒ Object
Writes a binary string to the File object of this instance.
325 326 327 |
# File 'lib/dicom/stream.rb', line 325 def write(binary) @file.write(binary) end |