magro 0.1.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []