axon 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +9 -3
- data/README.rdoc +29 -36
- data/Rakefile +26 -21
- data/TODO.rdoc +1 -6
- data/ext/axon/axon.c +6 -15
- data/ext/axon/extconf.rb +19 -9
- data/ext/axon/interpolation.c +147 -0
- data/ext/axon/jpeg.c +1207 -0
- data/ext/axon/png.c +542 -0
- data/lib/axon.rb +235 -32
- data/lib/axon/cropper.rb +80 -18
- data/lib/axon/fit.rb +69 -19
- data/lib/axon/generators.rb +109 -0
- data/lib/axon/scalers.rb +160 -0
- data/test/helper.rb +151 -6
- data/test/reader_tests.rb +37 -82
- data/test/scaler_tests.rb +102 -0
- data/test/stress_helper.rb +58 -0
- data/test/stress_tests.rb +8 -5
- data/test/test_bilinear_scaler.rb +60 -2
- data/test/test_cropper.rb +68 -1
- data/test/test_fit.rb +35 -0
- data/test/test_generators.rb +21 -0
- data/test/test_image.rb +61 -0
- data/test/test_jpeg_reader.rb +96 -94
- data/test/test_jpeg_writer.rb +95 -8
- data/test/test_nearest_neighbor_scaler.rb +28 -4
- data/test/test_png_reader.rb +12 -8
- data/test/test_png_writer.rb +8 -6
- data/test/writer_tests.rb +129 -111
- metadata +71 -128
- data/.gemtest +0 -0
- data/ext/axon/bilinear_interpolation.c +0 -115
- data/ext/axon/interpolation.h +0 -7
- data/ext/axon/jpeg_common.c +0 -118
- data/ext/axon/jpeg_common.h +0 -37
- data/ext/axon/jpeg_native_writer.c +0 -248
- data/ext/axon/jpeg_reader.c +0 -774
- data/ext/axon/nearest_neighbor_interpolation.c +0 -50
- data/ext/axon/png_common.c +0 -21
- data/ext/axon/png_common.h +0 -18
- data/ext/axon/png_native_writer.c +0 -166
- data/ext/axon/png_reader.c +0 -381
- data/lib/axon/axon.so +0 -0
- data/lib/axon/bilinear_scaler.rb +0 -60
- data/lib/axon/jpeg_writer.rb +0 -41
- data/lib/axon/nearest_neighbor_scaler.rb +0 -39
- data/lib/axon/png_writer.rb +0 -35
- data/lib/axon/scaler.rb +0 -41
- data/lib/axon/solid.rb +0 -23
- data/test/_test_readme.rb +0 -34
- data/test/test_exif.rb +0 -39
- data/test/test_generator.rb +0 -10
- data/test/test_icc.rb +0 -18
- data/test/test_jpeg.rb +0 -9
- data/test/test_png.rb +0 -9
@@ -0,0 +1,109 @@
|
|
1
|
+
module Axon
|
2
|
+
# == A Noise Image Generator
|
3
|
+
#
|
4
|
+
# Axon::Noise will generate images with random pixel color values.
|
5
|
+
#
|
6
|
+
# == Example
|
7
|
+
#
|
8
|
+
# Axon::Noise.new(100, 200, :components => 1)
|
9
|
+
#
|
10
|
+
class Noise
|
11
|
+
# The width of the generated image.
|
12
|
+
attr_reader :width
|
13
|
+
|
14
|
+
# The height of the generated image.
|
15
|
+
attr_reader :height
|
16
|
+
|
17
|
+
# The color model of the generated image.
|
18
|
+
attr_reader :color_model
|
19
|
+
|
20
|
+
# The components in the generated image.
|
21
|
+
attr_reader :components
|
22
|
+
|
23
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
24
|
+
attr_reader :lineno
|
25
|
+
|
26
|
+
# :call-seq:
|
27
|
+
# Noise.new(width, height, options = {})
|
28
|
+
#
|
29
|
+
# Creates a new noise image object with dimensions +width+ x +height+.
|
30
|
+
#
|
31
|
+
# +options+ may contain the following optional hash key values:
|
32
|
+
#
|
33
|
+
# * :color_model -- The color model of the generated image.
|
34
|
+
# * :components -- The number of components in the generated image.
|
35
|
+
#
|
36
|
+
def initialize(width, height, options=nil)
|
37
|
+
options ||= {}
|
38
|
+
|
39
|
+
@width = width
|
40
|
+
@height = height
|
41
|
+
@color_model = options[:color_model] || :RGB
|
42
|
+
@components = options[:components] || 3
|
43
|
+
@lineno = 0
|
44
|
+
@empty_string = String.new
|
45
|
+
if @empty_string.respond_to? :force_encoding
|
46
|
+
@empty_string.force_encoding('BINARY')
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Gets the next scanline from the generated image.
|
51
|
+
#
|
52
|
+
def gets
|
53
|
+
return nil if @lineno >= @height
|
54
|
+
sl = @empty_string.dup
|
55
|
+
(@width * @components).times{ sl << rand(2**8) }
|
56
|
+
@lineno += 1
|
57
|
+
sl
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# == A Solid Color Image Generator
|
62
|
+
#
|
63
|
+
# Axon::Solid will generate images with a solid color value.
|
64
|
+
#
|
65
|
+
# == Example
|
66
|
+
#
|
67
|
+
# Axon::Solid.new(100, 200, "\x0A\x14\x69")
|
68
|
+
#
|
69
|
+
class Solid
|
70
|
+
# The width of the generated image.
|
71
|
+
attr_reader :width
|
72
|
+
|
73
|
+
# The height of the generated image.
|
74
|
+
attr_reader :height
|
75
|
+
|
76
|
+
# The color model of the generated image.
|
77
|
+
attr_reader :color_model
|
78
|
+
|
79
|
+
# The components in the generated image.
|
80
|
+
attr_reader :components
|
81
|
+
|
82
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
83
|
+
attr_reader :lineno
|
84
|
+
|
85
|
+
# :call-seq:
|
86
|
+
# Solid.new(width, height, color = "\x00\x00\x00", color_model = :RGB)
|
87
|
+
#
|
88
|
+
# Creates a new solid color image object with dimensions +width+ x +height+.
|
89
|
+
#
|
90
|
+
# The optional argument +color+ is the binary value that will be assigned
|
91
|
+
# to each pixel.
|
92
|
+
#
|
93
|
+
def initialize(width, height, color=nil, color_model=nil)
|
94
|
+
@width, @height = width, height
|
95
|
+
@color = color || "\x00\x00\x00"
|
96
|
+
@color_model = color_model || :RGB
|
97
|
+
@components = @color.size
|
98
|
+
@lineno = 0
|
99
|
+
end
|
100
|
+
|
101
|
+
# Gets the next scanline from the generated image.
|
102
|
+
#
|
103
|
+
def gets
|
104
|
+
return nil if @lineno >= @height
|
105
|
+
@lineno += 1
|
106
|
+
@color * width
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/axon/scalers.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
module Axon
|
2
|
+
# == A Nearest-neighbor Image Scaler
|
3
|
+
#
|
4
|
+
# Axon::NearestNeighborScaler scales images quickly using the nearest-neighbor
|
5
|
+
# interpolation method.
|
6
|
+
#
|
7
|
+
# Nearest-neighbor interpolation selects the value of the nearest pixel when
|
8
|
+
# calculating colors in the scaled image.
|
9
|
+
#
|
10
|
+
# == Example
|
11
|
+
#
|
12
|
+
# n = Axon::NearestNeighborScaler.new(image_in, 50, 75)
|
13
|
+
# n.width # => 50
|
14
|
+
# n.height # => 75
|
15
|
+
# n.gets # => String
|
16
|
+
#
|
17
|
+
class NearestNeighborScaler
|
18
|
+
# The width of the generated image.
|
19
|
+
attr_reader :width
|
20
|
+
|
21
|
+
# The height of the generated image.
|
22
|
+
attr_reader :height
|
23
|
+
|
24
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
25
|
+
attr_reader :lineno
|
26
|
+
|
27
|
+
# :call-seq:
|
28
|
+
# NearestNeighborScaler.new(image_in, width, height)
|
29
|
+
#
|
30
|
+
# Scales +image_in+ to the size +width+ x +height+ using the
|
31
|
+
# nearest-neighbor interpolation method.
|
32
|
+
#
|
33
|
+
def initialize(source, width, height)
|
34
|
+
raise ArgumentError if width < 1 || height < 1
|
35
|
+
@width = width
|
36
|
+
@height = height
|
37
|
+
@source = source
|
38
|
+
@lineno = 0
|
39
|
+
@buf = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
# Gets the components in the scaled image. Same as the components of the
|
43
|
+
# source image.
|
44
|
+
#
|
45
|
+
def components
|
46
|
+
@source.components
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gets the color model of the scaled image. Same as the color model of the
|
50
|
+
# source image.
|
51
|
+
#
|
52
|
+
def color_model
|
53
|
+
@source.color_model
|
54
|
+
end
|
55
|
+
|
56
|
+
# Gets the next scanline from the cropped image.
|
57
|
+
#
|
58
|
+
def gets
|
59
|
+
return nil if @lineno >= @height
|
60
|
+
sample = (@lineno * @source.height / @height.to_f).floor
|
61
|
+
@lineno += 1
|
62
|
+
Interpolation.nearest(get_buf(sample), @width, components)
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def get_buf(line)
|
68
|
+
@buf ||= @source.gets
|
69
|
+
(line + 1 - @source.lineno).times{ @buf = @source.gets }
|
70
|
+
@buf
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
# == A Bilinear Image Scaler
|
75
|
+
#
|
76
|
+
# Axon::BilinearScaler scales images using the bilinear interpolation method.
|
77
|
+
#
|
78
|
+
# Bilinear interpolation calculates the color values in the resulting image by
|
79
|
+
# looking at the four nearest pixels for each pixel in the resulting image.
|
80
|
+
#
|
81
|
+
# This gives a more accurate representation than nearest-neighbor
|
82
|
+
# interpolation, at the expense of slightly blurring the resulting image.
|
83
|
+
#
|
84
|
+
# == Example
|
85
|
+
#
|
86
|
+
# n = Axon::BilinearScaler.new(image_in, 50, 75)
|
87
|
+
# n.width # => 50
|
88
|
+
# n.height # => 75
|
89
|
+
# n.gets # => String
|
90
|
+
#
|
91
|
+
class BilinearScaler
|
92
|
+
# The width of the generated image.
|
93
|
+
attr_reader :width
|
94
|
+
|
95
|
+
# The height of the generated image.
|
96
|
+
attr_reader :height
|
97
|
+
|
98
|
+
# The index of the next line that will be fetched by gets, starting at 0.
|
99
|
+
attr_reader :lineno
|
100
|
+
|
101
|
+
# :call-seq:
|
102
|
+
# BilinearScaler.new(image_in, width, height)
|
103
|
+
#
|
104
|
+
# Scales +image_in+ to the size +width+ x +height+ using the bilinear
|
105
|
+
# interpolation method.
|
106
|
+
#
|
107
|
+
def initialize(source, width, height)
|
108
|
+
raise ArgumentError if width < 1 || height < 1
|
109
|
+
@width = width
|
110
|
+
@height = height
|
111
|
+
@source = source
|
112
|
+
@lineno = 0
|
113
|
+
@buf1 = nil
|
114
|
+
@buf2 = nil
|
115
|
+
end
|
116
|
+
|
117
|
+
# Gets the components in the scaled image. Same as the components of the
|
118
|
+
# source image.
|
119
|
+
#
|
120
|
+
def components
|
121
|
+
@source.components
|
122
|
+
end
|
123
|
+
|
124
|
+
# Gets the color model of the scaled image. Same as the color model of the
|
125
|
+
# source image.
|
126
|
+
#
|
127
|
+
def color_model
|
128
|
+
@source.color_model
|
129
|
+
end
|
130
|
+
|
131
|
+
# Gets the next scanline from the cropped image.
|
132
|
+
#
|
133
|
+
def gets
|
134
|
+
return nil if @lineno >= @height
|
135
|
+
sample = @lineno * @source.height / @height.to_f
|
136
|
+
sample_i = sample.to_i
|
137
|
+
ty = sample - sample_i
|
138
|
+
@lineno += 1
|
139
|
+
get_buf(sample_i)
|
140
|
+
|
141
|
+
Interpolation.bilinear(@buf1, @buf2, @width, ty, components)
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def get_buf(line)
|
147
|
+
@buf1 = @buf2 = read_with_padding unless @buf2
|
148
|
+
(line + 2 - @source.lineno).times do
|
149
|
+
@buf1 = @buf2
|
150
|
+
@buf2 = read_with_padding if @source.lineno < @source.height
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def read_with_padding
|
155
|
+
line = @source.gets
|
156
|
+
line << line[-@source.components, @source.components]
|
157
|
+
line
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
data/test/helper.rb
CHANGED
@@ -1,17 +1,162 @@
|
|
1
|
+
require 'rubygems'
|
1
2
|
require 'minitest/autorun'
|
2
3
|
require 'axon'
|
3
4
|
require 'stringio'
|
4
|
-
require 'reader_tests'
|
5
|
-
require 'writer_tests'
|
6
5
|
|
7
6
|
module Axon
|
8
7
|
class AxonTestCase < MiniTest::Unit::TestCase
|
9
|
-
|
10
|
-
# Generate a solid velvet JPEG
|
8
|
+
# Generate a solid velvet image
|
11
9
|
def setup
|
12
|
-
|
13
|
-
@image = Solid.new 10, 15,
|
10
|
+
super
|
11
|
+
@image = Solid.new 10, 15, "\x0A\x14\x69"
|
14
12
|
@io_out = StringIO.new
|
13
|
+
@io_out.set_encoding 'ASCII-8BIT' if @io_out.respond_to?(:set_encoding)
|
14
|
+
end
|
15
|
+
|
16
|
+
def assert_image_dimensions(image, width, height)
|
17
|
+
cmp = image.components
|
18
|
+
|
19
|
+
assert_equal width, image.width
|
20
|
+
assert_equal height, image.height
|
21
|
+
|
22
|
+
height.times do |i|
|
23
|
+
assert_equal i, image.lineno
|
24
|
+
assert_equal width * cmp, image.gets.size, 'image.gets should return scanlines with length width'
|
25
|
+
end
|
26
|
+
|
27
|
+
assert_equal height, image.lineno
|
28
|
+
assert_nil image.gets, 'image.gets should be nil after reading height lines'
|
29
|
+
assert_equal height, image.lineno
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class CustomError < RuntimeError; end
|
34
|
+
|
35
|
+
module CallOrReturnValue
|
36
|
+
def call_or_return(*args)
|
37
|
+
@custom.respond_to?(:call) ? @custom.call(@parent, *args) : @custom
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class CustomImage
|
42
|
+
include CallOrReturnValue
|
43
|
+
|
44
|
+
def initialize(custom)
|
45
|
+
@parent = Solid.new 100, 200
|
46
|
+
@custom = custom
|
47
|
+
end
|
48
|
+
|
49
|
+
def height; @parent.height; end
|
50
|
+
def width; @parent.width; end
|
51
|
+
def color_model; @parent.color_model; end
|
52
|
+
def components; @parent.components; end
|
53
|
+
def gets; @parent.gets; end
|
54
|
+
def lineno; @parent.lineno; end
|
55
|
+
end
|
56
|
+
|
57
|
+
class CustomHeightImage < CustomImage
|
58
|
+
def height; call_or_return; end
|
59
|
+
end
|
60
|
+
|
61
|
+
class CustomWidthImage < CustomImage
|
62
|
+
def width; call_or_return; end
|
63
|
+
end
|
64
|
+
|
65
|
+
class CustomColorModelImage < CustomImage
|
66
|
+
def color_model; call_or_return; end
|
67
|
+
end
|
68
|
+
|
69
|
+
class CustomComponentsImage < CustomImage
|
70
|
+
def components; call_or_return; end
|
71
|
+
end
|
72
|
+
|
73
|
+
class CustomLinenoImage < CustomImage
|
74
|
+
def lineno; call_or_return; end
|
75
|
+
end
|
76
|
+
|
77
|
+
class CustomGetsImage < CustomImage
|
78
|
+
def gets; call_or_return; end
|
79
|
+
end
|
80
|
+
|
81
|
+
class CustomIO
|
82
|
+
include CallOrReturnValue
|
83
|
+
|
84
|
+
attr_accessor :custom
|
85
|
+
|
86
|
+
def initialize(custom, *args)
|
87
|
+
@parent = StringIO.new(*args)
|
88
|
+
@custom = custom
|
89
|
+
end
|
90
|
+
|
91
|
+
def write(*args); call_or_return(*args); end
|
92
|
+
def read(*args); call_or_return(*args); end
|
93
|
+
def string; @parent.string; end
|
94
|
+
end
|
95
|
+
|
96
|
+
class ArrayWrapper
|
97
|
+
attr_reader :lineno, :components, :color_model
|
98
|
+
|
99
|
+
def initialize(ary, components=nil, color_model=nil)
|
100
|
+
@ary = ary
|
101
|
+
@components = components || 3
|
102
|
+
@color_model = color_model || :RGB
|
103
|
+
@lineno = 0
|
104
|
+
end
|
105
|
+
|
106
|
+
def width
|
107
|
+
@ary[0].size
|
108
|
+
end
|
109
|
+
|
110
|
+
def height
|
111
|
+
@ary.size
|
112
|
+
end
|
113
|
+
|
114
|
+
def gets
|
115
|
+
return nil if @lineno > @ary.size
|
116
|
+
res = @ary[@lineno]
|
117
|
+
@lineno += 1
|
118
|
+
res
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class Repeater
|
123
|
+
attr_reader :lineno
|
124
|
+
|
125
|
+
def initialize(source)
|
126
|
+
@source = source
|
127
|
+
@data = []
|
128
|
+
@lineno = 0
|
129
|
+
end
|
130
|
+
|
131
|
+
def components
|
132
|
+
@source.components
|
133
|
+
end
|
134
|
+
|
135
|
+
def color_model
|
136
|
+
@source.color_model
|
137
|
+
end
|
138
|
+
|
139
|
+
def height
|
140
|
+
@source.height
|
141
|
+
end
|
142
|
+
|
143
|
+
def width
|
144
|
+
@source.width
|
145
|
+
end
|
146
|
+
|
147
|
+
def gets
|
148
|
+
if @data.size <= @lineno
|
149
|
+
res = @source.gets.dup
|
150
|
+
return nil unless res
|
151
|
+
@data << res
|
152
|
+
end
|
153
|
+
|
154
|
+
@lineno += 1
|
155
|
+
@data[@lineno - 1].dup
|
156
|
+
end
|
157
|
+
|
158
|
+
def rewind
|
159
|
+
@lineno = 0
|
15
160
|
end
|
16
161
|
end
|
17
162
|
end
|
data/test/reader_tests.rb
CHANGED
@@ -1,115 +1,70 @@
|
|
1
1
|
module Axon
|
2
2
|
module ReaderTests
|
3
|
-
def
|
4
|
-
assert_equal
|
5
|
-
assert_equal
|
3
|
+
def test_header_dimensions
|
4
|
+
assert_equal @image.width, @reader.width
|
5
|
+
assert_equal @image.height, @reader.height
|
6
6
|
end
|
7
7
|
|
8
|
-
def
|
9
|
-
assert_equal
|
10
|
-
assert_equal 15, @reader.height
|
8
|
+
def test_header_components
|
9
|
+
assert_equal @image.components, @reader.components
|
11
10
|
end
|
12
11
|
|
13
|
-
def
|
14
|
-
assert_equal
|
12
|
+
def test_header_color_model
|
13
|
+
assert_equal @image.color_model, @reader.color_model
|
15
14
|
end
|
16
15
|
|
17
|
-
def
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
class DoubleIO < StringIO
|
22
|
-
def read(*args)
|
23
|
-
s = super
|
24
|
-
s[0..20] * 100
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def test_io_returns_too_much
|
29
|
-
f = DoubleIO.new @data
|
30
|
-
assert_raises(RuntimeError) { @readerclass.new f }
|
31
|
-
end
|
32
|
-
|
33
|
-
class NilIO
|
34
|
-
def read(*args); end
|
16
|
+
def test_io_returns_too_much_data
|
17
|
+
io = CustomIO.new(Proc.new{ |io, *args| io.read(*args)[0..20] * 100 }, @data)
|
18
|
+
assert_raises(RuntimeError) { @readerclass.new io }
|
35
19
|
end
|
36
20
|
|
37
21
|
def test_io_returns_nil
|
38
|
-
assert_raises(RuntimeError) { @readerclass.new
|
22
|
+
assert_raises(RuntimeError) { @readerclass.new(CustomIO.new(nil)) }
|
39
23
|
end
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
end
|
46
|
-
|
47
|
-
def test_io_raises_exception
|
48
|
-
assert_raises(RuntimeError) { @readerclass.new RaiseIO.new }
|
24
|
+
|
25
|
+
def test_io_returns_one_byte_at_a_time
|
26
|
+
io = CustomIO.new(Proc.new{ |io, len| io.read(len || 1) }, @data)
|
27
|
+
r = @readerclass.new(io)
|
28
|
+
r.gets
|
49
29
|
end
|
50
30
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
end
|
31
|
+
def test_io_raises_exception
|
32
|
+
io = CustomIO.new(Proc.new{ raise CustomError }, @data)
|
33
|
+
assert_raises(CustomError) { @readerclass.new io }
|
55
34
|
end
|
56
35
|
|
57
36
|
def test_empty_string_io
|
58
|
-
assert_raises(RuntimeError) { @readerclass.new
|
59
|
-
end
|
60
|
-
|
61
|
-
class ThatsNotAStringIO
|
62
|
-
def read(*args)
|
63
|
-
:this_should_be_a_string
|
64
|
-
end
|
37
|
+
assert_raises(RuntimeError) { @readerclass.new(CustomIO.new("")) }
|
65
38
|
end
|
66
39
|
|
67
40
|
def test_not_a_string_io
|
68
|
-
assert_raises(TypeError) { @readerclass.new
|
41
|
+
assert_raises(TypeError) { @readerclass.new(CustomIO.new(:foo)) }
|
69
42
|
end
|
70
|
-
|
71
|
-
def test_each
|
72
|
-
size = @reader.width * @reader.components
|
73
43
|
|
74
|
-
|
75
|
-
|
44
|
+
def test_lineno
|
45
|
+
assert_equal 0, @reader.lineno
|
46
|
+
@reader.height.times do |i|
|
47
|
+
assert_equal i, @reader.lineno
|
48
|
+
@reader.gets
|
76
49
|
end
|
50
|
+
assert_equal nil, @reader.gets
|
51
|
+
assert_equal @reader.height, @reader.lineno
|
77
52
|
end
|
78
53
|
|
79
|
-
def
|
80
|
-
@reader.
|
81
|
-
|
82
|
-
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
class OneExceptionIO < StringIO
|
87
|
-
def initialize(*args)
|
88
|
-
@raised_exception = false
|
89
|
-
super
|
90
|
-
end
|
91
|
-
|
92
|
-
def read(*args)
|
93
|
-
unless @raised_exception
|
94
|
-
@raised_exception = true
|
95
|
-
raise 'heck'
|
96
|
-
end
|
97
|
-
super
|
54
|
+
def test_gets
|
55
|
+
size = @reader.width * @reader.components
|
56
|
+
@reader.height.times do
|
57
|
+
assert_equal size, @reader.gets.size
|
98
58
|
end
|
59
|
+
assert_equal nil, @reader.gets
|
99
60
|
end
|
100
61
|
|
101
62
|
def test_recovers_from_initial_io_exception
|
102
|
-
|
63
|
+
ex_io = CustomIO.new(Proc.new{ raise CustomError }, @data)
|
103
64
|
r = @readerclass.allocate
|
104
|
-
assert_raises(
|
105
|
-
r.send(:initialize,
|
106
|
-
r.
|
107
|
-
end
|
108
|
-
|
109
|
-
def test_multiple_each_calls
|
110
|
-
@reader.each{ }
|
111
|
-
@io_in.rewind
|
112
|
-
@reader.each{ }
|
65
|
+
assert_raises(CustomError) { r.send(:initialize, ex_io) }
|
66
|
+
r.send(:initialize, StringIO.new(@data))
|
67
|
+
r.gets
|
113
68
|
end
|
114
69
|
end
|
115
70
|
end
|