lib/chunky_png/palette.rb in chunky_png-0.0.2 vs lib/chunky_png/palette.rb in chunky_png-0.0.3
- old
+ new
@@ -1,18 +1,38 @@
module ChunkyPNG
-
- ###########################################
- # PALETTE CLASS
- ###########################################
-
+
+ # A palette describes the set of colors that is being used for an image.
+ #
+ # A PNG image can contain an explicit palette which defines the colors of that image,
+ # but can also use an implicit palette, e.g. all truecolor colors or all grayscale colors.
+ #
+ # This palette supports decoding colors from a palette if an explicit palette is provided
+ # in a PNG datastream, and it supports encoding colors to an explicit matrix.
+ #
+ # @see ChunkyPNG::Pixel
class Palette < SortedSet
- def initialize(enum)
+ # Builds a new palette given a set (Enumerable instance) of colors.
+ #
+ # @param [Enumerbale<ChunkyPNG::Pixel>] enum The set of colors to include in this palette.
+ # This Enumerbale can contains duplicates.
+ # @param [Array] decoding_map An array of colors in the exact order at which
+ # they appeared in the palette chunk, so that this array can be used for decoding.
+ def initialize(enum, decoding_map = nil)
super(enum)
- @decoding_map = enum if enum.kind_of?(Array)
+ @decoding_map = decoding_map if decoding_map
end
+ # Builds a palette instance from a PLTE chunk and optionally a tRNS chunk
+ # from a PNG datastream.
+ #
+ # This method will cerate a palette that is suitable for decoding an image.
+ #
+ # @param [ChunkyPNG::Chunk::Palette] The palette chunk to load from
+ # @param [ChunkyPNG::Chunk::Transparency, nil] The optional transparency chunk.
+ # @return [ChunkyPNG::Palette] The loaded palette instance.
+ # @see ChunkyPNG::Palette#can_decode?
def self.from_chunks(palette_chunk, transparency_chunk = nil)
return nil if palette_chunk.nil?
decoding_map = []
index = 0
@@ -29,49 +49,103 @@
bytes << alpha_channel[index]
decoding_map << ChunkyPNG::Pixel.rgba(*bytes)
index += 1
end
- self.new(decoding_map)
+ self.new(decoding_map, decoding_map)
end
+ # Builds a palette instance from a given pixel matrix.
+ # @param [ChunkyPNG::PixelMatrix] pixel_matrix The pixel matrix to create a palette for.
+ # @return [ChunkyPNG::Palette] The palette instance.
def self.from_pixel_matrix(pixel_matrix)
self.new(pixel_matrix.pixels)
end
+ # Builds a palette instance from a given set of pixels.
+ # @param [Enumerable<ChunkyPNG::Pixel>] pixels An enumeration of pixels to create a palette for
+ # @return [ChunkyPNG::Palette] The palette instance.
def self.from_pixels(pixels)
self.new(pixels)
end
+ # Checks whether the size of this palette is suitable for indexed storage.
+ # @return [true, false] True if the number of colors in this palette is less than 256.
def indexable?
size < 256
end
+ # Check whether this pelette only contains opaque colors.
+ # @return [true, false] True if all colors in this palette are opaque.
+ # @see ChunkyPNG::Pixel#opaque?
def opaque?
all? { |pixel| pixel.opaque? }
end
+
+ # Check whether this pelette only contains grayscale colors.
+ # @return [true, false] True if all colors in this palette are grayscale teints.
+ # @see ChunkyPNG::Pixel#grayscale??
+ def grayscale?
+ all? { |pixel| pixel.grayscale? }
+ end
+ # Checks whether this palette is suitable for decoding an image from a datastream.
+ #
+ # This requires that the positions of the colors in the original palette chunk is known,
+ # which is stored as an array in the +@decoding_map+ instance variable.
+ #
+ # @return [true, false] True if a decoding map was built when this palette was loaded.
def can_decode?
!@decoding_map.nil?
end
+ # Checks whether this palette is suitable for encoding an image from to datastream.
+ #
+ # This requires that the position of the color in the future palette chunk is known,
+ # which is stored as a hash in the +@encoding_map+ instance variable.
+ #
+ # @return [true, false] True if a encoding map was built when this palette was loaded.
def can_encode?
!@encoding_map.nil?
end
+ # Returns a color, given the position in the original palette chunk.
+ # @param [Fixnum] index The 0-based position of the color in the palette.
+ # @return [ChunkyPNG::Pixel] The color that is stored in the palette under the given index
+ # @see ChunkyPNG::Palette#can_decode?
def [](index)
@decoding_map[index]
end
+ # Returns the position of a color in the palette
+ # @param [ChunkyPNG::Pixel] color The color for which to look up the index.
+ # @return [Fixnum] The 0-based position of the color in the palette.
+ # @see ChunkyPNG::Palette#can_encode?
def index(color)
@encoding_map[color]
end
+ # Creates a tRNS chunk that corresponds with this palette to store the
+ # alpha channel of all colors.
+ #
+ # Note that this chunk can be left out of every color in the palette is
+ # opaque, and the image is encoded using indexed colors.
+ #
+ # @return [ChunkyPNG::Chunk::Transparency] The tRNS chunk.
def to_trns_chunk
ChunkyPNG::Chunk::Transparency.new('tRNS', map(&:a).pack('C*'))
end
+ # Creates a PLTE chunk that corresponds with this palette to store the
+ # r, g and b channels of all colors.
+ #
+ # Note that a PLTE chunk should only be included if the image is
+ # encoded using index colors. After this chunk has been built, the
+ # palette becomes suitable for encoding an image.
+ #
+ # @return [ChunkyPNG::Chunk::Palette] The PLTE chunk.
+ # @see ChunkyPNG::Palette#can_encode?
def to_plte_chunk
@encoding_map = {}
colors = []
each_with_index do |color, index|
@@ -80,16 +154,25 @@
end
ChunkyPNG::Chunk::Palette.new('PLTE', colors.pack('C*'))
end
+ # Determines the most suitable colormode for this palette.
+ # @return [Fixnum] The colormode which would create the smalles possible
+ # file for images that use this exact palette.
def best_colormode
- if indexable?
- ChunkyPNG::Chunk::Header::COLOR_INDEXED
+ if grayscale?
+ if opaque?
+ ChunkyPNG::COLOR_GRAYSCALE
+ else
+ ChunkyPNG::COLOR_GRAYSCALE_ALPHA
+ end
+ elsif indexable?
+ ChunkyPNG::COLOR_INDEXED
elsif opaque?
- ChunkyPNG::Chunk::Header::COLOR_TRUECOLOR
+ ChunkyPNG::COLOR_TRUECOLOR
else
- ChunkyPNG::Chunk::Header::COLOR_TRUECOLOR_ALPHA
+ ChunkyPNG::COLOR_TRUECOLOR_ALPHA
end
end
end
end