module ChunkyPNG::Canvas::Operations

def change_mask_color!(new_color)

Other tags:
    See: #extract_mask -
    See: #change_theme_color! -

Raises:
  • (ChunkyPNG::ExpectationFailed) - when this canvas is not a mask image, i.e. its palette

Parameters:
  • new_color (Integer) -- The color to replace the original mask color with.
def change_mask_color!(new_color)
  raise ChunkyPNG::ExpectationFailed, "This is not a mask image!" if palette.opaque_palette.size != 1
  pixels.map! { |pixel| (new_color & 0xffffff00) | ChunkyPNG::Color.a(pixel) }
  self
end

def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)

Other tags:
    See: #change_mask_color! -
    See: #change_theme_color! -

Returns:
  • (ChunkyPNG::Canvas) - Returns itself, but with the theme colored pixels changed.

Parameters:
  • tolerance (Integer) -- The tolerance level to use when extracting the mask image. Five is
  • The (Integer) -- backrgound color opn which the theme colored pixels are placed.
  • new_theme_color (Integer) -- The color to replace the old theme color with.
  • old_theme_color (Integer) -- The original theme color in this image.
def change_theme_color!(old_theme_color, new_theme_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
  base, mask = extract_mask(old_theme_color, bg_color, tolerance)
  mask.change_mask_color!(new_theme_color)
  self.replace(base.compose(mask))
end

def check_size_constraints!(other, offset_x, offset_y)

Raises:
  • (ChunkyPNG::OutOfBounds) - when the other image doesn't fit.

Parameters:
  • offset_y (Integer) -- The y offset on which the other image will be applied.
  • offset_x (Integer) -- The x offset on which the other image will be applied.
  • other (ChunkyPNG::Canvas) -- The other canvas
def check_size_constraints!(other, offset_x, offset_y)
  raise ChunkyPNG::OutOfBounds, "Background image width is too small!"  if width  < other.width  + offset_x
  raise ChunkyPNG::OutOfBounds, "Background image height is too small!" if height < other.height + offset_y
end

def compose(other, offset_x = 0, offset_y = 0)

Other tags:
    See: #replace -

Raises:
  • (ChunkyPNG::OutOfBounds) - when the other canvas doesn't fit on this one,

Returns:
  • (ChunkyPNG::Canvas) - Returns itself, but with the other canvas composed onto it.

Parameters:
  • offset_y (Integer) -- The y-offset to apply the new forgeround on.
  • offset_x (Integer) -- The x-offset to apply the new forgeround on.
  • other (ChunkyPNG::Canvas) -- The foreground canvas to compose on the
def compose(other, offset_x = 0, offset_y = 0)
  check_size_constraints!(other, offset_x, offset_y)
  for y in 0...other.height do
    for x in 0...other.width do
      set_pixel(x + offset_x, y + offset_y, ChunkyPNG::Color.compose(other.get_pixel(x, y), get_pixel(x + offset_x, y + offset_y)))
    end
  end
  self
end

def crop(x, y, crop_width, crop_height)

Raises:
  • (ChunkyPNG::OutOfBounds) - when the crop dimensions plus the given coordinates

Returns:
  • (ChunkyPNG::Canvas) - Returns the newly created cropped image.

Parameters:
  • crop_height (Integer) -- The height of the image to be cropped.
  • crop_width (Integer) -- The width of the image to be cropped.
  • y (Integer) -- The y-coordinate of the top left corner of the image to be cropped.
  • x (Integer) -- The x-coordinate of the top left corner of the image to be cropped.
def crop(x, y, crop_width, crop_height)
  
  raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_width + x > width
  raise ChunkyPNG::OutOfBounds, "Image width is too small!" if crop_height + y > height
  
  new_pixels = []
  for cy in 0...crop_height do
    new_pixels += pixels.slice((cy + y) * width + x, crop_width)
  end
  ChunkyPNG::Canvas.new(crop_width, crop_height, new_pixels)
end

def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)

Other tags:
    See: #change_mask_color! -
    See: #change_theme_color! -

Returns:
  • (Array) - An array with the base canvas and the mask

Parameters:
  • tolerance (Integer) -- The tolerance level to use when extracting the mask image. Five is
  • bg_color (Integer) -- The background color on which the theme colored pxiels are applied.
  • mask_color (Integer) -- The current theme color.
def extract_mask(mask_color, bg_color = ChunkyPNG::Color::WHITE, tolerance = 5)
  base_pixels = []
  mask_pixels = []
  pixels.each do |pixel|
    if ChunkyPNG::Color.alpha_decomposable?(pixel, mask_color, bg_color, tolerance)
      mask_pixels << ChunkyPNG::Color.decompose_color(pixel, mask_color, bg_color, tolerance)
      base_pixels << bg_color
    else
      mask_pixels << (mask_color & 0xffffff00)
      base_pixels << pixel
    end
  end
  
  [ self.class.new(width, height, base_pixels), self.class.new(width, height, mask_pixels) ]
end

def flip_horizontally

Returns:
  • (ChunkyPNG::Canvas) - The flipped image
def flip_horizontally
  self.class.new(width, height).tap do |flipped|
    for y in 0...height do
      flipped.replace_row!(height - (y + 1), row(y))
    end
  end
end

def flip_vertically

Returns:
  • (ChunkyPNG::Canvas) - The flipped image
def flip_vertically
  self.class.new(width, height).tap do |flipped|
    for x in 0...width do
      flipped.replace_column!(width - (x + 1), column(x))
    end
  end
end

def replace(other, offset_x = 0, offset_y = 0)

Other tags:
    See: #compose -

Raises:
  • (ChunkyPNG::OutOfBounds) - when the other canvas doesn't fit on this one,

Returns:
  • (ChunkyPNG::Canvas) - Returns itself, but with the other canvas composed onto it.
def replace(other, offset_x = 0, offset_y = 0)
  check_size_constraints!(other, offset_x, offset_y)
  for y in 0...other.height do
    pixels[(y + offset_y) * width + offset_x, other.width] = other.pixels[y * other.width, other.width]
  end
  self
end

def rotate_180

Returns:
  • (ChunkyPNG::Canvas) - The rotated image.
def rotate_180
  self.class.new(width, height).tap do |flipped|
    for y in 0...height do
      flipped.replace_row!(height - (y + 1), row(y).reverse)
    end
  end
end

def rotate_left

Returns:
  • (ChunkyPNG::Canvas) - The rotated image.
def rotate_left
  self.class.new(height, width).tap do |rotated|
    for i in 0...width do
      rotated.replace_row!(width - (i + 1), column(i))
    end
  end
end

def rotate_right

Returns:
  • (ChunkyPNG::Canvas) - The rotated image
def rotate_right
  self.class.new(height, width).tap do |rotated|
    for i in 0...width do
      rotated.replace_row!(i, column(i).reverse)
    end
  end
end