pnm 0.4.1 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: c8d01685f2bc40a0f3f6a862f25e2c6001d8f6a3
4
- data.tar.gz: 2817af37b0e92b2daa766334fa9363c8ca953315
2
+ SHA256:
3
+ metadata.gz: b5d51775ecf00c43299084927b3ce8e0fb182127accb347f25806a840e7389a4
4
+ data.tar.gz: 0ac3e779bb1af09853cf6429fdb0fe5ec1a6d5e951eaf0f227e97e7c81b9f053
5
5
  SHA512:
6
- metadata.gz: 1dd632513336784b890a6d7c2c81717bcabf12f511f0cdff8b9d93ee38bfbf3ffd1e5cd29463830ea4e190973d147bddc5d9bd297c6aec7dec4ffef670efbea9
7
- data.tar.gz: 9051a2ec9005e3100f56b2363c311d4fef8626458b1d0a99c0cd0d3c3c22b1417725ec3cbe34a7f802118f5665582c594deae2b3c4194d6da4fb124eb59a8c98
6
+ metadata.gz: aa8584a19eb7f6aad9513cc379a1700dfe9e1f5b9e58feaba2ae80e18c670050f9ba3fbd39f7528f3bad2bd59eb31ba491ae0f8673669454cbae92b4f996c416
7
+ data.tar.gz: 87e0d5751baa549e9f2f14be763d6b77a40bde876c23f9ee44df5ef8b1ec642024091e6d06e32172aef09e33323bca2cf5f1945e8cecf7e7aa9945629f448811
data/README.md CHANGED
@@ -20,17 +20,17 @@ Examples
20
20
  Create a PGM grayscale image from a two-dimensional array of gray values:
21
21
 
22
22
  ``` ruby
23
- require 'pnm'
23
+ require "pnm"
24
24
 
25
25
  # pixel data
26
26
  pixels = [[ 0, 10, 20],
27
27
  [10, 20, 30]]
28
28
 
29
- # optional settings
30
- options = {:maxgray => 30, :comment => 'Test Image'}
31
-
32
29
  # create the image object
33
- image = PNM.create(pixels, options)
30
+ image = PNM.create(pixels)
31
+
32
+ # create the image with additional optional settings
33
+ image = PNM.create(pixels, maxgray: 30, comment: "Test Image")
34
34
 
35
35
  # retrieve some image properties
36
36
  image.info # => "PGM 3x2 Grayscale"
@@ -49,19 +49,20 @@ and available options.
49
49
  Write an image to a file:
50
50
 
51
51
  ``` ruby
52
- image.write('test.pgm')
52
+ image.write("test.pgm")
53
+ image.write("test", add_extension: true) # adds the appropriate file extension
53
54
 
54
- # use ASCII or "plain" format (default is binary)
55
- image.write('test.pgm', :ascii)
55
+ # use ASCII or "plain" format (default is :binary)
56
+ image.write("test.pgm", encoding: :ascii)
56
57
 
57
58
  # write to an I/O stream
58
- File.open('test.pgm', 'w') {|f| image.write(f) }
59
+ File.open("test.pgm", "w") {|f| image.write(f) }
59
60
  ```
60
61
 
61
62
  Read an image from a file (returns a PNM::Image object):
62
63
 
63
64
  ``` ruby
64
- image = PNM.read('test.pgm')
65
+ image = PNM.read("test.pgm")
65
66
  image.comment # => "Test Image"
66
67
  image.maxgray # => 30
67
68
  image.pixels # => [[0, 10, 20], [10, 20, 30]]
@@ -70,8 +71,14 @@ image.pixels # => [[0, 10, 20], [10, 20, 30]]
70
71
  Force an image type:
71
72
 
72
73
  ``` ruby
73
- image = PNM.create([[0, 1],[1, 0]], :type => :ppm)
74
- image.info # => "PPM 2x2 Color"
74
+ color_image = PNM.create([[0, 1],[1, 0]], type: :ppm)
75
+ color_image.info # => "PPM 2x2 Color"
76
+ ```
77
+
78
+ Check equality of two images:
79
+
80
+ ``` ruby
81
+ color_image == image # => false
75
82
  ```
76
83
 
77
84
  Installation
@@ -91,17 +98,15 @@ Requirements
91
98
 
92
99
  - PNM has been tested with
93
100
 
94
- - Ruby 2.2,
95
- - Ruby 2.1,
96
- - Ruby 2.0.0,
97
- - Ruby 1.9.3,
98
- - JRuby 1.7.18,
99
- - Rubinius 2.2.10.
101
+ - Ruby 2.7
102
+ - Ruby 2.6, 2.5, 2.4, 2.3, 2.2, 2.1, 2.0.0,
103
+ - JRuby 9.2.13.0.
100
104
 
101
105
  Documentation
102
106
  -------------
103
107
 
104
- Documentation should be available via `ri PNM`.
108
+ Documentation should be available via `ri PNM` or can be found at
109
+ [www.rubydoc.info/gems/pnm/](http://www.rubydoc.info/gems/pnm/).
105
110
 
106
111
  Reporting bugs
107
112
  --------------
@@ -111,7 +116,7 @@ Report bugs on the PNM home page: <https://github.com/stomar/pnm/>
111
116
  License
112
117
  -------
113
118
 
114
- Copyright &copy; 2013-2015 Marcus Stollsteimer
119
+ Copyright &copy; 2013-2020 Marcus Stollsteimer
115
120
 
116
121
  `PNM` is free software: you can redistribute it and/or modify
117
122
  it under the terms of the GNU General Public License version 3 or later (GPLv3+),
data/Rakefile CHANGED
@@ -1,34 +1,35 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # rakefile for the PNM library.
2
4
  #
3
- # Copyright (C) 2013-2015 Marcus Stollsteimer
5
+ # Copyright (C) 2013-2020 Marcus Stollsteimer
4
6
 
5
- require 'rake/testtask'
7
+ require "rake/testtask"
6
8
 
7
- require_relative 'lib/pnm'
9
+ require_relative "lib/pnm"
8
10
 
9
11
 
10
12
  def gemspec_file
11
- 'pnm.gemspec'
13
+ "pnm.gemspec"
12
14
  end
13
15
 
14
16
 
15
- task :default => [:test]
17
+ task default: :test
16
18
 
17
19
  Rake::TestTask.new do |t|
18
- t.pattern = 'test/**/test_*.rb'
19
- t.ruby_opts << '-rubygems'
20
+ t.pattern = "test/**/test_*.rb"
20
21
  t.verbose = true
21
22
  t.warning = true
22
23
  end
23
24
 
24
25
 
25
- desc 'Run benchmarks'
26
+ desc "Run benchmarks"
26
27
  task :benchmark do
27
- Dir['benchmark/**/bm_*.rb'].each {|f| require_relative f }
28
+ Dir["benchmark/**/bm_*.rb"].each {|f| require_relative f }
28
29
  end
29
30
 
30
31
 
31
- desc 'Build gem'
32
+ desc "Build gem"
32
33
  task :build do
33
34
  sh "gem build #{gemspec_file}"
34
35
  end
@@ -1,11 +1,14 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
2
4
  # bm_converter.rb: Benchmarks for the PNM library.
3
5
  #
4
- # Copyright (C) 2013-2015 Marcus Stollsteimer
6
+ # Copyright (C) 2013-2020 Marcus Stollsteimer
5
7
 
6
- require 'benchmark'
7
- require_relative '../lib/pnm'
8
+ require "benchmark"
9
+ require_relative "../lib/pnm"
8
10
 
11
+ # Benchmarks for PNM::Converter.
9
12
  class ConverterBenchmark
10
13
 
11
14
  def initialize
@@ -14,7 +17,7 @@ class ConverterBenchmark
14
17
 
15
18
  @srcpath = File.dirname(__FILE__)
16
19
 
17
- print 'Initializing test data...'
20
+ print "Initializing test data..."
18
21
  @pbm_image = PNM.read(File.expand_path("#{@srcpath}/random_image.pbm"))
19
22
  @pgm_image = PNM.read(File.expand_path("#{@srcpath}/random_image.pgm"))
20
23
  @ppm_image = PNM.read(File.expand_path("#{@srcpath}/random_image.ppm"))
@@ -32,7 +35,7 @@ class ConverterBenchmark
32
35
  run_benchmark(@pgm_image)
33
36
  run_benchmark(@ppm_image)
34
37
 
35
- puts "\nTotal: " <<
38
+ puts "\nTotal: ".dup <<
36
39
  @user.round(2).to_s.ljust(11) <<
37
40
  @system.round(2).to_s.ljust(11) <<
38
41
  @total.round(2).to_s
@@ -40,43 +43,44 @@ class ConverterBenchmark
40
43
 
41
44
  def run_benchmark(image)
42
45
  type = image.type
43
- type_string = type.upcase
44
46
  width = image.width
45
47
  height = image.height
46
48
  array = image.pixels
47
49
  ascii = PNM::Converter.array2ascii(array)
48
50
  binary = PNM::Converter.array2binary(type, array)
51
+ type_string = type.upcase
49
52
 
50
53
  puts
51
54
 
52
55
  Benchmark.bm(18) do |bm|
53
- bm.report("#{type_string} / ascii2array") {
56
+
57
+ bm.report("#{type_string} / ascii2array") do
54
58
  @repetitions.times do
55
59
  PNM::Converter.ascii2array(type, width, height, ascii)
56
60
  end
57
- }
61
+ end
58
62
 
59
- bm.report("#{type_string} / array2ascii") {
63
+ bm.report("#{type_string} / array2ascii") do
60
64
  @repetitions.times do
61
65
  PNM::Converter.array2ascii(array)
62
66
  end
63
- }
67
+ end
64
68
 
65
- bm.report("#{type_string} / binary2array") {
69
+ bm.report("#{type_string} / binary2array") do
66
70
  @repetitions.times do
67
71
  PNM::Converter.binary2array(type, width, height, binary)
68
72
  end
69
- }
73
+ end
70
74
 
71
- bm.report("#{type_string} / array2binary") {
75
+ bm.report("#{type_string} / array2binary") do
72
76
  @repetitions.times do
73
77
  PNM::Converter.array2binary(type, array)
74
78
  end
75
- }
79
+ end
76
80
 
77
- @user += bm.list.map {|tms| tms.utime }.reduce(:+)
78
- @system += bm.list.map {|tms| tms.stime }.reduce(:+)
79
- @total += bm.list.map {|tms| tms.total }.reduce(:+)
81
+ @user += bm.list.map(&:utime).reduce(:+)
82
+ @system += bm.list.map(&:stime).reduce(:+)
83
+ @total += bm.list.map(&:total).reduce(:+)
80
84
  end
81
85
  end
82
86
  end
data/lib/pnm.rb CHANGED
@@ -1,12 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # = pnm.rb - create/read/write PNM image files (PBM, PGM, PPM)
2
4
  #
3
5
  # See PNM module for documentation.
4
6
 
5
- require_relative 'pnm/version'
6
- require_relative 'pnm/image'
7
- require_relative 'pnm/parser'
8
- require_relative 'pnm/converter'
9
- require_relative 'pnm/exceptions'
7
+ require_relative "pnm/version"
8
+ require_relative "pnm/image"
9
+ require_relative "pnm/parser"
10
+ require_relative "pnm/converter"
11
+ require_relative "pnm/exceptions"
10
12
 
11
13
 
12
14
  # PNM is a pure Ruby library for creating, reading,
@@ -26,17 +28,17 @@ require_relative 'pnm/exceptions'
26
28
  #
27
29
  # Create a PGM grayscale image from a two-dimensional array of gray values:
28
30
  #
29
- # require 'pnm'
31
+ # require "pnm"
30
32
  #
31
33
  # # pixel data
32
34
  # pixels = [[ 0, 10, 20],
33
35
  # [10, 20, 30]]
34
36
  #
35
- # # optional settings
36
- # options = {:maxgray => 30, :comment => 'Test Image'}
37
- #
38
37
  # # create the image object
39
- # image = PNM.create(pixels, options)
38
+ # image = PNM.create(pixels)
39
+ #
40
+ # # create the image with additional optional settings
41
+ # image = PNM.create(pixels, maxgray: 30, comment: "Test Image")
40
42
  #
41
43
  # # retrieve some image properties
42
44
  # image.info # => "PGM 3x2 Grayscale"
@@ -53,25 +55,30 @@ require_relative 'pnm/exceptions'
53
55
  #
54
56
  # Write an image to a file:
55
57
  #
56
- # image.write('test.pgm')
58
+ # image.write("test.pgm")
59
+ # image.write("test", add_extension: true) # adds the appropriate file extension
57
60
  #
58
- # # use ASCII or "plain" format (default is binary)
59
- # image.write('test.pgm', :ascii)
61
+ # # use ASCII or "plain" format (default is :binary)
62
+ # image.write("test.pgm", encoding: :ascii)
60
63
  #
61
64
  # # write to an I/O stream
62
- # File.open('test.pgm', 'w') {|f| image.write(f) }
65
+ # File.open("test.pgm", "w") {|f| image.write(f) }
63
66
  #
64
67
  # Read an image from a file (returns a PNM::Image object):
65
68
  #
66
- # image = PNM.read('test.pgm')
69
+ # image = PNM.read("test.pgm")
67
70
  # image.comment # => "Test Image"
68
71
  # image.maxgray # => 30
69
72
  # image.pixels # => [[0, 10, 20], [10, 20, 30]]
70
73
  #
71
74
  # Force an image type:
72
75
  #
73
- # image = PNM.create([[0, 1],[1, 0]], :type => :ppm)
74
- # image.info # => "PPM 2x2 Color"
76
+ # color_image = PNM.create([[0, 1],[1, 0]], type: :ppm)
77
+ # color_image.info # => "PPM 2x2 Color"
78
+ #
79
+ # Check equality of two images:
80
+ #
81
+ # color_image == image # => false
75
82
  #
76
83
  # == See also
77
84
  #
@@ -80,28 +87,28 @@ require_relative 'pnm/exceptions'
80
87
  #
81
88
  # == Author
82
89
  #
83
- # Copyright (C) 2013-2015 Marcus Stollsteimer
90
+ # Copyright (C) 2013-2020 Marcus Stollsteimer
84
91
  #
85
92
  # License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
86
93
  #
87
94
  module PNM
88
95
 
89
- LIBNAME = 'pnm'
90
- HOMEPAGE = 'https://github.com/stomar/pnm'
91
- TAGLINE = 'create/read/write PNM image files (PBM, PGM, PPM)'
96
+ LIBNAME = "pnm"
97
+ HOMEPAGE = "https://github.com/stomar/pnm"
98
+ TAGLINE = "create/read/write PNM image files (PBM, PGM, PPM)"
92
99
 
93
- COPYRIGHT = <<-copyright.gsub(/^ +/, '')
94
- Copyright (C) 2013-2015 Marcus Stollsteimer.
100
+ COPYRIGHT = <<-TEXT.gsub(/^ +/, "")
101
+ Copyright (C) 2013-2020 Marcus Stollsteimer.
95
102
  License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
96
103
  This is free software: you are free to change and redistribute it.
97
104
  There is NO WARRANTY, to the extent permitted by law.
98
- copyright
105
+ TEXT
99
106
 
100
107
  # Reads an image from +file+ (a filename or an IO object).
101
108
  #
102
109
  # Returns a PNM::Image object.
103
110
  def self.read(file)
104
- if file.kind_of?(String)
111
+ if file.is_a?(String)
105
112
  raw_data = File.binread(file)
106
113
  elsif file.respond_to?(:binmode)
107
114
  file.binmode
@@ -112,26 +119,20 @@ module PNM
112
119
 
113
120
  content = Parser.parse(raw_data)
114
121
 
115
- case content[:magic_number]
116
- when 'P1'
117
- type = :pbm
118
- encoding = :ascii
119
- when 'P2'
120
- type = :pgm
121
- encoding = :ascii
122
- when 'P3'
123
- type = :ppm
124
- encoding = :ascii
125
- when 'P4'
126
- type = :pbm
127
- encoding = :binary
128
- when 'P5'
129
- type = :pgm
130
- encoding = :binary
131
- when 'P6'
132
- type = :ppm
133
- encoding = :binary
134
- end
122
+ type, encoding = case content[:magic_number]
123
+ when "P1"
124
+ [:pbm, :ascii]
125
+ when "P2"
126
+ [:pgm, :ascii]
127
+ when "P3"
128
+ [:ppm, :ascii]
129
+ when "P4"
130
+ [:pbm, :binary]
131
+ when "P5"
132
+ [:pgm, :binary]
133
+ when "P6"
134
+ [:ppm, :binary]
135
+ end
135
136
 
136
137
  width = content[:width]
137
138
  height = content[:height]
@@ -142,10 +143,9 @@ module PNM
142
143
  Converter.binary2array(type, width, height, content[:data])
143
144
  end
144
145
 
145
- options = {:type => type, :maxgray => maxgray}
146
- options[:comment] = content[:comments].join("\n") if content[:comments]
146
+ comment = content[:comments].join("\n") if content[:comments]
147
147
 
148
- create(pixels, options)
148
+ create(pixels, type: type, maxgray: maxgray, comment: comment)
149
149
  end
150
150
 
151
151
  # Creates an image from a two-dimensional array of bilevel,
@@ -161,7 +161,7 @@ module PNM
161
161
  # corresponding to red, green, and blue (RGB);
162
162
  # a value of 0 means that the color is turned off.
163
163
  #
164
- # Optional settings that can be specified in the +options+ hash:
164
+ # Optional settings:
165
165
  #
166
166
  # +type+:: The type of the image (+:pbm+, +:pgm+, or +:ppm+).
167
167
  # By explicitly setting +type+, PGM images can be
@@ -179,16 +179,16 @@ module PNM
179
179
  # +comment+:: A multiline comment string.
180
180
  #
181
181
  # Returns a PNM::Image object.
182
- def self.create(pixels, options = {})
183
- Image.create(pixels, options)
182
+ def self.create(pixels, type: nil, maxgray: nil, comment: nil)
183
+ Image.create(pixels, type: type, maxgray: maxgray, comment: comment)
184
184
  end
185
185
 
186
186
  # @private
187
187
  def self.magic_number # :nodoc:
188
188
  {
189
- :pbm => {:ascii => 'P1', :binary => 'P4'},
190
- :pgm => {:ascii => 'P2', :binary => 'P5'},
191
- :ppm => {:ascii => 'P3', :binary => 'P6'}
189
+ pbm: { ascii: "P1", binary: "P4" },
190
+ pgm: { ascii: "P2", binary: "P5" },
191
+ ppm: { ascii: "P3", binary: "P6" }
192
192
  }
193
193
  end
194
194
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module PNM
2
4
 
3
5
  # @private
@@ -30,12 +32,12 @@ module PNM
30
32
  values = convert_to_integers(data, type)
31
33
  assert_data_size(values.size, values_per_row * height)
32
34
 
33
- case type
34
- when :pbm, :pgm
35
- pixel_matrix = values.each_slice(width).to_a
36
- when :ppm
37
- pixel_matrix = values.each_slice(3 * width).map {|row| row.each_slice(3).to_a }
38
- end
35
+ pixel_matrix = case type
36
+ when :pbm, :pgm
37
+ values.each_slice(width).to_a
38
+ when :ppm
39
+ values.each_slice(3 * width).map {|row| row.each_slice(3).to_a }
40
+ end
39
41
 
40
42
  pixel_matrix
41
43
  end
@@ -49,22 +51,21 @@ module PNM
49
51
  # Returns a two-dimensional array of bilevel, gray, or RGB values.
50
52
  def self.binary2array(type, width, height, data)
51
53
  bytes_per_row = byte_width(type, width)
54
+ expected_size = bytes_per_row * height
52
55
 
53
- if data.size == bytes_per_row * height + 1 && data[-1] =~ /[ \t\r\n]/
54
- data.slice!(-1)
55
- end
56
+ data.slice!(-1) if data.size == expected_size + 1 && data[-1] =~ /[ \t\r\n]/
56
57
 
57
- assert_data_size(data.size, bytes_per_row * height)
58
+ assert_data_size(data.size, expected_size)
58
59
 
59
- case type
60
- when :pbm
61
- rows = data.scan(/.{#{bytes_per_row}}/m)
62
- pixel_matrix = rows.map {|row| row.unpack('B*').first[0, width].each_char.map {|char| char.to_i } }
63
- when :pgm
64
- pixel_matrix = data.each_byte.each_slice(bytes_per_row).to_a
65
- when :ppm
66
- pixel_matrix = data.each_byte.each_slice(bytes_per_row).map {|row| row.each_slice(3).to_a }
67
- end
60
+ pixel_matrix = case type
61
+ when :pbm
62
+ rows = data.scan(/.{#{bytes_per_row}}/m)
63
+ rows.map {|row| row.unpack("B*").first[0, width].each_char.map(&:to_i) }
64
+ when :pgm
65
+ data.each_byte.each_slice(bytes_per_row).to_a
66
+ when :ppm
67
+ data.each_byte.each_slice(bytes_per_row).map {|row| row.each_slice(3).to_a }
68
+ end
68
69
 
69
70
  pixel_matrix
70
71
  end
@@ -75,12 +76,12 @@ module PNM
75
76
  #
76
77
  # Returns a string containing the pixel data in ASCII format.
77
78
  def self.array2ascii(data)
78
- case data.first.first
79
- when Array
80
- data_string = data.map {|row| row.flatten.join(' ') }.join("\n")
81
- else
82
- data_string = data.map {|row| row.join(' ') }.join("\n")
83
- end
79
+ data_string = case data.first.first
80
+ when Array
81
+ data.map {|row| row.flatten.join(" ") }.join("\n")
82
+ else
83
+ data.map {|row| row.join(" ") }.join("\n")
84
+ end
84
85
 
85
86
  data_string << "\n"
86
87
  end
@@ -94,38 +95,34 @@ module PNM
94
95
  def self.array2binary(type, data)
95
96
  height = data.size
96
97
 
97
- if type == :pbm
98
- binary_rows = data.map {|row| row.join }
99
- data_string = binary_rows.pack('B*' * height)
100
- else
101
- data_string = data.flatten.pack('C*')
102
- end
98
+ data_string = if type == :pbm
99
+ binary_rows = data.map(&:join)
100
+ binary_rows.pack("B*" * height)
101
+ else
102
+ data.flatten.pack("C*")
103
+ end
103
104
 
104
105
  data_string
105
106
  end
106
107
 
107
108
  def self.convert_to_integers(data, type)
108
- if type == :pbm
109
- values_as_string = data.gsub(/[ \t\r\n]+/, '').split('')
110
- else
111
- values_as_string = data.gsub(/\A[ \t\r\n]+/, '').split(/[ \t\r\n]+/)
112
- end
109
+ values_as_string = if type == :pbm
110
+ data.gsub(/[ \t\r\n]+/, "").split("")
111
+ else
112
+ data.gsub(/\A[ \t\r\n]+/, "").split(/[ \t\r\n]+/)
113
+ end
113
114
 
114
- values_as_string.map do |value|
115
- Integer(value)
116
- end
115
+ values_as_string.map {|value| Integer(value) }
117
116
  rescue ::ArgumentError => e
118
- if e.message.start_with?('invalid value for Integer')
119
- raise PNM::DataError, "invalid pixel value: Integer expected"
120
- else
121
- raise
122
- end
117
+ raise unless e.message.start_with?("invalid value for Integer")
118
+
119
+ raise PNM::DataError, "invalid pixel value: Integer expected"
123
120
  end
124
121
 
125
122
  def self.assert_data_size(actual, expected)
126
- unless actual == expected
127
- raise PNM::DataSizeError, 'data size does not match expected size'
128
- end
123
+ return if actual == expected
124
+
125
+ raise PNM::DataSizeError, "data size does not match expected size"
129
126
  end
130
127
  end
131
128
  end