dicom 0.9.6 → 0.9.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -13
- data/CHANGELOG.md +390 -376
- data/COPYING +674 -674
- data/Gemfile +2 -2
- data/Gemfile.lock +30 -28
- data/README.md +154 -152
- data/dicom.gemspec +30 -30
- data/lib/dicom/anonymizer.rb +677 -654
- data/lib/dicom/audit_trail.rb +109 -109
- data/lib/dicom/d_library.rb +269 -265
- data/lib/dicom/d_object.rb +465 -465
- data/lib/dicom/d_read.rb +21 -8
- data/lib/dicom/d_server.rb +329 -329
- data/lib/dicom/d_write.rb +355 -355
- data/lib/dicom/dictionary/elements.tsv +597 -86
- data/lib/dicom/dictionary/uids.tsv +4 -2
- data/lib/dicom/elemental_parent.rb +63 -63
- data/lib/dicom/extensions/array.rb +56 -56
- data/lib/dicom/extensions/hash.rb +30 -30
- data/lib/dicom/extensions/string.rb +125 -125
- data/lib/dicom/file_handler.rb +121 -121
- data/lib/dicom/general/constants.rb +210 -210
- data/lib/dicom/general/deprecated.rb +0 -320
- data/lib/dicom/general/logging.rb +155 -155
- data/lib/dicom/general/methods.rb +98 -82
- data/lib/dicom/general/variables.rb +28 -28
- data/lib/dicom/general/version.rb +5 -5
- data/lib/dicom/image_item.rb +836 -836
- data/lib/dicom/image_processor.rb +79 -79
- data/lib/dicom/image_processor_mini_magick.rb +71 -71
- data/lib/dicom/image_processor_r_magick.rb +106 -106
- data/lib/dicom/link.rb +1529 -1528
- data/rakefile.rb +29 -30
- metadata +43 -49
@@ -1,80 +1,80 @@
|
|
1
|
-
module DICOM
|
2
|
-
|
3
|
-
# This module is the general interface between the ImageItem class and the
|
4
|
-
# image methods found in the specific image processor modules.
|
5
|
-
#
|
6
|
-
module ImageProcessor
|
7
|
-
|
8
|
-
# Creates image objects from one or more compressed, binary string blobs.
|
9
|
-
#
|
10
|
-
# @param [Array<String>, String] blobs binary string blob(s) containing compressed pixel data
|
11
|
-
# @return [Array<MagickImage>, FalseClass] - an array of images, or false (if decompression failed)
|
12
|
-
#
|
13
|
-
def decompress(blobs)
|
14
|
-
raise ArgumentError, "Expected Array or String, got #{blobs.class}." unless [String, Array].include?(blobs.class)
|
15
|
-
blobs = [blobs] unless blobs.is_a?(Array)
|
16
|
-
begin
|
17
|
-
return image_module.decompress(blobs)
|
18
|
-
rescue
|
19
|
-
return false
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# Extracts an array of pixels (integers) from an image object.
|
24
|
-
#
|
25
|
-
# @param [MagickImage] image a Magick image object
|
26
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
27
|
-
# @return [Array<Integer>] an array of pixel values
|
28
|
-
#
|
29
|
-
def export_pixels(image, photometry)
|
30
|
-
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
31
|
-
image_module.export_pixels(image, photometry)
|
32
|
-
end
|
33
|
-
|
34
|
-
# Creates an image object from a binary string blob.
|
35
|
-
#
|
36
|
-
# @param [String] blob binary string blob containing pixel data
|
37
|
-
# @param [Integer] columns the number of columns
|
38
|
-
# @param [Integer] rows the number of rows
|
39
|
-
# @param [Integer] depth the bit depth of the encoded pixel data
|
40
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
41
|
-
# @return [MagickImage] a Magick image object
|
42
|
-
#
|
43
|
-
def import_pixels(blob, columns, rows, depth, photometry)
|
44
|
-
raise ArgumentError, "Expected String, got #{blob.class}." unless blob.is_a?(String)
|
45
|
-
image_module.import_pixels(blob, columns, rows, depth, photometry)
|
46
|
-
end
|
47
|
-
|
48
|
-
# Gives an array containing the image objects that are supported by the image processor.
|
49
|
-
#
|
50
|
-
# @return [Array<String>] the valid image classes
|
51
|
-
#
|
52
|
-
def valid_image_objects
|
53
|
-
return ['Magick::Image', 'MiniMagick::Image']
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
|
60
|
-
# Gives the specific image processor module corresponding to the specified
|
61
|
-
# image_processor module option.
|
62
|
-
#
|
63
|
-
# @raise [RuntimeError] if an unknown image processor is specified
|
64
|
-
# @return [DcmMiniMagick, DcmRMagick] the image processor module to be used
|
65
|
-
#
|
66
|
-
def image_module
|
67
|
-
case DICOM.image_processor
|
68
|
-
when :mini_magick
|
69
|
-
require 'mini_magick'
|
70
|
-
DcmMiniMagick
|
71
|
-
when :rmagick
|
72
|
-
require 'rmagick'
|
73
|
-
DcmRMagick
|
74
|
-
else
|
75
|
-
raise "Uknown image processor #{DICOM.image_processor}"
|
76
|
-
end
|
77
|
-
end
|
78
|
-
|
79
|
-
end
|
1
|
+
module DICOM
|
2
|
+
|
3
|
+
# This module is the general interface between the ImageItem class and the
|
4
|
+
# image methods found in the specific image processor modules.
|
5
|
+
#
|
6
|
+
module ImageProcessor
|
7
|
+
|
8
|
+
# Creates image objects from one or more compressed, binary string blobs.
|
9
|
+
#
|
10
|
+
# @param [Array<String>, String] blobs binary string blob(s) containing compressed pixel data
|
11
|
+
# @return [Array<MagickImage>, FalseClass] - an array of images, or false (if decompression failed)
|
12
|
+
#
|
13
|
+
def decompress(blobs)
|
14
|
+
raise ArgumentError, "Expected Array or String, got #{blobs.class}." unless [String, Array].include?(blobs.class)
|
15
|
+
blobs = [blobs] unless blobs.is_a?(Array)
|
16
|
+
begin
|
17
|
+
return image_module.decompress(blobs)
|
18
|
+
rescue
|
19
|
+
return false
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
# Extracts an array of pixels (integers) from an image object.
|
24
|
+
#
|
25
|
+
# @param [MagickImage] image a Magick image object
|
26
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
27
|
+
# @return [Array<Integer>] an array of pixel values
|
28
|
+
#
|
29
|
+
def export_pixels(image, photometry)
|
30
|
+
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
31
|
+
image_module.export_pixels(image, photometry)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Creates an image object from a binary string blob.
|
35
|
+
#
|
36
|
+
# @param [String] blob binary string blob containing pixel data
|
37
|
+
# @param [Integer] columns the number of columns
|
38
|
+
# @param [Integer] rows the number of rows
|
39
|
+
# @param [Integer] depth the bit depth of the encoded pixel data
|
40
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
41
|
+
# @return [MagickImage] a Magick image object
|
42
|
+
#
|
43
|
+
def import_pixels(blob, columns, rows, depth, photometry)
|
44
|
+
raise ArgumentError, "Expected String, got #{blob.class}." unless blob.is_a?(String)
|
45
|
+
image_module.import_pixels(blob, columns, rows, depth, photometry)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Gives an array containing the image objects that are supported by the image processor.
|
49
|
+
#
|
50
|
+
# @return [Array<String>] the valid image classes
|
51
|
+
#
|
52
|
+
def valid_image_objects
|
53
|
+
return ['Magick::Image', 'MiniMagick::Image']
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
|
60
|
+
# Gives the specific image processor module corresponding to the specified
|
61
|
+
# image_processor module option.
|
62
|
+
#
|
63
|
+
# @raise [RuntimeError] if an unknown image processor is specified
|
64
|
+
# @return [DcmMiniMagick, DcmRMagick] the image processor module to be used
|
65
|
+
#
|
66
|
+
def image_module
|
67
|
+
case DICOM.image_processor
|
68
|
+
when :mini_magick
|
69
|
+
require 'mini_magick'
|
70
|
+
DcmMiniMagick
|
71
|
+
when :rmagick
|
72
|
+
require 'rmagick'
|
73
|
+
DcmRMagick
|
74
|
+
else
|
75
|
+
raise "Uknown image processor #{DICOM.image_processor}"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
80
|
end
|
@@ -1,72 +1,72 @@
|
|
1
|
-
module DICOM
|
2
|
-
module ImageProcessor
|
3
|
-
|
4
|
-
# This module contains methods for interacting with pixel data using the mini_magick gem.
|
5
|
-
#
|
6
|
-
module DcmMiniMagick
|
7
|
-
|
8
|
-
class << self
|
9
|
-
|
10
|
-
# Creates image objects from an array of compressed, binary string blobs.
|
11
|
-
#
|
12
|
-
# @param [Array<String>] blobs an array of binary string blobs containing compressed pixel data
|
13
|
-
# @return [Array<MiniMagick::Image>, FalseClass] - an array of images, or false (if decompression failed)
|
14
|
-
#
|
15
|
-
def decompress(blobs)
|
16
|
-
images = Array.new
|
17
|
-
# We attempt to decompress the pixels using ImageMagick:
|
18
|
-
blobs.each do |string|
|
19
|
-
images << MiniMagick::Image.read(string)
|
20
|
-
end
|
21
|
-
return images
|
22
|
-
end
|
23
|
-
|
24
|
-
# Extracts an array of pixels (integers) from an image object.
|
25
|
-
#
|
26
|
-
# @note This feature is not available as of yet in the mini_magick image processor.
|
27
|
-
# If this feature is needed, please try another image processor (RMagick).
|
28
|
-
#
|
29
|
-
# @param [MiniMagick::Image] image a mini_magick image object
|
30
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
31
|
-
# @return [Array<Integer>] an array of pixel values
|
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.
|
39
|
-
#
|
40
|
-
# @param [String] blob binary string blob containing pixel data
|
41
|
-
# @param [Integer] columns the number of columns
|
42
|
-
# @param [Integer] rows the number of rows
|
43
|
-
# @param [Integer] depth the bit depth of the encoded pixel data
|
44
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
45
|
-
# @param [String] format the image format to use
|
46
|
-
# @return [Magick::Image] a mini_magick image object
|
47
|
-
#
|
48
|
-
def import_pixels(blob, columns, rows, depth, photometry, format='png')
|
49
|
-
image = MiniMagick::Image.import_pixels(blob, columns, rows, depth, im_map(photometry), format)
|
50
|
-
end
|
51
|
-
|
52
|
-
# Converts a given DICOM photometry string to a mini_magick pixel map string.
|
53
|
-
#
|
54
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
55
|
-
# @return [String] a mini_magick pixel map string
|
56
|
-
#
|
57
|
-
def im_map(photometry)
|
58
|
-
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
59
|
-
if photometry.include?('COLOR') or photometry.include?('RGB')
|
60
|
-
return 'rgb'
|
61
|
-
elsif photometry.include?('YBR')
|
62
|
-
return 'ybr'
|
63
|
-
else
|
64
|
-
return 'gray' # (Assuming monochromeX - greyscale)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
end
|
69
|
-
|
70
|
-
end
|
71
|
-
end
|
1
|
+
module DICOM
|
2
|
+
module ImageProcessor
|
3
|
+
|
4
|
+
# This module contains methods for interacting with pixel data using the mini_magick gem.
|
5
|
+
#
|
6
|
+
module DcmMiniMagick
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Creates image objects from an array of compressed, binary string blobs.
|
11
|
+
#
|
12
|
+
# @param [Array<String>] blobs an array of binary string blobs containing compressed pixel data
|
13
|
+
# @return [Array<MiniMagick::Image>, FalseClass] - an array of images, or false (if decompression failed)
|
14
|
+
#
|
15
|
+
def decompress(blobs)
|
16
|
+
images = Array.new
|
17
|
+
# We attempt to decompress the pixels using ImageMagick:
|
18
|
+
blobs.each do |string|
|
19
|
+
images << MiniMagick::Image.read(string)
|
20
|
+
end
|
21
|
+
return images
|
22
|
+
end
|
23
|
+
|
24
|
+
# Extracts an array of pixels (integers) from an image object.
|
25
|
+
#
|
26
|
+
# @note This feature is not available as of yet in the mini_magick image processor.
|
27
|
+
# If this feature is needed, please try another image processor (RMagick).
|
28
|
+
#
|
29
|
+
# @param [MiniMagick::Image] image a mini_magick image object
|
30
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
31
|
+
# @return [Array<Integer>] an array of pixel values
|
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.
|
39
|
+
#
|
40
|
+
# @param [String] blob binary string blob containing pixel data
|
41
|
+
# @param [Integer] columns the number of columns
|
42
|
+
# @param [Integer] rows the number of rows
|
43
|
+
# @param [Integer] depth the bit depth of the encoded pixel data
|
44
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
45
|
+
# @param [String] format the image format to use
|
46
|
+
# @return [Magick::Image] a mini_magick image object
|
47
|
+
#
|
48
|
+
def import_pixels(blob, columns, rows, depth, photometry, format='png')
|
49
|
+
image = MiniMagick::Image.import_pixels(blob, columns, rows, depth, im_map(photometry), format)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Converts a given DICOM photometry string to a mini_magick pixel map string.
|
53
|
+
#
|
54
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
55
|
+
# @return [String] a mini_magick pixel map string
|
56
|
+
#
|
57
|
+
def im_map(photometry)
|
58
|
+
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
59
|
+
if photometry.include?('COLOR') or photometry.include?('RGB')
|
60
|
+
return 'rgb'
|
61
|
+
elsif photometry.include?('YBR')
|
62
|
+
return 'ybr'
|
63
|
+
else
|
64
|
+
return 'gray' # (Assuming monochromeX - greyscale)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
end
|
72
72
|
end
|
@@ -1,107 +1,107 @@
|
|
1
|
-
module DICOM
|
2
|
-
module ImageProcessor
|
3
|
-
|
4
|
-
# This module contains methods for interacting with pixel data using the RMagick gem.
|
5
|
-
#
|
6
|
-
module DcmRMagick
|
7
|
-
|
8
|
-
class << self
|
9
|
-
|
10
|
-
# Creates image objects from an array of compressed, binary string blobs.
|
11
|
-
#
|
12
|
-
# === Note
|
13
|
-
#
|
14
|
-
# The method tries to use RMagick for unpacking, but unortunately, it seems that
|
15
|
-
# ImageMagick is not able to handle most of the compressed image variants used in the DICOM
|
16
|
-
# standard. To get a more robust implementation which is able to handle most types of
|
17
|
-
# compressed DICOM files, something else is needed.
|
18
|
-
#
|
19
|
-
# Probably a good candidate to use is the PVRG-JPEG library, which seems to be able to handle
|
20
|
-
# everything that is jpeg. It exists in the Ubuntu repositories, where it can be installed and
|
21
|
-
# run through terminal. For source code, and some additional information, check out this link:
|
22
|
-
# http://www.panix.com/~eli/jpeg/
|
23
|
-
#
|
24
|
-
# Another idea would be to study how other open source libraries, like GDCM handle these files.
|
25
|
-
#
|
26
|
-
# @param [Array<String>] blobs an array of binary string blobs containing compressed pixel data
|
27
|
-
# @return [Array<Magick::Image>, FalseClass] - an array of images, or false (if decompression failed)
|
28
|
-
#
|
29
|
-
def decompress(blobs)
|
30
|
-
# FIXME:
|
31
|
-
# The following transfer syntaxes have been verified as failing with ImageMagick:
|
32
|
-
# TXS_JPEG_LOSSLESS_NH is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
|
33
|
-
# TXS_JPEG_LOSSLESS_NH_FOP is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
|
34
|
-
# TXS_JPEG_2000_PART1_LOSSLESS is not supported by (my) ImageMagick version: "jpc_dec_decodepkts failed"
|
35
|
-
#
|
36
|
-
images = Array.new
|
37
|
-
# We attempt to decompress the pixels using ImageMagick:
|
38
|
-
blobs.each do |string|
|
39
|
-
images << Magick::Image.from_blob(string).first
|
40
|
-
end
|
41
|
-
return images
|
42
|
-
end
|
43
|
-
|
44
|
-
# Extracts an array of pixels (integers) from an image object.
|
45
|
-
#
|
46
|
-
# @param [Magick::Image] image an RMagick image object
|
47
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
48
|
-
# @return [Array<Integer>] an array of pixel values
|
49
|
-
#
|
50
|
-
def export_pixels(image, photometry)
|
51
|
-
raise ArgumentError, "Expected Magick::Image, got #{image.class}." unless image.is_a?(Magick::Image)
|
52
|
-
pixels = image.export_pixels(0, 0, image.columns, image.rows, rm_map(photometry))
|
53
|
-
return pixels
|
54
|
-
end
|
55
|
-
|
56
|
-
# Creates an image object from a binary string blob.
|
57
|
-
#
|
58
|
-
# @param [String] blob binary string blob containing pixel data
|
59
|
-
# @param [Integer] columns the number of columns
|
60
|
-
# @param [Integer] rows the number of rows
|
61
|
-
# @param [Integer] depth the bit depth of the encoded pixel data
|
62
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
63
|
-
# @param [String] format the image format to use
|
64
|
-
# @return [Magick::Image] an RMagick image object
|
65
|
-
#
|
66
|
-
def import_pixels(blob, columns, rows, depth, photometry, format='png')
|
67
|
-
image = Magick::Image.new(columns,rows).import_pixels(0, 0, columns, rows, rm_map(photometry), blob, rm_data_type(depth))
|
68
|
-
end
|
69
|
-
|
70
|
-
# Converts a given bit depth to an RMagick StorageType.
|
71
|
-
#
|
72
|
-
# @raise [ArgumentError] if given an unsupported bit depth
|
73
|
-
# @param [Integer] bit_depth the bit depth of the pixel data
|
74
|
-
# @return [Magick::CharPixel, Magick::ShortPixel] the proper storage type
|
75
|
-
#
|
76
|
-
def rm_data_type(bit_depth)
|
77
|
-
return case bit_depth
|
78
|
-
when 8
|
79
|
-
Magick::CharPixel
|
80
|
-
when 16
|
81
|
-
Magick::ShortPixel
|
82
|
-
else
|
83
|
-
raise ArgumentError, "Unsupported bit depth: #{bit_depth}."
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
# Converts a given DICOM photometry string to an RMagick pixel map string.
|
88
|
-
#
|
89
|
-
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
90
|
-
# @return [String] an RMagick pixel map string
|
91
|
-
#
|
92
|
-
def rm_map(photometry)
|
93
|
-
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
94
|
-
if photometry.include?('COLOR') or photometry.include?('RGB')
|
95
|
-
return 'RGB'
|
96
|
-
elsif photometry.include?('YBR')
|
97
|
-
return 'YBR'
|
98
|
-
else
|
99
|
-
return 'I' # (Assuming monochromeX - greyscale)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
end
|
104
|
-
|
105
|
-
end
|
106
|
-
end
|
1
|
+
module DICOM
|
2
|
+
module ImageProcessor
|
3
|
+
|
4
|
+
# This module contains methods for interacting with pixel data using the RMagick gem.
|
5
|
+
#
|
6
|
+
module DcmRMagick
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Creates image objects from an array of compressed, binary string blobs.
|
11
|
+
#
|
12
|
+
# === Note
|
13
|
+
#
|
14
|
+
# The method tries to use RMagick for unpacking, but unortunately, it seems that
|
15
|
+
# ImageMagick is not able to handle most of the compressed image variants used in the DICOM
|
16
|
+
# standard. To get a more robust implementation which is able to handle most types of
|
17
|
+
# compressed DICOM files, something else is needed.
|
18
|
+
#
|
19
|
+
# Probably a good candidate to use is the PVRG-JPEG library, which seems to be able to handle
|
20
|
+
# everything that is jpeg. It exists in the Ubuntu repositories, where it can be installed and
|
21
|
+
# run through terminal. For source code, and some additional information, check out this link:
|
22
|
+
# http://www.panix.com/~eli/jpeg/
|
23
|
+
#
|
24
|
+
# Another idea would be to study how other open source libraries, like GDCM handle these files.
|
25
|
+
#
|
26
|
+
# @param [Array<String>] blobs an array of binary string blobs containing compressed pixel data
|
27
|
+
# @return [Array<Magick::Image>, FalseClass] - an array of images, or false (if decompression failed)
|
28
|
+
#
|
29
|
+
def decompress(blobs)
|
30
|
+
# FIXME:
|
31
|
+
# The following transfer syntaxes have been verified as failing with ImageMagick:
|
32
|
+
# TXS_JPEG_LOSSLESS_NH is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
|
33
|
+
# TXS_JPEG_LOSSLESS_NH_FOP is not supported by (my) ImageMagick version: "Unsupported JPEG process: SOF type 0xc3"
|
34
|
+
# TXS_JPEG_2000_PART1_LOSSLESS is not supported by (my) ImageMagick version: "jpc_dec_decodepkts failed"
|
35
|
+
#
|
36
|
+
images = Array.new
|
37
|
+
# We attempt to decompress the pixels using ImageMagick:
|
38
|
+
blobs.each do |string|
|
39
|
+
images << Magick::Image.from_blob(string).first
|
40
|
+
end
|
41
|
+
return images
|
42
|
+
end
|
43
|
+
|
44
|
+
# Extracts an array of pixels (integers) from an image object.
|
45
|
+
#
|
46
|
+
# @param [Magick::Image] image an RMagick image object
|
47
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
48
|
+
# @return [Array<Integer>] an array of pixel values
|
49
|
+
#
|
50
|
+
def export_pixels(image, photometry)
|
51
|
+
raise ArgumentError, "Expected Magick::Image, got #{image.class}." unless image.is_a?(Magick::Image)
|
52
|
+
pixels = image.export_pixels(0, 0, image.columns, image.rows, rm_map(photometry))
|
53
|
+
return pixels
|
54
|
+
end
|
55
|
+
|
56
|
+
# Creates an image object from a binary string blob.
|
57
|
+
#
|
58
|
+
# @param [String] blob binary string blob containing pixel data
|
59
|
+
# @param [Integer] columns the number of columns
|
60
|
+
# @param [Integer] rows the number of rows
|
61
|
+
# @param [Integer] depth the bit depth of the encoded pixel data
|
62
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
63
|
+
# @param [String] format the image format to use
|
64
|
+
# @return [Magick::Image] an RMagick image object
|
65
|
+
#
|
66
|
+
def import_pixels(blob, columns, rows, depth, photometry, format='png')
|
67
|
+
image = Magick::Image.new(columns,rows).import_pixels(0, 0, columns, rows, rm_map(photometry), blob, rm_data_type(depth))
|
68
|
+
end
|
69
|
+
|
70
|
+
# Converts a given bit depth to an RMagick StorageType.
|
71
|
+
#
|
72
|
+
# @raise [ArgumentError] if given an unsupported bit depth
|
73
|
+
# @param [Integer] bit_depth the bit depth of the pixel data
|
74
|
+
# @return [Magick::CharPixel, Magick::ShortPixel] the proper storage type
|
75
|
+
#
|
76
|
+
def rm_data_type(bit_depth)
|
77
|
+
return case bit_depth
|
78
|
+
when 8
|
79
|
+
Magick::CharPixel
|
80
|
+
when 16
|
81
|
+
Magick::ShortPixel
|
82
|
+
else
|
83
|
+
raise ArgumentError, "Unsupported bit depth: #{bit_depth}."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
# Converts a given DICOM photometry string to an RMagick pixel map string.
|
88
|
+
#
|
89
|
+
# @param [String] photometry a code describing the photometry of the pixel data (e.g. 'MONOCHROME1' or 'COLOR')
|
90
|
+
# @return [String] an RMagick pixel map string
|
91
|
+
#
|
92
|
+
def rm_map(photometry)
|
93
|
+
raise ArgumentError, "Expected String, got #{photometry.class}." unless photometry.is_a?(String)
|
94
|
+
if photometry.include?('COLOR') or photometry.include?('RGB')
|
95
|
+
return 'RGB'
|
96
|
+
elsif photometry.include?('YBR')
|
97
|
+
return 'YBR'
|
98
|
+
else
|
99
|
+
return 'I' # (Assuming monochromeX - greyscale)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
end
|
107
107
|
end
|