chunky_png 1.3.0 → 1.3.1

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.
@@ -3,7 +3,7 @@ module ChunkyPNG
3
3
  # The Datastream class represents a PNG formatted datastream. It supports
4
4
  # both reading from and writing to strings, streams and files.
5
5
  #
6
- # A PNG datastream begins with the PNG signature, and than contains multiple
6
+ # A PNG datastream begins with the PNG signature, and then contains multiple
7
7
  # chunks, starting with a header (IHDR) chunk and finishing with an end
8
8
  # (IEND) chunk.
9
9
  #
@@ -1,24 +1,23 @@
1
1
  module ChunkyPNG
2
-
3
2
  # A palette describes the set of colors that is being used for an image.
4
3
  #
5
4
  # A PNG image can contain an explicit palette which defines the colors of
6
- # that image, but can also use an implicit palette, e.g. all truecolor
7
- # colors or all grayscale colors.
5
+ # that image, but can also use an implicit palette, e.g. all truecolor colors
6
+ # or all grayscale colors.
8
7
  #
9
- # This palette supports decoding colors from a palette if an explicit
10
- # palette is provided in a PNG datastream, and it supports encoding colors
11
- # to an explicit palette (stores as PLTE & tRNS chunks in a PNG file).
8
+ # This palette supports decoding colors from a palette if an explicit palette
9
+ # is provided in a PNG datastream, and it supports encoding colors to an
10
+ # explicit palette (stores as PLTE & tRNS chunks in a PNG file).
12
11
  #
13
12
  # @see ChunkyPNG::Color
14
13
  class Palette < SortedSet
15
-
16
14
  # Builds a new palette given a set (Enumerable instance) of colors.
17
15
  #
18
- # @param [Enumerable<Integer>] enum The set of colors to include in this palette.
19
- # This Enumerable can contains duplicates.
20
- # @param [Array] decoding_map An array of colors in the exact order at which
21
- # they appeared in the palette chunk, so that this array can be used for decoding.
16
+ # @param enum [Enumerable<Integer>] The set of colors to include in this
17
+ # palette.This Enumerable can contain duplicates.
18
+ # @param decoding_map [Array] An array of colors in the exact order at
19
+ # which they appeared in the palette chunk, so that this array can be
20
+ # used for decoding.
22
21
  def initialize(enum, decoding_map = nil)
23
22
  super(enum)
24
23
  @decoding_map = decoding_map if decoding_map
@@ -29,8 +28,10 @@ module ChunkyPNG
29
28
  #
30
29
  # This method will cerate a palette that is suitable for decoding an image.
31
30
  #
32
- # @param [ChunkyPNG::Chunk::Palette] The palette chunk to load from
33
- # @param [ChunkyPNG::Chunk::Transparency, nil] The optional transparency chunk.
31
+ # @param palette_chunk [ChunkyPNG::Chunk::Palette] The palette chunk to
32
+ # load from
33
+ # @param transparency_chunk [ChunkyPNG::Chunk::Transparency, nil] The
34
+ # optional transparency chunk.
34
35
  # @return [ChunkyPNG::Palette] The loaded palette instance.
35
36
  # @see ChunkyPNG::Palette#can_decode?
36
37
  def self.from_chunks(palette_chunk, transparency_chunk = nil)
@@ -53,25 +54,30 @@ module ChunkyPNG
53
54
  index += 1
54
55
  end
55
56
 
56
- self.new(decoding_map, decoding_map)
57
+ new(decoding_map, decoding_map)
57
58
  end
58
59
 
59
60
  # Builds a palette instance from a given canvas.
60
- # @param [ChunkyPNG::Canvas] canvas The canvas to create a palette for.
61
+ # @param canvas [ChunkyPNG::Canvas] The canvas to create a palette for.
61
62
  # @return [ChunkyPNG::Palette] The palette instance.
62
63
  def self.from_canvas(canvas)
63
- self.new(canvas.pixels)
64
+ # Although we don't need to call .uniq.sort before initializing, because
65
+ # Palette subclasses SortedSet, we get significantly better performance
66
+ # by doing so.
67
+ new(canvas.pixels.uniq.sort)
64
68
  end
65
69
 
66
70
  # Builds a palette instance from a given set of pixels.
67
- # @param [Enumerable<Integer>] pixels An enumeration of pixels to create a palette for
71
+ # @param pixels [Enumerable<Integer>] An enumeration of pixels to create a
72
+ # palette for
68
73
  # @return [ChunkyPNG::Palette] The palette instance.
69
74
  def self.from_pixels(pixels)
70
- self.new(pixels)
75
+ new(pixels)
71
76
  end
72
77
 
73
78
  # Checks whether the size of this palette is suitable for indexed storage.
74
- # @return [true, false] True if the number of colors in this palette is at most 256.
79
+ # @return [true, false] True if the number of colors in this palette is at
80
+ # most 256.
75
81
  def indexable?
76
82
  size <= 256
77
83
  end
@@ -84,56 +90,67 @@ module ChunkyPNG
84
90
  end
85
91
 
86
92
  # Check whether this palette only contains grayscale colors.
87
- # @return [true, false] True if all colors in this palette are grayscale teints.
93
+ # @return [true, false] True if all colors in this palette are grayscale
94
+ # teints.
88
95
  # @see ChunkyPNG::Color#grayscale??
89
96
  def grayscale?
90
97
  all? { |color| Color.grayscale?(color) }
91
98
  end
92
99
 
93
100
  # Check whether this palette only contains bacl and white.
94
- # @return [true, false] True if all colors in this palette are grayscale teints.
101
+ # @return [true, false] True if all colors in this palette are grayscale
102
+ # teints.
95
103
  # @see ChunkyPNG::Color#grayscale??
96
104
  def black_and_white?
97
105
  entries == [ChunkyPNG::Color::BLACK, ChunkyPNG::Color::WHITE]
98
106
  end
99
-
100
- # Returns a palette with all the opaque variants of the colors in this palette.
101
- # @return [ChunkyPNG::Palette] A new Palette instance with only opaque colors.
107
+
108
+ # Returns a palette with all the opaque variants of the colors in this
109
+ # palette.
110
+ # @return [ChunkyPNG::Palette] A new Palette instance with only opaque
111
+ # colors.
102
112
  # @see ChunkyPNG::Color#opaque!
103
113
  def opaque_palette
104
114
  self.class.new(map { |c| ChunkyPNG::Color.opaque!(c) })
105
115
  end
106
116
 
107
- # Checks whether this palette is suitable for decoding an image from a datastream.
117
+ # Checks whether this palette is suitable for decoding an image from a
118
+ # datastream.
108
119
  #
109
- # This requires that the positions of the colors in the original palette chunk is known,
110
- # which is stored as an array in the +@decoding_map+ instance variable.
120
+ # This requires that the positions of the colors in the original palette
121
+ # chunk is known, which is stored as an array in the +@decoding_map+
122
+ # instance variable.
111
123
  #
112
- # @return [true, false] True if a decoding map was built when this palette was loaded.
124
+ # @return [true, false] True if a decoding map was built when this palette
125
+ # was loaded.
113
126
  def can_decode?
114
127
  !@decoding_map.nil?
115
128
  end
116
129
 
117
- # Checks whether this palette is suitable for encoding an image from to datastream.
130
+ # Checks whether this palette is suitable for encoding an image from to
131
+ # datastream.
118
132
  #
119
- # This requires that the position of the color in the future palette chunk is known,
120
- # which is stored as a hash in the +@encoding_map+ instance variable.
133
+ # This requires that the position of the color in the future palette chunk
134
+ # is known, which is stored as a hash in the +@encoding_map+ instance
135
+ # variable.
121
136
  #
122
- # @return [true, false] True if a encoding map was built when this palette was loaded.
137
+ # @return [true, false] True if a encoding map was built when this palette
138
+ # was loaded.
123
139
  def can_encode?
124
140
  !@encoding_map.nil?
125
141
  end
126
142
 
127
143
  # Returns a color, given the position in the original palette chunk.
128
- # @param [Integer] index The 0-based position of the color in the palette.
129
- # @return [ChunkyPNG::Color] The color that is stored in the palette under the given index
144
+ # @param index [Integer] The 0-based position of the color in the palette.
145
+ # @return [ChunkyPNG::Color] The color that is stored in the palette under
146
+ # the given index
130
147
  # @see ChunkyPNG::Palette#can_decode?
131
148
  def [](index)
132
149
  @decoding_map[index]
133
150
  end
134
151
 
135
152
  # Returns the position of a color in the palette
136
- # @param [ChunkyPNG::Color] color The color for which to look up the index.
153
+ # @param color [ChunkyPNG::Color] The color for which to look up the index.
137
154
  # @return [Integer] The 0-based position of the color in the palette.
138
155
  # @see ChunkyPNG::Palette#can_encode?
139
156
  def index(color)
@@ -151,12 +168,12 @@ module ChunkyPNG
151
168
  ChunkyPNG::Chunk::Transparency.new('tRNS', map { |c| ChunkyPNG::Color.a(c) }.pack('C*'))
152
169
  end
153
170
 
154
- # Creates a PLTE chunk that corresponds with this palette to store the
155
- # r, g and b channels of all colors.
171
+ # Creates a PLTE chunk that corresponds with this palette to store the r,
172
+ # g, and b channels of all colors.
156
173
  #
157
- # Note that a PLTE chunk should only be included if the image is
158
- # encoded using index colors. After this chunk has been built, the
159
- # palette becomes suitable for encoding an image.
174
+ # @note A PLTE chunk should only be included if the image is encoded using
175
+ # index colors. After this chunk has been built, the palette becomes
176
+ # suitable for encoding an image.
160
177
  #
161
178
  # @return [ChunkyPNG::Chunk::Palette] The PLTE chunk.
162
179
  # @see ChunkyPNG::Palette#can_encode?
@@ -174,7 +191,7 @@ module ChunkyPNG
174
191
 
175
192
  # Determines the most suitable colormode for this palette.
176
193
  # @return [Integer] The colormode which would create the smallest possible
177
- # file for images that use this exact palette.
194
+ # file for images that use this exact palette.
178
195
  def best_color_settings
179
196
  if black_and_white?
180
197
  [ChunkyPNG::COLOR_GRAYSCALE, 1]
@@ -192,17 +209,17 @@ module ChunkyPNG
192
209
  [ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 8]
193
210
  end
194
211
  end
195
-
212
+
196
213
  # Determines the minimal bit depth required for an indexed image
197
- # @return [Integer] Number of bits per pixel, i.e. 1, 2, 4 or 8, or nil if this
198
- # image cannot be saved as an indexed image.
214
+ # @return [Integer] Number of bits per pixel, i.e. 1, 2, 4 or 8, or nil if
215
+ # this image cannot be saved as an indexed image.
199
216
  def determine_bit_depth
200
217
  case size
201
- when 1..2; 1
202
- when 3..4; 2
203
- when 5..16; 4
204
- when 17..256; 8
205
- else nil
218
+ when 1..2 then 1
219
+ when 3..4 then 2
220
+ when 5..16 then 4
221
+ when 17..256 then 8
222
+ else nil
206
223
  end
207
224
  end
208
225
  end
@@ -1,5 +1,5 @@
1
1
  module ChunkyPNG
2
2
  # The current version of ChunkyPNG.
3
3
  # Set it and commit the change this before running rake release.
4
- VERSION = "1.3.0"
4
+ VERSION = "1.3.1"
5
5
  end
@@ -11,6 +11,15 @@ describe ChunkyPNG::Canvas do
11
11
  end
12
12
  end
13
13
 
14
+ describe '.from_bgr_stream' do
15
+ it "should load an image correctly from a datastream" do
16
+ File.open(resource_file('pixelstream.bgr')) do |stream|
17
+ matrix = ChunkyPNG::Canvas.from_bgr_stream(240, 180, stream)
18
+ matrix.should == reference_canvas('pixelstream_reference')
19
+ end
20
+ end
21
+ end
22
+
14
23
  describe '.from_rgba_stream' do
15
24
  it "should load an image correctly from a datastream" do
16
25
  File.open(resource_file('pixelstream.rgba')) do |stream|
@@ -1,20 +1,20 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe 'ChunyPNG.Color' do
4
- it "should interpret 4 arguments as RGBA values" do
4
+ it 'should interpret 4 arguments as RGBA values' do
5
5
  ChunkyPNG::Color(1, 2, 3, 4).should == ChunkyPNG::Color.rgba(1, 2, 3, 4)
6
6
  end
7
-
8
- it "should interpret 3 arguments as RGBA values" do
7
+
8
+ it 'should interpret 3 arguments as RGBA values' do
9
9
  ChunkyPNG::Color(1, 2, 3).should == ChunkyPNG::Color.rgb(1, 2, 3)
10
10
  end
11
-
12
- it "should interpret 2 arguments as a color to parse and an opacity value" do
11
+
12
+ it 'should interpret 2 arguments as a color to parse and an opacity value' do
13
13
  ChunkyPNG::Color('0x0a649664', 0xaa).should == 0x0a6496aa
14
14
  ChunkyPNG::Color('spring green @ 0.6666', 0xff).should == 0x00ff7fff
15
15
  end
16
-
17
- it "should interpret 1 argument as a color to parse" do
16
+
17
+ it 'should interpret 1 argument as a color to parse' do
18
18
  ChunkyPNG::Color.should_receive(:parse).with('0x0a649664')
19
19
  ChunkyPNG::Color('0x0a649664')
20
20
  end
@@ -30,55 +30,55 @@ describe ChunkyPNG::Color do
30
30
  @non_opaque = 0x0a649664
31
31
  @fully_transparent = 0x0a649600
32
32
  end
33
-
33
+
34
34
  describe '#parse' do
35
- it "should interpret a hex string correctly" do
35
+ it 'should interpret a hex string correctly' do
36
36
  parse('0x0a649664').should == ChunkyPNG::Color.from_hex('#0a649664')
37
37
  end
38
38
 
39
- it "should interpret a color name correctly" do
39
+ it 'should interpret a color name correctly' do
40
40
  parse(:spring_green).should == 0x00ff7fff
41
41
  parse('spring green').should == 0x00ff7fff
42
42
  parse('spring green @ 0.6666').should == 0x00ff7faa
43
43
  end
44
-
45
- it "should return numbers as is" do
44
+
45
+ it 'should return numbers as is' do
46
46
  parse('12345').should == 12345
47
47
  parse(12345).should == 12345
48
48
  end
49
49
  end
50
50
 
51
51
  describe '#pixel_bytesize' do
52
- it "should return the normal amount of bytes with a bit depth of 8" do
52
+ it 'should return the normal amount of bytes with a bit depth of 8' do
53
53
  pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8).should == 3
54
54
  end
55
55
 
56
- it "should return a multiple of the normal amount of bytes with a bit depth greater than 8" do
56
+ it 'should return a multiple of the normal amount of bytes with a bit depth greater than 8' do
57
57
  pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 16).should == 6
58
58
  pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 16).should == 8
59
59
  pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 16).should == 4
60
60
  end
61
-
62
- it "should return 1 with a bit depth lower than 0" do
61
+
62
+ it 'should return 1 with a bit depth lower than 0' do
63
63
  pixel_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 4).should == 1
64
64
  pixel_bytesize(ChunkyPNG::COLOR_INDEXED, 2).should == 1
65
65
  pixel_bytesize(ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 1).should == 1
66
66
  end
67
67
  end
68
-
68
+
69
69
  describe '#pass_bytesize' do
70
- it "should calculate a pass size correctly" do
70
+ it 'should calculate a pass size correctly' do
71
71
  pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 10).should == 310
72
72
  end
73
-
74
- it "should return 0 if one of the dimensions is zero" do
73
+
74
+ it 'should return 0 if one of the dimensions is zero' do
75
75
  pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 0, 10).should == 0
76
76
  pass_bytesize(ChunkyPNG::COLOR_TRUECOLOR, 8, 10, 0).should == 0
77
77
  end
78
78
  end
79
79
 
80
80
  describe '#rgba' do
81
- it "should represent pixels as the correct number" do
81
+ it 'should represent pixels as the correct number' do
82
82
  rgba(255, 255, 255, 255).should == @white
83
83
  rgba( 0, 0, 0, 255).should == @black
84
84
  rgba( 10, 100, 150, 255).should == @opaque
@@ -86,9 +86,9 @@ describe ChunkyPNG::Color do
86
86
  rgba( 10, 100, 150, 0).should == @fully_transparent
87
87
  end
88
88
  end
89
-
89
+
90
90
  describe '#from_hex' do
91
- it "should load colors correctly from hex notation" do
91
+ it 'should load colors correctly from hex notation' do
92
92
  from_hex('0a649664').should == @non_opaque
93
93
  from_hex('#0a649664').should == @non_opaque
94
94
  from_hex('0x0a649664').should == @non_opaque
@@ -99,17 +99,17 @@ describe ChunkyPNG::Color do
99
99
  from_hex('#abc').should == 0xaabbccff
100
100
  from_hex('0xabc').should == 0xaabbccff
101
101
  end
102
-
103
- it "should allow setting opacity explicitly" do
102
+
103
+ it 'should allow setting opacity explicitly' do
104
104
  from_hex('0x0a6496', 0x64).should == @non_opaque
105
105
  from_hex('#0a6496', 0x64).should == @non_opaque
106
106
  from_hex('0xabc', 0xdd).should == 0xaabbccdd
107
107
  from_hex('#abc', 0xdd).should == 0xaabbccdd
108
108
  end
109
109
  end
110
-
110
+
111
111
  describe '#html_color' do
112
- it "should find the correct color value" do
112
+ it 'should find the correct color value' do
113
113
  html_color(:springgreen).should == 0x00ff7fff
114
114
  html_color(:spring_green).should == 0x00ff7fff
115
115
  html_color('springgreen').should == 0x00ff7fff
@@ -117,26 +117,26 @@ describe ChunkyPNG::Color do
117
117
  html_color('SpringGreen').should == 0x00ff7fff
118
118
  html_color('SPRING_GREEN').should == 0x00ff7fff
119
119
  end
120
-
121
- it "should set the opacity level explicitly" do
120
+
121
+ it 'should set the opacity level explicitly' do
122
122
  html_color(:springgreen, 0xff).should == 0x00ff7fff
123
123
  html_color(:springgreen, 0xaa).should == 0x00ff7faa
124
124
  html_color(:springgreen, 0x00).should == 0x00ff7f00
125
125
  end
126
-
127
- it "should set opacity levels from the color name" do
126
+
127
+ it 'should set opacity levels from the color name' do
128
128
  html_color('Spring green @ 1.0').should == 0x00ff7fff
129
129
  html_color('Spring green @ 0.666').should == 0x00ff7faa
130
130
  html_color('Spring green @ 0.0').should == 0x00ff7f00
131
131
  end
132
-
133
- it "should raise for an unkown color name" do
132
+
133
+ it 'should raise for an unkown color name' do
134
134
  lambda { html_color(:nonsense) }.should raise_error(ArgumentError)
135
135
  end
136
136
  end
137
-
137
+
138
138
  describe '#opaque?' do
139
- it "should correctly check for opaqueness" do
139
+ it 'should correctly check for opaqueness' do
140
140
  opaque?(@white).should be_true
141
141
  opaque?(@black).should be_true
142
142
  opaque?(@opaque).should be_true
@@ -144,47 +144,47 @@ describe ChunkyPNG::Color do
144
144
  opaque?(@fully_transparent).should be_false
145
145
  end
146
146
  end
147
-
148
- describe 'extractiion of separate color channels' do
149
- it "should extract components from a color correctly" do
147
+
148
+ describe 'extraction of separate color channels' do
149
+ it 'should extract components from a color correctly' do
150
150
  r(@opaque).should == 10
151
151
  g(@opaque).should == 100
152
152
  b(@opaque).should == 150
153
153
  a(@opaque).should == 255
154
154
  end
155
155
  end
156
-
156
+
157
157
  describe '#grayscale_teint' do
158
- it "should calculate the correct grayscale teint" do
158
+ it 'should calculate the correct grayscale teint' do
159
159
  grayscale_teint(@opaque).should == 79
160
160
  grayscale_teint(@non_opaque).should == 79
161
161
  end
162
162
  end
163
-
163
+
164
164
  describe '#to_grayscale' do
165
- it "should use the grayscale teint for r, g and b" do
165
+ it 'should use the grayscale teint for r, g and b' do
166
166
  gs = to_grayscale(@non_opaque)
167
167
  r(gs).should == grayscale_teint(@non_opaque)
168
168
  g(gs).should == grayscale_teint(@non_opaque)
169
169
  b(gs).should == grayscale_teint(@non_opaque)
170
170
  end
171
-
172
- it "should preserve the alpha channel" do
171
+
172
+ it 'should preserve the alpha channel' do
173
173
  a(to_grayscale(@non_opaque)).should == a(@non_opaque)
174
174
  a(to_grayscale(@opaque)).should == ChunkyPNG::Color::MAX
175
175
  end
176
176
  end
177
-
177
+
178
178
  describe '#to_hex' do
179
- it "should represent colors correcly using hex notation" do
179
+ it 'should represent colors correcly using hex notation' do
180
180
  to_hex(@white).should == '#ffffffff'
181
181
  to_hex(@black).should == '#000000ff'
182
182
  to_hex(@opaque).should == '#0a6496ff'
183
183
  to_hex(@non_opaque).should == '#0a649664'
184
184
  to_hex(@fully_transparent).should == '#0a649600'
185
185
  end
186
-
187
- it "should represent colors correcly using hex notation without alpha channel" do
186
+
187
+ it 'should represent colors correcly using hex notation without alpha channel' do
188
188
  to_hex(@white, false).should == '#ffffff'
189
189
  to_hex(@black, false).should == '#000000'
190
190
  to_hex(@opaque, false).should == '#0a6496'
@@ -194,58 +194,82 @@ describe ChunkyPNG::Color do
194
194
  end
195
195
 
196
196
  describe 'conversion to other formats' do
197
- it "should convert the individual color values back correctly" do
197
+ it 'should convert the individual color values back correctly' do
198
198
  to_truecolor_bytes(@opaque).should == [10, 100, 150]
199
199
  to_truecolor_alpha_bytes(@non_opaque).should == [10, 100, 150, 100]
200
200
  end
201
201
  end
202
-
202
+
203
203
  describe '#compose' do
204
204
 
205
- it "should use the foregorund color as is when the background color is fully transparent" do
205
+ it 'should use the foregorund color as is when the background color is fully transparent' do
206
206
  compose(@non_opaque, @fully_transparent).should == @non_opaque
207
207
  end
208
208
 
209
- it "should use the foregorund color as is when an opaque color is given as foreground color" do
209
+ it 'should use the foregorund color as is when an opaque color is given as foreground color' do
210
210
  compose(@opaque, @white).should == @opaque
211
211
  end
212
212
 
213
- it "should use the background color as is when a fully transparent pixel is given as foreground color" do
213
+ it 'should use the background color as is when a fully transparent pixel is given as foreground color' do
214
214
  compose(@fully_transparent, @white).should == @white
215
215
  end
216
216
 
217
- it "should compose pixels correctly with both algorithms" do
217
+ it 'should compose pixels correctly with both algorithms' do
218
218
  compose_quick(@non_opaque, @white).should == 0x9fc2d6ff
219
219
  compose_precise(@non_opaque, @white).should == 0x9fc2d6ff
220
220
  end
221
221
  end
222
-
222
+
223
223
  describe '#decompose_alpha' do
224
- it "should decompose the alpha channel correctly" do
224
+ it 'should decompose the alpha channel correctly' do
225
225
  decompose_alpha(0x9fc2d6ff, @opaque, @white).should == 0x00000064
226
226
  end
227
-
228
- it "should return fully transparent if the background channel matches the resulting color" do
227
+
228
+ it 'should return fully transparent if the background channel matches the resulting color' do
229
229
  decompose_alpha(0xabcdefff, 0xff000000, 0xabcdefff).should == 0x00
230
230
  end
231
-
232
- it "should return fully opaque if the background channel matches the mask color" do
231
+
232
+ it 'should return fully opaque if the background channel matches the mask color' do
233
233
  decompose_alpha(0xff000000, 0xabcdefff, 0xabcdefff).should == 0xff
234
234
  end
235
-
236
- it "should return fully opaque if the resulting color matches the mask color" do
235
+
236
+ it 'should return fully opaque if the resulting color matches the mask color' do
237
237
  decompose_alpha(0xabcdefff, 0xabcdefff, 0xffffffff).should == 255
238
- end
238
+ end
239
239
  end
240
-
240
+
241
241
  describe '#blend' do
242
- it "should blend colors correctly" do
242
+ it 'should blend colors correctly' do
243
243
  blend(@opaque, @black).should == 0x05324bff
244
244
  end
245
-
246
- it "should not matter what color is used as foreground, and what as background" do
245
+
246
+ it 'should not matter what color is used as foreground, and what as background' do
247
247
  blend(@opaque, @black).should == blend(@black, @opaque)
248
248
  end
249
249
  end
250
- end
251
250
 
251
+ describe '#euclidean_distance_rgba' do
252
+ subject { euclidean_distance_rgba(color_a, color_b) }
253
+
254
+ context 'with white and black' do
255
+ let(:color_a) { @white }
256
+ let(:color_b) { @black }
257
+
258
+ it { should == Math.sqrt(195_075) } # sqrt(255^2 * 3)
259
+ end
260
+
261
+ context 'with black and white' do
262
+ let(:color_a) { @black }
263
+ let(:color_b) { @white }
264
+
265
+ it { should == Math.sqrt(195_075) } # sqrt(255^2 * 3)
266
+ end
267
+
268
+ context 'with the same colors' do
269
+ let(:color_a) { @white }
270
+ let(:color_b) { @white }
271
+
272
+ it { should == 0 }
273
+ end
274
+ end
275
+ end