module ChunkyPNG::Color

def a(value)

Returns:
  • (Integer) - A value between 0 and MAX.

Parameters:
  • value (Integer) -- The color value.
def a(value)
  value & 0x000000ff
end

def alpha_decomposable?(color, mask, bg, tolerance = 1)

Other tags:
    See: #decompose_alpha -

Returns:
  • (Integer) - The decomposed alpha channel value, between 0 and 255.

Parameters:
  • tolerance (Integer) -- The decomposition tolerance level, a value between 0 and 255.
  • bg (Integer) -- The background color on which the color was composed.
  • mask (Integer) -- The opauqe variant of the color that was being composed
  • color (Integer) -- The color that was the result of compositing.
def alpha_decomposable?(color, mask, bg, tolerance = 1)
  components = decompose_alpha_components(color, mask, bg)
  sum = components.inject(0) { |a,b| a + b } 
  max = components.max * 3
  return components.max <= 255 && components.min >= 0 && (sum + tolerance * 3) >= max
end

def b(value)

Returns:
  • (Integer) - A value between 0 and MAX.

Parameters:
  • value (Integer) -- The color value.
def b(value)
  (value & 0x0000ff00) >> 8
end

def blend(fg, bg)

Returns:
  • (Integer) - The blended color.

Parameters:
  • bg (Integer) -- The foreground color.
  • fg (Integer) -- The foreground color.
def blend(fg, bg)
  (fg + bg) >> 1
end

def compose_precise(fg, bg)

Other tags:
    See: ChunkyPNG::Color#compose_quick -

Returns:
  • (Integer) - The composited color.

Parameters:
  • bg (Integer) -- The foreground color.
  • fg (Integer) -- The foreground color.
def compose_precise(fg, bg)
  return fg if opaque?(fg) || fully_transparent?(bg)
  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

def compose_quick(fg, bg)

Other tags:
    See: ChunkyPNG::Color#compose_precise -

Returns:
  • (Integer) - The composited color.

Parameters:
  • bg (Integer) -- The foreground color.
  • fg (Integer) -- The foreground color.
def compose_quick(fg, bg)
  return fg if opaque?(fg) || fully_transparent?(bg)
  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

def decompose_alpha(color, mask, bg)

Other tags:
    See: #alpha_decomposable? -

Returns:
  • (Integer) - The best fitting alpha channel, a value between 0 and 255.

Parameters:
  • bg (Integer) -- The background color on which the color was composed.
  • mask (Integer) -- The opauqe variant of the color that was being composed
  • color (Integer) -- The color that was the result of compositing.
def decompose_alpha(color, mask, bg)
  components = decompose_alpha_components(color, mask, bg)
  (components.inject(0) { |a,b| a + b } / 3.0).round
end

def decompose_alpha_component(channel, color, mask, bg)

Parameters:
  • The (Integer) -- decomposed alpha value for the channel.
  • bg (Integer) -- The background color on which the color was composed.
  • mask (Integer) -- The opauqe variant of the color that was being composed
  • color (Integer) -- The color that was the result of compositing.
  • The (:r, :g, :b) -- channel to decompose the alpha channel from.
def decompose_alpha_component(channel, color, mask, bg)
  ((send(channel, bg) - send(channel, color)).to_f / 
      (send(channel, bg) - send(channel, mask)).to_f * MAX).round
end

def decompose_alpha_components(color, mask, bg)

Returns:
  • (Array) - The decomposed alpha values for the r, g and b channels.

Parameters:
  • bg (Integer) -- The background color on which the color was composed.
  • mask (Integer) -- The opauqe variant of the color that was being composed
  • color (Integer) -- The color that was the result of compositing.
def decompose_alpha_components(color, mask, bg)
  [
    decompose_alpha_component(:r, color, mask, bg),
    decompose_alpha_component(:g, color, mask, bg),
    decompose_alpha_component(:b, color, mask, bg)
  ]
end

def decompose_color(color, mask, bg, tolerance = 1)

Returns:
  • (Integer) - The decomposed color,a variant of the masked color with the

Parameters:
  • tolerance (Integer) -- The decomposition tolerance level, a value between 0 and 255.
  • bg (Integer) -- The background color on which the color was composed.
  • mask (Integer) -- The opaque variant of the color that was being composed
  • color (Integer) -- The color that was the result of compositing.
def decompose_color(color, mask, bg, tolerance = 1)
  if alpha_decomposable?(color, mask, bg, tolerance)
    mask & 0xffffff00 | decompose_alpha(color, mask, bg)
  else
    mask & 0xffffff00
  end
end

def fade(color, factor)

Returns:
  • (Integer) - The faded color.

Parameters:
  • factor (Integer) -- Fade factor as an integer between 0 and 255.
  • color (Integer) -- The color to adjust.
def fade(color, factor)
  new_alpha = int8_mult(a(color), factor)
  (color & 0xffffff00) | new_alpha
end

def from_hex(hex_value, opacity = nil)

Returns:
  • (Integer) - The color value.

Parameters:
  • opacity (Integer) -- The opacity value for the color. Overrides any
  • str (String) -- The color in hex notation. @return [Integer] The
def from_hex(hex_value, opacity = nil)
  if HEX_COLOR_REGEXP =~ hex_value
    base_color = $1.hex << 8
    opacity  ||= $2 ? $2.hex : 0xff
    base_color | opacity
  else 
    raise ChunkyPNG::ExpectationFailed, "Not a valid hex color notation: #{hex_value.inspect}!"
  end
end

def from_rgb_stream(stream, pos = 0)

Returns:
  • (Integer) - The newly constructed color value.

Parameters:
  • pos (Integer) -- The position in the string to load the triple from.
  • stream (String) -- The string to load the color from. It should be
def from_rgb_stream(stream, pos = 0)
  rgb(*stream.unpack("@#{pos}C3"))
end

def from_rgba_stream(stream, pos = 0)

Returns:
  • (Integer) - The newly constructed color value.

Parameters:
  • pos (Integer) -- The position in the string to load the triple from.
  • stream (String) -- The string to load the color from. It should be
def from_rgba_stream(stream, pos = 0)
  rgba(*stream.unpack("@#{pos}C4"))
end

def fully_transparent?(value)

Returns:
  • (true, false) - True if the alpha channel equals 0.

Parameters:
  • value (Integer) -- The color to test.
def fully_transparent?(value)
  a(value) == 0x00000000
end

def g(value)

Returns:
  • (Integer) - A value between 0 and MAX.

Parameters:
  • value (Integer) -- The color value.
def g(value)
  (value & 0x00ff0000) >> 16
end

def grayscale(teint)

Returns:
  • (ChunkyPNG::Color) - The newly constructed color value.

Parameters:
  • teint (Integer) -- The grayscale teint (0-255), will be used as r, g, and b value.
def grayscale(teint)
  teint << 24 | teint << 16 | teint << 8 | 0xff
end

def grayscale?(value)

Returns:
  • (true, false) - True if the r, g and b component are equal.

Parameters:
  • value (Integer) -- The color to test.
def grayscale?(value)
  r(value) == b(value) && b(value) == g(value)
end

def grayscale_alpha(teint, a)

Returns:
  • (Integer) - The newly constructed color value.

Parameters:
  • a (Integer) -- The opacity (0-255)
  • teint (Integer) -- The grayscale teint (0-255), will be used as r, g, and b value.
def grayscale_alpha(teint, a)
  teint << 24 | teint << 16 | teint << 8 | a
end

def html_color(color_name, opacity = nil)

Raises:
  • (ChunkyPNG::Exception) - If the color name was not recognized.

Returns:
  • (Integer) - The color value.

Parameters:
  • opacity (Integer) -- The opacity value for the color between 0 and 255. Overrides
  • color_name (Symbol, String) -- The color name. It may include an opacity specifier
def html_color(color_name, opacity = nil)
  if color_name.to_s =~ HTML_COLOR_REGEXP
    opacity ||= $2 ? ($2.to_f * 255.0).round : 0xff
    base_color_name = $1.gsub(/[^a-z]+/i, '').downcase.to_sym
    return PREDEFINED_COLORS[base_color_name] | opacity if PREDEFINED_COLORS.has_key?(base_color_name)
  end
  raise ChunkyPNG::Exception, "Unknown color name #{color_name}!"
end

def int8_mult(a, b)

Returns:
  • (Integer) - The result of the multiplication.

Parameters:
  • b (Integer) -- The second fraction.
  • a (Integer) -- The first fraction.
def int8_mult(a, b)
  t = a * b + 0x80
  ((t >> 8) + t) >> 8
end

def opaque!(value)

Returns:
  • (Integer) - The opauq color

Parameters:
  • value (Integer) -- The color to transform.
def opaque!(value)
  value | 0x000000ff
end

def opaque?(value)

Returns:
  • (true, false) - True if the alpha channel equals MAX.

Parameters:
  • value (Integer) -- The color to test.
def opaque?(value)
  a(value) == 0x000000ff
end

def pass_bytesize(color_mode, depth, width, height)

Returns:
  • (Integer) - The number of bytes used per scanline in a datastream.

Parameters:
  • width (Integer) -- The height of the image pass.
  • width (Integer) -- The width of the image pass.
  • depth (Integer) -- The color depth of the pixels.
  • color_mode (Integer) -- The color mode in which the pixels are stored.
def pass_bytesize(color_mode, depth, width, height)
  return 0 if width == 0 || height == 0
  (scanline_bytesize(color_mode, depth, width) + 1) * height
end

def pixel_bitsize(color_mode, depth = 8)

Returns:
  • (Integer) - The number of bytes used per pixel in a datastream.

Parameters:
  • depth (Integer) -- The color depth of the pixels.
  • color_mode (Integer) -- The color mode in which the pixels are stored.
def pixel_bitsize(color_mode, depth = 8)
  samples_per_pixel(color_mode) * depth
end

def pixel_bytesize(color_mode, depth = 8)

Returns:
  • (Integer) - The number of bytes used per pixel in a datastream.

Parameters:
  • color_mode (Integer) -- The color mode in which the pixels are stored.
def pixel_bytesize(color_mode, depth = 8)
  return 1 if depth < 8
  (pixel_bitsize(color_mode, depth) + 7) >> 3
end

def r(value)

Returns:
  • (Integer) - A value between 0 and MAX.

Parameters:
  • value (Integer) -- The color value.
def r(value)
  (value & 0xff000000) >> 24
end

def rgb(r, g, b)

Returns:
  • (Integer) - The newly constructed color value.

Parameters:
  • b (Integer) -- The r-component (0-255)
  • g (Integer) -- The r-component (0-255)
  • r (Integer) -- The r-component (0-255)
def rgb(r, g, b)
  r << 24 | g << 16 | b << 8 | 0xff
end

def rgba(r, g, b, a)

Returns:
  • (Integer) - The newly constructed color value.

Parameters:
  • a (Integer) -- The opacity (0-255)
  • b (Integer) -- The r-component (0-255)
  • g (Integer) -- The r-component (0-255)
  • r (Integer) -- The r-component (0-255)
def rgba(r, g, b, a)
  r << 24 | g << 16 | b << 8 | a
end

def samples_per_pixel(color_mode)

Returns:
  • (Integer) - The number of sample values per pixel.

Parameters:
  • color_mode (Integer) -- The color mode being used.
def samples_per_pixel(color_mode)
  case color_mode
    when ChunkyPNG::COLOR_INDEXED;         1
    when ChunkyPNG::COLOR_TRUECOLOR;       3
    when ChunkyPNG::COLOR_TRUECOLOR_ALPHA; 4
    when ChunkyPNG::COLOR_GRAYSCALE;       1
    when ChunkyPNG::COLOR_GRAYSCALE_ALPHA; 2
    else raise ChunkyPNG::NotSupported, "Don't know the numer of samples for this colormode: #{color_mode}!"
  end
end

def scanline_bytesize(color_mode, depth, width)

Returns:
  • (Integer) - The number of bytes used per scanline in a datastream.

Parameters:
  • width (Integer) -- The number of pixels per scanline.
  • depth (Integer) -- The color depth of the pixels.
  • color_mode (Integer) -- The color mode in which the pixels are stored.
def scanline_bytesize(color_mode, depth, width)
  ((pixel_bitsize(color_mode, depth) * width) + 7) >> 3
end

def to_grayscale_alpha_bytes(color)

Returns:
  • (Array) - An array with 2 Integer elements.

Parameters:
  • color (Integer) -- The grayscale color to convert.
def to_grayscale_alpha_bytes(color)
  [b(color), a(color)] # assumption r == g == b
end

def to_grayscale_bytes(color)

Returns:
  • (Array) - An array with 1 Integer element.

Parameters:
  • color (Integer) -- The grayscale color to convert.
def to_grayscale_bytes(color)
  [b(color)] # assumption r == g == b
end

def to_hex(color, include_alpha = true)

Returns:
  • (String) - The color in hex notation, starting with a pound sign.

Parameters:
  • value (Integer) -- The color to convert.
def to_hex(color, include_alpha = true)
  include_alpha ? ('#%08x' % color) : ('#%06x' % [color >> 8])
end

def to_truecolor_alpha_bytes(color)

Returns:
  • (Array) - An array with 4 Integer elements.

Parameters:
  • color (Integer) -- The color to convert.
def to_truecolor_alpha_bytes(color)
  [r(color), g(color), b(color), a(color)]
end

def to_truecolor_bytes(color)

Returns:
  • (Array) - An array with 3 Integer elements.

Parameters:
  • color (Integer) -- The color to convert.
def to_truecolor_bytes(color)
  [r(color), g(color), b(color)]
end