chunky_png 1.3.2 → 1.3.3
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/BENCHMARKING.md +38 -0
- data/CONTRIBUTING.md +50 -0
- data/LICENSE +1 -1
- data/chunky_png.gemspec +12 -12
- data/lib/chunky_png/canvas/operations.rb +1 -1
- data/lib/chunky_png/color.rb +7 -7
- data/lib/chunky_png/dimension.rb +16 -15
- data/lib/chunky_png/version.rb +1 -1
- data/spec/chunky_png/canvas/adam7_interlacing_spec.rb +24 -24
- data/spec/chunky_png/canvas/data_url_exporting_spec.rb +2 -2
- data/spec/chunky_png/canvas/data_url_importing_spec.rb +4 -4
- data/spec/chunky_png/canvas/drawing_spec.rb +60 -60
- data/spec/chunky_png/canvas/masking_spec.rb +15 -15
- data/spec/chunky_png/canvas/operations_spec.rb +69 -66
- data/spec/chunky_png/canvas/png_decoding_spec.rb +26 -26
- data/spec/chunky_png/canvas/png_encoding_spec.rb +74 -74
- data/spec/chunky_png/canvas/resampling_spec.rb +47 -47
- data/spec/chunky_png/canvas/stream_exporting_spec.rb +20 -20
- data/spec/chunky_png/canvas/stream_importing_spec.rb +3 -3
- data/spec/chunky_png/canvas_spec.rb +95 -92
- data/spec/chunky_png/color_spec.rb +151 -151
- data/spec/chunky_png/datastream_spec.rb +6 -6
- data/spec/chunky_png/dimension_spec.rb +15 -15
- data/spec/chunky_png/image_spec.rb +4 -4
- data/spec/chunky_png/point_spec.rb +25 -25
- data/spec/chunky_png/rmagick_spec.rb +4 -4
- data/spec/chunky_png/vector_spec.rb +39 -34
- data/spec/chunky_png_spec.rb +1 -2
- data/spec/png_suite_spec.rb +38 -38
- data/spec/spec_helper.rb +14 -10
- metadata +37 -33
- data/BENCHMARKS.rdoc +0 -31
@@ -8,24 +8,24 @@ describe ChunkyPNG::Canvas::PNGDecoding do
|
|
8
8
|
it "should decode a line without filtering as is" do
|
9
9
|
stream = [ChunkyPNG::FILTER_NONE, 255, 255, 255, 255, 255, 255, 255, 255, 255].pack('C*')
|
10
10
|
decode_png_str_scanline(stream, 0, nil, 9, 3)
|
11
|
-
stream.unpack('@1C*').
|
11
|
+
expect(stream.unpack('@1C*')).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255]
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should decode a line with sub filtering correctly" do
|
15
15
|
# all white pixels
|
16
16
|
stream = [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0].pack('C*')
|
17
17
|
decode_png_str_scanline(stream, 0, nil, 9, 3)
|
18
|
-
stream.unpack('@1C*').
|
18
|
+
expect(stream.unpack('@1C*')).to eql [255, 255, 255, 255, 255, 255, 255, 255, 255]
|
19
19
|
|
20
20
|
# all black pixels
|
21
21
|
stream = [ChunkyPNG::FILTER_SUB, 0, 0, 0, 0, 0, 0, 0, 0, 0].pack('C*')
|
22
22
|
decode_png_str_scanline(stream, 0, nil, 9, 3)
|
23
|
-
stream.unpack('@1C*').
|
23
|
+
expect(stream.unpack('@1C*')).to eql [0, 0, 0, 0, 0, 0, 0, 0, 0]
|
24
24
|
|
25
25
|
# various colors
|
26
26
|
stream = [ChunkyPNG::FILTER_SUB, 255, 0, 45, 0, 255, 0, 112, 200, 178].pack('C*')
|
27
27
|
decode_png_str_scanline(stream, 0, nil, 9, 3)
|
28
|
-
stream.unpack('@1C*').
|
28
|
+
expect(stream.unpack('@1C*')).to eql [255, 0, 45, 255, 255, 45, 111, 199, 223]
|
29
29
|
end
|
30
30
|
|
31
31
|
it "should decode a line with up filtering correctly" do
|
@@ -34,15 +34,15 @@ describe ChunkyPNG::Canvas::PNGDecoding do
|
|
34
34
|
current = [ChunkyPNG::FILTER_UP, 0, 127, 255, 0, 127, 255, 0, 127, 255]
|
35
35
|
stream = (previous + current).pack('C*')
|
36
36
|
decode_png_str_scanline(stream, 10, 0, 9, 3)
|
37
|
-
stream.unpack('@11C9').
|
37
|
+
expect(stream.unpack('@11C9')).to eql [255, 126, 254, 127, 254, 126, 0, 127, 255]
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
it "should decode a line with average filtering correctly" do
|
41
41
|
previous = [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120]
|
42
42
|
current = [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53]
|
43
43
|
stream = (previous + current).pack('C*')
|
44
44
|
decode_png_str_scanline(stream, 13, 0, 12, 3)
|
45
|
-
stream.unpack('@14C12').
|
45
|
+
expect(stream.unpack('@14C12')).to eql [5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165]
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should decode a line with paeth filtering correctly" do
|
@@ -50,48 +50,48 @@ describe ChunkyPNG::Canvas::PNGDecoding do
|
|
50
50
|
current = [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0]
|
51
51
|
stream = (previous + current).pack('C*')
|
52
52
|
decode_png_str_scanline(stream, 13, 0, 12, 3)
|
53
|
-
stream.unpack('@14C12').
|
53
|
+
expect(stream.unpack('@14C12')).to eql [10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120]
|
54
54
|
end
|
55
55
|
end
|
56
|
-
|
56
|
+
|
57
57
|
describe '#decode_png_extract_4bit_value' do
|
58
58
|
it "should extract the high bits successfully" do
|
59
|
-
decode_png_extract_4bit_value('10010110'.to_i(2), 0).
|
59
|
+
expect(decode_png_extract_4bit_value('10010110'.to_i(2), 0)).to eql '1001'.to_i(2)
|
60
60
|
end
|
61
|
-
|
61
|
+
|
62
62
|
it "should extract the low bits successfully" do
|
63
|
-
decode_png_extract_4bit_value('10010110'.to_i(2), 17).
|
63
|
+
expect(decode_png_extract_4bit_value('10010110'.to_i(2), 17)).to eql '0110'.to_i(2)
|
64
64
|
end
|
65
65
|
end
|
66
|
-
|
66
|
+
|
67
67
|
describe '#decode_png_extract_2bit_value' do
|
68
68
|
it "should extract the first 2 bits successfully" do
|
69
|
-
decode_png_extract_2bit_value('10010110'.to_i(2), 0).
|
69
|
+
expect(decode_png_extract_2bit_value('10010110'.to_i(2), 0)).to eql '10'.to_i(2)
|
70
70
|
end
|
71
71
|
|
72
72
|
it "should extract the second 2 bits successfully" do
|
73
|
-
decode_png_extract_2bit_value('10010110'.to_i(2), 5).
|
73
|
+
expect(decode_png_extract_2bit_value('10010110'.to_i(2), 5)).to eql '01'.to_i(2)
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should extract the third 2 bits successfully" do
|
77
|
-
decode_png_extract_2bit_value('10010110'.to_i(2), 2).
|
77
|
+
expect(decode_png_extract_2bit_value('10010110'.to_i(2), 2)).to eql '01'.to_i(2)
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should extract the low two bits successfully" do
|
81
|
-
decode_png_extract_2bit_value('10010110'.to_i(2), 7).
|
81
|
+
expect(decode_png_extract_2bit_value('10010110'.to_i(2), 7)).to eql '10'.to_i(2)
|
82
82
|
end
|
83
83
|
end
|
84
|
-
|
84
|
+
|
85
85
|
describe '#decode_png_extract_1bit_value' do
|
86
86
|
it "should extract all separate bits correctly" do
|
87
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 0).
|
88
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 1).
|
89
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 2).
|
90
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 3).
|
91
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 4).
|
92
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 5).
|
93
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 6).
|
94
|
-
decode_png_extract_1bit_value('10010110'.to_i(2), 7).
|
87
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 0)).to eql 1
|
88
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 1)).to eql 0
|
89
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 2)).to eql 0
|
90
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 3)).to eql 1
|
91
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 4)).to eql 0
|
92
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 5)).to eql 1
|
93
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 6)).to eql 1
|
94
|
+
expect(decode_png_extract_1bit_value('10010110'.to_i(2), 7)).to eql 0
|
95
95
|
end
|
96
96
|
end
|
97
97
|
end
|
@@ -9,175 +9,175 @@ describe ChunkyPNG::Canvas::PNGEncoding do
|
|
9
9
|
canvas = ChunkyPNG::Canvas.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100))
|
10
10
|
color_mode = ChunkyPNG.const_get("COLOR_#{color_mode_name.to_s.upcase}")
|
11
11
|
blob = canvas.to_blob(:color_mode => color_mode)
|
12
|
-
|
12
|
+
|
13
13
|
ds = ChunkyPNG::Datastream.from_blob(blob)
|
14
|
-
ds.header_chunk.color.
|
15
|
-
ChunkyPNG::Canvas.from_datastream(ds).
|
14
|
+
expect(ds.header_chunk.color).to eql color_mode
|
15
|
+
expect(ChunkyPNG::Canvas.from_datastream(ds)).to eql ChunkyPNG::Canvas.new(10, 10, ChunkyPNG::Color.rgb(100, 100, 100))
|
16
16
|
end
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should encode an image with 2 colors using 1-bit indexed color mode" do
|
20
20
|
@canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p01.png'))
|
21
21
|
ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob)
|
22
|
-
ds.header_chunk.color.
|
23
|
-
ds.header_chunk.depth.
|
24
|
-
@canvas.
|
22
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED
|
23
|
+
expect(ds.header_chunk.depth).to eql 1
|
24
|
+
expect(@canvas).to eql ChunkyPNG::Canvas.from_datastream(ds)
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
it "should encode an image with 4 colors using 2-bit indexed color mode" do
|
28
28
|
@canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p02.png'))
|
29
29
|
ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob)
|
30
|
-
ds.header_chunk.color.
|
31
|
-
ds.header_chunk.depth.
|
32
|
-
@canvas.
|
30
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED
|
31
|
+
expect(ds.header_chunk.depth).to eql 2
|
32
|
+
expect(@canvas).to eql ChunkyPNG::Canvas.from_datastream(ds)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
it "should encode an image with 16 colors using 4-bit indexed color mode" do
|
36
36
|
@canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p04.png'))
|
37
37
|
ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob)
|
38
|
-
ds.header_chunk.color.
|
39
|
-
ds.header_chunk.depth.
|
40
|
-
@canvas.
|
38
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED
|
39
|
+
expect(ds.header_chunk.depth).to eql 4
|
40
|
+
expect(@canvas).to eql ChunkyPNG::Canvas.from_datastream(ds)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
43
|
it "should encode an image with 256 colors using 8-bit indexed color mode" do
|
44
44
|
@canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p08.png'))
|
45
45
|
ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob)
|
46
|
-
ds.header_chunk.color.
|
47
|
-
ds.header_chunk.depth.
|
48
|
-
@canvas.
|
46
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED
|
47
|
+
expect(ds.header_chunk.depth).to eql 8
|
48
|
+
expect(@canvas).to eql ChunkyPNG::Canvas.from_datastream(ds)
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should use a higher bit depth than necessary if requested" do
|
52
52
|
@canvas = ChunkyPNG::Canvas.from_file(png_suite_file('basic', 'basn3p01.png'))
|
53
53
|
ds = ChunkyPNG::Datastream.from_blob(@canvas.to_blob(:bit_depth => 4))
|
54
|
-
ds.header_chunk.color.
|
55
|
-
ds.header_chunk.depth.
|
56
|
-
@canvas.
|
54
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_INDEXED
|
55
|
+
expect(ds.header_chunk.depth).to eql 4
|
56
|
+
expect(@canvas).to eql ChunkyPNG::Canvas.from_datastream(ds)
|
57
57
|
end
|
58
|
-
|
58
|
+
|
59
59
|
it "should encode an image with interlacing correctly" do
|
60
60
|
input_canvas = ChunkyPNG::Canvas.from_file(resource_file('operations.png'))
|
61
61
|
blob = input_canvas.to_blob(:interlace => true)
|
62
|
-
|
62
|
+
|
63
63
|
ds = ChunkyPNG::Datastream.from_blob(blob)
|
64
|
-
ds.header_chunk.interlace.
|
65
|
-
ChunkyPNG::Canvas.from_datastream(ds).
|
64
|
+
expect(ds.header_chunk.interlace).to eql ChunkyPNG::INTERLACING_ADAM7
|
65
|
+
expect(ChunkyPNG::Canvas.from_datastream(ds)).to eql input_canvas
|
66
66
|
end
|
67
67
|
|
68
68
|
it "should save an image using the normal routine correctly" do
|
69
69
|
canvas = reference_canvas('operations')
|
70
|
-
Zlib::Deflate.
|
70
|
+
expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::DEFAULT_COMPRESSION).and_return('')
|
71
71
|
canvas.to_blob
|
72
72
|
end
|
73
73
|
|
74
74
|
it "should save an image using the :fast_rgba routine correctly" do
|
75
75
|
canvas = reference_canvas('operations')
|
76
|
-
canvas.
|
77
|
-
canvas.
|
78
|
-
canvas.
|
79
|
-
canvas.
|
80
|
-
canvas.
|
81
|
-
Zlib::Deflate.
|
76
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_none)
|
77
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_sub)
|
78
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_up)
|
79
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_average)
|
80
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_paeth)
|
81
|
+
expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_SPEED).and_return('')
|
82
82
|
canvas.to_blob(:fast_rgba)
|
83
83
|
end
|
84
84
|
|
85
85
|
it "should save an image using the :good_compression routine correctly" do
|
86
86
|
canvas = reference_canvas('operations')
|
87
|
-
canvas.
|
88
|
-
canvas.
|
89
|
-
canvas.
|
90
|
-
canvas.
|
91
|
-
canvas.
|
92
|
-
Zlib::Deflate.
|
87
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_none)
|
88
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_sub)
|
89
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_up)
|
90
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_average)
|
91
|
+
expect(canvas).to_not receive(:encode_png_str_scanline_paeth)
|
92
|
+
expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('')
|
93
93
|
canvas.to_blob(:good_compression)
|
94
94
|
end
|
95
95
|
|
96
96
|
it "should save an image using the :best_compression routine correctly" do
|
97
97
|
canvas = reference_canvas('operations')
|
98
|
-
canvas.
|
99
|
-
Zlib::Deflate.
|
98
|
+
expect(canvas).to receive(:encode_png_str_scanline_paeth).exactly(canvas.height).times
|
99
|
+
expect(Zlib::Deflate).to receive(:deflate).with(anything, Zlib::BEST_COMPRESSION).and_return('')
|
100
100
|
canvas.to_blob(:best_compression)
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
it "should save an image with black and white only if requested" do
|
104
104
|
ds = ChunkyPNG::Datastream.from_blob(reference_canvas('lines').to_blob(:black_and_white))
|
105
|
-
ds.header_chunk.color.
|
106
|
-
ds.header_chunk.depth.
|
105
|
+
expect(ds.header_chunk.color).to eql ChunkyPNG::COLOR_GRAYSCALE
|
106
|
+
expect(ds.header_chunk.depth).to eql 1
|
107
107
|
end
|
108
108
|
end
|
109
109
|
|
110
110
|
describe 'different color modes and bit depths' do
|
111
|
-
before do
|
111
|
+
before do
|
112
112
|
@canvas = ChunkyPNG::Canvas.new(2, 2)
|
113
|
-
|
113
|
+
|
114
114
|
@canvas[0, 0] = ChunkyPNG::Color.rgba( 1, 2, 3, 4)
|
115
115
|
@canvas[1, 0] = ChunkyPNG::Color.rgba(252, 253, 254, 255)
|
116
116
|
@canvas[0, 1] = ChunkyPNG::Color.rgba(255, 254, 253, 252)
|
117
117
|
@canvas[1, 1] = ChunkyPNG::Color.rgba( 4, 3, 2, 1)
|
118
|
-
|
118
|
+
|
119
119
|
@canvas.encoding_palette = @canvas.palette
|
120
120
|
@canvas.encoding_palette.to_plte_chunk
|
121
121
|
end
|
122
122
|
|
123
123
|
it "should encode using 8-bit RGBA mode correctly" do
|
124
124
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 8, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
125
|
-
stream.
|
125
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x01\x02\x03\x04\xFC\xFD\xFE\xFF\0\xFF\xFE\xFD\xFC\x04\x03\x02\x01")
|
126
126
|
end
|
127
127
|
|
128
128
|
it "should encode using 8 bit RGB mode correctly" do
|
129
129
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_TRUECOLOR, 8, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
130
|
-
stream.
|
130
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x01\x02\x03\xFC\xFD\xFE\0\xFF\xFE\xFD\x04\x03\x02")
|
131
131
|
end
|
132
132
|
|
133
133
|
it "should encode using 1-bit grayscale mode correctly" do
|
134
134
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_GRAYSCALE, 1, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
135
|
-
stream.
|
135
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x40\0\x80") # Using the B byte of the pixel == 3, assuming R == G == B for grayscale images
|
136
136
|
end
|
137
137
|
|
138
138
|
it "should encode using 2-bit grayscale mode correctly" do
|
139
139
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_GRAYSCALE, 2, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
140
|
-
stream.
|
140
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x30\0\xC0") # Using the B byte of the pixel == 3, assuming R == G == B for grayscale images
|
141
141
|
end
|
142
142
|
|
143
143
|
it "should encode using 4-bit grayscale mode correctly" do
|
144
144
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_GRAYSCALE, 4, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
145
|
-
stream.
|
145
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x0F\0\xF0") # Using the B byte of the pixel == 3, assuming R == G == B for grayscale images
|
146
146
|
end
|
147
147
|
|
148
148
|
it "should encode using 8-bit grayscale mode correctly" do
|
149
149
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_GRAYSCALE, 8, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
150
|
-
stream.
|
150
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x03\xFE\0\xFD\x02") # Using the B byte of the pixel == 3, assuming R == G == B for grayscale images
|
151
151
|
end
|
152
152
|
|
153
153
|
it "should not encode using 1-bit indexed mode because the image has too many colors" do
|
154
|
-
|
154
|
+
expect {
|
155
155
|
@canvas.encode_png_pixelstream(ChunkyPNG::COLOR_INDEXED, 1, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
156
|
-
}.
|
156
|
+
}.to raise_error(ChunkyPNG::ExpectationFailed)
|
157
157
|
end
|
158
|
-
|
158
|
+
|
159
159
|
it "should encode using 2-bit indexed mode correctly" do
|
160
160
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_INDEXED, 2, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
161
|
-
stream.
|
161
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x20\0\xD0")
|
162
162
|
end
|
163
|
-
|
163
|
+
|
164
164
|
it "should encode using 4-bit indexed mode correctly" do
|
165
165
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_INDEXED, 4, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
166
|
-
stream.
|
166
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x02\0\x31")
|
167
167
|
end
|
168
|
-
|
168
|
+
|
169
169
|
it "should encode using 8-bit indexed mode correctly" do
|
170
170
|
stream = @canvas.encode_png_pixelstream(ChunkyPNG::COLOR_INDEXED, 8, ChunkyPNG::INTERLACING_NONE, ChunkyPNG::FILTER_NONE)
|
171
|
-
stream.
|
171
|
+
expect(stream).to eql ChunkyPNG.force_binary("\0\x00\x02\0\x03\x01")
|
172
172
|
end
|
173
173
|
end
|
174
|
-
|
174
|
+
|
175
175
|
describe 'different filter methods' do
|
176
176
|
|
177
177
|
it "should encode a scanline without filtering correctly" do
|
178
178
|
stream = [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2].pack('C*')
|
179
179
|
encode_png_str_scanline_none(stream, 0, nil, 9, 3)
|
180
|
-
stream.unpack('C*').
|
180
|
+
expect(stream.unpack('C*')).to eql [ChunkyPNG::FILTER_NONE, 0, 0, 0, 1, 1, 1, 2, 2, 2]
|
181
181
|
end
|
182
182
|
|
183
183
|
it "should encode a scanline with sub filtering correctly" do
|
@@ -186,11 +186,11 @@ describe ChunkyPNG::Canvas::PNGEncoding do
|
|
186
186
|
|
187
187
|
# Check line with previous line
|
188
188
|
encode_png_str_scanline_sub(stream, 10, 0, 9, 3)
|
189
|
-
stream.unpack('@10C10').
|
189
|
+
expect(stream.unpack('@10C10')).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0]
|
190
190
|
|
191
191
|
# Check line without previous line
|
192
192
|
encode_png_str_scanline_sub(stream, 0, nil, 9, 3)
|
193
|
-
stream.unpack('@0C10').
|
193
|
+
expect(stream.unpack('@0C10')).to eql [ChunkyPNG::FILTER_SUB, 255, 255, 255, 0, 0, 0, 0, 0, 0]
|
194
194
|
end
|
195
195
|
|
196
196
|
it "should encode a scanline with up filtering correctly" do
|
@@ -199,37 +199,37 @@ describe ChunkyPNG::Canvas::PNGEncoding do
|
|
199
199
|
|
200
200
|
# Check line with previous line
|
201
201
|
encode_png_str_scanline_up(stream, 10, 0, 9, 3)
|
202
|
-
stream.unpack('@10C10').
|
202
|
+
expect(stream.unpack('@10C10')).to eql [ChunkyPNG::FILTER_UP, 0, 0, 0, 0, 0, 0, 0, 0, 0]
|
203
203
|
|
204
204
|
# Check line without previous line
|
205
205
|
encode_png_str_scanline_up(stream, 0, nil, 9, 3)
|
206
|
-
stream.unpack('@0C10').
|
206
|
+
expect(stream.unpack('@0C10')).to eql [ChunkyPNG::FILTER_UP, 255, 255, 255, 255, 255, 255, 255, 255, 255]
|
207
207
|
end
|
208
|
-
|
208
|
+
|
209
209
|
it "should encode a scanline with average filtering correctly" do
|
210
210
|
stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120,
|
211
211
|
ChunkyPNG::FILTER_NONE, 5, 10, 25, 45, 45, 55, 80, 125, 105, 150, 114, 165].pack('C*')
|
212
212
|
|
213
213
|
# Check line with previous line
|
214
214
|
encode_png_str_scanline_average(stream, 13, 0, 12, 3)
|
215
|
-
stream.unpack('@13C13').
|
215
|
+
expect(stream.unpack('@13C13')).to eql [ChunkyPNG::FILTER_AVERAGE, 0, 0, 10, 23, 15, 13, 23, 63, 38, 60, 253, 53]
|
216
216
|
|
217
217
|
# Check line without previous line
|
218
218
|
encode_png_str_scanline_average(stream, 0, nil, 12, 3)
|
219
|
-
stream.unpack('@0C13').
|
219
|
+
expect(stream.unpack('@0C13')).to eql [ChunkyPNG::FILTER_AVERAGE, 10, 20, 30, 35, 40, 45, 50, 55, 50, 65, 70, 80]
|
220
220
|
end
|
221
|
-
|
221
|
+
|
222
222
|
it "should encode a scanline with paeth filtering correctly" do
|
223
223
|
stream = [ChunkyPNG::FILTER_NONE, 10, 20, 30, 40, 50, 60, 70, 80, 80, 100, 110, 120,
|
224
224
|
ChunkyPNG::FILTER_NONE, 10, 20, 40, 60, 60, 60, 70, 120, 90, 120, 54, 120].pack('C*')
|
225
225
|
|
226
226
|
# Check line with previous line
|
227
227
|
encode_png_str_scanline_paeth(stream, 13, 0, 12, 3)
|
228
|
-
stream.unpack('@13C13').
|
228
|
+
expect(stream.unpack('@13C13')).to eql [ChunkyPNG::FILTER_PAETH, 0, 0, 10, 20, 10, 0, 0, 40, 10, 20, 190, 0]
|
229
229
|
|
230
230
|
# Check line without previous line
|
231
231
|
encode_png_str_scanline_paeth(stream, 0, nil, 12, 3)
|
232
|
-
stream.unpack('@0C13').
|
232
|
+
expect(stream.unpack('@0C13')).to eql [ChunkyPNG::FILTER_PAETH, 10, 20, 30, 30, 30, 30, 30, 30, 20, 30, 30, 40]
|
233
233
|
end
|
234
234
|
end
|
235
235
|
end
|
@@ -2,120 +2,120 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ChunkyPNG::Canvas::Resampling do
|
4
4
|
|
5
|
-
subject { reference_canvas('clock') }
|
5
|
+
subject { reference_canvas('clock') }
|
6
6
|
|
7
7
|
describe '#resample_nearest_neighbor' do
|
8
|
-
|
8
|
+
|
9
9
|
it "should downscale from 2x2 to 1x1 correctly" do
|
10
10
|
canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4])
|
11
|
-
canvas.resample_nearest_neighbor(1, 1).
|
11
|
+
expect(canvas.resample_nearest_neighbor(1, 1)).to eql ChunkyPNG::Canvas.new(1, 1, [4])
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
it "should upscale from 2x2 to 4x4 correctly" do
|
15
15
|
canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4])
|
16
|
-
canvas.resample_nearest_neighbor(4, 4).
|
16
|
+
expect(canvas.resample_nearest_neighbor(4, 4)).to eql ChunkyPNG::Canvas.new(4, 4, [1, 1, 2, 2, 1, 1, 2, 2, 3, 3, 4, 4, 3, 3, 4, 4])
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should upscale both axis of the image" do
|
20
|
-
subject.resample_nearest_neighbor(45, 45).
|
20
|
+
expect(subject.resample_nearest_neighbor(45, 45)).to eql reference_canvas('clock_nn_xup_yup')
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should downscale both axis of the image" do
|
24
|
-
subject.resample_nearest_neighbor(12, 12).
|
24
|
+
expect(subject.resample_nearest_neighbor(12, 12)).to eql reference_canvas('clock_nn_xdown_ydown')
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
it "should downscale the x-axis and upscale the y-axis of the image" do
|
28
|
-
subject.resample_nearest_neighbor(20, 50).
|
28
|
+
expect(subject.resample_nearest_neighbor(20, 50)).to eql reference_canvas('clock_nn_xdown_yup')
|
29
29
|
end
|
30
|
-
|
30
|
+
|
31
31
|
it "should not return itself" do
|
32
32
|
subject.resample_nearest_neighbor(1, 1).should_not equal(subject)
|
33
33
|
end
|
34
|
-
|
34
|
+
|
35
35
|
it "should not change the original image's dimensions" do
|
36
|
-
|
36
|
+
expect { subject.resample_nearest_neighbor(1, 1) }.to_not change { subject.dimension }
|
37
37
|
end
|
38
38
|
end
|
39
|
-
|
39
|
+
|
40
40
|
describe '#resample_nearest_neighbor!' do
|
41
41
|
it "should upscale both axis of the image" do
|
42
42
|
subject.resample_nearest_neighbor!(45, 45)
|
43
|
-
subject.
|
43
|
+
expect(subject).to eql reference_canvas('clock_nn_xup_yup')
|
44
44
|
end
|
45
|
-
|
45
|
+
|
46
46
|
it "should downscale both axis of the image" do
|
47
47
|
subject.resample_nearest_neighbor!(12, 12)
|
48
|
-
subject.
|
48
|
+
expect(subject).to eql reference_canvas('clock_nn_xdown_ydown')
|
49
49
|
end
|
50
|
-
|
50
|
+
|
51
51
|
it "should downscale the x-axis and upscale the y-axis of the image" do
|
52
52
|
subject.resample_nearest_neighbor!(20, 50)
|
53
|
-
subject.
|
53
|
+
expect(subject).to eql reference_canvas('clock_nn_xdown_yup')
|
54
54
|
end
|
55
|
-
|
55
|
+
|
56
56
|
it "should return itself" do
|
57
|
-
subject.resample_nearest_neighbor!(1, 1).
|
57
|
+
expect(subject.resample_nearest_neighbor!(1, 1)).to equal(subject)
|
58
58
|
end
|
59
|
-
|
59
|
+
|
60
60
|
it "should change the original image's dimensions" do
|
61
|
-
|
61
|
+
expect { subject.resample_nearest_neighbor!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension('1x1'))
|
62
62
|
end
|
63
63
|
end
|
64
|
-
|
64
|
+
|
65
65
|
describe "#resample_bilinear" do
|
66
66
|
it "should downscale from 2x2 to 1x1 correctly" do
|
67
67
|
canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4])
|
68
|
-
canvas.resample_bilinear(1, 1).
|
68
|
+
expect(canvas.resample_bilinear(1, 1)).to eql ChunkyPNG::Canvas.new(1, 1, [2])
|
69
69
|
end
|
70
|
-
|
70
|
+
|
71
71
|
it "should upscale from 2x2 to 4x4 correctly" do
|
72
72
|
canvas = ChunkyPNG::Canvas.new(2, 2, [1, 2, 3, 4])
|
73
|
-
canvas.resample_bilinear(4, 4).
|
73
|
+
expect(canvas.resample_bilinear(4, 4)).to eql ChunkyPNG::Canvas.new(4, 4, [1, 2, 1, 2, 2, 2, 2, 2, 2, 3, 3, 4, 3, 3, 4, 4])
|
74
74
|
end
|
75
|
-
|
75
|
+
|
76
76
|
it "should upscale both axis of the image" do
|
77
|
-
subject.resample_bilinear(45, 45).
|
77
|
+
expect(subject.resample_bilinear(45, 45)).to eql reference_canvas('clock_bl_xup_yup')
|
78
78
|
end
|
79
|
-
|
79
|
+
|
80
80
|
it "should downscale both axis of the image" do
|
81
|
-
subject.resample_bilinear(12, 12).
|
81
|
+
expect(subject.resample_bilinear(12, 12)).to eql reference_canvas('clock_bl_xdown_ydown')
|
82
82
|
end
|
83
|
-
|
83
|
+
|
84
84
|
it "should downscale the x-axis and upscale the y-axis of the image" do
|
85
|
-
subject.resample_bilinear(20, 50).
|
85
|
+
expect(subject.resample_bilinear(20, 50)).to eql reference_canvas('clock_bl_xdown_yup')
|
86
86
|
end
|
87
|
-
|
87
|
+
|
88
88
|
it "should not return itself" do
|
89
89
|
subject.resample_bilinear(1, 1).should_not equal(subject)
|
90
90
|
end
|
91
|
-
|
91
|
+
|
92
92
|
it "should not change the original image's dimensions" do
|
93
|
-
|
93
|
+
expect { subject.resample_bilinear(1, 1) }.to_not change { subject.dimension }
|
94
94
|
end
|
95
95
|
end
|
96
|
-
|
96
|
+
|
97
97
|
describe '#resample_bilinear!' do
|
98
98
|
it "should upscale both axis of the image" do
|
99
99
|
subject.resample_bilinear!(45, 45)
|
100
|
-
subject.
|
100
|
+
expect(subject).to eql reference_canvas('clock_bl_xup_yup')
|
101
101
|
end
|
102
|
-
|
102
|
+
|
103
103
|
it "should downscale both axis of the image" do
|
104
104
|
subject.resample_bilinear!(12, 12)
|
105
|
-
subject.
|
105
|
+
expect(subject).to eql reference_canvas('clock_bl_xdown_ydown')
|
106
106
|
end
|
107
|
-
|
107
|
+
|
108
108
|
it "should downscale the x-axis and upscale the y-axis of the image" do
|
109
109
|
subject.resample_bilinear!(20, 50)
|
110
|
-
subject.
|
110
|
+
expect(subject).to eql reference_canvas('clock_bl_xdown_yup')
|
111
111
|
end
|
112
|
-
|
112
|
+
|
113
113
|
it "should return itself" do
|
114
|
-
subject.resample_bilinear!(1, 1).
|
114
|
+
expect(subject.resample_bilinear!(1, 1)).to equal(subject)
|
115
115
|
end
|
116
|
-
|
116
|
+
|
117
117
|
it "should change the original image's dimensions" do
|
118
|
-
|
118
|
+
expect { subject.resample_bilinear!(1, 1) }.to change { subject.dimension }.to(ChunkyPNG::Dimension('1x1'))
|
119
119
|
end
|
120
120
|
end
|
121
121
|
end
|