pnm 0.3.4 → 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.
- checksums.yaml +4 -4
- data/README.md +3 -3
- data/lib/pnm.rb +39 -4
- data/lib/pnm/image.rb +213 -108
- data/lib/pnm/version.rb +2 -2
- data/test/test_exceptions.rb +22 -22
- data/test/test_image.rb +23 -23
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b65acf13eeae10d44cdb6819968ab967f240ec92
|
4
|
+
data.tar.gz: ac881cf1d053ee6110a2624c62092d1e93623414
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: aa018e4a6f04380252ba21c8a8e572138f55f78c57c2b67a1a2bedf7afdd3108287a2c283654177e163e9bc8d5df0ec3ca67a6906a4c678cd7bcf76b30499f63
|
7
|
+
data.tar.gz: 30ac4d58dd7ced728223abec188313480c19043908548a7a550c490c1dc745c47156886c22685c5d523ffbc782ea640289b5355a829c0f68c903110b79ff407f
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ pixels = [[ 0, 10, 20],
|
|
30
30
|
options = {:maxgray => 30, :comment => 'Test Image'}
|
31
31
|
|
32
32
|
# create the image object
|
33
|
-
image = PNM
|
33
|
+
image = PNM.create(pixels, options)
|
34
34
|
|
35
35
|
# retrieve some image properties
|
36
36
|
image.info # => "PGM 3x2 Grayscale"
|
@@ -43,7 +43,7 @@ Note that for PBM bilevel images a pixel value of 0 signifies white
|
|
43
43
|
(and 1 signifies black), whereas for PGM and PPM images a value of 0
|
44
44
|
signifies black.
|
45
45
|
|
46
|
-
See PNM
|
46
|
+
See PNM.create for a more detailed description of pixel data formats
|
47
47
|
and available options.
|
48
48
|
|
49
49
|
Write an image to a file:
|
@@ -70,7 +70,7 @@ image.pixels # => [[0, 10, 20], [10, 20, 30]]
|
|
70
70
|
Force an image type:
|
71
71
|
|
72
72
|
``` ruby
|
73
|
-
image = PNM
|
73
|
+
image = PNM.create([[0, 1],[1, 0]], :type => :ppm)
|
74
74
|
image.info # => "PPM 2x2 Color"
|
75
75
|
```
|
76
76
|
|
data/lib/pnm.rb
CHANGED
@@ -36,7 +36,7 @@ require_relative 'pnm/exceptions'
|
|
36
36
|
# options = {:maxgray => 30, :comment => 'Test Image'}
|
37
37
|
#
|
38
38
|
# # create the image object
|
39
|
-
# image = PNM
|
39
|
+
# image = PNM.create(pixels, options)
|
40
40
|
#
|
41
41
|
# # retrieve some image properties
|
42
42
|
# image.info # => "PGM 3x2 Grayscale"
|
@@ -48,7 +48,7 @@ require_relative 'pnm/exceptions'
|
|
48
48
|
# (and 1 signifies black), whereas for PGM and PPM images a value of 0
|
49
49
|
# signifies black.
|
50
50
|
#
|
51
|
-
# See PNM
|
51
|
+
# See PNM.create for a more detailed description of pixel data formats
|
52
52
|
# and available options.
|
53
53
|
#
|
54
54
|
# Write an image to a file:
|
@@ -70,7 +70,7 @@ require_relative 'pnm/exceptions'
|
|
70
70
|
#
|
71
71
|
# Force an image type:
|
72
72
|
#
|
73
|
-
# image = PNM
|
73
|
+
# image = PNM.create([[0, 1],[1, 0]], :type => :ppm)
|
74
74
|
# image.info # => "PPM 2x2 Color"
|
75
75
|
#
|
76
76
|
# == See also
|
@@ -145,7 +145,42 @@ module PNM
|
|
145
145
|
options = {:type => type, :maxgray => maxgray}
|
146
146
|
options[:comment] = content[:comments].join("\n") if content[:comments]
|
147
147
|
|
148
|
-
|
148
|
+
create(pixels, options)
|
149
|
+
end
|
150
|
+
|
151
|
+
# Creates an image from a two-dimensional array of bilevel,
|
152
|
+
# gray, or RGB values.
|
153
|
+
# The image type is guessed from the provided pixel data,
|
154
|
+
# unless it is explicitly set with the +type+ option.
|
155
|
+
#
|
156
|
+
# +pixels+:: The pixel data, given as a two-dimensional array of
|
157
|
+
#
|
158
|
+
# * for PBM: bilevel values of 0 (white) or 1 (black),
|
159
|
+
# * for PGM: gray values between 0 (black) and +maxgray+ (white),
|
160
|
+
# * for PPM: an array of 3 values between 0 and +maxgray+,
|
161
|
+
# corresponding to red, green, and blue (RGB);
|
162
|
+
# a value of 0 means that the color is turned off.
|
163
|
+
#
|
164
|
+
# Optional settings that can be specified in the +options+ hash:
|
165
|
+
#
|
166
|
+
# +type+:: The type of the image (+:pbm+, +:pgm+, or +:ppm+).
|
167
|
+
# By explicitly setting +type+, PGM images can be
|
168
|
+
# created from bilevel pixel data, and PPM images can be
|
169
|
+
# created from bilevel or gray pixel data.
|
170
|
+
# String values (<tt>"pbm"</tt>, <tt>"pgm"</tt>,
|
171
|
+
# or <tt>"ppm"</tt>) are also accepted.
|
172
|
+
# +maxgray+:: The maximum gray or color value.
|
173
|
+
# For PGM and PPM, +maxgray+ must be less or equal 255
|
174
|
+
# (the default value).
|
175
|
+
# For bilevel pixel data, setting +maxgray+ to a value
|
176
|
+
# greater than 1 implies a type of +:pgm+.
|
177
|
+
# When +type+ is explicitly set to +:pbm+,
|
178
|
+
# the +maxgray+ setting is disregarded.
|
179
|
+
# +comment+:: A multiline comment string.
|
180
|
+
#
|
181
|
+
# Returns a PNM::Image object.
|
182
|
+
def self.create(pixels, options = {})
|
183
|
+
Image.create(pixels, options)
|
149
184
|
end
|
150
185
|
|
151
186
|
# @private
|
data/lib/pnm/image.rb
CHANGED
@@ -1,15 +1,17 @@
|
|
1
1
|
module PNM
|
2
2
|
|
3
|
-
#
|
3
|
+
# Abstract base class for +PBM+, +PGM+, and +PPM+ images.
|
4
4
|
#
|
5
|
-
# Images can be created from pixel values, see
|
5
|
+
# Images can be created from pixel values, see PNM.create,
|
6
6
|
# or read from a file or I/O stream, see PNM.read.
|
7
7
|
#
|
8
8
|
# See PNM module for examples.
|
9
9
|
class Image
|
10
10
|
|
11
|
-
# The type of the image. See
|
12
|
-
|
11
|
+
# The type of the image. See PNM.create for details.
|
12
|
+
def type
|
13
|
+
# implemented by subclasses
|
14
|
+
end
|
13
15
|
|
14
16
|
# The width of the image in pixels.
|
15
17
|
attr_reader :width
|
@@ -18,11 +20,11 @@ module PNM
|
|
18
20
|
attr_reader :height
|
19
21
|
|
20
22
|
# The maximum gray or color value (for PBM always set to 1).
|
21
|
-
# See
|
23
|
+
# See PNM.create for details.
|
22
24
|
attr_reader :maxgray
|
23
25
|
|
24
26
|
# The pixel data, given as a two-dimensional array.
|
25
|
-
# See
|
27
|
+
# See PNM.create for details.
|
26
28
|
attr_reader :pixels
|
27
29
|
|
28
30
|
# An optional multiline comment string (or +nil+).
|
@@ -30,64 +32,54 @@ module PNM
|
|
30
32
|
|
31
33
|
# Creates an image from a two-dimensional array of bilevel,
|
32
34
|
# gray, or RGB values.
|
33
|
-
# The image type is guessed from the provided pixel data,
|
34
|
-
# unless it is explicitly set with the +type+ option.
|
35
|
-
#
|
36
|
-
# +pixels+:: The pixel data, given as a two-dimensional array of
|
37
|
-
#
|
38
|
-
# * for PBM: bilevel values of 0 (white) or 1 (black),
|
39
|
-
# * for PGM: gray values between 0 (black) and +maxgray+ (white),
|
40
|
-
# * for PPM: an array of 3 values between 0 and +maxgray+,
|
41
|
-
# corresponding to red, green, and blue (RGB);
|
42
|
-
# a value of 0 means that the color is turned off.
|
43
35
|
#
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
@type = options[:type]
|
62
|
-
@maxgray = options[:maxgray]
|
63
|
-
@comment = options[:comment]
|
64
|
-
@pixels = pixels.dup
|
36
|
+
# This method should be called as PNM.create.
|
37
|
+
# See there for a description of pixel data formats
|
38
|
+
# and available options.
|
39
|
+
def self.create(pixels, options = {})
|
40
|
+
assert_valid_array(pixels)
|
41
|
+
assert_valid_maxgray(options[:maxgray])
|
42
|
+
assert_valid_comment(options[:comment])
|
43
|
+
|
44
|
+
type = sanitize_and_assert_valid_type(options[:type])
|
45
|
+
type ||= detect_type(pixels, options[:maxgray])
|
46
|
+
|
47
|
+
# except for type detection, the maxgray option must be ignored for PBM
|
48
|
+
if type == :pbm
|
49
|
+
maxgray = nil
|
50
|
+
else
|
51
|
+
maxgray = options[:maxgray]
|
52
|
+
end
|
65
53
|
|
66
|
-
|
54
|
+
image_class = case type
|
55
|
+
when :pbm
|
56
|
+
PBMImage
|
57
|
+
when :pgm
|
58
|
+
PGMImage
|
59
|
+
when :ppm
|
60
|
+
PPMImage
|
61
|
+
end
|
67
62
|
|
68
|
-
|
69
|
-
|
70
|
-
assert_valid_comment if @comment
|
71
|
-
assert_valid_array
|
63
|
+
image_class.new(pixels, maxgray, options[:comment])
|
64
|
+
end
|
72
65
|
|
66
|
+
class << self
|
67
|
+
protected :new
|
68
|
+
end
|
69
|
+
|
70
|
+
# @private
|
71
|
+
#
|
72
|
+
# Invoked by ::create after basic input validations.
|
73
|
+
def initialize(pixels, maxgray, comment) # :nodoc:
|
74
|
+
@pixels = pixels.dup
|
73
75
|
@width = pixels.first.size
|
74
76
|
@height = pixels.size
|
77
|
+
@maxgray = maxgray || default_maxgray
|
78
|
+
@comment = comment
|
75
79
|
|
76
|
-
|
77
|
-
|
78
|
-
assert_matching_type_and_data
|
79
|
-
|
80
|
-
if @type == :pbm
|
81
|
-
@maxgray = 1
|
82
|
-
else
|
83
|
-
@maxgray ||= 255
|
84
|
-
end
|
85
|
-
|
86
|
-
assert_valid_pixel_values
|
80
|
+
assert_pixel_value_range
|
87
81
|
|
88
|
-
|
89
|
-
@pixels.map! {|row| row.map {|pixel| gray_to_rgb(pixel) } }
|
90
|
-
end
|
82
|
+
post_initialize
|
91
83
|
end
|
92
84
|
|
93
85
|
# Writes the image to +file+ (a filename or an IO object),
|
@@ -119,65 +111,46 @@ module PNM
|
|
119
111
|
|
120
112
|
# Returns a string representation for debugging.
|
121
113
|
def inspect
|
122
|
-
|
123
|
-
"#<%s:0x%x %s>" % [self.class.name, object_id, info]
|
124
|
-
else
|
125
|
-
"#<%s:0x%x %s, maxgray=%d>" % [self.class.name, object_id, info, maxgray]
|
126
|
-
end
|
114
|
+
# implemented by subclasses
|
127
115
|
end
|
128
116
|
|
129
117
|
private
|
130
118
|
|
131
|
-
def
|
132
|
-
|
133
|
-
|
134
|
-
'Bilevel'
|
135
|
-
when :pgm
|
136
|
-
'Grayscale'
|
137
|
-
when :ppm
|
138
|
-
'Color'
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
def detect_type(pixels, maxgray) # :nodoc:
|
143
|
-
if pixels.first.first.kind_of?(Array)
|
144
|
-
:ppm
|
145
|
-
elsif (maxgray && maxgray > 1) || pixels.flatten.max > 1
|
146
|
-
:pgm
|
147
|
-
else
|
148
|
-
:pbm
|
149
|
-
end
|
119
|
+
def self.assert_valid_array(pixels) # :nodoc:
|
120
|
+
assert_array_dimensions(pixels)
|
121
|
+
assert_pixel_types(pixels)
|
150
122
|
end
|
151
123
|
|
152
|
-
def
|
124
|
+
def self.assert_array_dimensions(pixels) # :nodoc:
|
153
125
|
msg = "invalid pixel data: Array expected"
|
154
126
|
raise PNM::ArgumentError, msg unless Array === pixels
|
155
127
|
|
156
128
|
msg = "invalid pixel array"
|
157
|
-
raise PNM::DataError, msg unless Array === pixels.first
|
158
129
|
|
130
|
+
raise PNM::DataError, msg unless pixels.map(&:class).uniq == [Array]
|
159
131
|
width = pixels.first.size
|
160
|
-
|
132
|
+
raise PNM::DataError, msg unless pixels.map(&:size).uniq == [width]
|
133
|
+
end
|
161
134
|
|
162
|
-
|
163
|
-
|
135
|
+
def self.assert_pixel_types(pixels) # :nodoc:
|
136
|
+
pixel_values = pixels.flatten(1)
|
137
|
+
is_color = (Array === pixel_values.first)
|
164
138
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
end
|
139
|
+
if is_color
|
140
|
+
pixel_values.each {|pixel| assert_valid_color_pixel(pixel) }
|
141
|
+
else
|
142
|
+
pixel_values.each {|pixel| assert_valid_pixel(pixel) }
|
170
143
|
end
|
171
144
|
end
|
172
145
|
|
173
|
-
def assert_valid_pixel(pixel) # :nodoc:
|
146
|
+
def self.assert_valid_pixel(pixel) # :nodoc:
|
174
147
|
unless Fixnum === pixel
|
175
148
|
msg = "invalid pixel value: Fixnum expected - #{pixel.inspect}"
|
176
149
|
raise PNM::DataError, msg
|
177
150
|
end
|
178
151
|
end
|
179
152
|
|
180
|
-
def assert_valid_color_pixel(pixel) # :nodoc:
|
153
|
+
def self.assert_valid_color_pixel(pixel) # :nodoc:
|
181
154
|
unless Array === pixel && pixel.map(&:class) == [Fixnum, Fixnum, Fixnum]
|
182
155
|
msg = "invalid pixel value: "
|
183
156
|
msg << "Array of 3 Fixnums expected - #{pixel.inspect}"
|
@@ -186,33 +159,53 @@ module PNM
|
|
186
159
|
end
|
187
160
|
end
|
188
161
|
|
189
|
-
def
|
162
|
+
def self.assert_valid_maxgray(maxgray) # :nodoc:
|
163
|
+
return unless maxgray
|
164
|
+
|
165
|
+
unless Fixnum === maxgray && maxgray > 0 && maxgray <= 255
|
166
|
+
raise PNM::ArgumentError, "invalid maxgray value - #{maxgray.inspect}"
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
def self.assert_valid_comment(comment) # :nodoc:
|
171
|
+
return unless comment
|
172
|
+
|
173
|
+
unless String === comment
|
174
|
+
raise PNM::ArgumentError, "invalid comment value - #{comment.inspect}"
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def self.sanitize_and_assert_valid_type(type) # :nodoc:
|
179
|
+
return unless type
|
180
|
+
|
181
|
+
type = type.to_sym if type.kind_of?(String)
|
182
|
+
|
190
183
|
unless [:pbm, :pgm, :ppm].include?(type)
|
191
184
|
msg = "invalid image type - #{type.inspect}"
|
192
185
|
raise PNM::ArgumentError, msg
|
193
186
|
end
|
194
|
-
end
|
195
187
|
|
196
|
-
|
197
|
-
if Array === pixels.first.first && [:pbm, :pgm].include?(type)
|
198
|
-
msg = "specified type does not match data - #{type.inspect}"
|
199
|
-
raise PNM::DataError, msg
|
200
|
-
end
|
188
|
+
type
|
201
189
|
end
|
202
190
|
|
203
|
-
def
|
204
|
-
|
205
|
-
|
191
|
+
def self.detect_type(pixels, maxgray) # :nodoc:
|
192
|
+
if pixels.first.first.kind_of?(Array)
|
193
|
+
:ppm
|
194
|
+
elsif (maxgray && maxgray > 1) || pixels.flatten.max > 1
|
195
|
+
:pgm
|
196
|
+
else
|
197
|
+
:pbm
|
206
198
|
end
|
207
199
|
end
|
208
200
|
|
209
|
-
def
|
210
|
-
|
211
|
-
|
201
|
+
def assert_grayscale_data # :nodoc:
|
202
|
+
if color_pixels?
|
203
|
+
msg = "specified type does not match RGB data - #{type.inspect}"
|
204
|
+
raise PNM::DataError, msg
|
212
205
|
end
|
213
206
|
end
|
214
207
|
|
215
|
-
def
|
208
|
+
def assert_pixel_value_range # :nodoc:
|
216
209
|
unless pixels.flatten.max <= maxgray
|
217
210
|
raise PNM::DataError, "invalid data: value(s) greater than maxgray"
|
218
211
|
end
|
@@ -221,17 +214,20 @@ module PNM
|
|
221
214
|
end
|
222
215
|
end
|
223
216
|
|
224
|
-
def
|
217
|
+
def header_without_maxgray(encoding) # :nodoc:
|
225
218
|
header = "#{PNM.magic_number[type][encoding]}\n"
|
226
219
|
comment_lines.each do |line|
|
227
220
|
header << (line.empty? ? "#\n" : "# #{line}\n")
|
228
221
|
end
|
229
222
|
header << "#{width} #{height}\n"
|
230
|
-
header << "#{maxgray}\n" unless type == :pbm
|
231
223
|
|
232
224
|
header
|
233
225
|
end
|
234
226
|
|
227
|
+
def header_with_maxgray(encoding) # :nodoc:
|
228
|
+
header_without_maxgray(encoding) << "#{maxgray}\n"
|
229
|
+
end
|
230
|
+
|
235
231
|
def comment_lines # :nodoc:
|
236
232
|
return [] unless comment
|
237
233
|
return [''] if comment.empty?
|
@@ -252,6 +248,115 @@ module PNM
|
|
252
248
|
header(:binary) << data_string
|
253
249
|
end
|
254
250
|
|
251
|
+
def color_pixels? # :nodoc:
|
252
|
+
(pixels.first.first).kind_of?(Array)
|
253
|
+
end
|
254
|
+
|
255
|
+
def inspect_string_with_maxgray # :nodoc:
|
256
|
+
"#<%s:0x%x %s, maxgray=%d>" % [self.class.name, object_id, info, maxgray]
|
257
|
+
end
|
258
|
+
|
259
|
+
def inspect_string_without_maxgray # :nodoc:
|
260
|
+
"#<%s:0x%x %s>" % [self.class.name, object_id, info]
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
|
265
|
+
# Class for +PBM+ images. See the Image class for documentation.
|
266
|
+
class PBMImage < Image
|
267
|
+
|
268
|
+
def type
|
269
|
+
:pbm
|
270
|
+
end
|
271
|
+
|
272
|
+
def inspect
|
273
|
+
inspect_string_without_maxgray
|
274
|
+
end
|
275
|
+
|
276
|
+
private
|
277
|
+
|
278
|
+
def post_initialize # :nodoc:
|
279
|
+
assert_grayscale_data
|
280
|
+
end
|
281
|
+
|
282
|
+
def default_maxgray # :nodoc:
|
283
|
+
1
|
284
|
+
end
|
285
|
+
|
286
|
+
def type_string # :nodoc:
|
287
|
+
"Bilevel"
|
288
|
+
end
|
289
|
+
|
290
|
+
def header(encoding) # :nodoc:
|
291
|
+
header_without_maxgray(encoding)
|
292
|
+
end
|
293
|
+
end
|
294
|
+
|
295
|
+
|
296
|
+
# Class for +PGM+ images. See the Image class for documentation.
|
297
|
+
class PGMImage < Image
|
298
|
+
|
299
|
+
def type
|
300
|
+
:pgm
|
301
|
+
end
|
302
|
+
|
303
|
+
def inspect
|
304
|
+
inspect_string_with_maxgray
|
305
|
+
end
|
306
|
+
|
307
|
+
private
|
308
|
+
|
309
|
+
def post_initialize # :nodoc:
|
310
|
+
assert_grayscale_data
|
311
|
+
end
|
312
|
+
|
313
|
+
def default_maxgray # :nodoc:
|
314
|
+
255
|
315
|
+
end
|
316
|
+
|
317
|
+
def type_string # :nodoc:
|
318
|
+
"Grayscale"
|
319
|
+
end
|
320
|
+
|
321
|
+
def header(encoding) # :nodoc:
|
322
|
+
header_with_maxgray(encoding)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
|
327
|
+
# Class for +PPM+ images. See the Image class for documentation.
|
328
|
+
class PPMImage < Image
|
329
|
+
|
330
|
+
def type
|
331
|
+
:ppm
|
332
|
+
end
|
333
|
+
|
334
|
+
def inspect
|
335
|
+
inspect_string_with_maxgray
|
336
|
+
end
|
337
|
+
|
338
|
+
private
|
339
|
+
|
340
|
+
def post_initialize # :nodoc:
|
341
|
+
convert_pixels_to_color unless color_pixels?
|
342
|
+
end
|
343
|
+
|
344
|
+
def default_maxgray # :nodoc:
|
345
|
+
255
|
346
|
+
end
|
347
|
+
|
348
|
+
def type_string # :nodoc:
|
349
|
+
"Color"
|
350
|
+
end
|
351
|
+
|
352
|
+
def header(encoding) # :nodoc:
|
353
|
+
header_with_maxgray(encoding)
|
354
|
+
end
|
355
|
+
|
356
|
+
def convert_pixels_to_color # :nodoc:
|
357
|
+
pixels.map! {|row| row.map {|pixel| gray_to_rgb(pixel) } }
|
358
|
+
end
|
359
|
+
|
255
360
|
def gray_to_rgb(gray_value) # :nodoc:
|
256
361
|
Array.new(3, gray_value)
|
257
362
|
end
|
data/lib/pnm/version.rb
CHANGED
data/test/test_exceptions.rb
CHANGED
@@ -7,111 +7,111 @@ require 'stringio'
|
|
7
7
|
require 'pnm'
|
8
8
|
|
9
9
|
|
10
|
-
describe 'PNM
|
10
|
+
describe 'PNM.create' do
|
11
11
|
|
12
12
|
it 'raises an exception for invalid data type (String)' do
|
13
13
|
data = '0'
|
14
|
-
lambda { PNM
|
14
|
+
lambda { PNM.create(data) }.must_raise PNM::ArgumentError
|
15
15
|
end
|
16
16
|
|
17
17
|
it 'raises an exception for invalid type' do
|
18
18
|
data = [[0, 0], [0, 0]]
|
19
|
-
lambda { PNM
|
19
|
+
lambda { PNM.create(data, :type => :abc) }.must_raise PNM::ArgumentError
|
20
20
|
end
|
21
21
|
|
22
22
|
it 'raises an exception for invalid maxgray (String)' do
|
23
23
|
data = [[0, 0], [0, 0]]
|
24
|
-
lambda { PNM
|
24
|
+
lambda { PNM.create(data, :maxgray => '255') }.must_raise PNM::ArgumentError
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'raises an exception for invalid maxgray (> 255)' do
|
28
28
|
data = [[0, 0], [0, 0]]
|
29
|
-
lambda { PNM
|
29
|
+
lambda { PNM.create(data, :maxgray => 256) }.must_raise PNM::ArgumentError
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'raises an exception for invalid maxgray (0)' do
|
33
33
|
data = [[0, 0], [0, 0]]
|
34
|
-
lambda { PNM
|
34
|
+
lambda { PNM.create(data, :maxgray => 0) }.must_raise PNM::ArgumentError
|
35
35
|
end
|
36
36
|
|
37
37
|
it 'raises an exception for invalid comment (Fixnum)' do
|
38
38
|
data = [[0, 0], [0, 0]]
|
39
|
-
lambda { PNM
|
39
|
+
lambda { PNM.create(data, :comment => 1) }.must_raise PNM::ArgumentError
|
40
40
|
end
|
41
41
|
|
42
42
|
it 'raises an exception for image type and data mismatch (PBM)' do
|
43
43
|
data = [[[0,0,0], [0,0,0]], [[0,0,0], [0,0,0]]]
|
44
|
-
lambda { PNM
|
44
|
+
lambda { PNM.create(data, :type => :pbm) }.must_raise PNM::DataError
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'raises an exception for image type and data mismatch (PGM)' do
|
48
48
|
data = [[[0,0,0], [0,0,0]], [[0,0,0], [0,0,0]]]
|
49
|
-
lambda { PNM
|
49
|
+
lambda { PNM.create(data, :type => :pgm) }.must_raise PNM::DataError
|
50
50
|
end
|
51
51
|
|
52
52
|
it 'raises an exception for non-integer pixel value (String)' do
|
53
53
|
data = [[0, 0], ['X', 0]]
|
54
|
-
lambda { PNM
|
54
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
55
55
|
end
|
56
56
|
|
57
57
|
it 'raises an exception for non-integer pixel value (Float)' do
|
58
58
|
data = [[0, 0], [0.5, 0]]
|
59
|
-
lambda { PNM
|
59
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
60
60
|
end
|
61
61
|
|
62
62
|
it 'raises an exception for rows of different size' do
|
63
63
|
data = [[0, 0], [0, 0, 0]]
|
64
|
-
lambda { PNM
|
64
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
65
65
|
end
|
66
66
|
|
67
67
|
it 'raises an exception for invalid array dimensions (#1)' do
|
68
68
|
data = [0, 0, 0]
|
69
|
-
lambda { PNM
|
69
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
70
70
|
end
|
71
71
|
|
72
72
|
it 'raises an exception for invalid array dimensions (#2)' do
|
73
73
|
data = [[0, 0], 0, 0]
|
74
|
-
lambda { PNM
|
74
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'raises an exception for invalid array dimensions (#3)' do
|
78
78
|
data = [[0, 0], [0, [0, 0]]]
|
79
|
-
lambda { PNM
|
79
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
80
80
|
end
|
81
81
|
|
82
82
|
it 'raises an exception for invalid array dimensions (#4)' do
|
83
83
|
data = [[[0,0], [0,0]], [[0,0], [0,0]]]
|
84
|
-
lambda { PNM
|
84
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
85
85
|
end
|
86
86
|
|
87
87
|
it 'raises an exception for invalid array dimensions (#5)' do
|
88
88
|
data = [[[0,0,0], [0,0,0]], [0 ,0]]
|
89
|
-
lambda { PNM
|
89
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
90
90
|
end
|
91
91
|
|
92
92
|
it 'raises an exception for invalid array dimensions (#6)' do
|
93
93
|
data = [[[0,0,0], 0], [0 ,0]]
|
94
|
-
lambda { PNM
|
94
|
+
lambda { PNM.create(data) }.must_raise PNM::DataError
|
95
95
|
end
|
96
96
|
|
97
97
|
it 'raises an exception for invalid PBM data (> 1)' do
|
98
98
|
data = [[0, 0], [2, 0]]
|
99
|
-
lambda { PNM
|
99
|
+
lambda { PNM.create(data, :type => :pbm) }.must_raise PNM::DataError
|
100
100
|
end
|
101
101
|
|
102
102
|
it 'raises an exception for invalid PBM data (< 0)' do
|
103
103
|
data = [[0, 0], [-1, 0]]
|
104
|
-
lambda { PNM
|
104
|
+
lambda { PNM.create(data, :type => :pbm) }.must_raise PNM::DataError
|
105
105
|
end
|
106
106
|
|
107
107
|
it 'raises an exception for invalid PGM data (> 255)' do
|
108
108
|
data = [[0, 0], [1, 500]]
|
109
|
-
lambda { PNM
|
109
|
+
lambda { PNM.create(data, :type => :pgm) }.must_raise PNM::DataError
|
110
110
|
end
|
111
111
|
|
112
112
|
it 'raises an exception for invalid PGM data (> maxgray)' do
|
113
113
|
data = [[0, 0], [1, 200]]
|
114
|
-
lambda { PNM
|
114
|
+
lambda { PNM.create(data, :maxgray => 100) }.must_raise PNM::DataError
|
115
115
|
end
|
116
116
|
end
|
117
117
|
|
data/test/test_image.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Copyright (C) 2013-2014 Marcus Stollsteimer
|
4
4
|
|
5
5
|
require 'minitest/autorun'
|
6
|
-
require 'pnm
|
6
|
+
require 'pnm'
|
7
7
|
|
8
8
|
|
9
9
|
describe PNM::Image do
|
@@ -19,7 +19,7 @@ describe PNM::Image do
|
|
19
19
|
[0,0,1,0,0],
|
20
20
|
[0,0,0,0,0]]
|
21
21
|
comment = 'Bilevel'
|
22
|
-
@bilevel = PNM
|
22
|
+
@bilevel = PNM.create(pixels, {:comment => comment})
|
23
23
|
|
24
24
|
pixels = [[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0],
|
25
25
|
[0,1,1,1,0,1,1,1,1,0,1,1,1,1,1,0],
|
@@ -27,95 +27,95 @@ describe PNM::Image do
|
|
27
27
|
[0,0,1,0,0,1,0,0,1,0,1,0,1,0,1,0],
|
28
28
|
[0,0,1,0,0,1,1,1,1,0,1,0,1,0,1,0],
|
29
29
|
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]]
|
30
|
-
@bilevel_2 = PNM
|
30
|
+
@bilevel_2 = PNM.create(pixels)
|
31
31
|
|
32
32
|
pixels = [[ 0, 50,100,150],
|
33
33
|
[ 50,100,150,200],
|
34
34
|
[100,150,200,250]]
|
35
35
|
comment = "Grayscale\n(with multiline comment)"
|
36
|
-
@grayscale = PNM
|
36
|
+
@grayscale = PNM.create(pixels, {:maxgray => 250, :comment => comment})
|
37
37
|
|
38
38
|
pixels = [[65,66], [13,10], [65,66]]
|
39
|
-
@grayscale_crlf = PNM
|
39
|
+
@grayscale_crlf = PNM.create(pixels)
|
40
40
|
|
41
41
|
pixels = [[[0,6,0], [1,5,1], [2,4,2], [3,3,4], [4,2,6]],
|
42
42
|
[[1,5,2], [2,4,2], [3,3,2], [4,2,2], [5,1,2]],
|
43
43
|
[[2,4,6], [3,3,4], [4,2,2], [5,1,1], [6,0,0]]]
|
44
|
-
@color = PNM
|
44
|
+
@color = PNM.create(pixels, {:maxgray => 6})
|
45
45
|
end
|
46
46
|
|
47
47
|
it 'sets maxgray to 1 for bilevel images' do
|
48
|
-
image = PNM
|
48
|
+
image = PNM.create([[0,1,0], [1,0,1]])
|
49
49
|
image.type.must_equal :pbm
|
50
50
|
image.maxgray.must_equal 1
|
51
51
|
end
|
52
52
|
|
53
53
|
it 'sets maxgray by default to 255 for grayscale images' do
|
54
|
-
image = PNM
|
54
|
+
image = PNM.create([[0,10,20], [10,20,30]])
|
55
55
|
image.type.must_equal :pgm
|
56
56
|
image.maxgray.must_equal 255
|
57
57
|
end
|
58
58
|
|
59
59
|
it 'sets maxgray by default to 255 for color images' do
|
60
|
-
image = PNM
|
60
|
+
image = PNM.create([[[0,0,0], [10,10,10]], [[10,10,10], [20,20,20]]])
|
61
61
|
image.type.must_equal :ppm
|
62
62
|
image.maxgray.must_equal 255
|
63
63
|
end
|
64
64
|
|
65
65
|
it 'accepts setting of maxgray to 1 for bilevel images' do
|
66
|
-
image = PNM
|
66
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:maxgray => 1})
|
67
67
|
image.type.must_equal :pbm
|
68
68
|
image.maxgray.must_equal 1
|
69
69
|
end
|
70
70
|
|
71
71
|
it 'ignores invalid maxgray for bilevel images and sets it to 1' do
|
72
|
-
image = PNM
|
72
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:type => :pbm, :maxgray => 255})
|
73
73
|
image.type.must_equal :pbm
|
74
74
|
image.maxgray.must_equal 1
|
75
75
|
end
|
76
76
|
|
77
77
|
it 'can create a grayscale image from bilevel values (using type)' do
|
78
|
-
image = PNM
|
78
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:type => :pgm})
|
79
79
|
image.type.must_equal :pgm
|
80
80
|
image.pixels.must_equal [[0,1,0], [1,0,1]]
|
81
81
|
image.maxgray.must_equal 255
|
82
82
|
end
|
83
83
|
|
84
84
|
it 'also accepts types given as string instead of symbol' do
|
85
|
-
image = PNM
|
85
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:type => "pgm"})
|
86
86
|
image.type.must_equal :pgm
|
87
87
|
end
|
88
88
|
|
89
89
|
it 'can create a grayscale image from bilevel values (using maxgray)' do
|
90
|
-
image = PNM
|
90
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:maxgray => 2})
|
91
91
|
image.type.must_equal :pgm
|
92
92
|
image.pixels.must_equal [[0,1,0], [1,0,1]]
|
93
93
|
image.maxgray.must_equal 2
|
94
94
|
end
|
95
95
|
|
96
96
|
it 'can create a color image from bilevel values' do
|
97
|
-
image = PNM
|
97
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:type => :ppm})
|
98
98
|
image.info.must_match %r{^PPM 3x2 Color}
|
99
99
|
image.pixels.must_equal [[[0,0,0], [1,1,1], [0,0,0]], [[1,1,1], [0,0,0], [1,1,1]]]
|
100
100
|
image.maxgray.must_equal 255
|
101
101
|
end
|
102
102
|
|
103
103
|
it 'can create a color image from bilevel values with a given maxgray' do
|
104
|
-
image = PNM
|
104
|
+
image = PNM.create([[0,1,0], [1,0,1]], {:type => :ppm, :maxgray => 2})
|
105
105
|
image.info.must_match %r{^PPM 3x2 Color}
|
106
106
|
image.pixels.must_equal [[[0,0,0], [1,1,1], [0,0,0]], [[1,1,1], [0,0,0], [1,1,1]]]
|
107
107
|
image.maxgray.must_equal 2
|
108
108
|
end
|
109
109
|
|
110
110
|
it 'can create a color image from gray values' do
|
111
|
-
image = PNM
|
111
|
+
image = PNM.create([[0,3,6], [3,6,9]], {:type => :ppm})
|
112
112
|
image.info.must_match %r{^PPM 3x2 Color}
|
113
113
|
image.pixels.must_equal [[[0,0,0], [3,3,3], [6,6,6]], [[3,3,3], [6,6,6], [9,9,9]]]
|
114
114
|
end
|
115
115
|
|
116
116
|
it 'does not modify the input data for color images created from gray values' do
|
117
117
|
data = [[0,3,6], [3,6,9]]
|
118
|
-
PNM
|
118
|
+
PNM.create(data, {:type => :ppm})
|
119
119
|
data.must_equal [[0,3,6], [3,6,9]]
|
120
120
|
end
|
121
121
|
|
@@ -168,9 +168,9 @@ describe PNM::Image do
|
|
168
168
|
end
|
169
169
|
|
170
170
|
it 'can return meaningful debugging information' do
|
171
|
-
@bilevel.inspect.must_match %r{^#<PNM
|
172
|
-
@grayscale.inspect.must_match %r{^#<PNM
|
173
|
-
@color.inspect.must_match %r{^#<PNM
|
171
|
+
@bilevel.inspect.must_match %r{^#<PNM::\w+Image:0x\h+ PBM 5x6 Bilevel>$}
|
172
|
+
@grayscale.inspect.must_match %r{^#<PNM::\w+Image:0x\h+ PGM 4x3 Grayscale, maxgray=250>$}
|
173
|
+
@color.inspect.must_match %r{^#<PNM::\w+Image:0x\h+ PPM 5x3 Color, maxgray=6>$}
|
174
174
|
end
|
175
175
|
|
176
176
|
it 'can write binary data containing CRLF' do
|
@@ -187,14 +187,14 @@ describe PNM::Image do
|
|
187
187
|
|
188
188
|
it 'can write zero-length comments' do
|
189
189
|
comment = ''
|
190
|
-
PNM
|
190
|
+
PNM.create([[0,0]], :comment => comment).write(@temp_path, :ascii)
|
191
191
|
File.binread(@temp_path).must_equal "P1\n#\n2 1\n0 0\n"
|
192
192
|
File.delete(@temp_path)
|
193
193
|
end
|
194
194
|
|
195
195
|
it 'can write comments with trailing zero-length line' do
|
196
196
|
comment = "An empty line:\n"
|
197
|
-
PNM
|
197
|
+
PNM.create([[0,0]], :comment => comment).write(@temp_path, :ascii)
|
198
198
|
File.binread(@temp_path).must_equal "P1\n# An empty line:\n#\n2 1\n0 0\n"
|
199
199
|
File.delete(@temp_path)
|
200
200
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pnm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marcus Stollsteimer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-12-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
80
80
|
version: '0'
|
81
81
|
requirements: []
|
82
82
|
rubyforge_project:
|
83
|
-
rubygems_version: 2.4.
|
83
|
+
rubygems_version: 2.4.5
|
84
84
|
signing_key:
|
85
85
|
specification_version: 4
|
86
86
|
summary: PNM - create/read/write PNM image files (PBM, PGM, PPM)
|