Class: ChunkyPNG::Palette
- Inherits:
-
SortedSet
- Object
- SortedSet
- ChunkyPNG::Palette
- Defined in:
- lib/chunky_png/palette.rb
Overview
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 palette (stores as PLTE & tRNS chunks in a PNG file).
Class Method Summary collapse
-
.from_canvas(canvas) ⇒ ChunkyPNG::Palette
Builds a palette instance from a given canvas.
-
.from_chunks(palette_chunk, transparency_chunk = nil) ⇒ ChunkyPNG::Palette
Builds a palette instance from a PLTE chunk and optionally a tRNS chunk from a PNG datastream.
-
.from_pixels(pixels) ⇒ ChunkyPNG::Palette
Builds a palette instance from a given set of pixels.
Instance Method Summary collapse
-
#[](index) ⇒ ChunkyPNG::Color
Returns a color, given the position in the original palette chunk.
-
#best_color_settings ⇒ Integer
Determines the most suitable colormode for this palette.
-
#black_and_white? ⇒ true, false
Check whether this palette only contains bacl and white.
-
#can_decode? ⇒ true, false
Checks whether this palette is suitable for decoding an image from a datastream.
-
#can_encode? ⇒ true, false
Checks whether this palette is suitable for encoding an image from to datastream.
-
#determine_bit_depth ⇒ Integer
Determines the minimal bit depth required for an indexed image.
-
#grayscale? ⇒ true, false
Check whether this palette only contains grayscale colors.
-
#index(color) ⇒ Integer
Returns the position of a color in the palette.
-
#indexable? ⇒ true, false
Checks whether the size of this palette is suitable for indexed storage.
-
#initialize(enum, decoding_map = nil) ⇒ Palette
constructor
Builds a new palette given a set (Enumerable instance) of colors.
-
#opaque? ⇒ true, false
Check whether this palette only contains opaque colors.
-
#opaque_palette ⇒ ChunkyPNG::Palette
Returns a palette with all the opaque variants of the colors in this palette.
-
#to_plte_chunk ⇒ ChunkyPNG::Chunk::Palette
Creates a PLTE chunk that corresponds with this palette to store the r, g, and b channels of all colors.
-
#to_trns_chunk ⇒ ChunkyPNG::Chunk::Transparency
Creates a tRNS chunk that corresponds with this palette to store the alpha channel of all colors.
Constructor Details
#initialize(enum, decoding_map = nil) ⇒ Palette
Builds a new palette given a set (Enumerable instance) of colors.
23 24 25 26 |
# File 'lib/chunky_png/palette.rb', line 23 def initialize(enum, decoding_map = nil) super(enum) @decoding_map = decoding_map if decoding_map end |
Class Method Details
.from_canvas(canvas) ⇒ ChunkyPNG::Palette
Builds a palette instance from a given canvas.
61 62 63 64 65 66 |
# File 'lib/chunky_png/palette.rb', line 61 def self.from_canvas(canvas) # Although we don't need to call .uniq.sort before initializing, because # Palette subclasses SortedSet, we get significantly better performance # by doing so. new(canvas.pixels.uniq.sort) end |
.from_chunks(palette_chunk, transparency_chunk = nil) ⇒ ChunkyPNG::Palette
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.
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/chunky_png/palette.rb', line 39 def self.from_chunks(palette_chunk, transparency_chunk = nil) return nil if palette_chunk.nil? decoding_map = [] index = 0 palatte_bytes = palette_chunk.content.unpack("C*") alpha_channel = transparency_chunk ? transparency_chunk.content.unpack("C*") : [] index = 0 palatte_bytes.each_slice(3) do |bytes| bytes << alpha_channel.fetch(index, ChunkyPNG::Color::MAX) decoding_map << ChunkyPNG::Color.rgba(*bytes) index += 1 end new(decoding_map, decoding_map) end |
.from_pixels(pixels) ⇒ ChunkyPNG::Palette
Builds a palette instance from a given set of pixels.
72 73 74 |
# File 'lib/chunky_png/palette.rb', line 72 def self.from_pixels(pixels) new(pixels) end |
Instance Method Details
#[](index) ⇒ ChunkyPNG::Color
Returns a color, given the position in the original palette chunk.
146 147 148 |
# File 'lib/chunky_png/palette.rb', line 146 def [](index) @decoding_map[index] end |
#best_color_settings ⇒ Integer
Determines the most suitable colormode for this palette.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 |
# File 'lib/chunky_png/palette.rb', line 193 def best_color_settings if black_and_white? [ChunkyPNG::COLOR_GRAYSCALE, 1] elsif grayscale? if opaque? [ChunkyPNG::COLOR_GRAYSCALE, 8] else [ChunkyPNG::COLOR_GRAYSCALE_ALPHA, 8] end elsif indexable? [ChunkyPNG::COLOR_INDEXED, determine_bit_depth] elsif opaque? [ChunkyPNG::COLOR_TRUECOLOR, 8] else [ChunkyPNG::COLOR_TRUECOLOR_ALPHA, 8] end end |
#black_and_white? ⇒ true, false
Check whether this palette only contains bacl and white.
102 103 104 |
# File 'lib/chunky_png/palette.rb', line 102 def black_and_white? entries == [ChunkyPNG::Color::BLACK, ChunkyPNG::Color::WHITE] end |
#can_decode? ⇒ true, false
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.
124 125 126 |
# File 'lib/chunky_png/palette.rb', line 124 def can_decode? !@decoding_map.nil? end |
#can_encode? ⇒ true, false
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.
137 138 139 |
# File 'lib/chunky_png/palette.rb', line 137 def can_encode? !@encoding_map.nil? end |
#determine_bit_depth ⇒ Integer
Determines the minimal bit depth required for an indexed image
214 215 216 217 218 219 220 221 |
# File 'lib/chunky_png/palette.rb', line 214 def determine_bit_depth case size when 1..2 then 1 when 3..4 then 2 when 5..16 then 4 when 17..256 then 8 end end |
#grayscale? ⇒ true, false
Check whether this palette only contains grayscale colors.
94 95 96 |
# File 'lib/chunky_png/palette.rb', line 94 def grayscale? all? { |color| Color.grayscale?(color) } end |
#index(color) ⇒ Integer
Returns the position of a color in the palette
154 155 156 |
# File 'lib/chunky_png/palette.rb', line 154 def index(color) color.nil? ? 0 : @encoding_map[color] end |
#indexable? ⇒ true, false
Checks whether the size of this palette is suitable for indexed storage.
79 80 81 |
# File 'lib/chunky_png/palette.rb', line 79 def indexable? size <= 256 end |
#opaque? ⇒ true, false
Check whether this palette only contains opaque colors.
86 87 88 |
# File 'lib/chunky_png/palette.rb', line 86 def opaque? all? { |color| Color.opaque?(color) } end |
#opaque_palette ⇒ ChunkyPNG::Palette
Returns a palette with all the opaque variants of the colors in this palette.
111 112 113 |
# File 'lib/chunky_png/palette.rb', line 111 def opaque_palette self.class.new(map { |c| ChunkyPNG::Color.opaque!(c) }) end |
#to_plte_chunk ⇒ ChunkyPNG::Chunk::Palette
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.
Creates a PLTE chunk that corresponds with this palette to store the r, g, and b channels of all colors.
178 179 180 181 182 183 184 185 186 187 188 |
# File 'lib/chunky_png/palette.rb', line 178 def to_plte_chunk @encoding_map = {} colors = [] each_with_index do |color, index| @encoding_map[color] = index colors += ChunkyPNG::Color.to_truecolor_bytes(color) end ChunkyPNG::Chunk::Palette.new("PLTE", colors.pack("C*")) end |
#to_trns_chunk ⇒ ChunkyPNG::Chunk::Transparency
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.
165 166 167 |
# File 'lib/chunky_png/palette.rb', line 165 def to_trns_chunk ChunkyPNG::Chunk::Transparency.new("tRNS", map { |c| ChunkyPNG::Color.a(c) }.pack("C*")) end |