dicom 0.9.4 → 0.9.5
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.
- checksums.yaml +7 -0
 - data/CHANGELOG.rdoc +44 -0
 - data/CONTRIBUTING.rdoc +83 -0
 - data/README.rdoc +3 -2
 - data/dicom.gemspec +12 -13
 - data/lib/dicom/anonymizer.rb +649 -670
 - data/lib/dicom/audit_trail.rb +7 -0
 - data/lib/dicom/constants.rb +1 -1
 - data/lib/dicom/d_library.rb +46 -31
 - data/lib/dicom/d_object.rb +38 -24
 - data/lib/dicom/d_read.rb +20 -6
 - data/lib/dicom/d_server.rb +3 -3
 - data/lib/dicom/d_write.rb +7 -2
 - data/lib/dicom/deprecated.rb +318 -0
 - data/lib/dicom/image_item.rb +62 -42
 - data/lib/dicom/image_processor.rb +2 -2
 - data/lib/dicom/image_processor_mini_magick.rb +6 -6
 - data/lib/dicom/image_processor_r_magick.rb +6 -6
 - data/lib/dicom/link.rb +7 -11
 - data/lib/dicom/logging.rb +2 -1
 - data/lib/dicom/variables.rb +36 -1
 - data/lib/dicom/version.rb +1 -1
 - data/rakefile.rb +3 -1
 - metadata +46 -63
 
    
        data/lib/dicom/image_item.rb
    CHANGED
    
    | 
         @@ -14,6 +14,27 @@ module DICOM 
     | 
|
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         
             
                include ImageProcessor
         
     | 
| 
       16 
16 
     | 
    
         | 
| 
      
 17 
     | 
    
         
            +
                # Creates an Element with the given arguments and connects it to self.
         
     | 
| 
      
 18 
     | 
    
         
            +
                #
         
     | 
| 
      
 19 
     | 
    
         
            +
                # @param [String] tag an element tag
         
     | 
| 
      
 20 
     | 
    
         
            +
                # @param [String, Integer, Float, Array, NilClass] value an element value
         
     | 
| 
      
 21 
     | 
    
         
            +
                # @param [Hash] options any options used for creating the element (see Element.new documentation)
         
     | 
| 
      
 22 
     | 
    
         
            +
                #
         
     | 
| 
      
 23 
     | 
    
         
            +
                def add_element(tag, value, options={})
         
     | 
| 
      
 24 
     | 
    
         
            +
                  add(e = Element.new(tag, value, options))
         
     | 
| 
      
 25 
     | 
    
         
            +
                  e
         
     | 
| 
      
 26 
     | 
    
         
            +
                end
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                # Creates a Sequence with the given arguments and connects it to self.
         
     | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # @param [String] tag a sequence tag
         
     | 
| 
      
 31 
     | 
    
         
            +
                # @param [Hash] options any options used for creating the sequence (see Sequence.new documentation)
         
     | 
| 
      
 32 
     | 
    
         
            +
                #
         
     | 
| 
      
 33 
     | 
    
         
            +
                def add_sequence(tag, options={})
         
     | 
| 
      
 34 
     | 
    
         
            +
                  add(s = Sequence.new(tag, options))
         
     | 
| 
      
 35 
     | 
    
         
            +
                  s
         
     | 
| 
      
 36 
     | 
    
         
            +
                end
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       17 
38 
     | 
    
         
             
                # Checks if colored pixel data is present.
         
     | 
| 
       18 
39 
     | 
    
         
             
                #
         
     | 
| 
       19 
40 
     | 
    
         
             
                # @return [Boolean] true if the object contains colored pixels, and false if not
         
     | 
| 
         @@ -22,7 +43,7 @@ module DICOM 
     | 
|
| 
       22 
43 
     | 
    
         
             
                  # "Photometric Interpretation" is contained in the data element "0028,0004":
         
     | 
| 
       23 
44 
     | 
    
         
             
                  begin
         
     | 
| 
       24 
45 
     | 
    
         
             
                    photometric = photometry
         
     | 
| 
       25 
     | 
    
         
            -
                    if photometric.include?( 
     | 
| 
      
 46 
     | 
    
         
            +
                    if photometric.include?('COLOR') or photometric.include?('RGB') or photometric.include?('YBR')
         
     | 
| 
       26 
47 
     | 
    
         
             
                      return true
         
     | 
| 
       27 
48 
     | 
    
         
             
                    else
         
     | 
| 
       28 
49 
     | 
    
         
             
                      return false
         
     | 
| 
         @@ -56,8 +77,8 @@ module DICOM 
     | 
|
| 
       56 
77 
     | 
    
         
             
                  raise ArgumentError, "Expected String, got #{bin.class}." unless bin.is_a?(String)
         
     | 
| 
       57 
78 
     | 
    
         
             
                  pixels = false
         
     | 
| 
       58 
79 
     | 
    
         
             
                  # We need to know what kind of bith depth and integer type the pixel data is saved with:
         
     | 
| 
       59 
     | 
    
         
            -
                  bit_depth_element = self[ 
     | 
| 
       60 
     | 
    
         
            -
                  pixel_representation_element = self[ 
     | 
| 
      
 80 
     | 
    
         
            +
                  bit_depth_element = self['0028,0100']
         
     | 
| 
      
 81 
     | 
    
         
            +
                  pixel_representation_element = self['0028,0103']
         
     | 
| 
       61 
82 
     | 
    
         
             
                  if bit_depth_element and pixel_representation_element
         
     | 
| 
       62 
83 
     | 
    
         
             
                    # Load the binary pixel data to the Stream instance:
         
     | 
| 
       63 
84 
     | 
    
         
             
                    stream.set_string(bin)
         
     | 
| 
         @@ -81,8 +102,8 @@ module DICOM 
     | 
|
| 
       81 
102 
     | 
    
         
             
                  raise ArgumentError, "Expected Array, got #{pixels.class}." unless pixels.is_a?(Array)
         
     | 
| 
       82 
103 
     | 
    
         
             
                  bin = false
         
     | 
| 
       83 
104 
     | 
    
         
             
                  # We need to know what kind of bith depth and integer type the pixel data is saved with:
         
     | 
| 
       84 
     | 
    
         
            -
                  bit_depth_element = self[ 
     | 
| 
       85 
     | 
    
         
            -
                  pixel_representation_element = self[ 
     | 
| 
      
 105 
     | 
    
         
            +
                  bit_depth_element = self['0028,0100']
         
     | 
| 
      
 106 
     | 
    
         
            +
                  pixel_representation_element = self['0028,0103']
         
     | 
| 
       86 
107 
     | 
    
         
             
                  if bit_depth_element and pixel_representation_element
         
     | 
| 
       87 
108 
     | 
    
         
             
                    template = template_string(bit_depth_element.value.to_i)
         
     | 
| 
       88 
109 
     | 
    
         
             
                    bin = stream.encode(pixels, template) if template
         
     | 
| 
         @@ -187,7 +208,7 @@ module DICOM 
     | 
|
| 
       187 
208 
     | 
    
         
             
                #
         
     | 
| 
       188 
209 
     | 
    
         
             
                def image_from_file(file)
         
     | 
| 
       189 
210 
     | 
    
         
             
                  raise ArgumentError, "Expected #{String}, got #{file.class}." unless file.is_a?(String)
         
     | 
| 
       190 
     | 
    
         
            -
                  f = File.new(file,  
     | 
| 
      
 211 
     | 
    
         
            +
                  f = File.new(file, 'rb')
         
     | 
| 
       191 
212 
     | 
    
         
             
                  bin = f.read(f.stat.size)
         
     | 
| 
       192 
213 
     | 
    
         
             
                  if bin.length > 0
         
     | 
| 
       193 
214 
     | 
    
         
             
                    # Write the binary data to the Pixel Data Element:
         
     | 
| 
         @@ -235,18 +256,18 @@ module DICOM 
     | 
|
| 
       235 
256 
     | 
    
         
             
                  parts = file.split('.')
         
     | 
| 
       236 
257 
     | 
    
         
             
                  if parts.length > 1
         
     | 
| 
       237 
258 
     | 
    
         
             
                    base = parts[0..-2].join
         
     | 
| 
       238 
     | 
    
         
            -
                    extension =  
     | 
| 
      
 259 
     | 
    
         
            +
                    extension = '.' + parts.last
         
     | 
| 
       239 
260 
     | 
    
         
             
                  else
         
     | 
| 
       240 
261 
     | 
    
         
             
                    base = file
         
     | 
| 
       241 
     | 
    
         
            -
                    extension =  
     | 
| 
      
 262 
     | 
    
         
            +
                    extension = ''
         
     | 
| 
       242 
263 
     | 
    
         
             
                  end
         
     | 
| 
       243 
264 
     | 
    
         
             
                  # Get the binary image strings and dump them to the file(s):
         
     | 
| 
       244 
265 
     | 
    
         
             
                  images = image_strings
         
     | 
| 
       245 
266 
     | 
    
         
             
                  images.each_index do |i|
         
     | 
| 
       246 
267 
     | 
    
         
             
                    if images.length == 1
         
     | 
| 
       247 
     | 
    
         
            -
                      f = File.new(file,  
     | 
| 
      
 268 
     | 
    
         
            +
                      f = File.new(file, 'wb')
         
     | 
| 
       248 
269 
     | 
    
         
             
                    else
         
     | 
| 
       249 
     | 
    
         
            -
                      f = File.new("#{base}-#{i}#{extension}",  
     | 
| 
      
 270 
     | 
    
         
            +
                      f = File.new("#{base}-#{i}#{extension}", 'wb')
         
     | 
| 
       250 
271 
     | 
    
         
             
                    end
         
     | 
| 
       251 
272 
     | 
    
         
             
                    f.write(images[i])
         
     | 
| 
       252 
273 
     | 
    
         
             
                    f.close
         
     | 
| 
         @@ -265,7 +286,7 @@ module DICOM 
     | 
|
| 
       265 
286 
     | 
    
         
             
                # @param [MagickImage] image the image to be assigned to the pixel data element
         
     | 
| 
       266 
287 
     | 
    
         
             
                #
         
     | 
| 
       267 
288 
     | 
    
         
             
                def image=(image)
         
     | 
| 
       268 
     | 
    
         
            -
                  raise ArgumentError, "Expected one of the supported image  
     | 
| 
      
 289 
     | 
    
         
            +
                  raise ArgumentError, "Expected one of the supported image classes: #{valid_image_objects} (got #{image.class})" unless valid_image_objects.include?(image.class.to_s)
         
     | 
| 
       269 
290 
     | 
    
         
             
                  # Export to pixels using the proper image processor:
         
     | 
| 
       270 
291 
     | 
    
         
             
                  pixels = export_pixels(image, photometry)
         
     | 
| 
       271 
292 
     | 
    
         
             
                  # Encode and write to the Pixel Data Element:
         
     | 
| 
         @@ -277,7 +298,7 @@ module DICOM 
     | 
|
| 
       277 
298 
     | 
    
         
             
                # @return [Integer, NilClass] the number of columns, or nil (if the columns value is undefined)
         
     | 
| 
       278 
299 
     | 
    
         
             
                #
         
     | 
| 
       279 
300 
     | 
    
         
             
                def num_cols
         
     | 
| 
       280 
     | 
    
         
            -
                  self[ 
     | 
| 
      
 301 
     | 
    
         
            +
                  self['0028,0011'].value rescue nil
         
     | 
| 
       281 
302 
     | 
    
         
             
                end
         
     | 
| 
       282 
303 
     | 
    
         | 
| 
       283 
304 
     | 
    
         
             
                # Gives the number of frames in the pixel data.
         
     | 
| 
         @@ -286,7 +307,7 @@ module DICOM 
     | 
|
| 
       286 
307 
     | 
    
         
             
                # @return [Integer] the number of rows
         
     | 
| 
       287 
308 
     | 
    
         
             
                #
         
     | 
| 
       288 
309 
     | 
    
         
             
                def num_frames
         
     | 
| 
       289 
     | 
    
         
            -
                  (self[ 
     | 
| 
      
 310 
     | 
    
         
            +
                  (self['0028,0008'].is_a?(Element) == true ? self['0028,0008'].value.to_i : 1)
         
     | 
| 
       290 
311 
     | 
    
         
             
                end
         
     | 
| 
       291 
312 
     | 
    
         | 
| 
       292 
313 
     | 
    
         
             
                # Gives the number of rows in the pixel data.
         
     | 
| 
         @@ -294,7 +315,7 @@ module DICOM 
     | 
|
| 
       294 
315 
     | 
    
         
             
                # @return [Integer, NilClass] the number of rows, or nil (if the rows value is undefined)
         
     | 
| 
       295 
316 
     | 
    
         
             
                #
         
     | 
| 
       296 
317 
     | 
    
         
             
                def num_rows
         
     | 
| 
       297 
     | 
    
         
            -
                  self[ 
     | 
| 
      
 318 
     | 
    
         
            +
                  self['0028,0010'].value rescue nil
         
     | 
| 
       298 
319 
     | 
    
         
             
                end
         
     | 
| 
       299 
320 
     | 
    
         | 
| 
       300 
321 
     | 
    
         
             
                # Creates an NArray containing the pixel data. If the pixel data is an image
         
     | 
| 
         @@ -402,22 +423,21 @@ module DICOM 
     | 
|
| 
       402 
423 
     | 
    
         
             
                # @param [Array<Integer>, NArray] values an Array (or NArray) containing integer pixel values
         
     | 
| 
       403 
424 
     | 
    
         
             
                #
         
     | 
| 
       404 
425 
     | 
    
         
             
                def pixels=(values)
         
     | 
| 
       405 
     | 
    
         
            -
                  raise ArgumentError, " 
     | 
| 
       406 
     | 
    
         
            -
                  if values. 
     | 
| 
       407 
     | 
    
         
            -
                    #  
     | 
| 
      
 426 
     | 
    
         
            +
                  raise ArgumentError, "The given argument does not respond to #to_a (got an argument of class #{values.class})" unless values.respond_to?(:to_a)
         
     | 
| 
      
 427 
     | 
    
         
            +
                  if values.class.ancestors.to_s.include?('NArray')
         
     | 
| 
      
 428 
     | 
    
         
            +
                    # With an NArray argument, make sure that it gets properly converted to an Array:
         
     | 
| 
       408 
429 
     | 
    
         
             
                    if values.shape.length > 2
         
     | 
| 
       409 
     | 
    
         
            -
                      #  
     | 
| 
      
 430 
     | 
    
         
            +
                      # For a 3D NArray we need to rearrange to ensure that the pixels get their
         
     | 
| 
      
 431 
     | 
    
         
            +
                      # proper order when converting to an ordinary Array instance:
         
     | 
| 
       410 
432 
     | 
    
         
             
                      narr = NArray.int(values.shape[1] * values.shape[2], values.shape[0])
         
     | 
| 
       411 
433 
     | 
    
         
             
                      values.shape[0].times do |i|
         
     | 
| 
       412 
434 
     | 
    
         
             
                        narr[true, i] = values[i, true, true].reshape(values.shape[1] * values.shape[2])
         
     | 
| 
       413 
435 
     | 
    
         
             
                      end
         
     | 
| 
       414 
     | 
    
         
            -
                      values = narr 
     | 
| 
       415 
     | 
    
         
            -
                    else
         
     | 
| 
       416 
     | 
    
         
            -
                      values = values.to_a
         
     | 
| 
      
 436 
     | 
    
         
            +
                      values = narr
         
     | 
| 
       417 
437 
     | 
    
         
             
                    end
         
     | 
| 
       418 
438 
     | 
    
         
             
                  end
         
     | 
| 
       419 
439 
     | 
    
         
             
                  # Encode the pixel data:
         
     | 
| 
       420 
     | 
    
         
            -
                  bin = encode_pixels(values.flatten)
         
     | 
| 
      
 440 
     | 
    
         
            +
                  bin = encode_pixels(values.to_a.flatten)
         
     | 
| 
       421 
441 
     | 
    
         
             
                  # Write the binary data to the Pixel Data Element:
         
     | 
| 
       422 
442 
     | 
    
         
             
                  write_pixels(bin)
         
     | 
| 
       423 
443 
     | 
    
         
             
                end
         
     | 
| 
         @@ -444,7 +464,7 @@ module DICOM 
     | 
|
| 
       444 
464 
     | 
    
         
             
                  raise "The 'Bits Allocated' Element is missing from this DICOM instance. Unable to encode/decode pixel data." unless exists?("0028,0100")
         
     | 
| 
       445 
465 
     | 
    
         
             
                  if photometry == PI_PALETTE_COLOR
         
     | 
| 
       446 
466 
     | 
    
         
             
                  # Only one channel is checked and it is assumed that all channels have the same number of bits.
         
     | 
| 
       447 
     | 
    
         
            -
                    return self[ 
     | 
| 
      
 467 
     | 
    
         
            +
                    return self['0028,1101'].value.split("\\").last.to_i
         
     | 
| 
       448 
468 
     | 
    
         
             
                  else
         
     | 
| 
       449 
469 
     | 
    
         
             
                    return bit_depth
         
     | 
| 
       450 
470 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -458,7 +478,7 @@ module DICOM 
     | 
|
| 
       458 
478 
     | 
    
         
             
                #
         
     | 
| 
       459 
479 
     | 
    
         
             
                def bit_depth
         
     | 
| 
       460 
480 
     | 
    
         
             
                  raise "The 'Bits Allocated' Element is missing from this DICOM instance. Unable to encode/decode pixel data." unless exists?("0028,0100")
         
     | 
| 
       461 
     | 
    
         
            -
                  return value( 
     | 
| 
      
 481 
     | 
    
         
            +
                  return value('0028,0100')
         
     | 
| 
       462 
482 
     | 
    
         
             
                end
         
     | 
| 
       463 
483 
     | 
    
         | 
| 
       464 
484 
     | 
    
         
             
                # Performs a run length decoding on the input stream.
         
     | 
| 
         @@ -524,7 +544,7 @@ module DICOM 
     | 
|
| 
       524 
544 
     | 
    
         
             
                #
         
     | 
| 
       525 
545 
     | 
    
         
             
                def photometry
         
     | 
| 
       526 
546 
     | 
    
         
             
                  raise "The 'Photometric Interpretation' Element is missing from this DICOM instance. Unable to encode/decode pixel data." unless exists?("0028,0004")
         
     | 
| 
       527 
     | 
    
         
            -
                  return value( 
     | 
| 
      
 547 
     | 
    
         
            +
                  return value('0028,0004').upcase
         
     | 
| 
       528 
548 
     | 
    
         
             
                end
         
     | 
| 
       529 
549 
     | 
    
         | 
| 
       530 
550 
     | 
    
         
             
                # Processes the pixel array based on attributes defined in the DICOM object,
         
     | 
| 
         @@ -539,16 +559,16 @@ module DICOM 
     | 
|
| 
       539 
559 
     | 
    
         
             
                  proper_rgb = false
         
     | 
| 
       540 
560 
     | 
    
         
             
                  photometric = photometry()
         
     | 
| 
       541 
561 
     | 
    
         
             
                  # (With RLE COLOR PALETTE the Planar Configuration is not set)
         
     | 
| 
       542 
     | 
    
         
            -
                  planar = self[ 
     | 
| 
      
 562 
     | 
    
         
            +
                  planar = self['0028,0006'].is_a?(Element) ? self['0028,0006'].value : 0
         
     | 
| 
       543 
563 
     | 
    
         
             
                  # Step 1: Produce an array with RGB values. At this time, YBR is not supported in ruby-dicom,
         
     | 
| 
       544 
564 
     | 
    
         
             
                  # so this leaves us with a possible conversion from PALETTE COLOR:
         
     | 
| 
       545 
     | 
    
         
            -
                  if photometric.include?( 
     | 
| 
      
 565 
     | 
    
         
            +
                  if photometric.include?('COLOR')
         
     | 
| 
       546 
566 
     | 
    
         
             
                    # Pseudo colors (rgb values grabbed from a lookup table):
         
     | 
| 
       547 
567 
     | 
    
         
             
                    rgb = Array.new(pixels.length*3)
         
     | 
| 
       548 
568 
     | 
    
         
             
                    # Prepare the lookup data arrays:
         
     | 
| 
       549 
     | 
    
         
            -
                    lookup_binaries = [self[ 
     | 
| 
      
 569 
     | 
    
         
            +
                    lookup_binaries = [self['0028,1201'].bin, self['0028,1202'].bin, self['0028,1203'].bin]
         
     | 
| 
       550 
570 
     | 
    
         
             
                    lookup_values = Array.new
         
     | 
| 
       551 
     | 
    
         
            -
                    nr_bits = self[ 
     | 
| 
      
 571 
     | 
    
         
            +
                    nr_bits = self['0028,1101'].value.split("\\").last.to_i
         
     | 
| 
       552 
572 
     | 
    
         
             
                    template = template_string(nr_bits)
         
     | 
| 
       553 
573 
     | 
    
         
             
                    lookup_binaries.each do |bin|
         
     | 
| 
       554 
574 
     | 
    
         
             
                      stream.set_string(bin)
         
     | 
| 
         @@ -561,7 +581,7 @@ module DICOM 
     | 
|
| 
       561 
581 
     | 
    
         
             
                    end
         
     | 
| 
       562 
582 
     | 
    
         
             
                    # As we have now ordered the pixels in RGB order, modify planar configuration to reflect this:
         
     | 
| 
       563 
583 
     | 
    
         
             
                    planar = 0
         
     | 
| 
       564 
     | 
    
         
            -
                  elsif photometric.include?( 
     | 
| 
      
 584 
     | 
    
         
            +
                  elsif photometric.include?('YBR')
         
     | 
| 
       565 
585 
     | 
    
         
             
                    rgb = false
         
     | 
| 
       566 
586 
     | 
    
         
             
                  else
         
     | 
| 
       567 
587 
     | 
    
         
             
                    rgb = pixels
         
     | 
| 
         @@ -739,13 +759,13 @@ module DICOM 
     | 
|
| 
       739 
759 
     | 
    
         
             
                #
         
     | 
| 
       740 
760 
     | 
    
         
             
                def signed_pixels?
         
     | 
| 
       741 
761 
     | 
    
         
             
                  raise "The 'Pixel Representation' data element is missing from this DICOM instance. Unable to process pixel data." unless exists?("0028,0103")
         
     | 
| 
       742 
     | 
    
         
            -
                  case value( 
     | 
| 
      
 762 
     | 
    
         
            +
                  case value('0028,0103')
         
     | 
| 
       743 
763 
     | 
    
         
             
                  when 1
         
     | 
| 
       744 
764 
     | 
    
         
             
                    return true
         
     | 
| 
       745 
765 
     | 
    
         
             
                  when 0
         
     | 
| 
       746 
766 
     | 
    
         
             
                    return false
         
     | 
| 
       747 
767 
     | 
    
         
             
                  else
         
     | 
| 
       748 
     | 
    
         
            -
                    raise "Invalid value encountered (#{value( 
     | 
| 
      
 768 
     | 
    
         
            +
                    raise "Invalid value encountered (#{value('0028,0103')}) in the 'Pixel Representation' data element. Expected 0 or 1."
         
     | 
| 
       749 
769 
     | 
    
         
             
                  end
         
     | 
| 
       750 
770 
     | 
    
         
             
                end
         
     | 
| 
       751 
771 
     | 
    
         | 
| 
         @@ -757,22 +777,22 @@ module DICOM 
     | 
|
| 
       757 
777 
     | 
    
         
             
                #
         
     | 
| 
       758 
778 
     | 
    
         
             
                def template_string(depth)
         
     | 
| 
       759 
779 
     | 
    
         
             
                  template = false
         
     | 
| 
       760 
     | 
    
         
            -
                  pixel_representation = self[ 
     | 
| 
      
 780 
     | 
    
         
            +
                  pixel_representation = self['0028,0103'].value.to_i
         
     | 
| 
       761 
781 
     | 
    
         
             
                  # Number of bytes used per pixel will determine how to unpack this:
         
     | 
| 
       762 
782 
     | 
    
         
             
                  case depth
         
     | 
| 
       763 
783 
     | 
    
         
             
                  when 8 # (1 byte)
         
     | 
| 
       764 
     | 
    
         
            -
                    template =  
     | 
| 
      
 784 
     | 
    
         
            +
                    template = 'BY' # Byte/Character/Fixnum
         
     | 
| 
       765 
785 
     | 
    
         
             
                  when 16 # (2 bytes)
         
     | 
| 
       766 
786 
     | 
    
         
             
                    if pixel_representation == 1
         
     | 
| 
       767 
     | 
    
         
            -
                     template =  
     | 
| 
      
 787 
     | 
    
         
            +
                     template = 'SS' # Signed short
         
     | 
| 
       768 
788 
     | 
    
         
             
                    else
         
     | 
| 
       769 
     | 
    
         
            -
                      template =  
     | 
| 
      
 789 
     | 
    
         
            +
                      template = 'US' # Unsigned short
         
     | 
| 
       770 
790 
     | 
    
         
             
                    end
         
     | 
| 
       771 
791 
     | 
    
         
             
                  when 32 # (4 bytes)
         
     | 
| 
       772 
792 
     | 
    
         
             
                    if pixel_representation == 1
         
     | 
| 
       773 
     | 
    
         
            -
                      template =  
     | 
| 
      
 793 
     | 
    
         
            +
                      template = 'SL' # Signed long
         
     | 
| 
       774 
794 
     | 
    
         
             
                    else
         
     | 
| 
       775 
     | 
    
         
            -
                      template =  
     | 
| 
      
 795 
     | 
    
         
            +
                      template = 'UL' # Unsigned long
         
     | 
| 
       776 
796 
     | 
    
         
             
                    end
         
     | 
| 
       777 
797 
     | 
    
         
             
                  when 12
         
     | 
| 
       778 
798 
     | 
    
         
             
                    # 12 BIT SIMPLY NOT IMPLEMENTED YET!
         
     | 
| 
         @@ -793,10 +813,10 @@ module DICOM 
     | 
|
| 
       793 
813 
     | 
    
         
             
                # @return [Array<Integer, NilClass>] center, width, intercept and slope
         
     | 
| 
       794 
814 
     | 
    
         
             
                #
         
     | 
| 
       795 
815 
     | 
    
         
             
                def window_level_values
         
     | 
| 
       796 
     | 
    
         
            -
                  center = (self[ 
     | 
| 
       797 
     | 
    
         
            -
                  width = (self[ 
     | 
| 
       798 
     | 
    
         
            -
                  intercept = (self[ 
     | 
| 
       799 
     | 
    
         
            -
                  slope = (self[ 
     | 
| 
      
 816 
     | 
    
         
            +
                  center = (self['0028,1050'].is_a?(Element) == true ? self['0028,1050'].value.to_i : nil)
         
     | 
| 
      
 817 
     | 
    
         
            +
                  width = (self['0028,1051'].is_a?(Element) == true ? self['0028,1051'].value.to_i : nil)
         
     | 
| 
      
 818 
     | 
    
         
            +
                  intercept = (self['0028,1052'].is_a?(Element) == true ? self['0028,1052'].value.to_i : 0)
         
     | 
| 
      
 819 
     | 
    
         
            +
                  slope = (self['0028,1053'].is_a?(Element) == true ? self['0028,1053'].value.to_i : 1)
         
     | 
| 
       800 
820 
     | 
    
         
             
                  return center, width, intercept, slope
         
     | 
| 
       801 
821 
     | 
    
         
             
                end
         
     | 
| 
       802 
822 
     | 
    
         | 
| 
         @@ -47,10 +47,10 @@ module DICOM 
     | 
|
| 
       47 
47 
     | 
    
         | 
| 
       48 
48 
     | 
    
         
             
                # Gives an array containing the image objects that are supported by the image processor.
         
     | 
| 
       49 
49 
     | 
    
         
             
                #
         
     | 
| 
       50 
     | 
    
         
            -
                # @return [Array] the valid image classes
         
     | 
| 
      
 50 
     | 
    
         
            +
                # @return [Array<String>] the valid image classes
         
     | 
| 
       51 
51 
     | 
    
         
             
                #
         
     | 
| 
       52 
52 
     | 
    
         
             
                def valid_image_objects
         
     | 
| 
       53 
     | 
    
         
            -
                  return [Magick::Image, MiniMagick::Image]
         
     | 
| 
      
 53 
     | 
    
         
            +
                  return ['Magick::Image', 'MiniMagick::Image']
         
     | 
| 
       54 
54 
     | 
    
         
             
                end
         
     | 
| 
       55 
55 
     | 
    
         | 
| 
       56 
56 
     | 
    
         | 
| 
         @@ -45,7 +45,7 @@ module DICOM 
     | 
|
| 
       45 
45 
     | 
    
         
             
                    # @param [String] format the image format to use
         
     | 
| 
       46 
46 
     | 
    
         
             
                    # @return [Magick::Image] a mini_magick image object
         
     | 
| 
       47 
47 
     | 
    
         
             
                    #
         
     | 
| 
       48 
     | 
    
         
            -
                    def import_pixels(blob, columns, rows, depth, photometry, format= 
     | 
| 
      
 48 
     | 
    
         
            +
                    def import_pixels(blob, columns, rows, depth, photometry, format='png')
         
     | 
| 
       49 
49 
     | 
    
         
             
                      image = MiniMagick::Image.import_pixels(blob, columns, rows, depth, im_map(photometry), format)
         
     | 
| 
       50 
50 
     | 
    
         
             
                    end
         
     | 
| 
       51 
51 
     | 
    
         | 
| 
         @@ -56,12 +56,12 @@ module DICOM 
     | 
|
| 
       56 
56 
     | 
    
         
             
                    #
         
     | 
| 
       57 
57 
     | 
    
         
             
                    def im_map(photometry)
         
     | 
| 
       58 
58 
     | 
    
         
             
                      raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
         
     | 
| 
       59 
     | 
    
         
            -
                      if photometry.include?( 
     | 
| 
       60 
     | 
    
         
            -
                        return  
     | 
| 
       61 
     | 
    
         
            -
                      elsif photometry.include?( 
     | 
| 
       62 
     | 
    
         
            -
                        return  
     | 
| 
      
 59 
     | 
    
         
            +
                      if photometry.include?('COLOR') or photometry.include?('RGB')
         
     | 
| 
      
 60 
     | 
    
         
            +
                        return 'rgb'
         
     | 
| 
      
 61 
     | 
    
         
            +
                      elsif photometry.include?('YBR')
         
     | 
| 
      
 62 
     | 
    
         
            +
                        return 'ybr'
         
     | 
| 
       63 
63 
     | 
    
         
             
                      else
         
     | 
| 
       64 
     | 
    
         
            -
                        return  
     | 
| 
      
 64 
     | 
    
         
            +
                        return 'gray' # (Assuming monochromeX - greyscale)
         
     | 
| 
       65 
65 
     | 
    
         
             
                      end
         
     | 
| 
       66 
66 
     | 
    
         
             
                    end
         
     | 
| 
       67 
67 
     | 
    
         | 
| 
         @@ -63,7 +63,7 @@ module DICOM 
     | 
|
| 
       63 
63 
     | 
    
         
             
                    # @param [String] format the image format to use
         
     | 
| 
       64 
64 
     | 
    
         
             
                    # @return [Magick::Image] an RMagick image object
         
     | 
| 
       65 
65 
     | 
    
         
             
                    #
         
     | 
| 
       66 
     | 
    
         
            -
                    def import_pixels(blob, columns, rows, depth, photometry, format= 
     | 
| 
      
 66 
     | 
    
         
            +
                    def import_pixels(blob, columns, rows, depth, photometry, format='png')
         
     | 
| 
       67 
67 
     | 
    
         
             
                      image = Magick::Image.new(columns,rows).import_pixels(0, 0, columns, rows, rm_map(photometry), blob, rm_data_type(depth))
         
     | 
| 
       68 
68 
     | 
    
         
             
                    end
         
     | 
| 
       69 
69 
     | 
    
         | 
| 
         @@ -91,12 +91,12 @@ module DICOM 
     | 
|
| 
       91 
91 
     | 
    
         
             
                    #
         
     | 
| 
       92 
92 
     | 
    
         
             
                    def rm_map(photometry)
         
     | 
| 
       93 
93 
     | 
    
         
             
                      raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
         
     | 
| 
       94 
     | 
    
         
            -
                      if photometry.include?( 
     | 
| 
       95 
     | 
    
         
            -
                        return  
     | 
| 
       96 
     | 
    
         
            -
                      elsif photometry.include?( 
     | 
| 
       97 
     | 
    
         
            -
                        return  
     | 
| 
      
 94 
     | 
    
         
            +
                      if photometry.include?('COLOR') or photometry.include?('RGB')
         
     | 
| 
      
 95 
     | 
    
         
            +
                        return 'RGB'
         
     | 
| 
      
 96 
     | 
    
         
            +
                      elsif photometry.include?('YBR')
         
     | 
| 
      
 97 
     | 
    
         
            +
                        return 'YBR'
         
     | 
| 
       98 
98 
     | 
    
         
             
                      else
         
     | 
| 
       99 
     | 
    
         
            -
                        return  
     | 
| 
      
 99 
     | 
    
         
            +
                        return 'I' # (Assuming monochromeX - greyscale)
         
     | 
| 
       100 
100 
     | 
    
         
             
                      end
         
     | 
| 
       101 
101 
     | 
    
         
             
                    end
         
     | 
| 
       102 
102 
     | 
    
         | 
    
        data/lib/dicom/link.rb
    CHANGED
    
    | 
         @@ -1415,7 +1415,7 @@ module DICOM 
     | 
|
| 
       1415 
1415 
     | 
    
         
             
                    # Convert the variable to an empty string.
         
     | 
| 
       1416 
1416 
     | 
    
         
             
                    data = ""
         
     | 
| 
       1417 
1417 
     | 
    
         
             
                  end
         
     | 
| 
       1418 
     | 
    
         
            -
                   
     | 
| 
      
 1418 
     | 
    
         
            +
                  data
         
     | 
| 
       1419 
1419 
     | 
    
         
             
                end
         
     | 
| 
       1420 
1420 
     | 
    
         | 
| 
       1421 
1421 
     | 
    
         
             
                # Receives the data from an incoming network transmission.
         
     | 
| 
         @@ -1423,17 +1423,13 @@ module DICOM 
     | 
|
| 
       1423 
1423 
     | 
    
         
             
                #
         
     | 
| 
       1424 
1424 
     | 
    
         
             
                def receive_transmission_data
         
     | 
| 
       1425 
1425 
     | 
    
         
             
                  data = false
         
     | 
| 
       1426 
     | 
    
         
            -
                   
     | 
| 
       1427 
     | 
    
         
            -
                   
     | 
| 
       1428 
     | 
    
         
            -
             
     | 
| 
       1429 
     | 
    
         
            -
                   
     | 
| 
       1430 
     | 
    
         
            -
                     
     | 
| 
       1431 
     | 
    
         
            -
                      Thread.kill(thr)
         
     | 
| 
       1432 
     | 
    
         
            -
                      logger.error("No answer was received within the specified timeout period. Aborting.")
         
     | 
| 
       1433 
     | 
    
         
            -
                      stop_receiving
         
     | 
| 
       1434 
     | 
    
         
            -
                    end
         
     | 
| 
      
 1426 
     | 
    
         
            +
                  response = IO.select([@session], nil, nil, @timeout)
         
     | 
| 
      
 1427 
     | 
    
         
            +
                  if response.nil?
         
     | 
| 
      
 1428 
     | 
    
         
            +
                    logger.error("No answer was received within the specified timeout period. Aborting.")
         
     | 
| 
      
 1429 
     | 
    
         
            +
                  else
         
     | 
| 
      
 1430 
     | 
    
         
            +
                    data = @session.recv(@max_receive_size)
         
     | 
| 
       1435 
1431 
     | 
    
         
             
                  end
         
     | 
| 
       1436 
     | 
    
         
            -
                   
     | 
| 
      
 1432 
     | 
    
         
            +
                  data
         
     | 
| 
       1437 
1433 
     | 
    
         
             
                end
         
     | 
| 
       1438 
1434 
     | 
    
         | 
| 
       1439 
1435 
     | 
    
         
             
                # Sets some default values related to encoding.
         
     | 
    
        data/lib/dicom/logging.rb
    CHANGED
    
    | 
         @@ -122,6 +122,7 @@ module DICOM 
     | 
|
| 
       122 
122 
     | 
    
         
             
                  end
         
     | 
| 
       123 
123 
     | 
    
         | 
| 
       124 
124 
     | 
    
         
             
                  # The logger object setter.
         
     | 
| 
      
 125 
     | 
    
         
            +
                  #
         
     | 
| 
       125 
126 
     | 
    
         
             
                  # This method is used to replace the default logger instance with
         
     | 
| 
       126 
127 
     | 
    
         
             
                  # a custom logger of your own.
         
     | 
| 
       127 
128 
     | 
    
         
             
                  #
         
     | 
| 
         @@ -152,4 +153,4 @@ module DICOM 
     | 
|
| 
       152 
153 
     | 
    
         
             
              # Include the Logging module so we can use DICOM.logger.
         
     | 
| 
       153 
154 
     | 
    
         
             
              include Logging
         
     | 
| 
       154 
155 
     | 
    
         | 
| 
       155 
     | 
    
         
            -
            end
         
     | 
| 
      
 156 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/dicom/variables.rb
    CHANGED
    
    | 
         @@ -36,6 +36,41 @@ module DICOM 
     | 
|
| 
       36 
36 
     | 
    
         
             
                  return uid
         
     | 
| 
       37 
37 
     | 
    
         
             
                end
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
      
 39 
     | 
    
         
            +
                # Loads DICOM data to DObject instances and returns them in an array.
         
     | 
| 
      
 40 
     | 
    
         
            +
                # Invalid DICOM sources (files) are ignored.
         
     | 
| 
      
 41 
     | 
    
         
            +
                # If no valid DICOM source is given, an empty array is returned.
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param [String, DObject, Array<String, DObject>] data single or multiple DICOM data (directories, file paths, binary strings, DICOM objects)
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @return [Array<DObject>] an array of successfully loaded DICOM objects
         
     | 
| 
      
 45 
     | 
    
         
            +
                #
         
     | 
| 
      
 46 
     | 
    
         
            +
                def load(data)
         
     | 
| 
      
 47 
     | 
    
         
            +
                  data = Array[data] unless data.respond_to?(:to_ary)
         
     | 
| 
      
 48 
     | 
    
         
            +
                  ary = Array.new
         
     | 
| 
      
 49 
     | 
    
         
            +
                  data.each do |element|
         
     | 
| 
      
 50 
     | 
    
         
            +
                    if element.is_a?(String)
         
     | 
| 
      
 51 
     | 
    
         
            +
                      begin
         
     | 
| 
      
 52 
     | 
    
         
            +
                        if File.directory?(element)
         
     | 
| 
      
 53 
     | 
    
         
            +
                          files = Dir[File.join(element, '**/*')].reject {|f| File.directory?(f) }
         
     | 
| 
      
 54 
     | 
    
         
            +
                          dcms = files.collect {|f| DObject.read(f)}
         
     | 
| 
      
 55 
     | 
    
         
            +
                        elsif File.file?(element)
         
     | 
| 
      
 56 
     | 
    
         
            +
                          dcms = [DObject.read(element)]
         
     | 
| 
      
 57 
     | 
    
         
            +
                        else
         
     | 
| 
      
 58 
     | 
    
         
            +
                          dcms = [DObject.parse(element)]
         
     | 
| 
      
 59 
     | 
    
         
            +
                        end
         
     | 
| 
      
 60 
     | 
    
         
            +
                      rescue
         
     | 
| 
      
 61 
     | 
    
         
            +
                        dcms = [DObject.parse(element)]
         
     | 
| 
      
 62 
     | 
    
         
            +
                      end
         
     | 
| 
      
 63 
     | 
    
         
            +
                      ary += dcms.keep_if {|dcm| dcm.read?}
         
     | 
| 
      
 64 
     | 
    
         
            +
                    else
         
     | 
| 
      
 65 
     | 
    
         
            +
                      # The element was not a string, and the only remaining valid element type is a DICOM object:
         
     | 
| 
      
 66 
     | 
    
         
            +
                      raise ArgumentError, "Invalid element (#{element.class}) given. Expected string or DObject." unless element.respond_to?(:to_dcm)
         
     | 
| 
      
 67 
     | 
    
         
            +
                      element.was_dcm_on_input = true
         
     | 
| 
      
 68 
     | 
    
         
            +
                      ary << element.to_dcm
         
     | 
| 
      
 69 
     | 
    
         
            +
                    end
         
     | 
| 
      
 70 
     | 
    
         
            +
                  end
         
     | 
| 
      
 71 
     | 
    
         
            +
                  ary
         
     | 
| 
      
 72 
     | 
    
         
            +
                end
         
     | 
| 
      
 73 
     | 
    
         
            +
             
     | 
| 
       39 
74 
     | 
    
         
             
                # Use tags as key. Example: '0010,0010'
         
     | 
| 
       40 
75 
     | 
    
         
             
                #
         
     | 
| 
       41 
76 
     | 
    
         
             
                def key_use_tags
         
     | 
| 
         @@ -65,6 +100,6 @@ module DICOM 
     | 
|
| 
       65 
100 
     | 
    
         
             
              # The default key representation.
         
     | 
| 
       66 
101 
     | 
    
         
             
              self.key_representation = :name
         
     | 
| 
       67 
102 
     | 
    
         
             
              # The default source application entity title.
         
     | 
| 
       68 
     | 
    
         
            -
              self.source_app_title = ' 
     | 
| 
      
 103 
     | 
    
         
            +
              self.source_app_title = 'RUBY-DICOM'
         
     | 
| 
       69 
104 
     | 
    
         | 
| 
       70 
105 
     | 
    
         
             
            end
         
     | 
    
        data/lib/dicom/version.rb
    CHANGED
    
    
    
        data/rakefile.rb
    CHANGED
    
    | 
         @@ -1,8 +1,10 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Available commands:
         
     | 
| 
       2 
2 
     | 
    
         
             
            # Testing the specification:
         
     | 
| 
       3 
3 
     | 
    
         
             
            #   bundle exec rake spec
         
     | 
| 
       4 
     | 
    
         
            -
            # Building a gem  
     | 
| 
      
 4 
     | 
    
         
            +
            # Building a gem from source with rake:
         
     | 
| 
       5 
5 
     | 
    
         
             
            #   bundle exec rake package
         
     | 
| 
      
 6 
     | 
    
         
            +
            # Building a gem from source with rubygems:
         
     | 
| 
      
 7 
     | 
    
         
            +
            #   bundle exec gem build dicom.gemspec
         
     | 
| 
       6 
8 
     | 
    
         
             
            # Create html documentation files:
         
     | 
| 
       7 
9 
     | 
    
         
             
            #   bundle exec rake yard
         
     | 
| 
       8 
10 
     | 
    
         |