magro 0.1.0 → 0.4.0

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.
@@ -9,11 +9,14 @@ module Magro
9
9
  # @param filename [String] Path to image file to be loaded.
10
10
  # Currently, the following file formats are support:
11
11
  # Portbale Network Graphics (*.png) and JPEG files (*.jpeg, *.jpg, *jpe).
12
+ # @raise [ArgumentError] This error is raised when filename is not String.
13
+ # @raise [IOError] This error is raised when failed to read image file.
14
+ # @raise [NoMemoryError] If memory allocation of image data fails, this error is raised.
12
15
  # @return [Numo::UInt8] (shape: [height, width, n_channels]) Loaded image.
13
16
  def imread(filename)
14
17
  raise ArgumentError, 'Expect class of filename to be String.' unless filename.is_a?(String)
15
- return read_jpg(filename) if filename =~ /\.(jpeg|jpg|jpe)$/
16
- return read_png(filename) if filename =~ /\.png$/
18
+ return read_jpg(filename) if filename.downcase =~ /\.(jpeg|jpg|jpe)$/
19
+ return read_png(filename) if filename.downcase =~ /\.png$/
17
20
  end
18
21
 
19
22
  # Saves an image to file.
@@ -22,12 +25,15 @@ module Magro
22
25
  # Portbale Network Graphics (*.png) and JPEG files (*.jpeg, *.jpg, *jpe).
23
26
  # @param image [Numo::UInt8] (shape: [height, width, n_channels]) Image data to be saved.
24
27
  # @param quality [Integer] Quality parameter of jpeg image that takes a value between 0 to 100.
28
+ # @raise [ArgumentError] If filename is not String or image is not Numo::NArray, this error is raised.
29
+ # @raise [IOError] This error is raised when failed to read image file.
30
+ # @raise [NoMemoryError] If memory allocation of image data fails, this error is raised.
25
31
  # @return [Boolean] true if file save is successful.
26
32
  def imsave(filename, image, quality: nil)
27
33
  raise ArgumentError, 'Expect class of filename to be String.' unless filename.is_a?(String)
28
34
  raise ArgumentError, 'Expect class of image to be Numo::NArray.' unless image.is_a?(Numo::NArray)
29
35
 
30
- if filename =~ /\.(jpeg|jpg|jpe)$/
36
+ if filename.downcase =~ /\.(jpeg|jpg|jpe)$/
31
37
  unless quality.nil?
32
38
  raise ArgumentError, 'Expect class of quality to be Numeric.' unless quality.is_a?(Numeric)
33
39
  raise ArgumentError, 'Range of quality value between 0 to 100.' unless quality.between?(0, 100)
@@ -35,7 +41,7 @@ module Magro
35
41
  return save_jpg(filename, image, quality)
36
42
  end
37
43
 
38
- return save_png(filename, image) if filename =~ /\.png$/
44
+ return save_png(filename, image) if filename.downcase =~ /\.png$/
39
45
 
40
46
  false
41
47
  end
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Magro
4
+ # Transform module provide functions of image transfom.
5
+ module Transform
6
+ module_function
7
+
8
+ # Resizes an image with bilinear interpolation method.
9
+ #
10
+ # @example
11
+ # require 'numo/narray'
12
+ # require 'magro'
13
+ #
14
+ # image = Numo::UInt8.new(16, 16).seq
15
+ # resized = Magro::Transform.resize(image, height: 64, width: 64)
16
+ #
17
+ # @param image [Numo::UInt8] (shape: [height, width, n_channels] or [height, width]) Image data to be saved.
18
+ # @param height [Integer] Requested height in pixels.
19
+ # @param width [Integer] Requested width in pixels.
20
+ # @return [Numo::UInt8] (shape: [height, width, n_channels] or [height, width]) Resized image data.
21
+ def resize(image, height:, width:)
22
+ n_channels = image.shape[2]
23
+
24
+ if n_channels.nil?
25
+ bilinear_resize(image, height, width)
26
+ else
27
+ resized = image.class.zeros(height, width, n_channels)
28
+ n_channels.times { |c| resized[true, true, c] = bilinear_resize(image[true, true, c], height, width) }
29
+ resized
30
+ end
31
+ end
32
+
33
+ # private
34
+
35
+ def bilinear_resize(image, new_height, new_width)
36
+ height, width = image.shape
37
+
38
+ y_ratio = height.fdiv(new_height)
39
+ x_ratio = width.fdiv(new_width)
40
+
41
+ y, x = Numo::Int32.new(new_height * new_width).seq.divmod(new_width)
42
+
43
+ y_p = Numo::Int32.cast((y_ratio * (y + 0.5) - 0.5).floor).clip(0, height - 1)
44
+ x_p = Numo::Int32.cast((x_ratio * (x + 0.5) - 0.5).floor).clip(0, width - 1)
45
+ y_n = Numo::Int32.cast((y_ratio * (y + 0.5) - 0.5).ceil).clip(0, height - 1)
46
+ x_n = Numo::Int32.cast((x_ratio * (x + 0.5) - 0.5).ceil).clip(0, width - 1)
47
+
48
+ flt = image.flatten
49
+ a = flt[y_p * width + x_p]
50
+ b = flt[y_p * width + x_n]
51
+ c = flt[y_n * width + x_p]
52
+ d = flt[y_n * width + x_n]
53
+
54
+ y_d = y_ratio * (y + 0.5) - 0.5
55
+ x_d = x_ratio * (x + 0.5) - 0.5
56
+ y_d = y_d.class.maximum(0, y_d - y_d.floor)
57
+ x_d = x_d.class.maximum(0, x_d - x_d.floor)
58
+
59
+ resized = a * (1 - x_d) * (1 - y_d) + b * x_d * (1 - y_d) + c * (1 - x_d) * y_d + d * x_d * y_d
60
+
61
+ resized = resized.round.clip(image.class::MIN, image.class::MAX) if integer_narray?(image)
62
+ resized = image.class.cast(resized) unless resized.is_a?(image.class)
63
+ resized.reshape(new_height, new_width)
64
+ end
65
+
66
+ INTEGER_NARRAY = %w[Numo::Int8 Numo::Int16 Numo::Int32 Numo::Int64
67
+ Numo::UInt8 Numo::UInt16 Numo::UInt32 Numo::UInt64].freeze
68
+
69
+ private_constant :INTEGER_NARRAY
70
+
71
+ def integer_narray?(image)
72
+ INTEGER_NARRAY.include?(image.class.to_s)
73
+ end
74
+
75
+ private_class_method :bilinear_resize, :integer_narray?
76
+ end
77
+ end
@@ -3,5 +3,5 @@
3
3
  # Magro is an image processing library in Ruby.
4
4
  module Magro
5
5
  # The version of Magro you are using.
6
- VERSION = '0.1.0'
6
+ VERSION = '0.4.0'
7
7
  end
@@ -8,12 +8,22 @@ Gem::Specification.new do |spec|
8
8
  spec.authors = ['yoshoku']
9
9
  spec.email = ['yoshoku@outlook.com']
10
10
 
11
- spec.summary = 'Magro is an image processing library for Ruby.'
12
- spec.description = 'Magro is an image processing library for Ruby.'
11
+ spec.summary = 'Magro is a minimal image processing library for Ruby.'
12
+ spec.description = <<~MSG
13
+ Magro is a minimal image processing library for Ruby.
14
+ Magro uses Numo::NArray arrays as image objects and provides basic image processing functions.
15
+ Current supporting features are reading and writing JPEG and PNG images,
16
+ image resizing with bilinear interpolation method, and image filtering.
17
+ MSG
13
18
 
14
19
  spec.homepage = 'https://github.com/yoshoku/magro'
15
20
  spec.license = 'BSD-3-Clause'
16
21
 
22
+ spec.metadata['homepage_uri'] = spec.homepage
23
+ spec.metadata['source_code_uri'] = 'https://github.com/yoshoku/magro'
24
+ spec.metadata['changelog_uri'] = 'https://github.com/yoshoku/magro/blob/master/CHANGELOG.md'
25
+ spec.metadata['documentation_uri'] = 'https://yoshoku.github.io/magro/doc/'
26
+
17
27
  # Specify which files should be added to the gem when it is released.
18
28
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
19
29
  spec.files = Dir.chdir(File.expand_path(__dir__)) do
@@ -26,9 +36,4 @@ Gem::Specification.new do |spec|
26
36
  spec.extensions = ['ext/magro/extconf.rb']
27
37
 
28
38
  spec.add_runtime_dependency 'numo-narray', '~> 0.9.1'
29
-
30
- spec.add_development_dependency 'bundler', '~> 2.0'
31
- spec.add_development_dependency 'rake', '~> 10.0'
32
- spec.add_development_dependency 'rake-compiler', '~> 1.0'
33
- spec.add_development_dependency 'rspec', '~> 3.0'
34
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: magro
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - yoshoku
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-08-04 00:00:00.000000000 Z
11
+ date: 2020-07-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: numo-narray
@@ -24,63 +24,11 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 0.9.1
27
- - !ruby/object:Gem::Dependency
28
- name: bundler
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - "~>"
32
- - !ruby/object:Gem::Version
33
- version: '2.0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - "~>"
39
- - !ruby/object:Gem::Version
40
- version: '2.0'
41
- - !ruby/object:Gem::Dependency
42
- name: rake
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '10.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '10.0'
55
- - !ruby/object:Gem::Dependency
56
- name: rake-compiler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '1.0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '1.0'
69
- - !ruby/object:Gem::Dependency
70
- name: rspec
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '3.0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '3.0'
83
- description: Magro is an image processing library for Ruby.
27
+ description: |
28
+ Magro is a minimal image processing library for Ruby.
29
+ Magro uses Numo::NArray arrays as image objects and provides basic image processing functions.
30
+ Current supporting features are reading and writing JPEG and PNG images,
31
+ image resizing with bilinear interpolation method, and image filtering.
84
32
  email:
85
33
  - yoshoku@outlook.com
86
34
  executables: []
@@ -88,6 +36,7 @@ extensions:
88
36
  - ext/magro/extconf.rb
89
37
  extra_rdoc_files: []
90
38
  files:
39
+ - ".coveralls.yml"
91
40
  - ".gitignore"
92
41
  - ".rspec"
93
42
  - ".travis.yml"
@@ -100,17 +49,25 @@ files:
100
49
  - bin/console
101
50
  - bin/setup
102
51
  - ext/magro/extconf.rb
52
+ - ext/magro/imgrw.c
53
+ - ext/magro/imgrw.h
103
54
  - ext/magro/magro.c
104
55
  - ext/magro/magro.h
105
56
  - lib/magro.rb
57
+ - lib/magro/filter.rb
106
58
  - lib/magro/io.rb
59
+ - lib/magro/transform.rb
107
60
  - lib/magro/version.rb
108
61
  - magro.gemspec
109
62
  homepage: https://github.com/yoshoku/magro
110
63
  licenses:
111
64
  - BSD-3-Clause
112
- metadata: {}
113
- post_install_message:
65
+ metadata:
66
+ homepage_uri: https://github.com/yoshoku/magro
67
+ source_code_uri: https://github.com/yoshoku/magro
68
+ changelog_uri: https://github.com/yoshoku/magro/blob/master/CHANGELOG.md
69
+ documentation_uri: https://yoshoku.github.io/magro/doc/
70
+ post_install_message:
114
71
  rdoc_options: []
115
72
  require_paths:
116
73
  - lib
@@ -125,9 +82,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
82
  - !ruby/object:Gem::Version
126
83
  version: '0'
127
84
  requirements: []
128
- rubyforge_project:
129
- rubygems_version: 2.6.14.4
130
- signing_key:
85
+ rubygems_version: 3.1.2
86
+ signing_key:
131
87
  specification_version: 4
132
- summary: Magro is an image processing library for Ruby.
88
+ summary: Magro is a minimal image processing library for Ruby.
133
89
  test_files: []