dicom 0.8 → 0.9

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.
@@ -0,0 +1,69 @@
1
+ module DICOM
2
+ module ImageProcessor
3
+
4
+ # Creates image objects from one or more compressed, binary string blobs.
5
+ # Returns an array of images. If decompression fails, returns false.
6
+ #
7
+ # === Parameters
8
+ #
9
+ # * <tt>blobs</tt> -- Binary string blob(s) containing compressed pixel data.
10
+ #
11
+ def decompress(blobs)
12
+ raise ArgumentError, "Expected Array or String, got #{blobs.class}." unless [String, Array].include?(blobs.class)
13
+ blobs = [blobs] unless blobs.is_a?(Array)
14
+ begin
15
+ return image_module.decompress(blobs)
16
+ rescue
17
+ return false
18
+ end
19
+ end
20
+
21
+ # Extracts an array of pixels (integers) from an image object.
22
+ #
23
+ # === Parameters
24
+ #
25
+ # * <tt>image</tt> -- An Rmagick image object.
26
+ #
27
+ def export_pixels(image, photometry)
28
+ raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
29
+ image_module.export_pixels(image, photometry)
30
+ end
31
+
32
+ # Creates an image object from a binary string blob.
33
+ #
34
+ # === Parameters
35
+ #
36
+ # * <tt>blob</tt> -- Binary string blob containing raw pixel data.
37
+ # * <tt>columns</tt> -- Number of columns.
38
+ # * <tt>rows</tt> -- Number of rows.
39
+ # * <tt>depth</tt> -- Bit depth of the encoded pixel data.
40
+ # * <tt>photometry</tt> -- String describing the DICOM photometry of the pixel data. Example: 'MONOCHROME1', 'RGB'.
41
+ #
42
+ def import_pixels(blob, columns, rows, depth, photometry)
43
+ raise ArgumentError, "Expected String, got #{blob.class}." unless blob.is_a?(String)
44
+ image_module.import_pixels(blob, columns, rows, depth, photometry)
45
+ end
46
+
47
+ # Returns an array containing the image objects that are supported by the image processor.
48
+ #
49
+ def valid_image_objects
50
+ return [Magick::Image, MiniMagick::Image]
51
+ end
52
+
53
+
54
+ private
55
+
56
+
57
+ def image_module
58
+ case DICOM.image_processor
59
+ when :mini_magick
60
+ DcmMiniMagick
61
+ when :rmagick
62
+ DcmRMagick
63
+ else
64
+ raise "Uknown image processor #{DICOM.image_processor}"
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,74 @@
1
+ module DICOM
2
+ module ImageProcessor
3
+ module DcmMiniMagick
4
+
5
+ class << self
6
+
7
+ # Creates image objects from an array of compressed, binary string blobs.
8
+ # Returns an array of images. If decompression fails, returns false.
9
+ #
10
+ # === Parameters
11
+ #
12
+ # * <tt>blobs</tt> -- An array of binary string blobs containing compressed pixel data.
13
+ #
14
+ def decompress(blobs)
15
+ images = Array.new
16
+ # We attempt to decompress the pixels using ImageMagick:
17
+ blobs.each do |string|
18
+ images << MiniMagick::Image.read(string)
19
+ end
20
+ return images
21
+ end
22
+
23
+ # Extracts an array of pixels (integers) from an image object.
24
+ #
25
+ # === Notes
26
+ #
27
+ # * This feature is not available as of yet in the mini_magick image processor. If this feature is needed, please try another image processor (RMagick).
28
+ #
29
+ # === Parameters
30
+ #
31
+ # * <tt>image</tt> -- An MiniMagick image object.
32
+ #
33
+ def export_pixels(image, photometry)
34
+ raise ArgumentError, "Expected MiniMagick::Image, got #{image.class}." unless image.is_a?(MiniMagick::Image)
35
+ raise "Exporting pixels is not yet available with the mini_magick processor. Please try another image processor (RMagick)."
36
+ end
37
+
38
+ # Creates an image object from a binary string blob which contains raw pixel data.
39
+ #
40
+ # === Parameters
41
+ #
42
+ # * <tt>blob</tt> -- Binary string blob containing raw pixel data.
43
+ # * <tt>columns</tt> -- Number of columns.
44
+ # * <tt>rows</tt> -- Number of rows.
45
+ # * <tt>depth</tt> -- Bit depth of the encoded pixel data.
46
+ # * <tt>photometry</tt> -- String describing the DICOM photometry of the pixel data.
47
+ # * <tt>format</tt> -- String describing the image format to be used when creating the image object. Defaults to 'png'.
48
+ #
49
+ def import_pixels(blob, columns, rows, depth, photometry, format="png")
50
+ image = MiniMagick::Image.import_pixels(blob, columns, rows, depth, im_map(photometry), format)
51
+ end
52
+
53
+ # Returns an ImageMagick pixel map string based on the input DICOM photometry string.
54
+ #
55
+ # === Parameters
56
+ #
57
+ # * <tt>photometry</tt> -- String describing the photometry of the pixel data. Example: 'MONOCHROME1' or 'COLOR'.
58
+ #
59
+ def im_map(photometry)
60
+ raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
61
+ if photometry.include?("COLOR") or photometry.include?("RGB")
62
+ return "rgb"
63
+ elsif photometry.include?("YBR")
64
+ return "ybr"
65
+ else
66
+ return "gray" # (Assuming monochromeX - greyscale)
67
+ end
68
+ end
69
+
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,102 @@
1
+ module DICOM
2
+ module ImageProcessor
3
+ module DcmRMagick
4
+
5
+ class << self
6
+
7
+ # Creates image objects from an array of compressed, binary string blobs.
8
+ # Returns an array of images. If decompression fails, returns false.
9
+ #
10
+ # === Notes
11
+ #
12
+ # The method tries to use RMagick of unpacking, but it seems that ImageMagick is not able to handle most of the
13
+ # compressed image variants used in the DICOM standard. To get a more robust implementation which is able to handle
14
+ # most types of compressed DICOM files, something else is needed.
15
+ #
16
+ # Probably a good candidate to use is the PVRG-JPEG library, which seems to be able to handle everything that is jpeg.
17
+ # It exists in the Ubuntu repositories, where it can be installed and run through terminal. For source code, and some
18
+ # additional information, check this link: http://www.panix.com/~eli/jpeg/
19
+ #
20
+ # Another idea would be to study how other open source libraries, like GDCM handle these files.
21
+ #
22
+ # === Parameters
23
+ #
24
+ # * <tt>blobs</tt> -- An array of binary string blobs containing compressed pixel data.
25
+ #
26
+ #--
27
+ # The following transfer syntaxes have been verified as failing with ImageMagick:
28
+ # TXS_JPEG_LOSSLESS_NH is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
29
+ # TXS_JPEG_LOSSLESS_NH_FOP is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
30
+ # TXS_JPEG_2000_PART1_LOSSLESS is not supported by (my) ImageMagick version: "jpc_dec_decodepkts failed"
31
+ #
32
+ def decompress(blobs)
33
+ images = Array.new
34
+ # We attempt to decompress the pixels using ImageMagick:
35
+ blobs.each do |string|
36
+ images << Magick::Image.from_blob(string).first
37
+ end
38
+ return images
39
+ end
40
+
41
+ # Extracts an array of pixels (integers) from an image object.
42
+ #
43
+ # === Parameters
44
+ #
45
+ # * <tt>image</tt> -- An Rmagick image object.
46
+ #
47
+ def export_pixels(image, photometry)
48
+ raise ArgumentError, "Expected Magick::Image, got #{image.class}." unless image.is_a?(Magick::Image)
49
+ pixels = image.export_pixels(0, 0, image.columns, image.rows, rm_map(photometry))
50
+ return pixels
51
+ end
52
+
53
+ # Creates an image object from a binary string blob which contains raw pixel data.
54
+ #
55
+ # === Parameters
56
+ #
57
+ # * <tt>blob</tt> -- Binary string blob containing raw pixel data.
58
+ # * <tt>columns</tt> -- Number of columns.
59
+ # * <tt>rows</tt> -- Number of rows.
60
+ # * <tt>depth</tt> -- Bit depth of the encoded pixel data.
61
+ # * <tt>photometry</tt> -- String describing the DICOM photometry of the pixel data.
62
+ # * <tt>format</tt> -- String describing the image format to be used when creating the image object. Defaults to 'png'.
63
+ #
64
+ def import_pixels(blob, columns, rows, depth, photometry, format="png")
65
+ image = Magick::Image.new(columns,rows).import_pixels(0, 0, columns, rows, rm_map(photometry), blob, rm_data_type(depth))
66
+ end
67
+
68
+ # Returns the RMagick StorageType pixel value corresponding to the given bit length.
69
+ #
70
+ def rm_data_type(bit_depth)
71
+ return case bit_depth
72
+ when 8
73
+ Magick::CharPixel
74
+ when 16
75
+ Magick::ShortPixel
76
+ else
77
+ raise ArgumentError, "Unsupported bit depth: #{bit_depth}."
78
+ end
79
+ end
80
+
81
+ # Returns an RMagick pixel map string based on the input DICOM photometry string.
82
+ #
83
+ # === Parameters
84
+ #
85
+ # * <tt>photometry</tt> -- String describing the photometry of the pixel data. Example: 'MONOCHROME1' or 'COLOR'.
86
+ #
87
+ def rm_map(photometry)
88
+ raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
89
+ if photometry.include?("COLOR") or photometry.include?("RGB")
90
+ return "RGB"
91
+ elsif photometry.include?("YBR")
92
+ return "YBR"
93
+ else
94
+ return "I" # (Assuming monochromeX - greyscale)
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ end
101
+ end
102
+ end
@@ -1,13 +1,16 @@
1
- # Copyright 2010 Christoffer Lervag
2
-
3
1
  module DICOM
4
2
 
5
3
  # The Item class handles information related to items - the elements contained in sequences.
6
4
  #
7
- class Item < SuperItem
5
+ # === Inheritance
6
+ #
7
+ # As the Item class inherits from the ImageItem class, which itself inherits from the Parent class,
8
+ # all ImageItem and Parent methods are also available to instances of Item.
9
+ #
10
+ class Item < ImageItem
8
11
 
9
- # Include the Elements mix-in module:
10
- include Elements
12
+ # Include the Elemental mix-in module:
13
+ include Elemental
11
14
 
12
15
  # The index of this Item in the group of items belonging to its parent. If the Item is without parent, index is nil.
13
16
  attr_accessor :index
@@ -47,13 +50,15 @@ module DICOM
47
50
  @value = nil
48
51
  @name = options[:name] || "Item"
49
52
  @vr = options[:vr] || ITEM_VR
50
- @bin = options[:bin]
51
- @length = options[:length]
52
- @length = -1 unless options[:length] or options[:bin]
53
+ if options[:bin]
54
+ self.bin = options[:bin]
55
+ else
56
+ @length = options[:length] || -1
57
+ end
53
58
  if options[:parent]
54
59
  @parent = options[:parent]
55
60
  @index = options[:index] if options[:index]
56
- @parent.add_item(self, :index => options[:index])
61
+ @parent.add_item(self, :index => options[:index], :no_follow => true)
57
62
  end
58
63
  end
59
64
 
@@ -69,18 +74,15 @@ module DICOM
69
74
  # obj["7FE0,0010"][1].children.first.bin = jpeg_binary_string
70
75
  #
71
76
  def bin=(new_bin)
72
- if new_bin.is_a?(String)
73
- # Add an empty byte at the end if the length of the binary is odd:
74
- if new_bin.length[0] == 1
75
- @bin = new_bin + "\x00"
76
- else
77
- @bin = new_bin
78
- end
79
- @value = nil
80
- @length = @bin.length
77
+ raise ArgumentError, "Invalid parameter type. String was expected, got #{new_bin.class}." unless new_bin.is_a?(String)
78
+ # Add an empty byte at the end if the length of the binary is odd:
79
+ if new_bin.length[0] == 1
80
+ @bin = new_bin + "\x00"
81
81
  else
82
- raise "Invalid parameter type. String was expected, got #{new_bin.class}."
82
+ @bin = new_bin
83
83
  end
84
+ @value = nil
85
+ @length = @bin.length
84
86
  end
85
87
 
86
88
  end
@@ -1,5 +1,3 @@
1
- # Copyright 2009-2010 Christoffer Lervag
2
-
3
1
  module DICOM
4
2
 
5
3
  # This class handles the construction and interpretation of network packages as well as network communication.
@@ -8,7 +6,7 @@ module DICOM
8
6
 
9
7
  # A customized FileHandler class to use instead of the default FileHandler included with Ruby DICOM.
10
8
  attr_accessor :file_handler
11
- # The maximum allowed size of network packages (in bytes).
9
+ # The maximum allowed size of network packages (in bytes).
12
10
  attr_accessor :max_package_size
13
11
  # A hash which keeps track of the relationship between context ID and chosen transfer syntax.
14
12
  attr_accessor :presentation_contexts
@@ -32,7 +30,7 @@ module DICOM
32
30
  # * <tt>:ae</tt> -- String. The name of the client (application entity).
33
31
  # * <tt>:file_handler</tt> -- A customized FileHandler class to use instead of the default FileHandler.
34
32
  # * <tt>:host_ae</tt> -- String. The name of the server (application entity).
35
- # * <tt>:max_package_size</tt> -- Fixnum. The maximum allowed size of network packages (in bytes).
33
+ # * <tt>:max_package_size</tt> -- Fixnum. The maximum allowed size of network packages (in bytes).
36
34
  # * <tt>:timeout</tt> -- Fixnum. The maximum period to wait for an answer before aborting the communication.
37
35
  # * <tt>:verbose</tt> -- Boolean. If set to false, the DLink instance will run silently and not output warnings and error messages to the screen. Defaults to true.
38
36
  #
@@ -121,17 +119,19 @@ module DICOM
121
119
  # encodes the presentation context, we pass on a one-element array containing nil).
122
120
  abstract_syntaxes = Array.new(1, nil)
123
121
  # Note: The order of which these components are built is not arbitrary.
124
- append_application_context(info[:application_context])
122
+ append_application_context
125
123
  # Reset the presentation context instance variable:
126
124
  @presentation_contexts = Hash.new
125
+ # Create the presentation context hash object that will be passed to the builder method:
126
+ p_contexts = Hash.new
127
127
  # Build the presentation context strings, one by one:
128
128
  info[:pc].each do |pc|
129
- context_id = pc[:presentation_context_id]
130
- result = pc[:result]
131
- transfer_syntax = pc[:selected_transfer_syntax]
132
- @presentation_contexts[context_id] = transfer_syntax
133
- append_presentation_contexts(abstract_syntaxes, ITEM_PRESENTATION_CONTEXT_RESPONSE, transfer_syntax, context_id, result)
129
+ @presentation_contexts[pc[:presentation_context_id]] = pc[:selected_transfer_syntax]
130
+ # Add the information from this pc item to the p_contexts hash:
131
+ p_contexts[pc[:abstract_syntax]] = Hash.new unless p_contexts[pc[:abstract_syntax]]
132
+ p_contexts[pc[:abstract_syntax]][pc[:presentation_context_id]] = {:transfer_syntaxes => [pc[:selected_transfer_syntax]], :result => pc[:result]}
134
133
  end
134
+ append_presentation_contexts(p_contexts, ITEM_PRESENTATION_CONTEXT_RESPONSE)
135
135
  append_user_information(@user_information)
136
136
  # Header must be built last, because we need to know the length of the other components.
137
137
  append_association_header(PDU_ASSOCIATION_ACCEPT, info[:called_ae])
@@ -170,20 +170,18 @@ module DICOM
170
170
  #
171
171
  # === Parameters
172
172
  #
173
- # * <tt>ac_uid</tt> -- The application context UID string.
174
- # * <tt>as</tt> -- An array of abstract syntax strings.
175
- # * <tt>ts</tt> -- An array of transfer syntax strings.
173
+ # * <tt>presentation_contexts</tt> -- A hash containing abstract_syntaxes, presentation context ids and transfer syntaxes.
176
174
  # * <tt>user_info</tt> -- A user information items array.
177
175
  #
178
- def build_association_request(ac_uid, as, ts, user_info)
176
+ def build_association_request(presentation_contexts, user_info)
179
177
  # Big endian encoding:
180
178
  @outgoing.endian = @net_endian
181
179
  # Clear the outgoing binary string:
182
180
  @outgoing.reset
183
181
  # Note: The order of which these components are built is not arbitrary.
184
182
  # (The first three are built 'in order of appearance', the header is built last, but is put first in the message)
185
- append_application_context(ac_uid)
186
- append_presentation_contexts(as, ITEM_PRESENTATION_CONTEXT_REQUEST, ts)
183
+ append_application_context
184
+ append_presentation_contexts(presentation_contexts, ITEM_PRESENTATION_CONTEXT_REQUEST, request=true)
187
185
  append_user_information(user_info)
188
186
  # Header must be built last, because we need to know the length of the other components.
189
187
  append_association_header(PDU_ASSOCIATION_REQUEST, @host_ae)
@@ -1136,19 +1134,15 @@ module DICOM
1136
1134
 
1137
1135
  # Builds the application context (which is part of the association request/response).
1138
1136
  #
1139
- # === Parameters
1140
- #
1141
- # * <tt>ac_uid</tt> -- Application context UID string.
1142
- #
1143
- def append_application_context(ac_uid)
1137
+ def append_application_context
1144
1138
  # Application context item type (1 byte)
1145
1139
  @outgoing.encode_last(ITEM_APPLICATION_CONTEXT, "HEX")
1146
1140
  # Reserved (1 byte)
1147
1141
  @outgoing.encode_last("00", "HEX")
1148
1142
  # Application context item length (2 bytes)
1149
- @outgoing.encode_last(ac_uid.length, "US")
1143
+ @outgoing.encode_last(APPLICATION_CONTEXT.length, "US")
1150
1144
  # Application context (variable length)
1151
- @outgoing.encode_last(ac_uid, "STR")
1145
+ @outgoing.encode_last(APPLICATION_CONTEXT, "STR")
1152
1146
  end
1153
1147
 
1154
1148
  # Builds the binary string that makes up the header part the association request/response.
@@ -1202,70 +1196,58 @@ module DICOM
1202
1196
  #
1203
1197
  # === Parameters
1204
1198
  #
1205
- # * <tt>abstract_syntaxes</tt> -- An array of abstract syntax strings.
1206
- # * <tt>pc</tt> -- Presentation context item (request or response).
1207
- # * <tt>ts</tt> -- An array of transfer syntax strings.
1208
- # * <tt>context_id</tt> -- The ID of the current presentation context.
1209
- # * <tt>result</tt> -- The result (accepted/refused) for the current presentation context.
1210
- #
1211
- def append_presentation_contexts(abstract_syntaxes, pc, ts, context_id=nil, result=ACCEPTANCE)
1212
- # One presentation context for each abstract syntax:
1213
- abstract_syntaxes.each_with_index do |as, index|
1214
- # PRESENTATION CONTEXT:
1215
- # Presentation context item type (1 byte)
1216
- @outgoing.encode_last(pc, "HEX")
1217
- # Reserved (1 byte)
1218
- @outgoing.encode_last("00", "HEX")
1219
- # Presentation context item length (2 bytes)
1220
- if ts.is_a?(Array)
1221
- ts_length = 4*ts.length + ts.join.length
1222
- else # (String)
1223
- ts_length = 4 + ts.length
1224
- end
1225
- if as
1226
- items_length = 4 + (4 + as.length) + ts_length
1227
- else
1199
+ # * <tt>presentation_contexts</tt> -- A nested hash object with abstract syntaxes, presentation context ids, transfer syntaxes and result codes.
1200
+ # * <tt>item_type</tt> -- Presentation context item (request or response).
1201
+ # * <tt>request</tt> -- Boolean. If true, an ossociate request message is generated, if false, an asoociate accept message is generated.
1202
+ #
1203
+ def append_presentation_contexts(presentation_contexts, item_type, request=false)
1204
+ # Iterate the abstract syntaxes:
1205
+ presentation_contexts.each_pair do |abstract_syntax, context_ids|
1206
+ # Iterate the context ids:
1207
+ context_ids.each_pair do |context_id, syntax|
1208
+ # PRESENTATION CONTEXT:
1209
+ # Presentation context item type (1 byte)
1210
+ @outgoing.encode_last(item_type, "HEX")
1211
+ # Reserved (1 byte)
1212
+ @outgoing.encode_last("00", "HEX")
1213
+ # Presentation context item length (2 bytes)
1214
+ ts_length = 4*syntax[:transfer_syntaxes].length + syntax[:transfer_syntaxes].join.length
1215
+ # Abstract syntax item only included in requests, not accepts:
1228
1216
  items_length = 4 + ts_length
1229
- end
1230
- @outgoing.encode_last(items_length, "US")
1231
- # Presentation context ID (1 byte)
1232
- # Generate a number based on the index of the abstract syntax, unless one has been supplied to this method already.
1233
- # (NB! This number should be odd, and in the range 1..255)
1234
- if context_id
1235
- presentation_context_id = context_id
1236
- else
1237
- presentation_context_id = index*2 + 1
1238
- end
1239
- @outgoing.encode_last(presentation_context_id, "BY")
1240
- # Reserved (1 byte)
1241
- @outgoing.encode_last("00", "HEX")
1242
- # (1 byte) Reserved (for association request) & Result/reason (for association accept response)
1243
- @outgoing.encode_last(result, "BY")
1244
- # Reserved (1 byte)
1245
- @outgoing.encode_last("00", "HEX")
1246
- ## ABSTRACT SYNTAX SUB-ITEM: (only for request, not response)
1247
- if as
1248
- # Abstract syntax item type (1 byte)
1249
- @outgoing.encode_last(ITEM_ABSTRACT_SYNTAX, "HEX")
1217
+ items_length += 4 + abstract_syntax.length if request
1218
+ @outgoing.encode_last(items_length, "US")
1219
+ # Presentation context ID (1 byte)
1220
+ @outgoing.encode_last(context_id, "BY")
1250
1221
  # Reserved (1 byte)
1251
1222
  @outgoing.encode_last("00", "HEX")
1252
- # Abstract syntax item length (2 bytes)
1253
- @outgoing.encode_last(as.length, "US")
1254
- # Abstract syntax (variable length)
1255
- @outgoing.encode_last(as, "STR")
1256
- end
1257
- ## TRANSFER SYNTAX SUB-ITEM (not included if result indicates error):
1258
- if result == ACCEPTANCE
1259
- ts = [ts] if ts.is_a?(String)
1260
- ts.each do |t|
1261
- # Transfer syntax item type (1 byte)
1262
- @outgoing.encode_last(ITEM_TRANSFER_SYNTAX, "HEX")
1223
+ # (1 byte) Reserved (for association request) & Result/reason (for association accept response)
1224
+ result = (syntax[:result] ? syntax[:result] : 0)
1225
+ @outgoing.encode_last(result, "BY")
1226
+ # Reserved (1 byte)
1227
+ @outgoing.encode_last("00", "HEX")
1228
+ ## ABSTRACT SYNTAX SUB-ITEM: (only for request, not response)
1229
+ if request
1230
+ # Abstract syntax item type (1 byte)
1231
+ @outgoing.encode_last(ITEM_ABSTRACT_SYNTAX, "HEX")
1263
1232
  # Reserved (1 byte)
1264
1233
  @outgoing.encode_last("00", "HEX")
1265
- # Transfer syntax item length (2 bytes)
1266
- @outgoing.encode_last(t.length, "US")
1267
- # Transfer syntax (variable length)
1268
- @outgoing.encode_last(t, "STR")
1234
+ # Abstract syntax item length (2 bytes)
1235
+ @outgoing.encode_last(abstract_syntax.length, "US")
1236
+ # Abstract syntax (variable length)
1237
+ @outgoing.encode_last(abstract_syntax, "STR")
1238
+ end
1239
+ ## TRANSFER SYNTAX SUB-ITEM (not included if result indicates error):
1240
+ if result == ACCEPTANCE
1241
+ syntax[:transfer_syntaxes].each do |t|
1242
+ # Transfer syntax item type (1 byte)
1243
+ @outgoing.encode_last(ITEM_TRANSFER_SYNTAX, "HEX")
1244
+ # Reserved (1 byte)
1245
+ @outgoing.encode_last("00", "HEX")
1246
+ # Transfer syntax item length (2 bytes)
1247
+ @outgoing.encode_last(t.length, "US")
1248
+ # Transfer syntax (variable length)
1249
+ @outgoing.encode_last(t, "STR")
1250
+ end
1269
1251
  end
1270
1252
  end
1271
1253
  end