Class: ZIMG::Color

Inherits:
Object
  • Object
show all
Includes:
DeepCopyable
Defined in:
lib/zimg/color.rb

Direct Known Subclasses

BMP::Color

Constant Summary collapse

BLACK =
Color.new(0, 0, 0)
WHITE =
Color.new(255, 255, 255)
RED =
Color.new(255, 0,  0)
GREEN =
Color.new(0, 255,  0)
BLUE =
Color.new(0, 0, 255)
YELLOW =
Color.new(255, 255, 0)
CYAN =
Color.new(0, 255, 255)
PURPLE =
MAGENTA =
Color.new(255, 0, 255)
TRANSPARENT =
Color.new(0, 0, 0, 0)
ANSI_COLORS =
%i[black red green yellow blue magenta cyan white].freeze
ASCII_MAP =

see misc/gen_ascii_map.rb

["        '''''''```,,",
",,---:::::;;;;~~\"\"\"\"",
"\"!!!!!!<++*^^^(((LLJ",
"=??vvv]ts[j1122FFuoo",
"CeyyPEah55333VVmmXA4",
"G9$666666RRRRRR00MQQ",
"NNW####&&&&&%%%%%%%%",
"@@@@@@@"].join

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from DeepCopyable

#deep_copy

Constructor Details

#initialize(*a) ⇒ Color

Returns a new instance of Color.



10
11
12
13
14
15
16
17
18
19
# File 'lib/zimg/color.rb', line 10

def initialize *a
  h = a.last.is_a?(Hash) ? a.pop : {}
  @r, @g, @b, @a = *a

  # default sample depth for r,g,b and alpha = 8 bits
  @depth = h[:depth] || 8

  # default ALPHA = 0xff - opaque
  @a ||= h[:alpha] || h[:a] || (2**@depth - 1)
end

Instance Attribute Details

#aObject Also known as: alpha

Returns the value of attribute a.



6
7
8
# File 'lib/zimg/color.rb', line 6

def a
  @a
end

#bObject

Returns the value of attribute b.



5
6
7
# File 'lib/zimg/color.rb', line 5

def b
  @b
end

#depthObject

Returns the value of attribute depth.



5
6
7
# File 'lib/zimg/color.rb', line 5

def depth
  @depth
end

#gObject

Returns the value of attribute g.



5
6
7
# File 'lib/zimg/color.rb', line 5

def g
  @g
end

#rObject

Returns the value of attribute r.



5
6
7
# File 'lib/zimg/color.rb', line 5

def r
  @r
end

Class Method Details

.from_grayscale(value, *args) ⇒ Object

from_grayscale level from_grayscale level, :depth => 16 from_grayscale level, alpha from_grayscale level, alpha, :depth => 16



97
98
99
# File 'lib/zimg/color.rb', line 97

def from_grayscale value, *args
  Color.new value, value, value, *args
end

.from_html(value, *args) ⇒ Object Also known as: from_css

value: (String) “#ff00ff”, “#f0f”, “f0f”, “eebbcc” alpha can be set via :alpha => N optional hash argument



103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/zimg/color.rb', line 103

def from_html value, *args
  s = value.tr("#", "")
  case s.size
  when 3
    r, g, b = s.chars.map { |x| x.to_i(16) * 17 }
  when 6
    r, g, b = s.scan(/../).map { |x| x.to_i(16) }
  else
    raise ArgumentError, "invalid HTML color #{s}"
  end
  Color.new r, g, b, *args
end

Instance Method Details

#&(other) ⇒ Object

AND this color with other one, returns new Color



239
240
241
# File 'lib/zimg/color.rb', line 239

def &(other)
  op :&, other
end

#+(other) ⇒ Object

add other color to this one, returns new Color



229
230
231
# File 'lib/zimg/color.rb', line 229

def +(other)
  op :+, other
end

#-(other) ⇒ Object

subtract other color from this one, returns new Color



224
225
226
# File 'lib/zimg/color.rb', line 224

def -(other)
  op :-, other
end

#<=>(other) ⇒ Object

compare with other color



212
213
214
215
216
217
218
219
220
221
# File 'lib/zimg/color.rb', line 212

def <=>(other)
  c1, c2 =
    if depth > other.depth
      [self, other.to_depth(depth)]
    else
      [to_depth(other.depth), other]
    end
  r = c1.to_grayscale <=> c2.to_grayscale
  r == 0 ? (c1.to_a <=> c2.to_a) : r
end

#==(other) ⇒ Object Also known as: eql?

compare with other color



198
199
200
201
202
203
204
205
206
207
208
# File 'lib/zimg/color.rb', line 198

def ==(other)
  return false unless other.is_a?(Color)

  c1, c2 =
    if depth > other.depth
      [self, other.to_depth(depth)]
    else
      [to_depth(other.depth), other]
    end
  c1.r == c2.r && c1.g == c2.g && c1.b == c2.b && c1.a == c2.a
end

#^(other) ⇒ Object

XOR this color with other one, returns new Color



234
235
236
# File 'lib/zimg/color.rb', line 234

def ^(other)
  op :^, other
end

#black?Boolean

Returns:

  • (Boolean)


72
73
74
# File 'lib/zimg/color.rb', line 72

def black?
  r == 0 && g == 0 && b == 0
end

#euclidian(other_color) ⇒ Object



59
60
61
62
63
64
65
# File 'lib/zimg/color.rb', line 59

def euclidian(other_color)
  # TODO: different depths
  r  = (self.r.to_i - other_color.r.to_i)**2
  r += (g.to_i - other_color.g.to_i)**2
  r += (b.to_i - other_color.b.to_i)**2
  Math.sqrt r
end

#hashObject

for Array.uniq()



271
272
273
# File 'lib/zimg/color.rb', line 271

def hash
  to_i
end

#inspectObject



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/zimg/color.rb', line 178

def inspect
  s = String.new
  s << "#<Color"
  if depth == 16
    s << " r=#{r ? format("%04x", r) : "????"}"
    s << " g=#{g ? format("%04x", g) : "????"}"
    s << " b=#{b ? format("%04x", b) : "????"}"
    s << format(" alpha=%04x", alpha) if alpha && alpha != 0xffff
  else
    s << " #"
    s << (r ? format("%02x", r) : "??")
    s << (g ? format("%02x", g) : "??")
    s << (b ? format("%02x", b) : "??")
    s << format(" alpha=%02x", alpha) if alpha && alpha != 0xff
  end
  s << " depth=#{depth}" if depth != 8
  s << ">"
end

#op(op, c = nil) ⇒ Object

Op! op! op! Op!! Oppan Gangnam Style!!



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
# File 'lib/zimg/color.rb', line 249

def op(op, c = nil)
  # XXX what to do with alpha?
  max = 2**depth - 1
  if c
    c = c.to_depth(depth)
    Color.new(
      @r.send(op, c.r) & max,
      @g.send(op, c.g) & max,
      @b.send(op, c.b) & max,
      depth: depth
    )
  else
    Color.new(
      @r.send(op) & max,
      @g.send(op) & max,
      @b.send(op) & max,
      depth: depth
    )
  end
end

#opaque?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/zimg/color.rb', line 80

def opaque?
  a.nil? || a == 2**depth - 1
end

#to_aObject



129
130
131
# File 'lib/zimg/color.rb', line 129

def to_a
  [r, g, b, a]
end

#to_ansiObject

convert to ANSI color name



142
143
144
145
146
147
148
# File 'lib/zimg/color.rb', line 142

def to_ansi
  return to_depth(8).to_ansi if depth != 8

  a = ANSI_COLORS.map { |c| self.class.const_get(c.to_s.upcase) }
  a.map! { |c| euclidian(c) }
  ANSI_COLORS[a.index(a.min)]
end

#to_ascii(map = ASCII_MAP) ⇒ Object

try to convert to one pseudographics ASCII character



137
138
139
# File 'lib/zimg/color.rb', line 137

def to_ascii(map = ASCII_MAP)
  map[to_grayscale * (map.size - 1) / (2**@depth - 1), 1]
end

#to_cssObject Also known as: to_html

HTML/CSS color in notation like #33aa88



151
152
153
154
155
# File 'lib/zimg/color.rb', line 151

def to_css
  return to_depth(8).to_css if depth != 8

  format("#%02X%02X%02X", r, g, b)
end

#to_depth(new_depth) ⇒ Object

change bit depth, return new Color



161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
# File 'lib/zimg/color.rb', line 161

def to_depth(new_depth)
  return self if depth == new_depth

  color = Color.new depth: new_depth
  if new_depth > depth
    %w[r g b a].each do |part|
      color.send("#{part}=", (2**new_depth - 1) / (2**depth - 1) * send(part))
    end
  else
    # new_depth < self.depth
    %w[r g b a].each do |part|
      color.send("#{part}=", send(part) >> (depth - new_depth))
    end
  end
  color
end

#to_gray_alphaObject



88
89
90
# File 'lib/zimg/color.rb', line 88

def to_gray_alpha
  [to_grayscale, alpha]
end

#to_grayscaleObject



84
85
86
# File 'lib/zimg/color.rb', line 84

def to_grayscale
  (r + g + b) / 3
end

#to_iObject

simple conversions



121
122
123
# File 'lib/zimg/color.rb', line 121

def to_i
  ((a || 0) << 24) + ((r || 0) << 16) + ((g || 0) << 8) + (b || 0)
end

#to_sObject



125
126
127
# File 'lib/zimg/color.rb', line 125

def to_s
  format("%02X%02X%02X", r, g, b)
end

#transparent?Boolean

Returns:

  • (Boolean)


76
77
78
# File 'lib/zimg/color.rb', line 76

def transparent?
  a == 0
end

#white?Boolean

Returns:

  • (Boolean)


67
68
69
70
# File 'lib/zimg/color.rb', line 67

def white?
  max = 2**depth - 1
  r == max && g == max && b == max
end

#|(other) ⇒ Object

OR this color with other one, returns new Color



244
245
246
# File 'lib/zimg/color.rb', line 244

def |(other)
  op :|, other
end