Class: ChunkyPNG::Palette
- Inherits:
-
Set
- Object
- Set
- 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 27 28 |
# File 'lib/chunky_png/palette.rb', line 23 def initialize(enum, decoding_map = nil) super(enum.sort.freeze) @decoding_map = decoding_map if decoding_map @encoding_map = {} freeze end |
Class Method Details
.from_canvas(canvas) ⇒ ChunkyPNG::Palette
Builds a palette instance from a given canvas.
63 64 65 66 67 68 |
# File 'lib/chunky_png/palette.rb', line 63 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.
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/chunky_png/palette.rb', line 41 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.
74 75 76 |
# File 'lib/chunky_png/palette.rb', line 74 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.
148 149 150 |
# File 'lib/chunky_png/palette.rb', line 148 def [](index) @decoding_map[index] end |
#best_color_settings ⇒ Integer
Determines the most suitable colormode for this palette.
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
# File 'lib/chunky_png/palette.rb', line 195 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.
104 105 106 |
# File 'lib/chunky_png/palette.rb', line 104 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.
126 127 128 |
# File 'lib/chunky_png/palette.rb', line 126 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.
139 140 141 |
# File 'lib/chunky_png/palette.rb', line 139 def can_encode? !@encoding_map.empty? end |
#determine_bit_depth ⇒ Integer
Determines the minimal bit depth required for an indexed image
216 217 218 219 220 221 222 223 |
# File 'lib/chunky_png/palette.rb', line 216 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.
96 97 98 |
# File 'lib/chunky_png/palette.rb', line 96 def grayscale? all? { |color| Color.grayscale?(color) } end |
#index(color) ⇒ Integer
Returns the position of a color in the palette
156 157 158 |
# File 'lib/chunky_png/palette.rb', line 156 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.
81 82 83 |
# File 'lib/chunky_png/palette.rb', line 81 def indexable? size <= 256 end |
#opaque? ⇒ true, false
Check whether this palette only contains opaque colors.
88 89 90 |
# File 'lib/chunky_png/palette.rb', line 88 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.
113 114 115 |
# File 'lib/chunky_png/palette.rb', line 113 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.
180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/chunky_png/palette.rb', line 180 def to_plte_chunk @encoding_map.clear 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.
167 168 169 |
# File 'lib/chunky_png/palette.rb', line 167 def to_trns_chunk ChunkyPNG::Chunk::Transparency.new("tRNS", map { |c| ChunkyPNG::Color.a(c) }.pack("C*")) end |