Class: Color::Palette::AdobeColor
- Includes:
- Enumerable
- Defined in:
- lib/extensions/pdf-writer/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.
Methods included from Enumerable
#all?, #any?, #collect, #detect, #each_with_index, #find_all, #group_by, #inject, #max, #member?, #min, #sort, #sort_by, #to_a, #to_set
Constructor Details
#initialize(palette) ⇒ AdobeColor
Create a new AdobeColor palette from the palette file as a string.
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 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 58 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.
52 53 54 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 52 def lost @lost end |
#statistics ⇒ Object (readonly)
Returns statistics about the nature of the colours loaded.
48 49 50 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 48 def statistics @statistics end |
#version ⇒ Object (readonly)
Returns the value of attribute version.
222 223 224 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 222 def version @version end |
Class Method Details
.from_file(filename) ⇒ Object
Create an AdobeColor palette object from the named file.
37 38 39 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 37 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.
42 43 44 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 42 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.
200 201 202 203 204 205 206 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 200 def [](key) if key.kind_of?(Numeric) @colors[key] else @names[key] end end |
#each ⇒ Object
Loops through each colour.
209 210 211 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 209 def each @colors.each { |el| yield el } end |
#each_name ⇒ Object
Loops through each named colour set.
214 215 216 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 214 def each_name #:yields color_name, color_set:# @names.each { |color_name, color_set| yield color_name, color_set } end |
#size ⇒ Object
218 219 220 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 218 def size @colors.size end |
#to_aco(version = @version) ⇒ Object
:nodoc:
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 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 224 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.
193 194 195 |
# File 'lib/extensions/pdf-writer/color/palette/adobecolor.rb', line 193 def values_at(*selectors) @colors.values_at(*selectors) end |