moduleChunkyPNG# The ChunkPNG::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.classCanvasincludePNGEncodingextendPNGDecodingextendAdam7InterlacingincludeOperationsincludeDrawing# @return [Integer] The number of columns in this canvasattr_reader:width# @return [Integer] The number of rows in this canvasattr_reader:height# @return [Array<ChunkyPNG::Color>] The list of pixels in this canvas.# This array always should have +width * height+ elements.attr_reader:pixels# Initializes a new Canvas instance# @param [Integer] width The width in pixels of this canvas# @param [Integer] width The height in pixels of this canvas# @param [ChunkyPNG::Pixel, Array<ChunkyPNG::Color>] initial The initial value of te pixels:## * If a color is passed to this parameter, this color will be used as background color.## * If an array of pixels is provided, these pixels will be used as initial value. Note# that the amount of pixels in this array should equal +width * height+.definitialize(width,height,initial=ChunkyPNG::Color::TRANSPARENT)@width,@height=width,heightifinitial.kind_of?(Fixnum)@pixels=Array.new(width*height,initial)elsifinitial.kind_of?(Array)&&initial.size==width*height@pixels=initialelseraise"Cannot use this value as initial canvas: #{initial.inspect}!"endenddefinitialize_copy(other)@width,@height=other.width,other.height@pixels=other.pixels.dupend# Returns the size ([width, height]) for this canvas.# @return Array An array with the width and height of this canvas as elements.defsize[@width,@height]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 [ChunkyPNG::Color] pixel The new pixel for the provided coordinates.def[]=(x,y,color)@pixels[y*width+x]=colorend# Returns a single pixel from this canvas.# @param [Integer] x The x-coordinate of the pixel (column)# @param [Integer] y The y-coordinate of the pixel (row)# @return [ChunkyPNG::Color] The current pixel at the provided coordinates.def[](x,y)@pixels[y*width+x]end# Returns the palette used for this canvas.# @return [ChunkyPNG::Palette] A pallete which contains all the colors that are# being used for this image.defpaletteChunkyPNG::Palette.from_canvas(self)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.defeql?(other)other.kind_of?(self.class)&&other.pixels==self.pixels&&other.width==self.width&&other.height==self.heightendalias:==:eql?# Creates an ChunkyPNG::Image object from this canvasdefto_imageChunkyPNG::Image.from_canvas(self)end################################################################## CONSTRUCTORS################################################################## 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.defself.from_canvas(canvas)self.new(canvas.width,canvas.height,canvas.pixels.dup)end# Creates a canvas by reading pixels from an RGB formatted stream with a# provided with and height. ## Every pixel should be represented by 3 bytes in the stream, in the correct# RGB order. This format closely resembles the internal representation of a# canvas object, so this kind of stream can be read extremely quickly.## @param [Integer] width The width of the new canvas.# @param [Integer] height The height of the new canvas.# @param [#read, String] stream The stream to read the pixel data from.# @return [ChunkyPNG::Canvas] The newly constructed canvas instance.defself.from_rgb_stream(width,height,stream)string=stream.respond_to?(:read)?stream.read(3*width*height):stream.to_s[0,3*width*height]string<<"\255"# Add a fourth byte to the last RGB triple.unpacker='NX'*(width*height)pixels=string.unpack(unpacker).map{|color|color|0x000000ff}self.new(width,height,pixels)end# Creates a canvas by reading pixels from an RGBA formatted stream with a# provided with and height. ## Every pixel should be represented by 4 bytes in the stream, in the correct# RGBA order. This format is exactly like the internal representation of a# canvas object, so this kind of stream can be read extremely quickly.## @param [Integer] width The width of the new canvas. # @param [Integer] height The height of the new canvas. # @param [#read, String] stream The stream to read the pixel data from. # @return [ChunkyPNG::Canvas] The newly constructed canvas instance.defself.from_rgba_stream(width,height,stream)string=stream.respond_to?(:read)?stream.read(4*width*height):stream.to_s[0,4*width*height]self.new(width,height,string.unpack("N*"))end################################################################## EXPORTING################################################################## Creates an RGB-formatted pixelstream with the pixel data from this canvas.## Note that this format is fast but bloated, because no compression is used# and the internal representation is left intact. However, to reconstruct the# canvas, the width and height should be known.## @return [String] The RGBA-formatted pixel data.defto_rgba_streampixels.pack('N*')end# Creates an RGB-formatted pixelstream with the pixel data from this canvas.## Note that this format is fast but bloated, because no compression is used# and the internal representation is almost left intact. However, to reconstruct # the canvas, the width and height should be known.## @return [String] The RGB-formatted pixel data.defto_rgb_streampacker='NX'*(width*height)pixels.pack(packer)endendend