Class: XRVG::Color

Inherits:
Object show all
Defined in:
lib/color.rb

Overview

  • Must optimize 4D vector operations (as C extension ?)

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(r, g, b, a) ⇒ Color

builder

r, g, b, a must be between 0.0 and 1.0



35
36
37
38
39
40
41
42
# File 'lib/color.rb', line 35

def initialize( r, g, b, a)
  # cannot trim because otherwise color interpolation cannot be right !!
  # r = Range.O.trim( r )
  # g = Range.O.trim( g )
  # b = Range.O.trim( b )
  # a = Range.O.trim( a )
  @items = [r,g,b,a]
end

Class Method Details

.[](*args) ⇒ Object

Color builder

only allows to build 4D vector, with composants between 0.0 and 1.0



27
28
29
30
# File 'lib/color.rb', line 27

def Color.[]( *args )
  # TODO : check args number
  Color.new( *args )
end

.black(opacity = 1.0) ⇒ Object

return a black color vector



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

def Color.black(opacity=1.0)
  return Color[0.0, 0.0, 0.0, opacity]
end

.blue(opacity = 1.0) ⇒ Object

return a blue color vector



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

def Color.blue(opacity=1.0)
  return Color[0.0, 0.0, 1.0, opacity]
end

.getHSLcomponent(tC, p, q) ⇒ Object

:nodoc:



311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
# File 'lib/color.rb', line 311

def Color.getHSLcomponent( tC, p, q ) #:nodoc:
  while tC < 0.0
    tC = tC + 1.0
  end
  while tC > 1.0
    tC = tC - 1.0
  end

  if tC < (1.0 / 6.0)
    tC = p + ( (q-p) * 6.0 * tC )
  elsif tC >=(1.0 / 6.0) and tC < 0.5
    tC = q
  elsif tC >= 0.5 and tC < (2.0 / 3.0)
    tC = p + ( (q-p) * 6.0 * ((2.0 / 3.0) - tC) )
  else
    tC = p
  end
  return tC
end

.green(opacity = 1.0) ⇒ Object

return a green color vector



248
249
250
# File 'lib/color.rb', line 248

def Color.green(opacity=1.0)
  return Color[0.0, 1.0, 0.0, opacity]
end

.grey(light, opacity = 1.0) ⇒ Object

return a grey color vector



258
259
260
# File 'lib/color.rb', line 258

def Color.grey(light,opacity=1.0)
  return Color[light, light, light, opacity]
end

.hsl(h, s, l) ⇒ Object



343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/color.rb', line 343

def Color.hsl( h, s, l)
  h *= 360.0
  if l < 0.5
    q = l * (1.0 + s)
  else
    q = l+ s - (l * s)
  end
  p = 2 * l - q
  hk = h / 360.0
  tR = hk + 1.0 / 3.0
  tG = hk
  tB = hk - 1.0 / 3.0

  tR = self.getHSLcomponent( tR, p, q )
  tG = self.getHSLcomponent( tG, p, q )
  tB = self.getHSLcomponent( tB, p, q )
  return [tR, tG, tB]
end

.hsla(h, s, l, a) ⇒ Object

build a color vector from hsl parametrization (convert from hsl to rgb) h, s, l being between 0.0 and 1.0 taken from [[en.wikipedia.org/wiki/HSV_color_space]] h, s, l must be between 0.0 and 1.0



334
335
336
337
338
339
340
341
# File 'lib/color.rb', line 334

def Color.hsla( h, s, l, a)
  h = Range.O.trim( h )
  s = Range.O.trim( s )
  l = Range.O.trim( l )
  a = Range.O.trim( a )
  values = Color.hsl( h, s, l ) + [a]
  return Color[*values]
end

.hsv(h, s, v) ⇒ Object



277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
# File 'lib/color.rb', line 277

def Color.hsv( h, s, v)
  if s == 0.0
    return [v, v, v]
  end
  h *= 360.0
  hi = (h/60.0).floor
  if hi == 6
    hi = 5
  end
  f  = (h/60.0) - hi
  p  = v * ( 1 -             s )
  q  = v * ( 1 -       f   * s )
  t  = v * ( 1 - ( 1 - f ) * s )
  if hi == 0 
    return [ v, t, p] 
  end
  if hi == 1 
    return [ q, v, p] 
  end
  if hi == 2 
    return [ p, v, t] 
  end
  if hi == 3 
    return [ p, q, v] 
  end
  if hi == 4 
    return [ t, p, v] 
  end
  if hi == 5 
    return [ v, p, q] 
  end
end

.hsva(h, s, v, a) ⇒ Object

build a color vector from hsv parametrization (convert from hsv to rgb) h, s, v being between 0.0 and 1.0

taken from wikipedia

error on algo with h = 1.0 => hi == 6 must be taken into account



268
269
270
271
272
273
274
275
# File 'lib/color.rb', line 268

def Color.hsva( h, s, v, a)
  h = Range.O.trim( h )
  s = Range.O.trim( s )
  v = Range.O.trim( v )
  a = Range.O.trim( a )
  values = Color.hsv(h,s,v) + [a]
  return Color[*values]
end

.orange(opacity = 1.0) ⇒ Object

return a orange color vector



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

def Color.orange(opacity=1.0)
  return Color[1.0, 0.5, 0.0, opacity]
end

.rand(opacity = 1.0) ⇒ Object

return a random color vector, with 1.0 opacity !!

Color.rand => Color[0.2345, 0.987623, 0.4123, 1.0]


218
219
220
# File 'lib/color.rb', line 218

def Color.rand( opacity=1.0 )
  return Color[Kernel::rand,Kernel::rand,Kernel::rand,opacity] 
end

.red(opacity = 1.0) ⇒ Object

return a red color vector



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

def Color.red(opacity=1.0)
  return Color[1.0, 0.0, 0.0, opacity]
end

.rgb2h(r, g, b) ⇒ Object



363
364
365
366
367
368
369
370
371
372
373
374
375
376
# File 'lib/color.rb', line 363

def Color.rgb2h(r,g,b)
  result = 0.0
  range = [r,g,b].range
  if range.begin == range.end
    result = 0.0
  elsif range.end == r
    result = (60.0 * (g - b) / range.size +   0.0)
  elsif range.end == g
    result = (60.0 * (b - r) / range.size + 120.0)
  else
    result = (60.0 * (r - g) / range.size + 240.0)
  end
  return (result % 360.0) / 360.0
end

.rgb2hsl(r, g, b) ⇒ Object



403
404
405
406
407
# File 'lib/color.rb', line 403

def Color.rgb2hsl(r,g,b)
  h    = Color.rgb2h(r,g,b)
  s, l = Color.rgb2sl(r,g,b)
  return [h,s,l]
end

.rgb2hsv(r, g, b) ⇒ Object



409
410
411
412
413
# File 'lib/color.rb', line 409

def Color.rgb2hsv(r,g,b)
  h    = Color.rgb2h(r,g,b)
  s, v = Color.rgb2sv(r,g,b)
  return [h,s,v]
end

.rgb2sl(r, g, b) ⇒ Object



378
379
380
381
382
383
384
385
386
387
388
389
390
# File 'lib/color.rb', line 378

def Color.rgb2sl(r,g,b)
  range = [r,g,b].range
  l = range.middle
  s = 0.0
  if range.begin == range.end
    s = 0.0
  elsif l <= 0.5
    s = range.size / (2.0 * l)
  else
    s = range.size / (2.0 - 2.0 * l)
  end
  return [s,l]
end

.rgb2sv(r, g, b) ⇒ Object



392
393
394
395
396
397
398
399
400
401
# File 'lib/color.rb', line 392

def Color.rgb2sv(r,g,b)
  range = [r,g,b].range
  v = range.end
  if v == 0.0
    s = 0.0
  else
    s = (1.0 - (range.begin/range.end))
  end
  return [s,v]
end

.white(opacity = 1.0) ⇒ Object

return a white color vector



253
254
255
# File 'lib/color.rb', line 253

def Color.white(opacity=1.0)
  return Color[1.0, 1.0, 1.0, opacity]
end

.yellow(opacity = 1.0) ⇒ Object

return a yellow color vector



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

def Color.yellow(opacity=1.0)
  return Color[1.0, 1.0, 0.0, opacity]
end

Instance Method Details

#*(scalar) ⇒ Object

define scalar multiplication, for interpolation



58
59
60
61
62
63
# File 'lib/color.rb', line 58

def *( scalar )
  return Color[ self.r * scalar,
                self.g * scalar,
                self.b * scalar,
                self.a * scalar ]
end

#+(other) ⇒ Object

define addition operation, for interpolation



50
51
52
53
54
55
# File 'lib/color.rb', line 50

def +( other )
  return Color[ self.r + other.r,
                self.g + other.g,
                self.b + other.b,
                self.a + other.a ]
end

#==(other) ⇒ Object

equality operator



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

def ==( other )
  return (self.rgba == other.rgba)
end

#[](index) ⇒ Object

delegation componant indexation method



45
46
47
# File 'lib/color.rb', line 45

def [](index)
  return @items[index]
end

#a(val = nil) ⇒ Object

return the opacity composant

Color[0.1,0.2,0.3,0.4].r => 0.4


118
119
120
121
122
123
124
# File 'lib/color.rb', line 118

def a(val=nil)
  if not val
    return self[3]
  else
    return Color[ self.r, self.g, self.b, val ]
  end
end

#a=(n) ⇒ Object

set the opacity composant

Color[0.1,0.2,0.3,0.4].a = 0.5 => Color[0.1,0.2,0.3,0.5]


198
199
200
# File 'lib/color.rb', line 198

def a=(n)
  @items[3] = n
end

#b(val = nil) ⇒ Object

return the blue composant

Color[0.1,0.2,0.3,0.4].r => 0.3


108
109
110
111
112
113
114
# File 'lib/color.rb', line 108

def b(val=nil)
  if not val
    return self[2]
  else
    return Color[ self.r, self.g, val, self.a ]
  end
end

#b=(n) ⇒ Object

set the blue composant

Color[0.1,0.2,0.3,0.4].b = 0.5 => Color[0.1,0.2,0.5,0.4]


192
193
194
# File 'lib/color.rb', line 192

def b=(n)
  @items[2] = n
end

#complementObject

compute complementary color

Color.red.complement => Color.green


204
205
206
207
208
# File 'lib/color.rb', line 204

def complement
  newvalues = self.rgba[0..-2].map {|v| Range.O.complement( v )}
  newvalues += [self.a]
  return Color[ *newvalues ]
end

#format255Object

return an array containing colors on 255 integer format

Color[0.0,1.0,0.0,1.0].format255 => [0,255,0,255]


212
213
214
# File 'lib/color.rb', line 212

def format255()
  return @items.map {|v| (v * 255.0).to_i}
end

#g(val = nil) ⇒ Object

return the green composant

Color[0.1,0.2,0.3,0.4].r => 0.2


98
99
100
101
102
103
104
# File 'lib/color.rb', line 98

def g(val=nil)
  if not val
    return self[1]
  else
    return Color[ self.r, val, self.b, self.a ]
  end
end

#g=(n) ⇒ Object

set the green composant

Color[0.1,0.2,0.3,0.4].g = 0.5 => Color[0.1,0.5,0.3,0.4]


186
187
188
# File 'lib/color.rb', line 186

def g=(n)
  @items[1] = n
end

#hslaObject

return hsla components



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

def hsla
  return (Color.rgb2hsl(self.r, self.g, self.b) + [self.a])
end

#hsvaObject

return hsva components



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

def hsva
  return (Color.rgb2hsv(self.r, self.g, self.b) + [self.a])
end

#hue(newhue = nil) ⇒ Object

get or set hue of color

Color.red.hue        => 0.0
Color.red.hue( 0.1 ) => Color.hsva( 0.1, 1.0, 1.0, 1.0 )


129
130
131
132
133
134
135
136
137
# File 'lib/color.rb', line 129

def hue(newhue=nil)
  if not newhue
    return self.hsva[0]
  else
    hsva = self.hsva
    hsva[0] = newhue
    return Color.hsva( *hsva )
  end
end

#lightness(newlight = nil) ⇒ Object

set lightness (from hsl) of color

Color.white.lightness        => 1.0
Color.white.lightness( 0.1 ) => Color.hsla( 1.0, 1.0, 0.1, 1.0 )


168
169
170
171
172
173
174
175
176
# File 'lib/color.rb', line 168

def lightness(newlight=nil)
  if not newlight
    return self.hsla[2]
  else
    hsla = self.hsla
    hsla[2] = newlight
    return Color.hsla( *hsla )
  end
end

#r(val = nil) ⇒ Object

return the red composant

Color[0.1,0.2,0.3,0.4].r        => 0.1
Color[0.1,0.2,0.3,0.4].r( 0.3 ) => Color[0.3,0.2,0.3,0.4]


88
89
90
91
92
93
94
# File 'lib/color.rb', line 88

def r(val=nil)
  if not val
    return self[0]
  else
    return Color[ val, self.g, self.b, self.a ]
  end
end

#r=(n) ⇒ Object

set the red composant

Color[0.1,0.2,0.3,0.4].r = 0.5 => Color[0.5,0.2,0.3,0.4]


180
181
182
# File 'lib/color.rb', line 180

def r=(n)
  @items[0]= n
end

#rgbaObject

return [r,g,b,a]



66
67
68
# File 'lib/color.rb', line 66

def rgba
  return @items
end

#saturation(newsat = nil) ⇒ Object

set saturation of color

Color.red.saturation        => 1.0
Color.red.saturation( 0.1 ) => Color.hsva( 0.0, 0.1, 1.0, 1.0 )


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

def saturation(newsat=nil)
  if not newsat
    return self.hsva[1]
  else
    hsva = self.hsva
    hsva[1] = newsat
    return Color.hsva( *hsva )
  end
end

#svgObject

get svg description of a color



416
417
418
419
420
421
422
# File 'lib/color.rb', line 416

def svg
  values = self[0..2].map do |v|
    v = Range.O.trim( v )
    (255.0 * v).to_i 
  end
  return "rgb(#{values.join(",")})"
end

#value(newval = nil) ⇒ Object

set value (from hsv) of color

Color.red.value        => 1.0
Color.red.value( 0.1 ) => Color.hsva( 0.0, 1.0, 0.1, 1.0 )


155
156
157
158
159
160
161
162
163
# File 'lib/color.rb', line 155

def value(newval=nil)
  if not newval
    return self.hsva[2]
  else
    hsva = self.hsva
    hsva[2] = newval
    return Color.hsva( *hsva )
  end
end