ndav-magick-image 0.0.1 → 0.0.2
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 +4 -4
- data/README.md +10 -10
- data/lib/ndav/magick/image.rb +51 -16
- data/ndav-magick-image.gemspec +1 -1
- data/test/helper.rb +15 -0
- data/test/test_memory_viewable.rb +25 -32
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: '0996608a78022414f8bd891b56e9505ae3f0f1784efe2b32e55b158ddfe53fce'
|
|
4
|
+
data.tar.gz: a6e1042355ee3cc29adfe82d1b50d805eefc151d0961e8304fc61f0284eb0fcc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 07c973f3747bd2358672c1729700f1a09f0d0d95cf33ee292e133962cf1f54e2158a5189001f2848246678c6e3d49136e05aeb1975f7947546cbbf0f61210c23
|
|
7
|
+
data.tar.gz: b8062885f5f5e2e53ca33cbab91ca36ca1aff098001b66444f3da463e611e20ea951600e7b863eed7b09942604d274bfc97184db8a0a199ed9f06226c1792c35
|
data/README.md
CHANGED
|
@@ -60,9 +60,9 @@ The shape is `[height, width, channels]`. Channels vary based on the image attri
|
|
|
60
60
|
|
|
61
61
|
### format and item size ###
|
|
62
62
|
|
|
63
|
-
Currently, this bridge
|
|
63
|
+
Currently, this bridge exports `Magick::Image`'s MemoryCiew using `Magick::QuantumPixel`. Therefore, the MemoryView's format and item_size depend on the build options of ImageMagick. You can check the format with `NDAV::Magick::Image::MemoryViewable::FORMAT`.
|
|
64
64
|
|
|
65
|
-
|
|
65
|
+
On the other hand, this bridge can import MemoryViews whose format differs from `NDAV::Magick::Image::MemoryViewable::FORMAT`. Formats that are not currently supported might be supported in the future.
|
|
66
66
|
|
|
67
67
|
EXAMPLE
|
|
68
68
|
-------
|
|
@@ -82,25 +82,25 @@ image = image_list[0]
|
|
|
82
82
|
numo = NumoNArray(image)
|
|
83
83
|
abort "Use RGB image" unless numo.shape[2] == 3
|
|
84
84
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
noised
|
|
88
|
-
noised.inplace.clip(
|
|
85
|
+
# Assumes numo is Numo::SFloat here. It depends on your environment.
|
|
86
|
+
noise = Numo::SFloat.new(numo.shape).rand(0, -Magick::QuantumRange / 2)
|
|
87
|
+
noised = numo + noise
|
|
88
|
+
noised.inplace.clip(0, Magick::QuantumRange)
|
|
89
89
|
|
|
90
|
-
noised_image = MagickImage(
|
|
90
|
+
noised_image = MagickImage(noised)
|
|
91
91
|
noised_image.write "noised.png"
|
|
92
|
+
|
|
92
93
|
```
|
|
93
94
|
|
|
94
95
|
| Before | After |
|
|
95
96
|
|--------|-------|
|
|
96
|
-
| [](https://gyazo.com/905f541f15c0d57db5fc7ea3f6edaf07) | [](https://gyazo.com/905f541f15c0d57db5fc7ea3f6edaf07) | [](https://gyazo.com/c8c7191713d97fffaa2509e6b0874aab) |
|
|
97
98
|
|
|
98
99
|
TODO
|
|
99
100
|
----
|
|
100
101
|
|
|
101
|
-
* Support HDRI
|
|
102
102
|
* Support zero-copy
|
|
103
|
-
* Support
|
|
103
|
+
* Support export in non-ImageMagick-native format
|
|
104
104
|
|
|
105
105
|
LICENSE
|
|
106
106
|
-------
|
data/lib/ndav/magick/image.rb
CHANGED
|
@@ -4,6 +4,16 @@ require "rmagick"
|
|
|
4
4
|
class NDAV
|
|
5
5
|
module Magick
|
|
6
6
|
module Image
|
|
7
|
+
IS_HDRI_SUPPORTED = ::Magick::Magick_features.match?(/\bHDRI\b/)
|
|
8
|
+
COLORSPACE_TO_MAP = {
|
|
9
|
+
::Magick::GRAYColorspace => "I",
|
|
10
|
+
::Magick::LinearGRAYColorspace => "I",
|
|
11
|
+
::Magick::RGBColorspace => "RGB",
|
|
12
|
+
::Magick::ScRGBColorspace => "RGB",
|
|
13
|
+
::Magick::SRGBColorspace => "RGB",
|
|
14
|
+
::Magick::CMYColorspace => "CMY",
|
|
15
|
+
::Magick::CMYKColorspace => "CMYK"
|
|
16
|
+
}
|
|
7
17
|
CHANNELS_TO_MAP = {
|
|
8
18
|
nil => "I",
|
|
9
19
|
1 => "I",
|
|
@@ -11,11 +21,32 @@ class NDAV
|
|
|
11
21
|
3 => "RGB",
|
|
12
22
|
4 => "RGBA"
|
|
13
23
|
}
|
|
24
|
+
FORMAT_TO_TYPE = Hash.new {|types, format| types[format] = type_from_format(format)}
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
# TODO: Support more formats like "CCC"
|
|
28
|
+
def type_from_format(format)
|
|
29
|
+
item_desc = NDAV::ITEM_DESCS[format]
|
|
30
|
+
return unless item_desc.length == 1
|
|
31
|
+
|
|
32
|
+
component = item_desc[0]
|
|
33
|
+
return unless component.repeat == 1
|
|
34
|
+
|
|
35
|
+
case component.format
|
|
36
|
+
when MemoryViewable::FORMAT then ::Magick::QuantumPixel
|
|
37
|
+
when "C" then ::Magick::CharPixel
|
|
38
|
+
when "S" then ::Magick::ShortPixel
|
|
39
|
+
when "L" then ::Magick::IntegerPixel
|
|
40
|
+
when "f" then ::Magick::FloatPixel
|
|
41
|
+
when "d" then ::Magick::DoublePixel
|
|
42
|
+
else raise "Unsupported format: #{format}"
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
end
|
|
14
46
|
|
|
15
47
|
module FromNDAV
|
|
16
48
|
# TODO: Support more formats
|
|
17
49
|
def from_ndav(ndav)
|
|
18
|
-
raise %|Currently, supports only format "C", but is "#{ndav.format}"| unless ndav.format == "C"
|
|
19
50
|
raise "Currently, supports only row-major contiguous NDAV" unless ndav.row_major_contiguous?
|
|
20
51
|
raise "ndim must be 2 or 3 but is #{ndav.ndim}" unless [2, 3].include? ndav.ndim
|
|
21
52
|
|
|
@@ -24,33 +55,37 @@ class NDAV
|
|
|
24
55
|
raise "Unsupported channels: #{channels}" unless map
|
|
25
56
|
|
|
26
57
|
image = ::Magick::Image.new(width, height)
|
|
27
|
-
image.import_pixels 0, 0, width, height, map, ndav.to_s
|
|
58
|
+
image.import_pixels 0, 0, width, height, map, ndav.to_s, FORMAT_TO_TYPE[ndav.format]
|
|
28
59
|
image
|
|
29
60
|
end
|
|
30
61
|
end
|
|
31
62
|
|
|
32
63
|
module MemoryViewable
|
|
64
|
+
FORMAT = case [::Magick::MAGICKCORE_QUANTUM_DEPTH, NDAV::Magick::Image::IS_HDRI_SUPPORTED]
|
|
65
|
+
in [ 8, true ] then "f"
|
|
66
|
+
in [ 8, false] then "C"
|
|
67
|
+
in [16, true ] then "f"
|
|
68
|
+
in [16, false] then "S"
|
|
69
|
+
in [32, true ] then "f"
|
|
70
|
+
in [32, false] then "L"
|
|
71
|
+
in [64, true ] then "d"
|
|
72
|
+
end
|
|
73
|
+
ITEM_SIZE = NDAV::ITEM_SIZES[FORMAT]
|
|
74
|
+
|
|
33
75
|
private
|
|
34
76
|
|
|
35
|
-
# TODO: Support HDRI
|
|
36
77
|
def ndav_descriptor(**)
|
|
37
|
-
map =
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
when [true, false] then "I"
|
|
41
|
-
when [false, true] then "RGBA"
|
|
42
|
-
else "RGB"
|
|
43
|
-
end
|
|
78
|
+
map = COLORSPACE_TO_MAP[colorspace]
|
|
79
|
+
Kernel.raise "Unsupported color space: #{colorspace}" unless map
|
|
80
|
+
map += "A" if alpha?
|
|
44
81
|
shape = [rows, columns, map.length]
|
|
45
|
-
format = "C"
|
|
46
|
-
item_size = ::NDAV::ITEM_SIZES[format]
|
|
47
82
|
|
|
48
83
|
{
|
|
49
|
-
data: export_pixels_to_str(0, 0, columns, rows, map, ::Magick::
|
|
84
|
+
data: export_pixels_to_str(0, 0, columns, rows, map, ::Magick::QuantumPixel),
|
|
50
85
|
shape:,
|
|
51
|
-
strides:
|
|
52
|
-
format
|
|
53
|
-
byte_size: shape.reduce(
|
|
86
|
+
strides: NDAV.default_strides(shape:, item_size: ITEM_SIZE),
|
|
87
|
+
format: FORMAT,
|
|
88
|
+
byte_size: shape.reduce(ITEM_SIZE, :*),
|
|
54
89
|
readonly?: true
|
|
55
90
|
}
|
|
56
91
|
end
|
data/ndav-magick-image.gemspec
CHANGED
data/test/helper.rb
CHANGED
|
@@ -3,3 +3,18 @@ require "test/unit"
|
|
|
3
3
|
require "test/unit/notify"
|
|
4
4
|
require "fiddle"
|
|
5
5
|
require "tmpdir"
|
|
6
|
+
|
|
7
|
+
module Helper
|
|
8
|
+
private
|
|
9
|
+
|
|
10
|
+
def make_image(width, height)
|
|
11
|
+
ratio = (2 ** ::Magick::MAGICKCORE_QUANTUM_DEPTH - 1) / 255
|
|
12
|
+
[
|
|
13
|
+
[[255, 255, 255] * width] * (height / 2),
|
|
14
|
+
[[ 0, 255, 0] * width] * (height / 2)
|
|
15
|
+
# ].flatten.collect {|item| round_trip(item * ratio, NDAV::Magick::Image::MemoryViewable::FORMAT)}
|
|
16
|
+
].flatten.collect {|item| item * ratio}
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Test::Unit::TestCase.include Helper
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
require_relative "helper"
|
|
2
2
|
|
|
3
3
|
class TestMemoryViewable < Test::Unit::TestCase
|
|
4
|
+
FORMAT = NDAV::Magick::Image::MemoryViewable::FORMAT
|
|
5
|
+
ITEM_SIZE = NDAV::ITEM_SIZES[FORMAT]
|
|
6
|
+
|
|
4
7
|
def setup
|
|
5
8
|
@width = 3
|
|
6
9
|
@height = 2
|
|
@@ -18,14 +21,10 @@ class TestMemoryViewable < Test::Unit::TestCase
|
|
|
18
21
|
Fiddle::MemoryView.export @image do |view|
|
|
19
22
|
assert_equal 3, view.ndim
|
|
20
23
|
assert_equal [@height, @width, 3], view.shape
|
|
21
|
-
assert_equal
|
|
22
|
-
assert_equal
|
|
23
|
-
assert_equal @width * @height * 3, view.byte_size
|
|
24
|
-
assert_equal
|
|
25
|
-
[[255, 255, 255] * @width] * (@height / 2),
|
|
26
|
-
[[ 0, 255, 0] * @width] * (@height / 2)
|
|
27
|
-
].flatten,
|
|
28
|
-
view.to_s.unpack("C*")
|
|
24
|
+
assert_equal ITEM_SIZE, view.item_size
|
|
25
|
+
assert_equal FORMAT, view.format
|
|
26
|
+
assert_equal @width * @height * 3 * ITEM_SIZE, view.byte_size
|
|
27
|
+
assert_equal make_image(@width, @height), view.to_s.unpack("#{FORMAT}*")
|
|
29
28
|
end
|
|
30
29
|
end
|
|
31
30
|
|
|
@@ -35,44 +34,38 @@ class TestMemoryViewable < Test::Unit::TestCase
|
|
|
35
34
|
Fiddle::MemoryView.export @image do |view|
|
|
36
35
|
assert_equal 3, view.ndim
|
|
37
36
|
assert_equal [@height, @width, 4], view.shape
|
|
38
|
-
assert_equal
|
|
39
|
-
assert_equal
|
|
40
|
-
assert_equal @width * @height * 4, view.byte_size
|
|
37
|
+
assert_equal ITEM_SIZE, view.item_size
|
|
38
|
+
assert_equal FORMAT, view.format
|
|
39
|
+
assert_equal @width * @height * 4* ITEM_SIZE, view.byte_size
|
|
41
40
|
end
|
|
42
41
|
end
|
|
43
42
|
|
|
44
43
|
def test_grayscale
|
|
45
|
-
image =
|
|
44
|
+
@image.colorspace = Magick::GRAYColorspace
|
|
46
45
|
|
|
47
|
-
Fiddle::MemoryView.export image do |view|
|
|
46
|
+
Fiddle::MemoryView.export @image do |view|
|
|
48
47
|
assert_equal 3, view.ndim
|
|
49
48
|
assert_equal [@height, @width, 1], view.shape
|
|
50
|
-
assert_equal
|
|
51
|
-
assert_equal
|
|
52
|
-
assert_equal @width * @height * 1, view.byte_size
|
|
53
|
-
assert_equal
|
|
54
|
-
|
|
55
|
-
[[182] * @width] * (@height / 2)
|
|
56
|
-
].flatten,
|
|
57
|
-
view.to_s.unpack("C*")
|
|
49
|
+
assert_equal ITEM_SIZE, view.item_size
|
|
50
|
+
assert_equal FORMAT, view.format
|
|
51
|
+
assert_equal @width * @height * 1 * ITEM_SIZE, view.byte_size
|
|
52
|
+
assert_equal @image.export_pixels_to_str(0, 0, @width, @height, "I", Magick::QuantumPixel).unpack("#{FORMAT}*"),
|
|
53
|
+
view.to_s.unpack("#{FORMAT}*")
|
|
58
54
|
end
|
|
59
55
|
end
|
|
60
56
|
|
|
61
57
|
def test_gray_alpha
|
|
62
|
-
image =
|
|
63
|
-
image.alpha Magick::OnAlphaChannel
|
|
58
|
+
@image.colorspace = Magick::GRAYColorspace
|
|
59
|
+
@image.alpha Magick::OnAlphaChannel
|
|
64
60
|
|
|
65
|
-
Fiddle::MemoryView.export image do |view|
|
|
61
|
+
Fiddle::MemoryView.export @image do |view|
|
|
66
62
|
assert_equal 3, view.ndim
|
|
67
63
|
assert_equal [@height, @width, 2], view.shape
|
|
68
|
-
assert_equal
|
|
69
|
-
assert_equal
|
|
70
|
-
assert_equal @width * @height * 2, view.byte_size
|
|
71
|
-
assert_equal
|
|
72
|
-
|
|
73
|
-
[[182, 255] * @width] * (@height / 2)
|
|
74
|
-
].flatten,
|
|
75
|
-
view.to_s.unpack("C*")
|
|
64
|
+
assert_equal ITEM_SIZE, view.item_size
|
|
65
|
+
assert_equal FORMAT, view.format
|
|
66
|
+
assert_equal @width * @height * 2 * ITEM_SIZE, view.byte_size
|
|
67
|
+
assert_equal @image.export_pixels_to_str(0, 0, @width, @height, "IA", Magick::QuantumPixel).unpack("#{FORMAT}*"),
|
|
68
|
+
view.to_s.unpack("#{FORMAT}*")
|
|
76
69
|
end
|
|
77
70
|
end
|
|
78
71
|
|