Class: Color::Palette::AdobeColor
- Inherits:
-
Object
- Object
- Color::Palette::AdobeColor
- Includes:
- Enumerable
- Defined in:
- lib/color/palette/adobecolor.rb
Overview
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.
Constant Summary collapse
- UwToSw =
Use this to convert the unsigned word to the signed word, if necessary.
proc { |n| (n >= (2 ** 16)) ? n - (2 ** 32) : n }
Instance Attribute Summary collapse
-
#lost ⇒ Object
readonly
Contains the “lost” colours in the palette.
-
#statistics ⇒ Object
readonly
Returns statistics about the nature of the colours loaded.
-
#version ⇒ Object
readonly
Returns the value of attribute version.
Class Method Summary collapse
-
.from_file(filename) ⇒ Object
Create an AdobeColor palette object from the named file.
-
.from_io(io) ⇒ Object
Create an AdobeColor palette object from the provided IO.
Instance Method Summary collapse
-
#[](key) ⇒ Object
If a Numeric
key
is provided, the single colour value at that position will be returned. -
#each ⇒ Object
Loops through each colour.
-
#each_name ⇒ Object
Loops through each named colour set.
-
#initialize(palette) ⇒ AdobeColor
constructor
Create a new AdobeColor palette from the palette file as a string.
- #size ⇒ Object
-
#to_aco(version = @version) ⇒ Object
:nodoc:.
-
#values_at(*selectors) ⇒ Object
Provides the colour or colours at the provided selectors.
Constructor Details
#initialize(palette) ⇒ AdobeColor
Create a new AdobeColor palette from the palette file as a string.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 |
# 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 |
Instance Attribute Details
#lost ⇒ Object (readonly)
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.
40 41 42 |
# File 'lib/color/palette/adobecolor.rb', line 40 def lost @lost end |
#statistics ⇒ Object (readonly)
Returns statistics about the nature of the colours loaded.
36 37 38 |
# File 'lib/color/palette/adobecolor.rb', line 36 def statistics @statistics end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
210 211 212 |
# File 'lib/color/palette/adobecolor.rb', line 210 def version @version end |
Class Method Details
.from_file(filename) ⇒ Object
Create an AdobeColor palette object from the named file.
25 26 27 |
# File 'lib/color/palette/adobecolor.rb', line 25 def from_file(filename) File.open(filename, "rb") { |io| Color::Palette::AdobeColor.from_io(io) } end |
.from_io(io) ⇒ Object
Create an AdobeColor palette object from the provided IO.
30 31 32 |
# File 'lib/color/palette/adobecolor.rb', line 30 def from_io(io) Color::Palette::AdobeColor.new(io.read) end |
Instance Method Details
#[](key) ⇒ Object
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.
188 189 190 191 192 193 194 |
# File 'lib/color/palette/adobecolor.rb', line 188 def [](key) if key.kind_of?(Numeric) @colors[key] else @names[key] end end |
#each ⇒ Object
Loops through each colour.
197 198 199 |
# File 'lib/color/palette/adobecolor.rb', line 197 def each @colors.each { |el| yield el } end |
#each_name ⇒ Object
Loops through each named colour set.
202 203 204 |
# 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 |
#size ⇒ Object
206 207 208 |
# File 'lib/color/palette/adobecolor.rb', line 206 def size @colors.size end |
#to_aco(version = @version) ⇒ Object
:nodoc:
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 |
# File 'lib/color/palette/adobecolor.rb', line 212 def to_aco(version = @version) #:nodoc: res = "" res << [ version, @order.size ].pack("nn") @order.each do |cnpair| color, name = *cnpair # Note: HSB and CMYK formats are lost by the conversions performed on # import. They are turned into RGB and WCMYK, respectively. cstr = case color when Array color when Color::RGB r = [(color.red * 256).round, 65535].min g = [(color.green * 256).round, 65535].min b = [(color.blue * 256).round, 65535].min [ 0, r, g, b, 0 ] when Color::GrayScale g = [(color.gray * 100).round, 10000].min [ 8, g, 0, 0, 0 ] when Color::CMYK c = [(color.cyan * 100).round, 10000].min m = [(color.magenta * 100).round, 10000].min y = [(color.yellow * 100).round, 10000].min k = [(color.black * 100).round, 10000].min [ 9, c, m, y, k ] end cstr = cstr.pack("nnnnn") nstr = "" if version == 2 if (name.size / 2 * 2) == name.size # only where s[0] == byte! nstr << [ 0, (name.size / 2) + 1 ].pack("nn") nstr << name nstr << [ 0 ].pack("n") else nstr << [ 0, 1, 0 ].pack("nnn") end end res << cstr << nstr end res end |
#values_at(*selectors) ⇒ Object
Provides the colour or colours at the provided selectors.
181 182 183 |
# File 'lib/color/palette/adobecolor.rb', line 181 def values_at(*selectors) @colors.values_at(*selectors) end |