Module: ChunkyPNG::Color
Overview
The Color module defines methods for handling colors. Within the ChunkyPNG library, the concepts of pixels and colors are both used, and they are both represented by a Fixnum.
Pixels/colors are represented in RGBA componetns. Each of the four components is stored with a depth of 8 bits (maximum value = 255 = MAX). Together, these components are stored in a 4-byte Fixnum.
A color will always be represented using these 4 components in memory. When the image is encoded, a more suitable representation can be used (e.g. rgb, grayscale, palette-based), for which several conversion methods are provided in this module.
Constant Summary collapse
- MAX =
The maximum value of each color component.
0xff
- BLACK =
Black pixel/color
rgb( 0, 0, 0)
- WHITE =
White pixel/color
rgb(255, 255, 255)
- TRANSPARENT =
Fully transparent pixel/color
rgba(255, 255, 255, 0)
Instance Method Summary collapse
-
#a(value) ⇒ Fixnum
Returns the alpha channel value for the color value.
-
#b(value) ⇒ Fixnum
Returns the blue-component from the color value.
-
#blend(fg, bg) ⇒ Fixnum
Blends the foreground and background color by taking the average of the components.
-
#bytesize(color_mode) ⇒ Fixnum
Returns the size in bytes of a pixel when it is stored using a given color mode.
-
#compose_precise(fg, bg) ⇒ Fixnum
Composes two colors with an alpha channel using floating point math.
-
#compose_quick(fg, bg) ⇒ Fixnum
(also: #compose)
Composes two colors with an alpha channel using integer math.
-
#from_hex(str) ⇒ Object
Creates a color by converting it from a string in hex notation.
-
#from_rgb_stream(stream, pos = 0) ⇒ Fixnum
Creates a color by unpacking an rgb triple from a string.
-
#from_rgba_stream(stream, pos = 0) ⇒ Fixnum
Creates a color by unpacking an rgba triple from a string.
-
#fully_transparent?(value) ⇒ true, false
Returns true if this color is fully transparent.
-
#g(value) ⇒ Fixnum
Returns the green-component from the color value.
-
#grayscale(teint, a = MAX) ⇒ ChunkyPNG::Color
Creates a new color using a grayscale teint.
-
#grayscale?(value) ⇒ true, false
Returns true if this color is fully transparent.
-
#grayscale_alpha(teint, a) ⇒ Fixnum
Creates a new color using a grayscale teint and alpha value.
-
#int8_mult(a, b) ⇒ Fixnum
Multiplies two fractions using integer math, where the fractions are stored using an integer between 0 and 255.
-
#opaque?(value) ⇒ true, false
Returns true if this color is fully opaque.
-
#r(value) ⇒ Fixnum
Returns the red-component from the color value.
-
#rgb(r, g, b, a = MAX) ⇒ Fixnum
Creates a new color using an r, g, b triple.
-
#rgba(r, g, b, a) ⇒ Fixnum
Creates a new color using an r, g, b triple and an alpha value.
-
#to_grayscale_alpha_bytes(color) ⇒ Array<Fixnum>
Returns an array with the grayscale teint and alpha channel values for this color.
-
#to_grayscale_bytes(color) ⇒ Array<Fixnum>
Returns an array with the grayscale teint value for this color.
-
#to_hex(color, include_alpha = true) ⇒ String
Returns a string representing this color using hex notation (i.e. #rrggbbaa).
-
#to_truecolor_alpha_bytes(color) ⇒ Array<Fixnum>
Returns an array with the separate RGBA values for this color.
-
#to_truecolor_bytes(color) ⇒ Array<Fixnum>
Returns an array with the separate RGB values for this color.
Instance Method Details
#a(value) ⇒ Fixnum
Returns the alpha channel value for the color value.
121 122 123 |
# File 'lib/chunky_png/color.rb', line 121 def a(value) value & 0x000000ff end |
#b(value) ⇒ Fixnum
Returns the blue-component from the color value.
113 114 115 |
# File 'lib/chunky_png/color.rb', line 113 def b(value) (value & 0x0000ff00) >> 8 end |
#blend(fg, bg) ⇒ Fixnum
Blends the foreground and background color by taking the average of the components.
221 222 223 |
# File 'lib/chunky_png/color.rb', line 221 def blend(fg, bg) (fg + bg) >> 1 end |
#bytesize(color_mode) ⇒ Fixnum
Returns the size in bytes of a pixel when it is stored using a given color mode.
296 297 298 299 300 301 302 303 304 305 |
# File 'lib/chunky_png/color.rb', line 296 def bytesize(color_mode) case color_mode when ChunkyPNG::COLOR_INDEXED then 1 when ChunkyPNG::COLOR_TRUECOLOR then 3 when ChunkyPNG::COLOR_TRUECOLOR_ALPHA then 4 when ChunkyPNG::COLOR_GRAYSCALE then 1 when ChunkyPNG::COLOR_GRAYSCALE_ALPHA then 2 else raise "Don't know the bytesize of pixels in this colormode: #{color_mode}!" end end |
#compose_precise(fg, bg) ⇒ Fixnum
Composes two colors with an alpha channel using floating point math.
This method uses more precise floating point math, but this precision is lost when the result is converted back to an integer. Because it is slower than the version based on integer math, that version is preferred.
198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/chunky_png/color.rb', line 198 def compose_precise(fg, bg) return fg if opaque?(fg) return bg if fully_transparent?(fg) fg_a = a(fg).to_f / MAX bg_a = a(bg).to_f / MAX a_com = (1.0 - fg_a) * bg_a new_r = (fg_a * r(fg) + a_com * r(bg)).round new_g = (fg_a * g(fg) + a_com * g(bg)).round new_b = (fg_a * b(fg) + a_com * b(bg)).round new_a = ((fg_a + a_com) * MAX).round rgba(new_r, new_g, new_b, new_a) end |
#compose_quick(fg, bg) ⇒ Fixnum Also known as: compose
Composes two colors with an alpha channel using integer math.
This version is faster than the version based on floating point math, so this compositing function is used by default.
176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/chunky_png/color.rb', line 176 def compose_quick(fg, bg) return fg if opaque?(fg) return bg if fully_transparent?(fg) a_com = int8_mult(0xff - a(fg), a(bg)) new_r = int8_mult(a(fg), r(fg)) + int8_mult(a_com, r(bg)) new_g = int8_mult(a(fg), g(fg)) + int8_mult(a_com, g(bg)) new_b = int8_mult(a(fg), b(fg)) + int8_mult(a_com, b(bg)) new_a = a(fg) + a_com rgba(new_r, new_g, new_b, new_a) end |
#from_hex(str) ⇒ Object
Creates a color by converting it from a string in hex notation.
It supports colors with (#rrggbbaa) or without (#rrggbb) alpha channel. Color strings may include the prefix “0x” or “#”.
converted color value.
81 82 83 84 85 86 87 |
# File 'lib/chunky_png/color.rb', line 81 def from_hex(str) case str when /^(?:#|0x)?([0-9a-f]{6})$/i then ($1.hex << 8) | 0xff when /^(?:#|0x)?([0-9a-f]{8})$/i then $1.hex else raise "Not a valid hex color notation: #{str.inspect}!" end end |
#from_rgb_stream(stream, pos = 0) ⇒ Fixnum
Creates a color by unpacking an rgb triple from a string.
60 61 62 |
# File 'lib/chunky_png/color.rb', line 60 def from_rgb_stream(stream, pos = 0) rgb(*stream.unpack("@#{pos}C3")) end |
#from_rgba_stream(stream, pos = 0) ⇒ Fixnum
Creates a color by unpacking an rgba triple from a string
70 71 72 |
# File 'lib/chunky_png/color.rb', line 70 def from_rgba_stream(stream, pos = 0) rgba(*stream.unpack("@#{pos}C4")) end |
#fully_transparent?(value) ⇒ true, false
Returns true if this color is fully transparent.
145 146 147 |
# File 'lib/chunky_png/color.rb', line 145 def fully_transparent?(value) a(value) == 0x00000000 end |
#g(value) ⇒ Fixnum
Returns the green-component from the color value.
105 106 107 |
# File 'lib/chunky_png/color.rb', line 105 def g(value) (value & 0x00ff0000) >> 16 end |
#grayscale(teint, a = MAX) ⇒ ChunkyPNG::Color
Creates a new color using a grayscale teint.
40 41 42 |
# File 'lib/chunky_png/color.rb', line 40 def grayscale(teint, a = MAX) rgba(teint, teint, teint, a) end |
#grayscale?(value) ⇒ true, false
Returns true if this color is fully transparent.
137 138 139 |
# File 'lib/chunky_png/color.rb', line 137 def grayscale?(value) r(value) == b(value) && b(value) == g(value) end |
#grayscale_alpha(teint, a) ⇒ Fixnum
Creates a new color using a grayscale teint and alpha value.
46 47 48 |
# File 'lib/chunky_png/color.rb', line 46 def grayscale_alpha(teint, a) rgba(teint, teint, teint, a) end |
#int8_mult(a, b) ⇒ Fixnum
Multiplies two fractions using integer math, where the fractions are stored using an integer between 0 and 255. This method is used as a helper method for compositing colors using integer math.
This is a quicker implementation of ((a * b) / 255.0).round.
162 163 164 165 |
# File 'lib/chunky_png/color.rb', line 162 def int8_mult(a, b) t = a * b + 0x80 ((t >> 8) + t) >> 8 end |
#opaque?(value) ⇒ true, false
Returns true if this color is fully opaque.
129 130 131 |
# File 'lib/chunky_png/color.rb', line 129 def opaque?(value) a(value) == 0x000000ff end |
#r(value) ⇒ Fixnum
Returns the red-component from the color value.
97 98 99 |
# File 'lib/chunky_png/color.rb', line 97 def r(value) (value & 0xff000000) >> 24 end |
#rgb(r, g, b, a = MAX) ⇒ Fixnum
Creates a new color using an r, g, b triple.
34 35 36 |
# File 'lib/chunky_png/color.rb', line 34 def rgb(r, g, b, a = MAX) rgba(r, g, b, a) end |
#rgba(r, g, b, a) ⇒ Fixnum
Creates a new color using an r, g, b triple and an alpha value.
28 29 30 |
# File 'lib/chunky_png/color.rb', line 28 def rgba(r, g, b, a) r << 24 | g << 16 | b << 8 | a end |
#to_grayscale_alpha_bytes(color) ⇒ Array<Fixnum>
Returns an array with the grayscale teint and alpha channel values for this color.
This method expects the r,g and b value to be equal.
272 273 274 |
# File 'lib/chunky_png/color.rb', line 272 def to_grayscale_alpha_bytes(color) [r(color), a(color)] # assumption r == g == b end |
#to_grayscale_bytes(color) ⇒ Array<Fixnum>
Returns an array with the grayscale teint value for this color.
This method expects the r,g and b value to be equal, and the alpha channel will be discarded.
261 262 263 |
# File 'lib/chunky_png/color.rb', line 261 def to_grayscale_bytes(color) [r(color)] # assumption r == g == b end |
#to_hex(color, include_alpha = true) ⇒ String
Returns a string representing this color using hex notation (i.e. #rrggbbaa).
233 234 235 |
# File 'lib/chunky_png/color.rb', line 233 def to_hex(color, include_alpha = true) include_alpha ? ('#%08x' % color) : ('#%06x' % [color >> 8]) end |
#to_truecolor_alpha_bytes(color) ⇒ Array<Fixnum>
Returns an array with the separate RGBA values for this color.
241 242 243 |
# File 'lib/chunky_png/color.rb', line 241 def to_truecolor_alpha_bytes(color) [r(color), g(color), b(color), a(color)] end |
#to_truecolor_bytes(color) ⇒ Array<Fixnum>
Returns an array with the separate RGB values for this color. The alpha channel will be discarded.
250 251 252 |
# File 'lib/chunky_png/color.rb', line 250 def to_truecolor_bytes(color) [r(color), g(color), b(color)] end |