class ChunkyPNG::Canvas
The ChunkyPNG::Canvas
class represents a raster image as a matrix of pixels.
This class supports loading a Canvas
from a PNG datastream, and creating a {ChunkyPNG::Datastream PNG datastream} based on this matrix. ChunkyPNG
only supports 8-bit color depth, otherwise all of the PNG format’s variations are supported for both reading and writing.
This class offers per-pixel access to the matrix by using x,y coordinates. It uses a palette (see {ChunkyPNG::Palette}) to keep track of the different colors used in this matrix.
The pixels in the canvas are stored as 4-byte fixnum, representing 32-bit RGBA colors (8 bit per channel). The module {ChunkyPNG::Color} is provided to work more easily with these number as color values.
The module {ChunkyPNG::Canvas::Operations} is imported for operations on the whole canvas, like cropping and alpha compositing. Simple drawing functions are imported from the {ChunkyPNG::Canvas::Drawing} module.
Attributes
@return [Integer] The number of rows in this canvas
@return [Array<ChunkyPNG::Color>] The list of pixels in this canvas.
This array always should have +width * height+ elements.
@return [Integer] The number of columns in this canvas
Public Class Methods
Source
# File lib/chunky_png/canvas.rb 105 def self.from_canvas(canvas) 106 new(canvas.width, canvas.height, canvas.pixels.dup) 107 end
Creates a new canvas instance by duplicating another instance. @param [ChunkyPNG::Canvas] canvas The canvas to duplicate @return [ChunkyPNG::Canvas] The newly constructed canvas instance.
Source
# File lib/chunky_png/canvas.rb 79 def initialize(width, height, initial = ChunkyPNG::Color::TRANSPARENT) 80 @width, @height = width, height 81 82 if initial.is_a?(Array) 83 pixel_count = width * height 84 unless initial.length == pixel_count 85 raise ArgumentError, "The initial array should have #{width}x#{height} = #{pixel_count} elements!" 86 end 87 @pixels = initial 88 else 89 @pixels = Array.new(width * height, ChunkyPNG::Color.parse(initial)) 90 end 91 end
Initializes a new Canvas
instance.
@overload initialize(width, height, background_color)
@param [Integer] width The width in pixels of this canvas @param [Integer] height The height in pixels of this canvas @param [Integer, ...] background_color The initial background color of this canvas. This can be a color value or any value that {ChunkyPNG::Color#parse} can handle.
@overload initialize(width, height, initial)
@param [Integer] width The width in pixels of this canvas @param [Integer] height The height in pixels of this canvas @param [Array<Integer>] initial The initial pizel values. Must be an array with <tt>width * height</tt> elements.
Public Instance Methods
Source
# File lib/chunky_png/canvas.rb 174 def [](x, y) 175 assert_xy!(x, y) 176 @pixels[y * width + x] 177 end
Returns a single pixel’s color value from this canvas. @param [Integer] x The x-coordinate of the pixel (column) @param [Integer] y The y-coordinate of the pixel (row) @return [Integer] The current color value at the provided coordinates. @raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the
image's dimensions.
@see get_pixel
Source
# File lib/chunky_png/canvas.rb 135 def []=(x, y, color) 136 assert_xy!(x, y) 137 @pixels[y * width + x] = ChunkyPNG::Color.parse(color) 138 end
Replaces a single pixel in this canvas. @param [Integer] x The x-coordinate of the pixel (column) @param [Integer] y The y-coordinate of the pixel (row) @param [Integer] color The new color for the provided coordinates. @return [Integer] The new color value for this pixel, i.e.
<tt>color</tt>.
@raise [ChunkyPNG::OutOfBounds] when the coordinates are outside of the
image's dimensions.
@see set_pixel
Source
# File lib/chunky_png/canvas.rb 122 def area 123 pixels.length 124 end
Returns the area of this canvas in number of pixels. @return [Integer] The number of pixels in this canvas
Source
# File lib/chunky_png/canvas.rb 200 def column(x) 201 assert_x!(x) 202 (0...height).inject([]) { |pixels, y| pixels << get_pixel(x, y) } 203 end
Returns an extracted column as vector of pixels. @param [Integer] x The 0-based column index. @return [Array<Integer>] The vector of pixels in the requested column.
Source
# File lib/chunky_png/canvas.rb 116 def dimension 117 ChunkyPNG::Dimension.new(width, height) 118 end
Returns the dimension (width x height) for this canvas. @return [ChunkyPNG::Dimension] A dimension instance with the width and
height set for this canvas.
Source
# File lib/chunky_png/canvas.rb 277 def eql?(other) 278 other.is_a?(self.class) && 279 other.pixels == pixels && 280 other.width == width && 281 other.height == height 282 end
Equality check to compare this canvas with other matrices. @param other The object to compare this Matrix to. @return [true, false] True if the size and pixel values of the other
canvas are exactly the same as this canvas's size and pixel values.
Source
# File lib/chunky_png/canvas.rb 185 def get_pixel(x, y) 186 @pixels[y * width + x] 187 end
Returns a single pixel from this canvas, without checking bounds. The return value for this method is undefined if the coordinates are out of bounds.
@param (see []
) @return [Integer] The current pixel at the provided coordinates.
Source
# File lib/chunky_png/canvas.rb 233 def include_point?(*point_like) 234 dimension.include?(ChunkyPNG::Point(*point_like)) 235 end
Checks whether the given coordinates are in the range of the canvas @param [ChunkyPNG::Point, Array, Hash, String] point_like The point to
check.
@return [true, false] True if the x and y coordinates of the point are
within the limits of this canvas.
@see ChunkyPNG.Point
Source
# File lib/chunky_png/canvas.rb 262 def include_x?(x) 263 x >= 0 && x < width 264 end
Checks whether the given x-coordinate is in the range of the canvas @param [Integer] x The y-coordinate of the pixel (column) @return [true, false] True if the x-coordinate is in the range of this
canvas.
Source
# File lib/chunky_png/canvas.rb 246 def include_xy?(x, y) 247 y >= 0 && y < height && x >= 0 && x < width 248 end
Checks whether the given x- and y-coordinate are in the range of the canvas
@param [Integer] x The x-coordinate of the pixel (column) @param [Integer] y The y-coordinate of the pixel (row) @return [true, false] True if the x- and y-coordinate is in the range of
this canvas.
Source
# File lib/chunky_png/canvas.rb 254 def include_y?(y) 255 y >= 0 && y < height 256 end
Checks whether the given y-coordinate is in the range of the canvas @param [Integer] y The y-coordinate of the pixel (row) @return [true, false] True if the y-coordinate is in the range of this
canvas.
Source
# File lib/chunky_png/canvas.rb 97 def initialize_copy(other) 98 @width, @height = other.width, other.height 99 @pixels = other.pixels.dup 100 end
Initializes a new Canvas
instances when being cloned. @param [ChunkyPNG::Canvas] other The canvas to duplicate @return [void] @private
Source
# File lib/chunky_png/canvas.rb 299 def inspect 300 inspected = +"<#{self.class.name} #{width}x#{height} [" 301 for y in 0...height 302 inspected << "\n\t[" << row(y).map { |p| ChunkyPNG::Color.to_hex(p) }.join(" ") << "]" 303 end 304 inspected << "\n]>" 305 end
Alternative implementation of the inspect method. @return [String] A nicely formatted string representation of this canvas. @private
Source
# File lib/chunky_png/canvas.rb 269 def palette 270 ChunkyPNG::Palette.from_canvas(self) 271 end
Returns the palette used for this canvas. @return [ChunkyPNG::Palette] A palette which contains all the colors that
are being used for this image.
Source
# File lib/chunky_png/canvas.rb 220 def replace_column!(x, vector) 221 assert_x!(x) && assert_height!(vector.length) 222 for y in 0...height do 223 set_pixel(x, y, vector[y]) 224 end 225 end
Replaces a column of pixels on this canvas. @param [Integer] x The 0-based column index. @param [Array<Integer>] vector The vector of pixels to replace the column
with.
@return [void]
Source
# File lib/chunky_png/canvas.rb 210 def replace_row!(y, vector) 211 assert_y!(y) && assert_width!(vector.length) 212 pixels[y * width, width] = vector 213 end
Replaces a row of pixels on this canvas. @param [Integer] y The 0-based row index. @param [Array<Integer>] vector The vector of pixels to replace the row
with.
@return [void]
Source
# File lib/chunky_png/canvas.rb 192 def row(y) 193 assert_y!(y) 194 pixels.slice(y * width, width) 195 end
Returns an extracted row as vector of pixels @param [Integer] y The 0-based row index @return [Array<Integer>] The vector of pixels in the requested row
Source
# File lib/chunky_png/canvas.rb 150 def set_pixel(x, y, color) 151 @pixels[y * width + x] = color 152 end
Replaces a single pixel in this canvas, without bounds checking.
This method return value and effects are undefined for coordinates out of bounds of the canvas.
@param [Integer] x The x-coordinate of the pixel (column) @param [Integer] y The y-coordinate of the pixel (row) @param [Integer] color The new color for the provided coordinates. @return [Integer] The new color value for this pixel, i.e.
<tt>color</tt>.
Source
# File lib/chunky_png/canvas.rb 162 def set_pixel_if_within_bounds(x, y, color) 163 return unless include_xy?(x, y) 164 @pixels[y * width + x] = color 165 end
Replaces a single pixel in this canvas, with bounds checking. It will do noting if the provided coordinates are out of bounds.
@param [Integer] x The x-coordinate of the pixel (column) @param [Integer] y The y-coordinate of the pixel (row) @param [Integer] color The new color value for the provided coordinates. @return [Integer] The new color value for this pixel, i.e.
<tt>color</tt>, or <tt>nil</tt> if the coordinates are out of bounds.
Source
# File lib/chunky_png/canvas.rb 292 def to_image 293 ChunkyPNG::Image.from_canvas(self) 294 end
Creates an ChunkyPNG::Image
object from this canvas. @return [ChunkyPNG::Image] This canvas wrapped in an Image
instance.
Protected Instance Methods
Source
# File lib/chunky_png/canvas.rb 344 def assert_height!(vector_length) 345 if height != vector_length 346 raise ChunkyPNG::ExpectationFailed, 347 "The length of the vector (#{vector_length}) does not match the canvas height (#{height})!" 348 end 349 true 350 end
Throws an exception if the vector_length does not match this canvas’ height.
Source
# File lib/chunky_png/canvas.rb 363 def assert_size!(matrix_width, matrix_height) 364 if width != matrix_width 365 raise ChunkyPNG::ExpectationFailed, 366 "The width of the matrix does not match the canvas width!" 367 end 368 if height != matrix_height 369 raise ChunkyPNG::ExpectationFailed, 370 "The height of the matrix does not match the canvas height!" 371 end 372 true 373 end
Throws an exception if the matrix width and height does not match this canvas’ dimensions.
Source
# File lib/chunky_png/canvas.rb 354 def assert_width!(vector_length) 355 if width != vector_length 356 raise ChunkyPNG::ExpectationFailed, 357 "The length of the vector (#{vector_length}) does not match the canvas width (#{width})!" 358 end 359 true 360 end
Throws an exception if the vector_length does not match this canvas’ width.
Source
# File lib/chunky_png/canvas.rb 319 def assert_x!(x) 320 unless include_x?(x) 321 raise ChunkyPNG::OutOfBounds, "Column index #{x} out of bounds!" 322 end 323 true 324 end
Throws an exception if the x-coordinate is out of bounds.
Source
# File lib/chunky_png/canvas.rb 335 def assert_xy!(x, y) 336 unless include_xy?(x, y) 337 raise ChunkyPNG::OutOfBounds, "Coordinates (#{x},#{y}) out of bounds!" 338 end 339 true 340 end
Throws an exception if the x- or y-coordinate is out of bounds.
Source
# File lib/chunky_png/canvas.rb 327 def assert_y!(y) 328 unless include_y?(y) 329 raise ChunkyPNG::OutOfBounds, "Row index #{y} out of bounds!" 330 end 331 true 332 end
Throws an exception if the y-coordinate is out of bounds.
Source
# File lib/chunky_png/canvas.rb 310 def replace_canvas!(new_width, new_height, new_pixels) 311 unless new_pixels.length == new_width * new_height 312 raise ArgumentError, "The provided pixel array should have #{new_width * new_height} items" 313 end 314 @width, @height, @pixels = new_width, new_height, new_pixels 315 self 316 end
Replaces the image, given a new width, new height, and a new pixel array.