class Color::Palette::AdobeColor
A class that can read an Adobe Color
palette file (used for Photoshop swatches) and provide a Hash-like interface to the contents. Not all colour formats in ACO files are supported. Based largely off the information found by Larry Tesler.
Not all Adobe Color
files have named colours; all named entries are returned as an array.
pal = Color::Palette::AdobeColor.from_file(my_aco_palette) pal[0] => Color::RGB<...> pal["white"] => [ Color::RGB<...> ] pal["unknown"] => [ Color::RGB<...>, Color::RGB<...>, ... ]
AdobeColor
palettes are always indexable by insertion order (an integer key).
Version 2 palettes use UTF-16 colour names.
Attributes
Contains the “lost” colours in the palette. These colours could not be properly loaded (e.g., L*a*b* is not supported by Color
, so it is “lost”) or are not understood by the algorithms.
Returns statistics about the nature of the colours loaded.
Public Class Methods
Source
# File lib/color/palette/adobecolor.rb, line 25 def from_file(filename) File.open(filename, "rb") { |io| Color::Palette::AdobeColor.from_io(io) } end
Create an AdobeColor
palette object from the named file.
Source
# File lib/color/palette/adobecolor.rb, line 30 def from_io(io) Color::Palette::AdobeColor.new(io.read) end
Create an AdobeColor
palette object from the provided IO.
Source
# File lib/color/palette/adobecolor.rb, line 46 def initialize(palette) @colors = [] @names = {} @statistics = Hash.new(0) @lost = [] @order = [] @version = nil class << palette def readwords(count = 1) @offset ||= 0 raise IndexError if @offset >= self.size val = self[@offset, count * 2] raise IndexError if val.nil? or val.size < (count * 2) val = val.unpack("n" * count) @offset += count * 2 val end def readutf16(count = 1) @offset ||= 0 raise IndexError if @offset >= self.size val = self[@offset, count * 2] raise IndexError if val.nil? or val.size < (count * 2) @offset += count * 2 val end end @version, count = palette.readwords 2 raise "Unknown AdobeColor palette version #@version." unless @version.between?(1, 2) count.times do space, w, x, y, z = palette.readwords 5 name = nil if @version == 2 raise IndexError unless palette.readwords == [ 0 ] len = palette.readwords name = palette.readutf16(len[0] - 1) raise IndexError unless palette.readwords == [ 0 ] end color = case space when 0 then # RGB @statistics[:rgb] += 1 Color::RGB.new(w / 256, x / 256, y / 256) when 1 then # HS[BV] -- Convert to RGB @statistics[:hsb] += 1 h = w / 65535.0 s = x / 65535.0 v = y / 65535.0 if defined?(Color::HSB) Color::HSB.from_fraction(h, s, v) else @statistics[:converted] += 1 if Color.near_zero_or_less?(s) Color::RGB.from_fraction(v, v, v) else if Color.near_one_or_more?(h) vh = 0 else vh = h * 6.0 end vi = vh.floor v1 = v.to_f * (1 - s.to_f) v2 = v.to_f * (1 - s.to_f * (vh - vi)) v3 = v.to_f * (1 - s.to_f * (1 - (vh - vi))) case vi when 0 then Color::RGB.from_fraction(v, v3, v1) when 1 then Color::RGB.from_fraction(v2, v, v1) when 2 then Color::RGB.from_fraction(v1, v, v3) when 3 then Color::RGB.from_fraction(v1, v2, v) when 4 then Color::RGB.from_fraction(v3, v1, v) else Color::RGB.from_fraction(v, v1, v2) end end end when 2 then # CMYK @statistics[:cmyk] += 1 Color::CMYK.from_percent(100 - (w / 655.35), 100 - (x / 655.35), 100 - (y / 655.35), 100 - (z / 655.35)) when 7 then # L*a*b* @statistics[:lab] += 1 l = [w, 10000].min / 100.0 a = [[-12800, UwToSw[x]].max, 12700].min / 100.0 b = [[-12800, UwToSw[x]].max, 12700].min / 100.0 if defined? Color::Lab Color::Lab.new(l, a, b) else [ space, w, x, y, z ] end when 8 then # Grayscale @statistics[:gray] += 1 g = [w, 10000].min / 100.0 Color::GrayScale.new(g) when 9 then # Wide CMYK @statistics[:wcmyk] += 1 c = [w, 10000].min / 100.0 m = [x, 10000].min / 100.0 y = [y, 10000].min / 100.0 k = [z, 10000].min / 100.0 Color::CMYK.from_percent(c, m, y, k) else @statistics[space] += 1 [ space, w, x, y, z ] end @order << [ color, name ] if color.kind_of? Array @lost << color else @colors << color if name @names[name] ||= [] @names[name] << color end end end end
Create a new AdobeColor
palette from the palette file as a string.
Public Instance Methods
Source
# File lib/color/palette/adobecolor.rb, line 188 def [](key) if key.kind_of?(Numeric) @colors[key] else @names[key] end end
If a Numeric key
is provided, the single colour value at that position will be returned. If a String key
is provided, the colour set (an array) for that colour name will be returned.
Source
# File lib/color/palette/adobecolor.rb, line 197 def each @colors.each { |el| yield el } end
Loops through each colour.
Source
# File lib/color/palette/adobecolor.rb, line 202 def each_name #:yields color_name, color_set:# @names.each { |color_name, color_set| yield color_name, color_set } end
Loops through each named colour set.
Source
# File lib/color/palette/adobecolor.rb, line 181 def values_at(*selectors) @colors.values_at(*selectors) end
Provides the colour or colours at the provided selectors.