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.
@@ -51,8 +51,8 @@ module ChunkyPNG
51
51
  # @param [#read, String] stream The stream to read the pixel data from.
52
52
  # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
53
53
  def from_bgr_stream(width, height, stream)
54
- string = ChunkyPNG::EXTRA_BYTE # Add a first byte to the first BGR triple.
55
- string << stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height]
54
+ string = ChunkyPNG::EXTRA_BYTE.dup # Add a first byte to the first BGR triple.
55
+ string << (stream.respond_to?(:read) ? stream.read(3 * width * height) : stream.to_s[0, 3 * width * height])
56
56
  pixels = string.unpack("@1" << ('XV' * (width * height))).map { |color| color | 0x000000ff }
57
57
  self.new(width, height, pixels)
58
58
  end
@@ -1,8 +1,7 @@
1
1
  module ChunkyPNG
2
-
3
2
  # A PNG datastream consists of multiple chunks. This module, and the classes
4
- # contained within, help with handling these chunks. It supports both
5
- # reading and writing chunks.
3
+ # contained within, help with handling these chunks. It supports both reading
4
+ # and writing chunks.
6
5
  #
7
6
  # All chunk types are instances of the {ChunkyPNG::Chunk::Base} class. For
8
7
  # some chunk types a specialized class is available, e.g. the IHDR chunk is
@@ -12,13 +11,11 @@ module ChunkyPNG
12
11
  #
13
12
  # @see ChunkyPNG::Datastream
14
13
  module Chunk
15
-
16
14
  # Reads a chunk from an IO stream.
17
15
  #
18
- # @param [IO, #read] io The IO stream to read from.
16
+ # @param io [IO, #read] The IO stream to read from.
19
17
  # @return [ChunkyPNG::Chung::Base] The loaded chunk instance.
20
18
  def self.read(io)
21
-
22
19
  length, type = io.read(8).unpack('Na4')
23
20
  content = io.read(length)
24
21
  crc = io.read(4).unpack('N').first
@@ -27,13 +24,13 @@ module ChunkyPNG
27
24
 
28
25
  CHUNK_TYPES.fetch(type, Generic).read(type, content)
29
26
  end
30
-
27
+
31
28
  # Verifies the CRC of a chunk.
32
- # @param [String] type The chunk's type.
33
- # @param [String] content The chunk's content.
34
- # @param [Integer] content The chunk's content.
35
- # @raise [RuntimeError] An exception is raised if the found CRC value
36
- # is not equal to the expected CRC value.
29
+ # @param type [String] The chunk's type.
30
+ # @param content [String] The chunk's content.
31
+ # @param found_crc [Integer] The chunk's found CRC value.
32
+ # @raise [RuntimeError] An exception is raised if the found CRC value is
33
+ # not equal to the expected CRC value.
37
34
  def self.verify_crc!(type, content, found_crc)
38
35
  expected_crc = Zlib.crc32(content, Zlib.crc32(type))
39
36
  raise ChunkyPNG::CRCMismatch, "Chuck CRC mismatch!" if found_crc != expected_crc
@@ -47,15 +44,14 @@ module ChunkyPNG
47
44
  #
48
45
  # @abstract
49
46
  class Base
50
-
51
47
  # The four-character type indicator for the chunk. This field is used to
52
48
  # find the correct class for a chunk when it is loaded from a PNG stream.
53
49
  # @return [String]
54
50
  attr_accessor :type
55
51
 
56
52
  # Initializes the chunk instance.
57
- # @param [String] type The four character chunk type indicator.
58
- # @param [Hash] attributes A hash of attributes to set on this chunk.
53
+ # @param type [String] The four character chunk type indicator.
54
+ # @param attributes [Hash] A hash of attributes to set on this chunk.
59
55
  def initialize(type, attributes = {})
60
56
  self.type = type
61
57
  attributes.each { |k, v| send("#{k}=", v) }
@@ -63,8 +59,8 @@ module ChunkyPNG
63
59
 
64
60
  # Writes the chunk to the IO stream, using the provided content.
65
61
  # The checksum will be calculated and appended to the stream.
66
- # @param [IO] io The IO stream to write to.
67
- # @param [String] content The content for this chunk.
62
+ # @param io [IO] The IO stream to write to.
63
+ # @param content [String] The content for this chunk.
68
64
  def write_with_crc(io, content)
69
65
  io << [content.length].pack('N') << type << content
70
66
  io << [Zlib.crc32(content, Zlib.crc32(type))].pack('N')
@@ -74,47 +70,44 @@ module ChunkyPNG
74
70
  #
75
71
  # It will call the +content+ method to get the content for this chunk,
76
72
  # and will calculate and append the checksum automatically.
77
- # @param [IO] io The IO stream to write to.
73
+ # @param io [IO] The IO stream to write to.
78
74
  def write(io)
79
75
  write_with_crc(io, content || '')
80
76
  end
81
77
  end
82
78
 
83
- # The Generic chunk type will read the content from the chunk as it,
79
+ # The Generic chunk type will read the content from the chunk as it,
84
80
  # and will write it back as it was read.
85
81
  class Generic < Base
86
-
87
- # The attribute to store the content from the chunk, which gets
82
+ # The attribute to store the content from the chunk, which gets
88
83
  # written by the +write+ method.
89
84
  attr_accessor :content
90
85
 
91
-
92
86
  def initialize(type, content = '')
93
87
  super(type, :content => content)
94
88
  end
95
89
 
96
90
  # Creates an instance, given the chunk's type and content.
97
- # @param [String] type The four character chunk type indicator.
98
- # @param [String] content The content read from the chunk.
91
+ # @param type [String] The four character chunk type indicator.
92
+ # @param content [String] The content read from the chunk.
99
93
  # @return [ChunkyPNG::Chunk::Generic] The new chunk instance.
100
94
  def self.read(type, content)
101
- self.new(type, content)
95
+ new(type, content)
102
96
  end
103
97
  end
104
98
 
105
- # The header (IHDR) chunk is the first chunk of every PNG image, and
106
- # contains information about the image: i.e. its width, height, color
99
+ # The header (IHDR) chunk is the first chunk of every PNG image, and
100
+ # contains information about the image: i.e. its width, height, color
107
101
  # depth, color mode, compression method, filtering method and interlace
108
102
  # method.
109
103
  #
110
- # ChunkyPNG supports all values for these variables that are defined in
111
- # the PNG spec, except for color depth: Only 8-bit depth images are
112
- # supported. Note that it is still possible to access the chunk for such
113
- # an image, but ChunkyPNG will raise an exception if you try to access
114
- # the pixel data.
104
+ # ChunkyPNG supports all values for these variables that are defined in the
105
+ # PNG spec, except for color depth: Only 8-bit depth images are supported.
106
+ # Note that it is still possible to access the chunk for such an image, but
107
+ # ChunkyPNG will raise an exception if you try to access the pixel data.
115
108
  class Header < Base
116
-
117
- attr_accessor :width, :height, :depth, :color, :compression, :filtering, :interlace
109
+ attr_accessor :width, :height, :depth, :color, :compression, :filtering,
110
+ :interlace
118
111
 
119
112
  def initialize(attrs = {})
120
113
  super('IHDR', attrs)
@@ -125,36 +118,45 @@ module ChunkyPNG
125
118
  @interlace ||= ChunkyPNG::INTERLACING_NONE
126
119
  end
127
120
 
128
- # Reads the 13 bytes of content from the header chunk to set the image attributes.
129
- # @param [String] type The four character chunk type indicator (= "IHDR").
130
- # @param [String] content The 13 bytes of content read from the chunk.
131
- # @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the
132
- # variables set to the values according to the content.
121
+ # Reads the 13 bytes of content from the header chunk to set the image
122
+ # attributes.
123
+ # @param type [String] The four character chunk type indicator (= "IHDR").
124
+ # @param content [String] The 13 bytes of content read from the chunk.
125
+ # @return [ChunkyPNG::Chunk::End] The new Header chunk instance with the
126
+ # variables set to the values according to the content.
133
127
  def self.read(type, content)
134
128
  fields = content.unpack('NNC5')
135
- self.new(:width => fields[0], :height => fields[1], :depth => fields[2], :color => fields[3],
136
- :compression => fields[4], :filtering => fields[5], :interlace => fields[6])
129
+ new(:width => fields[0],
130
+ :height => fields[1],
131
+ :depth => fields[2],
132
+ :color => fields[3],
133
+ :compression => fields[4],
134
+ :filtering => fields[5],
135
+ :interlace => fields[6])
137
136
  end
138
137
 
139
- # Returns the content for this chunk when it gets written to a file, by packing the
140
- # image information variables into the correct format.
138
+ # Returns the content for this chunk when it gets written to a file, by
139
+ # packing the image information variables into the correct format.
141
140
  # @return [String] The 13-byte content for the header chunk.
142
141
  def content
143
- [width, height, depth, color, compression, filtering, interlace].pack('NNC5')
142
+ [width, height, depth, color, compression, filtering, interlace].
143
+ pack('NNC5')
144
144
  end
145
145
  end
146
146
 
147
- # The End (IEND) chunk indicates the last chunk of a PNG stream. It does not
148
- # contain any data.
147
+ # The End (IEND) chunk indicates the last chunk of a PNG stream. It does
148
+ # not contain any data.
149
149
  class End < Base
150
-
150
+
151
151
  def initialize
152
152
  super('IEND')
153
153
  end
154
-
154
+
155
155
  # Reads the END chunk. It will check if the content is empty.
156
- # @param [String] type The four character chunk type indicator (= "IEND").
157
- # @param [String] content The content read from the chunk. Should be empty.
156
+ # @param type [String] The four character chunk type indicator (=
157
+ # "IEND").
158
+ # @param content [String] The content read from the chunk. Should be
159
+ # empty.
158
160
  # @return [ChunkyPNG::Chunk::End] The new End chunk instance.
159
161
  # @raise [RuntimeError] Raises an exception if the content was not empty.
160
162
  def self.read(type, content)
@@ -173,46 +175,56 @@ module ChunkyPNG
173
175
  # 8-bit RGB colors this image is using.
174
176
  #
175
177
  # @see ChunkyPNG::Chunk::Transparency
176
- # @see ChunkyPNG::Palette
178
+ # @see ChunkyPNG::Palette
177
179
  class Palette < Generic
178
180
  end
179
181
 
180
182
  # A transparency (tRNS) chunk defines the transparency for an image.
181
183
  #
182
- # * For indexed images, it contains the alpha channel for the colors defined in the Palette (PLTE) chunk.
183
- # * For grayscale images, it contains the grayscale teint that should be considered fully transparent.
184
- # * For truecolor images, it contains the color that should be considered fully transparent.
184
+ # * For indexed images, it contains the alpha channel for the colors
185
+ # defined in the Palette (PLTE) chunk.
186
+ # * For grayscale images, it contains the grayscale teint that should be
187
+ # considered fully transparent.
188
+ # * For truecolor images, it contains the color that should be considered
189
+ # fully transparent.
185
190
  #
186
- # Images having a color mode that already includes an alpha channel, this chunk should not be included.
191
+ # Images having a color mode that already includes an alpha channel, this
192
+ # chunk should not be included.
187
193
  #
188
194
  # @see ChunkyPNG::Chunk::Palette
189
195
  # @see ChunkyPNG::Palette
190
196
  class Transparency < Generic
191
-
192
197
  # Returns the alpha channel for the palette of an indexed image.
193
198
  #
194
- # This method should only be used for images having color mode ChunkyPNG::COLOR_INDEXED (3).
199
+ # This method should only be used for images having color mode
200
+ # ChunkyPNG::COLOR_INDEXED (3).
195
201
  #
196
- # @return [Array<Integer>] Returns an array of alpha channel values [0-255].
202
+ # @return [Array<Integer>] Returns an array of alpha channel values
203
+ # [0-255].
197
204
  def palette_alpha_channel
198
205
  content.unpack('C*')
199
206
  end
200
-
207
+
201
208
  # Returns the truecolor entry to be replaced by transparent pixels,
202
209
  #
203
- # This method should only be used for images having color mode ChunkyPNG::COLOR_TRUECOLOR (2).
210
+ # This method should only be used for images having color mode
211
+ # ChunkyPNG::COLOR_TRUECOLOR (2).
204
212
  #
205
213
  # @return [Integer] The color to replace with fully transparent pixels.
206
214
  def truecolor_entry(bit_depth)
207
- values = content.unpack('nnn').map { |c| ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", c) }
215
+ values = content.unpack('nnn').map do |c|
216
+ ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", c)
217
+ end
208
218
  ChunkyPNG::Color.rgb(*values)
209
219
  end
210
220
 
211
221
  # Returns the grayscale entry to be replaced by transparent pixels.
212
222
  #
213
- # This method should only be used for images having color mode ChunkyPNG::COLOR_GRAYSCALE (0).
223
+ # This method should only be used for images having color mode
224
+ # ChunkyPNG::COLOR_GRAYSCALE (0).
214
225
  #
215
- # @return [Integer] The (grayscale) color to replace with fully transparent pixels.
226
+ # @return [Integer] The (grayscale) color to replace with fully
227
+ # transparent pixels.
216
228
  def grayscale_entry(bit_depth)
217
229
  value = ChunkyPNG::Canvas.send(:"decode_png_resample_#{bit_depth}bit_value", content.unpack('n')[0])
218
230
  ChunkyPNG::Color.grayscale(value)
@@ -220,16 +232,15 @@ module ChunkyPNG
220
232
  end
221
233
 
222
234
  class ImageData < Generic
223
-
224
235
  def self.read(type, content)
225
236
  raise ExpectationFailed, 'The IDAT chunk should not be empty!' if content.bytesize == 0
226
237
  super
227
238
  end
228
-
239
+
229
240
  def self.combine_chunks(data_chunks)
230
241
  Zlib::Inflate.inflate(data_chunks.map { |c| c.content }.join(''))
231
242
  end
232
-
243
+
233
244
  def self.split_in_chunks(data, level = Zlib::DEFAULT_COMPRESSION, chunk_size = 2147483647)
234
245
  streamdata = Zlib::Deflate.deflate(data, level)
235
246
  # TODO: Split long streamdata over multiple chunks
@@ -237,16 +248,15 @@ module ChunkyPNG
237
248
  end
238
249
  end
239
250
 
240
- # The Text (tEXt) chunk contains keyword/value metadata about the PNG stream.
241
- # In this chunk, the value is stored uncompressed.
251
+ # The Text (tEXt) chunk contains keyword/value metadata about the PNG
252
+ # stream. In this chunk, the value is stored uncompressed.
242
253
  #
243
- # The tEXt chunk only supports Latin-1 encoded textual data. If you need UTF-8
244
- # support, check out the InternationalText chunk type.
254
+ # The tEXt chunk only supports Latin-1 encoded textual data. If you need
255
+ # UTF-8 support, check out the InternationalText chunk type.
245
256
  #
246
257
  # @see ChunkyPNG::Chunk::CompressedText
247
258
  # @see ChunkyPNG::Chunk::InternationalText
248
259
  class Text < Base
249
-
250
260
  attr_accessor :keyword, :value
251
261
 
252
262
  def initialize(keyword, value)
@@ -259,8 +269,8 @@ module ChunkyPNG
259
269
  new(keyword, value)
260
270
  end
261
271
 
262
- # Creates the content to write to the stream, by concatenating the keyword
263
- # with the value, joined by a null character.
272
+ # Creates the content to write to the stream, by concatenating the
273
+ # keyword with the value, joined by a null character.
264
274
  #
265
275
  # @return The content that should be written to the datastream.
266
276
  def content
@@ -268,14 +278,13 @@ module ChunkyPNG
268
278
  end
269
279
  end
270
280
 
271
- # The CompressedText (zTXt) chunk contains keyword/value metadata about
272
- # the PNG stream. In this chunk, the value is compressed using Deflate
281
+ # The CompressedText (zTXt) chunk contains keyword/value metadata about the
282
+ # PNG stream. In this chunk, the value is compressed using Deflate
273
283
  # compression.
274
284
  #
275
285
  # @see ChunkyPNG::Chunk::CompressedText
276
286
  # @see ChunkyPNG::Chunk::InternationalText
277
287
  class CompressedText < Base
278
-
279
288
  attr_accessor :keyword, :value
280
289
 
281
290
  def initialize(keyword, value)
@@ -289,40 +298,49 @@ module ChunkyPNG
289
298
  new(keyword, Zlib::Inflate.inflate(value))
290
299
  end
291
300
 
292
- # Creates the content to write to the stream, by concatenating the keyword
293
- # with the deflated value, joined by a null character.
301
+ # Creates the content to write to the stream, by concatenating the
302
+ # keyword with the deflated value, joined by a null character.
294
303
  #
295
304
  # @return The content that should be written to the datastream.
296
305
  def content
297
- [keyword, ChunkyPNG::COMPRESSION_DEFAULT, Zlib::Deflate.deflate(value)].pack('Z*Ca*')
306
+ [keyword, ChunkyPNG::COMPRESSION_DEFAULT, Zlib::Deflate.deflate(value)].
307
+ pack('Z*Ca*')
298
308
  end
299
309
  end
300
310
 
301
- # The Text (iTXt) chunk contains keyword/value metadata about the PNG stream.
302
- # The metadata in this chunk can be encoded using UTF-8 characters. Moreover,
303
- # it is possible to define the language of the metadata, and give a translation
304
- # of the keyword name. Finally, it supports bot compressed and uncompressed
305
- # values.
306
- #
307
- # @todo This chunk is currently not implemented, but merely read and written
308
- # back intact.
311
+ # The Text (iTXt) chunk contains keyword/value metadata about the PNG
312
+ # stream.
313
+ #
314
+ # The metadata in this chunk can be encoded using UTF-8 characters.
315
+ # Moreover, it is possible to define the language of the metadata, and give
316
+ # a translation of the keyword name. Finally, it supports bot compressed
317
+ # and uncompressed values.
318
+ #
319
+ # @todo This chunk is currently not implemented, but merely read and
320
+ # written back intact.
309
321
  #
310
322
  # @see ChunkyPNG::Chunk::Text
311
323
  # @see ChunkyPNG::Chunk::CompressedText
312
324
  class InternationalText < Generic
313
-
314
325
  # TODO
315
326
  end
316
327
 
317
- # Maps chunk types to classes, based on the four byte chunk type indicator at the
318
- # beginning of a chunk.
328
+ # Maps chunk types to classes, based on the four byte chunk type indicator
329
+ # at the beginning of a chunk.
319
330
  #
320
- # If a chunk type is not specified in this hash, the Generic chunk type will be used.
331
+ # If a chunk type is not specified in this hash, the Generic chunk type
332
+ # will be used.
321
333
  #
322
334
  # @see ChunkyPNG::Chunk.read
323
335
  CHUNK_TYPES = {
324
- 'IHDR' => Header, 'IEND' => End, 'IDAT' => ImageData, 'PLTE' => Palette, 'tRNS' => Transparency,
325
- 'tEXt' => Text, 'zTXt' => CompressedText, 'iTXt' => InternationalText
336
+ 'IHDR' => Header,
337
+ 'IEND' => End,
338
+ 'IDAT' => ImageData,
339
+ 'PLTE' => Palette,
340
+ 'tRNS' => Transparency,
341
+ 'tEXt' => Text,
342
+ 'zTXt' => CompressedText,
343
+ 'iTXt' => InternationalText,
326
344
  }
327
345
  end
328
346
  end
@@ -1,5 +1,5 @@
1
1
  module ChunkyPNG
2
-
2
+
3
3
  # Factory method to return a color value, based on the arguments given.
4
4
  #
5
5
  # @overload Color(r, g, b, a)
@@ -12,15 +12,18 @@ module ChunkyPNG
12
12
  #
13
13
  # @overload Color(hex_value, opacity = nil)
14
14
  # @param (see ChunkyPNG::Color.from_hex)
15
- # @return [Integer] The hex color value, with the opacity applied if one was given.
15
+ # @return [Integer] The hex color value, with the opacity applied if one
16
+ # was given.
16
17
  #
17
18
  # @overload Color(color_name, opacity = nil)
18
19
  # @param (see ChunkyPNG::Color.html_color)
19
- # @return [Integer] The hex color value, with the opacity applied if one was given.
20
+ # @return [Integer] The hex color value, with the opacity applied if one
21
+ # was given.
20
22
  #
21
23
  # @overload Color(color_value, opacity = nil)
22
24
  # @param [Integer, :to_i] The color value.
23
- # @return [Integer] The color value, with the opacity applied if one was given.
25
+ # @return [Integer] The color value, with the opacity applied if one was
26
+ # given.
24
27
  #
25
28
  # @return [Integer] The determined color value as RGBA integer.
26
29
  # @raise [ArgumentError] if the arguments weren't understood as a color.
@@ -54,7 +57,7 @@ module ChunkyPNG
54
57
 
55
58
  # @return [Integer] The maximum value of each color component.
56
59
  MAX = 0xff
57
-
60
+
58
61
  # @private
59
62
  # @return [Regexp] The regexp to parse 3-digit hex color values.
60
63
  HEX3_COLOR_REGEXP = /\A(?:#|0x)?([0-9a-f]{3})\z/i
@@ -66,7 +69,7 @@ module ChunkyPNG
66
69
  # @private
67
70
  # @return [Regexp] The regexp to parse named color values.
68
71
  HTML_COLOR_REGEXP = /^([a-z][a-z_ ]+[a-z])(?:\ ?\@\ ?(1\.0|0\.\d+))?$/i
69
-
72
+
70
73
  ####################################################################
71
74
  # CONSTRUCTING COLOR VALUES
72
75
  ####################################################################
@@ -76,7 +79,8 @@ module ChunkyPNG
76
79
  # It supports color numbers, colors in hex notation and named HTML colors.
77
80
  #
78
81
  # @param [Integer, String] The color value.
79
- # @return [Integer] The color value, with the opacity applied if one was given.
82
+ # @return [Integer] The color value, with the opacity applied if one was
83
+ # given.
80
84
  def parse(source)
81
85
  return source if source.kind_of?(Integer)
82
86
  case source.to_s
@@ -107,14 +111,16 @@ module ChunkyPNG
107
111
  end
108
112
 
109
113
  # Creates a new color using a grayscale teint.
110
- # @param [Integer] teint The grayscale teint (0-255), will be used as r, g, and b value.
114
+ # @param [Integer] teint The grayscale teint (0-255), will be used as r, g,
115
+ # and b value.
111
116
  # @return [Integer] The newly constructed color value.
112
117
  def grayscale(teint)
113
118
  teint << 24 | teint << 16 | teint << 8 | 0xff
114
119
  end
115
120
 
116
121
  # Creates a new color using a grayscale teint and alpha value.
117
- # @param [Integer] teint The grayscale teint (0-255), will be used as r, g, and b value.
122
+ # @param [Integer] teint The grayscale teint (0-255), will be used as r, g,
123
+ # and b value.
118
124
  # @param [Integer] a The opacity (0-255)
119
125
  # @return [Integer] The newly constructed color value.
120
126
  def grayscale_alpha(teint, a)
@@ -127,7 +133,7 @@ module ChunkyPNG
127
133
 
128
134
  # Creates a color by unpacking an rgb triple from a string.
129
135
  #
130
- # @param [String] stream The string to load the color from. It should be
136
+ # @param [String] stream The string to load the color from. It should be
131
137
  # at least 3 + pos bytes long.
132
138
  # @param [Integer] pos The position in the string to load the triple from.
133
139
  # @return [Integer] The newly constructed color value.
@@ -137,15 +143,15 @@ module ChunkyPNG
137
143
 
138
144
  # Creates a color by unpacking an rgba triple from a string
139
145
  #
140
- # @param [String] stream The string to load the color from. It should be
146
+ # @param [String] stream The string to load the color from. It should be
141
147
  # at least 4 + pos bytes long.
142
148
  # @param [Integer] pos The position in the string to load the triple from.
143
149
  # @return [Integer] The newly constructed color value.
144
150
  def from_rgba_stream(stream, pos = 0)
145
151
  rgba(*stream.unpack("@#{pos}C4"))
146
152
  end
147
-
148
- # Creates a color by converting it from a string in hex notation.
153
+
154
+ # Creates a color by converting it from a string in hex notation.
149
155
  #
150
156
  # It supports colors with (#rrggbbaa) or without (#rrggbb) alpha channel
151
157
  # as well as the 3-digit short format (#rgb) for those without.
@@ -181,7 +187,7 @@ module ChunkyPNG
181
187
  def r(value)
182
188
  (value & 0xff000000) >> 24
183
189
  end
184
-
190
+
185
191
  # Returns the green-component from the color value.
186
192
  #
187
193
  # @param [Integer] value The color value.
@@ -189,7 +195,7 @@ module ChunkyPNG
189
195
  def g(value)
190
196
  (value & 0x00ff0000) >> 16
191
197
  end
192
-
198
+
193
199
  # Returns the blue-component from the color value.
194
200
  #
195
201
  # @param [Integer] value The color value.
@@ -197,7 +203,7 @@ module ChunkyPNG
197
203
  def b(value)
198
204
  (value & 0x0000ff00) >> 8
199
205
  end
200
-
206
+
201
207
  # Returns the alpha channel value for the color value.
202
208
  #
203
209
  # @param [Integer] value The color value.
@@ -205,7 +211,7 @@ module ChunkyPNG
205
211
  def a(value)
206
212
  value & 0x000000ff
207
213
  end
208
-
214
+
209
215
  # Returns true if this color is fully opaque.
210
216
  #
211
217
  # @param [Integer] value The color to test.
@@ -213,14 +219,14 @@ module ChunkyPNG
213
219
  def opaque?(value)
214
220
  a(value) == 0x000000ff
215
221
  end
216
-
222
+
217
223
  # Returns the opaque value of this color by removing the alpha channel.
218
224
  # @param [Integer] value The color to transform.
219
225
  # @return [Integer] The opaque color
220
226
  def opaque!(value)
221
227
  value | 0x000000ff
222
228
  end
223
-
229
+
224
230
  # Returns true if this color is fully transparent.
225
231
  #
226
232
  # @param [Integer] value The color to test.
@@ -228,7 +234,7 @@ module ChunkyPNG
228
234
  def grayscale?(value)
229
235
  r(value) == b(value) && b(value) == g(value)
230
236
  end
231
-
237
+
232
238
  # Returns true if this color is fully transparent.
233
239
  #
234
240
  # @param [Integer] value The color to test.
@@ -241,9 +247,9 @@ module ChunkyPNG
241
247
  # ALPHA COMPOSITION
242
248
  ####################################################################
243
249
 
244
- # Multiplies two fractions using integer math, where the fractions are stored using an
245
- # integer between 0 and 255. This method is used as a helper method for compositing
246
- # colors using integer math.
250
+ # Multiplies two fractions using integer math, where the fractions are
251
+ # stored using an integer between 0 and 255. This method is used as a
252
+ # helper method for compositing colors using integer math.
247
253
  #
248
254
  # This is a quicker implementation of ((a * b) / 255.0).round.
249
255
  #
@@ -257,8 +263,8 @@ module ChunkyPNG
257
263
 
258
264
  # Composes two colors with an alpha channel using integer math.
259
265
  #
260
- # This version is faster than the version based on floating point math, so this
261
- # compositing function is used by default.
266
+ # This version is faster than the version based on floating point math, so
267
+ # this compositing function is used by default.
262
268
  #
263
269
  # @param [Integer] fg The foreground color.
264
270
  # @param [Integer] bg The foreground color.
@@ -267,7 +273,7 @@ module ChunkyPNG
267
273
  def compose_quick(fg, bg)
268
274
  return fg if opaque?(fg) || fully_transparent?(bg)
269
275
  return bg if fully_transparent?(fg)
270
-
276
+
271
277
  a_com = int8_mult(0xff - a(fg), a(bg))
272
278
  new_r = int8_mult(a(fg), r(fg)) + int8_mult(a_com, r(bg))
273
279
  new_g = int8_mult(a(fg), g(fg)) + int8_mult(a_com, g(bg))
@@ -278,9 +284,9 @@ module ChunkyPNG
278
284
 
279
285
  # Composes two colors with an alpha channel using floating point math.
280
286
  #
281
- # This method uses more precise floating point math, but this precision is lost
282
- # when the result is converted back to an integer. Because it is slower than
283
- # the version based on integer math, that version is preferred.
287
+ # This method uses more precise floating point math, but this precision is
288
+ # lost when the result is converted back to an integer. Because it is
289
+ # slower than the version based on integer math, that version is preferred.
284
290
  #
285
291
  # @param [Integer] fg The foreground color.
286
292
  # @param [Integer] bg The foreground color.
@@ -289,7 +295,7 @@ module ChunkyPNG
289
295
  def compose_precise(fg, bg)
290
296
  return fg if opaque?(fg) || fully_transparent?(bg)
291
297
  return bg if fully_transparent?(fg)
292
-
298
+
293
299
  fg_a = a(fg).to_f / MAX
294
300
  bg_a = a(bg).to_f / MAX
295
301
  a_com = (1.0 - fg_a) * bg_a
@@ -302,8 +308,8 @@ module ChunkyPNG
302
308
  end
303
309
 
304
310
  alias :compose :compose_quick
305
-
306
- # Blends the foreground and background color by taking the average of
311
+
312
+ # Blends the foreground and background color by taking the average of
307
313
  # the components.
308
314
  #
309
315
  # @param [Integer] fg The foreground color.
@@ -313,8 +319,8 @@ module ChunkyPNG
313
319
  (fg + bg) >> 1
314
320
  end
315
321
 
316
- # Interpolates the foreground and background colors by the given alpha value.
317
- # This also blends the alpha channels themselves.
322
+ # Interpolates the foreground and background colors by the given alpha
323
+ # value. This also blends the alpha channels themselves.
318
324
  #
319
325
  # A blending factor of 255 will give entirely the foreground,
320
326
  # while a blending factor of 0 will give the background.
@@ -326,37 +332,39 @@ module ChunkyPNG
326
332
  def interpolate_quick(fg, bg, alpha)
327
333
  return fg if alpha >= 255
328
334
  return bg if alpha <= 0
329
-
335
+
330
336
  alpha_com = 255 - alpha
331
337
 
332
338
  new_r = int8_mult(alpha, r(fg)) + int8_mult(alpha_com, r(bg))
333
339
  new_g = int8_mult(alpha, g(fg)) + int8_mult(alpha_com, g(bg))
334
340
  new_b = int8_mult(alpha, b(fg)) + int8_mult(alpha_com, b(bg))
335
341
  new_a = int8_mult(alpha, a(fg)) + int8_mult(alpha_com, a(bg))
336
-
337
- return rgba(new_r, new_g, new_b, new_a)
342
+
343
+ rgba(new_r, new_g, new_b, new_a)
338
344
  end
339
345
 
340
346
  # Calculates the grayscale teint of an RGB color.
341
347
  #
342
- # @param [Integer] color The color to convert.
348
+ # @param [Integer] color The color to convert.
343
349
  # @return [Integer] The grayscale teint of the input color, 0-255.
344
350
  def grayscale_teint(color)
345
351
  (r(color) * 0.3 + g(color) * 0.59 + b(color) * 0.11).round
346
352
  end
347
-
353
+
348
354
  # Converts a color to a fiting grayscale value. It will conserve the alpha
349
355
  # channel.
350
356
  #
351
- # This method will return a full color value, with the R, G, and B value set
352
- # to the grayscale teint calcuated from the input color's R, G and B values.
357
+ # This method will return a full color value, with the R, G, and B value
358
+ # set to the grayscale teint calcuated from the input color's R, G and B
359
+ # values.
353
360
  #
354
361
  # @param [Integer] color The color to convert.
355
- # @return [Integer] The input color, converted to the best fitting grayscale.
362
+ # @return [Integer] The input color, converted to the best fitting
363
+ # grayscale.
356
364
  # @see #grayscale_teint
357
365
  def to_grayscale(color)
358
366
  grayscale_alpha(grayscale_teint(color), a(color))
359
- end
367
+ end
360
368
 
361
369
  # Lowers the intensity of a color, by lowering its alpha by a given factor.
362
370
  # @param [Integer] color The color to adjust.
@@ -366,21 +374,23 @@ module ChunkyPNG
366
374
  new_alpha = int8_mult(a(color), factor)
367
375
  (color & 0xffffff00) | new_alpha
368
376
  end
369
-
377
+
370
378
  # Decomposes a color, given a color, a mask color and a background color.
371
379
  # The returned color will be a variant of the mask color, with the alpha
372
- # channel set to the best fitting value. This basically is the reverse
380
+ # channel set to the best fitting value. This basically is the reverse
373
381
  # operation if alpha composition.
374
382
  #
375
383
  # If the color cannot be decomposed, this method will return the fully
376
384
  # transparent variant of the mask color.
377
385
  #
378
386
  # @param [Integer] color The color that was the result of compositing.
379
- # @param [Integer] mask The opaque variant of the color that was being composed
387
+ # @param [Integer] mask The opaque variant of the color that was being
388
+ # composed
380
389
  # @param [Integer] bg The background color on which the color was composed.
381
- # @param [Integer] tolerance The decomposition tolerance level, a value between 0 and 255.
382
- # @return [Integer] The decomposed color,a variant of the masked color with the
383
- # alpha channel set to an appropriate value.
390
+ # @param [Integer] tolerance The decomposition tolerance level, a value
391
+ # between 0 and 255.
392
+ # @return [Integer] The decomposed color, a variant of the masked color
393
+ # with the alpha channel set to an appropriate value.
384
394
  def decompose_color(color, mask, bg, tolerance = 1)
385
395
  if alpha_decomposable?(color, mask, bg, tolerance)
386
396
  mask & 0xffffff00 | decompose_alpha(color, mask, bg)
@@ -388,62 +398,71 @@ module ChunkyPNG
388
398
  mask & 0xffffff00
389
399
  end
390
400
  end
391
-
401
+
392
402
  # Checks whether an alpha channel value can successfully be composed
393
403
  # given the resulting color, the mask color and a background color,
394
- # all of which should be opaque.
404
+ # all of which should be opaque.
395
405
  #
396
406
  # @param [Integer] color The color that was the result of compositing.
397
- # @param [Integer] mask The opaque variant of the color that was being composed
407
+ # @param [Integer] mask The opaque variant of the color that was being
408
+ # composed
398
409
  # @param [Integer] bg The background color on which the color was composed.
399
- # @param [Integer] tolerance The decomposition tolerance level, a value between 0 and 255.
400
- # @return [Boolean] True if the alpha component can be decomposed successfully.
410
+ # @param [Integer] tolerance The decomposition tolerance level, a value
411
+ # between 0 and 255.
412
+ # @return [Boolean] True if the alpha component can be decomposed
413
+ # successfully.
401
414
  # @see #decompose_alpha
402
415
  def alpha_decomposable?(color, mask, bg, tolerance = 1)
403
416
  components = decompose_alpha_components(color, mask, bg)
404
- sum = components.inject(0) { |a,b| a + b }
417
+ sum = components.inject(0) { |a,b| a + b }
405
418
  max = components.max * 3
406
- return components.max <= 255 && components.min >= 0 && (sum + tolerance * 3) >= max
419
+ components.max <= 255 && components.min >= 0 && (sum + tolerance * 3) >= max
407
420
  end
408
-
409
- # Decomposes the alpha channel value given the resulting color, the mask color
410
- # and a background color, all of which should be opaque.
421
+
422
+ # Decomposes the alpha channel value given the resulting color, the mask
423
+ # color and a background color, all of which should be opaque.
411
424
  #
412
- # Make sure to call {#alpha_decomposable?} first to see if the alpha channel
413
- # value can successfully decomposed with a given tolerance, otherwise the return
414
- # value of this method is undefined.
425
+ # Make sure to call {#alpha_decomposable?} first to see if the alpha
426
+ # channel value can successfully decomposed with a given tolerance,
427
+ # otherwise the return value of this method is undefined.
415
428
  #
416
429
  # @param [Integer] color The color that was the result of compositing.
417
- # @param [Integer] mask The opaque variant of the color that was being composed
430
+ # @param [Integer] mask The opaque variant of the color that was being
431
+ # composed
418
432
  # @param [Integer] bg The background color on which the color was composed.
419
- # @return [Integer] The best fitting alpha channel, a value between 0 and 255.
433
+ # @return [Integer] The best fitting alpha channel, a value between 0 and
434
+ # 255.
420
435
  # @see #alpha_decomposable?
421
436
  def decompose_alpha(color, mask, bg)
422
437
  components = decompose_alpha_components(color, mask, bg)
423
438
  (components.inject(0) { |a,b| a + b } / 3.0).round
424
439
  end
425
-
440
+
426
441
  # Decomposes an alpha channel for either the r, g or b color channel.
427
- # @param [:r, :g, :b] channel The channel to decompose the alpha channel from.
442
+ # @param [:r, :g, :b] channel The channel to decompose the alpha channel
443
+ # from.
428
444
  # @param [Integer] color The color that was the result of compositing.
429
- # @param [Integer] mask The opaque variant of the color that was being composed
445
+ # @param [Integer] mask The opaque variant of the color that was being
446
+ # composed
430
447
  # @param [Integer] bg The background color on which the color was composed.
431
448
  # @return [Integer] The decomposed alpha value for the channel.
432
449
  def decompose_alpha_component(channel, color, mask, bg)
433
450
  cc, mc, bc = send(channel, color), send(channel, mask), send(channel, bg)
434
-
451
+
435
452
  return 0x00 if bc == cc
436
453
  return 0xff if bc == mc
437
454
  return 0xff if cc == mc
438
-
455
+
439
456
  (((bc - cc).to_f / (bc - mc).to_f) * MAX).round
440
457
  end
441
-
458
+
442
459
  # Decomposes the alpha channels for the r, g and b color channel.
443
460
  # @param [Integer] color The color that was the result of compositing.
444
- # @param [Integer] mask The opaque variant of the color that was being composed
445
- # @param [Integer] bg The background color on which the color was composed.
446
- # @return [Array<Integer>] The decomposed alpha values for the r, g and b channels.
461
+ # @param [Integer] mask The opaque variant of the color that was being
462
+ # composed
463
+ # @param [Integer] bg The background color on which the color was composed.
464
+ # @return [Array<Integer>] The decomposed alpha values for the r, g and b
465
+ # channels.
447
466
  def decompose_alpha_components(color, mask, bg)
448
467
  [
449
468
  decompose_alpha_component(:r, color, mask, bg),
@@ -456,7 +475,8 @@ module ChunkyPNG
456
475
  # CONVERSIONS
457
476
  ####################################################################
458
477
 
459
- # Returns a string representing this color using hex notation (i.e. #rrggbbaa).
478
+ # Returns a string representing this color using hex notation (i.e.
479
+ # #rrggbbaa).
460
480
  #
461
481
  # @param [Integer] value The color to convert.
462
482
  # @return [String] The color in hex notation, starting with a pound sign.
@@ -472,8 +492,8 @@ module ChunkyPNG
472
492
  [r(color), g(color), b(color), a(color)]
473
493
  end
474
494
 
475
- # Returns an array with the separate RGB values for this color.
476
- # The alpha channel will be discarded.
495
+ # Returns an array with the separate RGB values for this color. The alpha
496
+ # channel will be discarded.
477
497
  #
478
498
  # @param [Integer] color The color to convert.
479
499
  # @return [Array<Integer>] An array with 3 Integer elements.
@@ -483,7 +503,7 @@ module ChunkyPNG
483
503
 
484
504
  # Returns an array with the grayscale teint value for this color.
485
505
  #
486
- # This method expects the r,g and b value to be equal, and the alpha
506
+ # This method expects the r, g, and b value to be equal, and the alpha
487
507
  # channel will be discarded.
488
508
  #
489
509
  # @param [Integer] color The grayscale color to convert.
@@ -492,189 +512,220 @@ module ChunkyPNG
492
512
  [b(color)] # assumption r == g == b
493
513
  end
494
514
 
495
- # Returns an array with the grayscale teint and alpha channel values
496
- # for this color.
515
+ # Returns an array with the grayscale teint and alpha channel values for
516
+ # this color.
497
517
  #
498
- # This method expects the color to be grayscale, i.e. r,g and b value
499
- # to be equal and uses only the B channel. If you need to convert a
500
- # color to grayscale first, see {#to_grayscale}.
518
+ # This method expects the color to be grayscale, i.e. r, g, and b value to
519
+ # be equal and uses only the B channel. If you need to convert a color to
520
+ # grayscale first, see {#to_grayscale}.
501
521
  #
502
522
  # @param [Integer] color The grayscale color to convert.
503
523
  # @return [Array<Integer>] An array with 2 Integer elements.
504
- # @see #to_grascale
524
+ # @see #to_grayscale
505
525
  def to_grayscale_alpha_bytes(color)
506
526
  [b(color), a(color)] # assumption r == g == b
507
527
  end
508
528
 
529
+ ####################################################################
530
+ # COMPARISON
531
+ ####################################################################
532
+
533
+ # Compute the Euclidean distance between 2 colors in RGBA
534
+ #
535
+ # This method simply takes the Euclidean distance between the RGBA channels
536
+ # of 2 colors, which gives us a measure of how different the two colors
537
+ # are.
538
+ #
539
+ # Although it would be more perceptually accurate to calculate a proper
540
+ # Delta E in Lab colorspace, this method should serve many use-cases while
541
+ # avoiding the overhead of converting RGBA to Lab.
542
+ #
543
+ # @param color_a [Integer]
544
+ # @param color_b [Integer]
545
+ # @return [Float]
546
+ def euclidean_distance_rgba(pixel_after, pixel_before)
547
+ Math.sqrt(
548
+ (r(pixel_after) - r(pixel_before))**2 +
549
+ (g(pixel_after) - g(pixel_before))**2 +
550
+ (b(pixel_after) - b(pixel_before))**2 +
551
+ (a(pixel_after) - a(pixel_before))**2
552
+ )
553
+ end
554
+
555
+ # Could be simplified as MAX * 2, but this format mirrors the math in
556
+ # {#euclidean_distance_rgba}
557
+ # @return [Float] The maximum Euclidean distance of two RGBA colors.
558
+ MAX_EUCLIDEAN_DISTANCE_RGBA = Math.sqrt(MAX**2 * 4)
559
+
509
560
  ####################################################################
510
561
  # COLOR CONSTANTS
511
562
  ####################################################################
512
563
 
513
564
  # @return [Hash<Symbol, Integer>] All the predefined color names in HTML.
514
565
  PREDEFINED_COLORS = {
515
- :aliceblue => 0xf0f8ff00,
516
- :antiquewhite => 0xfaebd700,
517
- :aqua => 0x00ffff00,
518
- :aquamarine => 0x7fffd400,
519
- :azure => 0xf0ffff00,
520
- :beige => 0xf5f5dc00,
521
- :bisque => 0xffe4c400,
522
- :black => 0x00000000,
523
- :blanchedalmond => 0xffebcd00,
524
- :blue => 0x0000ff00,
525
- :blueviolet => 0x8a2be200,
526
- :brown => 0xa52a2a00,
527
- :burlywood => 0xdeb88700,
528
- :cadetblue => 0x5f9ea000,
529
- :chartreuse => 0x7fff0000,
530
- :chocolate => 0xd2691e00,
531
- :coral => 0xff7f5000,
532
- :cornflowerblue => 0x6495ed00,
533
- :cornsilk => 0xfff8dc00,
534
- :crimson => 0xdc143c00,
535
- :cyan => 0x00ffff00,
536
- :darkblue => 0x00008b00,
537
- :darkcyan => 0x008b8b00,
538
- :darkgoldenrod => 0xb8860b00,
539
- :darkgray => 0xa9a9a900,
540
- :darkgrey => 0xa9a9a900,
541
- :darkgreen => 0x00640000,
542
- :darkkhaki => 0xbdb76b00,
543
- :darkmagenta => 0x8b008b00,
544
- :darkolivegreen => 0x556b2f00,
545
- :darkorange => 0xff8c0000,
546
- :darkorchid => 0x9932cc00,
547
- :darkred => 0x8b000000,
548
- :darksalmon => 0xe9967a00,
549
- :darkseagreen => 0x8fbc8f00,
550
- :darkslateblue => 0x483d8b00,
551
- :darkslategray => 0x2f4f4f00,
552
- :darkslategrey => 0x2f4f4f00,
553
- :darkturquoise => 0x00ced100,
554
- :darkviolet => 0x9400d300,
555
- :deeppink => 0xff149300,
556
- :deepskyblue => 0x00bfff00,
557
- :dimgray => 0x69696900,
558
- :dimgrey => 0x69696900,
559
- :dodgerblue => 0x1e90ff00,
560
- :firebrick => 0xb2222200,
561
- :floralwhite => 0xfffaf000,
562
- :forestgreen => 0x228b2200,
563
- :fuchsia => 0xff00ff00,
564
- :gainsboro => 0xdcdcdc00,
565
- :ghostwhite => 0xf8f8ff00,
566
- :gold => 0xffd70000,
567
- :goldenrod => 0xdaa52000,
568
- :gray => 0x80808000,
569
- :grey => 0x80808000,
570
- :green => 0x00800000,
571
- :greenyellow => 0xadff2f00,
572
- :honeydew => 0xf0fff000,
573
- :hotpink => 0xff69b400,
574
- :indianred => 0xcd5c5c00,
575
- :indigo => 0x4b008200,
576
- :ivory => 0xfffff000,
577
- :khaki => 0xf0e68c00,
578
- :lavender => 0xe6e6fa00,
579
- :lavenderblush => 0xfff0f500,
580
- :lawngreen => 0x7cfc0000,
581
- :lemonchiffon => 0xfffacd00,
582
- :lightblue => 0xadd8e600,
583
- :lightcoral => 0xf0808000,
584
- :lightcyan => 0xe0ffff00,
566
+ :aliceblue => 0xf0f8ff00,
567
+ :antiquewhite => 0xfaebd700,
568
+ :aqua => 0x00ffff00,
569
+ :aquamarine => 0x7fffd400,
570
+ :azure => 0xf0ffff00,
571
+ :beige => 0xf5f5dc00,
572
+ :bisque => 0xffe4c400,
573
+ :black => 0x00000000,
574
+ :blanchedalmond => 0xffebcd00,
575
+ :blue => 0x0000ff00,
576
+ :blueviolet => 0x8a2be200,
577
+ :brown => 0xa52a2a00,
578
+ :burlywood => 0xdeb88700,
579
+ :cadetblue => 0x5f9ea000,
580
+ :chartreuse => 0x7fff0000,
581
+ :chocolate => 0xd2691e00,
582
+ :coral => 0xff7f5000,
583
+ :cornflowerblue => 0x6495ed00,
584
+ :cornsilk => 0xfff8dc00,
585
+ :crimson => 0xdc143c00,
586
+ :cyan => 0x00ffff00,
587
+ :darkblue => 0x00008b00,
588
+ :darkcyan => 0x008b8b00,
589
+ :darkgoldenrod => 0xb8860b00,
590
+ :darkgray => 0xa9a9a900,
591
+ :darkgrey => 0xa9a9a900,
592
+ :darkgreen => 0x00640000,
593
+ :darkkhaki => 0xbdb76b00,
594
+ :darkmagenta => 0x8b008b00,
595
+ :darkolivegreen => 0x556b2f00,
596
+ :darkorange => 0xff8c0000,
597
+ :darkorchid => 0x9932cc00,
598
+ :darkred => 0x8b000000,
599
+ :darksalmon => 0xe9967a00,
600
+ :darkseagreen => 0x8fbc8f00,
601
+ :darkslateblue => 0x483d8b00,
602
+ :darkslategray => 0x2f4f4f00,
603
+ :darkslategrey => 0x2f4f4f00,
604
+ :darkturquoise => 0x00ced100,
605
+ :darkviolet => 0x9400d300,
606
+ :deeppink => 0xff149300,
607
+ :deepskyblue => 0x00bfff00,
608
+ :dimgray => 0x69696900,
609
+ :dimgrey => 0x69696900,
610
+ :dodgerblue => 0x1e90ff00,
611
+ :firebrick => 0xb2222200,
612
+ :floralwhite => 0xfffaf000,
613
+ :forestgreen => 0x228b2200,
614
+ :fuchsia => 0xff00ff00,
615
+ :gainsboro => 0xdcdcdc00,
616
+ :ghostwhite => 0xf8f8ff00,
617
+ :gold => 0xffd70000,
618
+ :goldenrod => 0xdaa52000,
619
+ :gray => 0x80808000,
620
+ :grey => 0x80808000,
621
+ :green => 0x00800000,
622
+ :greenyellow => 0xadff2f00,
623
+ :honeydew => 0xf0fff000,
624
+ :hotpink => 0xff69b400,
625
+ :indianred => 0xcd5c5c00,
626
+ :indigo => 0x4b008200,
627
+ :ivory => 0xfffff000,
628
+ :khaki => 0xf0e68c00,
629
+ :lavender => 0xe6e6fa00,
630
+ :lavenderblush => 0xfff0f500,
631
+ :lawngreen => 0x7cfc0000,
632
+ :lemonchiffon => 0xfffacd00,
633
+ :lightblue => 0xadd8e600,
634
+ :lightcoral => 0xf0808000,
635
+ :lightcyan => 0xe0ffff00,
585
636
  :lightgoldenrodyellow => 0xfafad200,
586
- :lightgray => 0xd3d3d300,
587
- :lightgrey => 0xd3d3d300,
588
- :lightgreen => 0x90ee9000,
589
- :lightpink => 0xffb6c100,
590
- :lightsalmon => 0xffa07a00,
591
- :lightseagreen => 0x20b2aa00,
592
- :lightskyblue => 0x87cefa00,
593
- :lightslategray => 0x77889900,
594
- :lightslategrey => 0x77889900,
595
- :lightsteelblue => 0xb0c4de00,
596
- :lightyellow => 0xffffe000,
597
- :lime => 0x00ff0000,
598
- :limegreen => 0x32cd3200,
599
- :linen => 0xfaf0e600,
600
- :magenta => 0xff00ff00,
601
- :maroon => 0x80000000,
602
- :mediumaquamarine => 0x66cdaa00,
603
- :mediumblue => 0x0000cd00,
604
- :mediumorchid => 0xba55d300,
605
- :mediumpurple => 0x9370d800,
606
- :mediumseagreen => 0x3cb37100,
607
- :mediumslateblue => 0x7b68ee00,
608
- :mediumspringgreen => 0x00fa9a00,
609
- :mediumturquoise => 0x48d1cc00,
610
- :mediumvioletred => 0xc7158500,
611
- :midnightblue => 0x19197000,
612
- :mintcream => 0xf5fffa00,
613
- :mistyrose => 0xffe4e100,
614
- :moccasin => 0xffe4b500,
615
- :navajowhite => 0xffdead00,
616
- :navy => 0x00008000,
617
- :oldlace => 0xfdf5e600,
618
- :olive => 0x80800000,
619
- :olivedrab => 0x6b8e2300,
620
- :orange => 0xffa50000,
621
- :orangered => 0xff450000,
622
- :orchid => 0xda70d600,
623
- :palegoldenrod => 0xeee8aa00,
624
- :palegreen => 0x98fb9800,
625
- :paleturquoise => 0xafeeee00,
626
- :palevioletred => 0xd8709300,
627
- :papayawhip => 0xffefd500,
628
- :peachpuff => 0xffdab900,
629
- :peru => 0xcd853f00,
630
- :pink => 0xffc0cb00,
631
- :plum => 0xdda0dd00,
632
- :powderblue => 0xb0e0e600,
633
- :purple => 0x80008000,
634
- :red => 0xff000000,
635
- :rosybrown => 0xbc8f8f00,
636
- :royalblue => 0x4169e100,
637
- :saddlebrown => 0x8b451300,
638
- :salmon => 0xfa807200,
639
- :sandybrown => 0xf4a46000,
640
- :seagreen => 0x2e8b5700,
641
- :seashell => 0xfff5ee00,
642
- :sienna => 0xa0522d00,
643
- :silver => 0xc0c0c000,
644
- :skyblue => 0x87ceeb00,
645
- :slateblue => 0x6a5acd00,
646
- :slategray => 0x70809000,
647
- :slategrey => 0x70809000,
648
- :snow => 0xfffafa00,
649
- :springgreen => 0x00ff7f00,
650
- :steelblue => 0x4682b400,
651
- :tan => 0xd2b48c00,
652
- :teal => 0x00808000,
653
- :thistle => 0xd8bfd800,
654
- :tomato => 0xff634700,
655
- :turquoise => 0x40e0d000,
656
- :violet => 0xee82ee00,
657
- :wheat => 0xf5deb300,
658
- :white => 0xffffff00,
659
- :whitesmoke => 0xf5f5f500,
660
- :yellow => 0xffff0000,
661
- :yellowgreen => 0x9acd3200
637
+ :lightgray => 0xd3d3d300,
638
+ :lightgrey => 0xd3d3d300,
639
+ :lightgreen => 0x90ee9000,
640
+ :lightpink => 0xffb6c100,
641
+ :lightsalmon => 0xffa07a00,
642
+ :lightseagreen => 0x20b2aa00,
643
+ :lightskyblue => 0x87cefa00,
644
+ :lightslategray => 0x77889900,
645
+ :lightslategrey => 0x77889900,
646
+ :lightsteelblue => 0xb0c4de00,
647
+ :lightyellow => 0xffffe000,
648
+ :lime => 0x00ff0000,
649
+ :limegreen => 0x32cd3200,
650
+ :linen => 0xfaf0e600,
651
+ :magenta => 0xff00ff00,
652
+ :maroon => 0x80000000,
653
+ :mediumaquamarine => 0x66cdaa00,
654
+ :mediumblue => 0x0000cd00,
655
+ :mediumorchid => 0xba55d300,
656
+ :mediumpurple => 0x9370d800,
657
+ :mediumseagreen => 0x3cb37100,
658
+ :mediumslateblue => 0x7b68ee00,
659
+ :mediumspringgreen => 0x00fa9a00,
660
+ :mediumturquoise => 0x48d1cc00,
661
+ :mediumvioletred => 0xc7158500,
662
+ :midnightblue => 0x19197000,
663
+ :mintcream => 0xf5fffa00,
664
+ :mistyrose => 0xffe4e100,
665
+ :moccasin => 0xffe4b500,
666
+ :navajowhite => 0xffdead00,
667
+ :navy => 0x00008000,
668
+ :oldlace => 0xfdf5e600,
669
+ :olive => 0x80800000,
670
+ :olivedrab => 0x6b8e2300,
671
+ :orange => 0xffa50000,
672
+ :orangered => 0xff450000,
673
+ :orchid => 0xda70d600,
674
+ :palegoldenrod => 0xeee8aa00,
675
+ :palegreen => 0x98fb9800,
676
+ :paleturquoise => 0xafeeee00,
677
+ :palevioletred => 0xd8709300,
678
+ :papayawhip => 0xffefd500,
679
+ :peachpuff => 0xffdab900,
680
+ :peru => 0xcd853f00,
681
+ :pink => 0xffc0cb00,
682
+ :plum => 0xdda0dd00,
683
+ :powderblue => 0xb0e0e600,
684
+ :purple => 0x80008000,
685
+ :red => 0xff000000,
686
+ :rosybrown => 0xbc8f8f00,
687
+ :royalblue => 0x4169e100,
688
+ :saddlebrown => 0x8b451300,
689
+ :salmon => 0xfa807200,
690
+ :sandybrown => 0xf4a46000,
691
+ :seagreen => 0x2e8b5700,
692
+ :seashell => 0xfff5ee00,
693
+ :sienna => 0xa0522d00,
694
+ :silver => 0xc0c0c000,
695
+ :skyblue => 0x87ceeb00,
696
+ :slateblue => 0x6a5acd00,
697
+ :slategray => 0x70809000,
698
+ :slategrey => 0x70809000,
699
+ :snow => 0xfffafa00,
700
+ :springgreen => 0x00ff7f00,
701
+ :steelblue => 0x4682b400,
702
+ :tan => 0xd2b48c00,
703
+ :teal => 0x00808000,
704
+ :thistle => 0xd8bfd800,
705
+ :tomato => 0xff634700,
706
+ :turquoise => 0x40e0d000,
707
+ :violet => 0xee82ee00,
708
+ :wheat => 0xf5deb300,
709
+ :white => 0xffffff00,
710
+ :whitesmoke => 0xf5f5f500,
711
+ :yellow => 0xffff0000,
712
+ :yellowgreen => 0x9acd3200
662
713
  }
663
-
714
+
664
715
  # Gets a color value based on a HTML color name.
665
- #
666
- # The color name is flexible. E.g. <tt>'yellowgreen'</tt>, <tt>'Yellow green'</tt>,
667
- # <tt>'YellowGreen'</tt>, <tt>'YELLOW_GREEN'</tt> and <tt>:yellow_green</tt> will
668
- # all return the same color value.
669
- #
670
- # You can include a opacity level in the color name (e.g. <tt>'red @ 0.5'</tt>) or give
671
- # an explicit opacity value as second argument. If no opacity value is given, the color
672
- # will be fully opaque.
673
- #
674
- # @param [Symbol, String] color_name The color name. It may include an opacity specifier
675
- # like <tt>@ 0.8</tt> to set the color's opacity.
676
- # @param [Integer] opacity The opacity value for the color between 0 and 255. Overrides
677
- # any opacity value given in the color name.
716
+ #
717
+ # The color name is flexible. E.g. <tt>'yellowgreen'</tt>, <tt>'Yellow
718
+ # green'</tt>, <tt>'YellowGreen'</tt>, <tt>'YELLOW_GREEN'</tt> and
719
+ # <tt>:yellow_green</tt> will all return the same color value.
720
+ #
721
+ # You can include a opacity level in the color name (e.g. <tt>'red @
722
+ # 0.5'</tt>) or give an explicit opacity value as second argument. If no
723
+ # opacity value is given, the color will be fully opaque.
724
+ #
725
+ # @param [Symbol, String] color_name The color name. It may include an
726
+ # opacity specifier like <tt>@ 0.8</tt> to set the color's opacity.
727
+ # @param [Integer] opacity The opacity value for the color between 0 and
728
+ # 255. Overrides any opacity value given in the color name.
678
729
  # @return [Integer] The color value.
679
730
  # @raise [ChunkyPNG::Exception] If the color name was not recognized.
680
731
  def html_color(color_name, opacity = nil)
@@ -709,37 +760,45 @@ module ChunkyPNG
709
760
  when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; 4
710
761
  when ChunkyPNG::COLOR_GRAYSCALE; 1
711
762
  when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; 2
712
- else raise ChunkyPNG::NotSupported, "Don't know the numer of samples for this colormode: #{color_mode}!"
763
+ else raise ChunkyPNG::NotSupported, "Don't know the number of samples for this colormode: #{color_mode}!"
713
764
  end
714
765
  end
715
766
 
716
- # Returns the size in bytes of a pixel when it is stored using a given color mode.
717
- # @param [Integer] color_mode The color mode in which the pixels are stored.
767
+ # Returns the size in bytes of a pixel when it is stored using a given
768
+ # color mode.
769
+ #
770
+ # @param [Integer] color_mode The color mode in which the pixels are
771
+ # stored.
718
772
  # @return [Integer] The number of bytes used per pixel in a datastream.
719
773
  def pixel_bytesize(color_mode, depth = 8)
720
774
  return 1 if depth < 8
721
775
  (pixel_bitsize(color_mode, depth) + 7) >> 3
722
776
  end
723
-
724
- # Returns the size in bits of a pixel when it is stored using a given color mode.
725
- # @param [Integer] color_mode The color mode in which the pixels are stored.
777
+
778
+ # Returns the size in bits of a pixel when it is stored using a given color
779
+ # mode.
780
+ #
781
+ # @param [Integer] color_mode The color mode in which the pixels are
782
+ # stored.
726
783
  # @param [Integer] depth The color depth of the pixels.
727
784
  # @return [Integer] The number of bytes used per pixel in a datastream.
728
785
  def pixel_bitsize(color_mode, depth = 8)
729
786
  samples_per_pixel(color_mode) * depth
730
787
  end
731
-
788
+
732
789
  # Returns the number of bytes used per scanline.
733
- # @param [Integer] color_mode The color mode in which the pixels are stored.
790
+ # @param [Integer] color_mode The color mode in which the pixels are
791
+ # stored.
734
792
  # @param [Integer] depth The color depth of the pixels.
735
793
  # @param [Integer] width The number of pixels per scanline.
736
794
  # @return [Integer] The number of bytes used per scanline in a datastream.
737
795
  def scanline_bytesize(color_mode, depth, width)
738
796
  ((pixel_bitsize(color_mode, depth) * width) + 7) >> 3
739
797
  end
740
-
798
+
741
799
  # Returns the number of bytes used for an image pass
742
- # @param [Integer] color_mode The color mode in which the pixels are stored.
800
+ # @param [Integer] color_mode The color mode in which the pixels are
801
+ # stored.
743
802
  # @param [Integer] depth The color depth of the pixels.
744
803
  # @param [Integer] width The width of the image pass.
745
804
  # @param [Integer] width The height of the image pass.