Class: Pixelart::Gradient

Inherits:
Object
  • Object
show all
Defined in:
lib/pixelart/colors/gradient.rb

Instance Method Summary collapse

Constructor Details

#initialize(*stops) ⇒ Gradient

Returns a new instance of Gradient.



13
14
15
16
17
18
19
20
21
# File 'lib/pixelart/colors/gradient.rb', line 13

def initialize( *stops )
  ## note:  convert stop colors to rgb triplets e.g.
  ##         from #ffffff to [255,255,255]
  ##              #000000 to [0,0,0]  etc.
  @stops = stops.map do |stop|
             stop = Color.parse( stop )
             [Color.r(stop), Color.g(stop), Color.b(stop)]
           end
end

Instance Method Details

#colors(steps) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
# File 'lib/pixelart/colors/gradient.rb', line 24

def colors( steps )
   segments = @stops.size - 1

   ## note: gradient will include start (first)
   ##   AND stop color (last) - stop color is NOT excluded for now!!
   if segments == 1
      start = @stops[0]
      stop  = @stops[1]

      gradient = linear_gradient( start, stop, steps,
                                  include_stop: true )
   else
     steps_per_segment, mod = steps.divmod( segments )
     raise ArgumentError, "steps (#{steps}) must be divisible by # of segments (#{segments}); expected mod of 0 but got #{mod}"   if mod != 0

     gradient = []
     segments.times do |segment|
       start = @stops[segment]
       stop  = @stops[segment+1]
       include_stop =  (segment == segments-1)  ## note: only include stop if last segment!!

       # print "  segment #{segment+1}/#{segments} #{steps_per_segment} color(s) - "
       # print "  start: #{start.inspect}  "
       # print  include_stop ? 'include' : 'exclude'
       # print " stop:  #{stop.inspect}"
       # print "\n"

       gradient += linear_gradient( start, stop, steps_per_segment,
                                    include_stop: include_stop )
     end
   end

   ## convert to color (Integer)
   gradient.map do |color|
     Color.rgb( *color )
   end
end

#interpolate(start, stop, steps, n) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/pixelart/colors/gradient.rb', line 64

def interpolate( start, stop, steps, n )
  ## note: n - expected to start with 1,2,3,etc.
  color = []
  3.times do |i|
    stepize = Float(stop[i] - start[i]) / Float(steps-1)
    value = stepize * n
    ## convert back to Integer from Float
    ##   add 0.5 for rounding up (starting with 0.5) - why? why not?
    value = (value+0.5).to_i
    value = start[i] + value

    color << value
  end
  color
end

#linear_gradient(start, stop, steps, include_stop: true) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/pixelart/colors/gradient.rb', line 81

def linear_gradient( start, stop, steps,
                      include_stop: true )

  gradient = [start]  ## auto-add start color (first color in gradient)

  if include_stop
    1.upto( steps-2 ).each do |n|  ## sub two (-2), that is, start and stop color
      gradient << interpolate( start, stop, steps, n )
    end
    # note: use original passed in stop color (should match calculated)
    gradient << stop
  else
    1.upto( steps-1 ).each do |n|  ## sub one (-1), that is, start color only
      ## note: add one (+1) to steps because stop color gets excluded (not included)!!
      gradient << interpolate( start, stop, steps+1, n )
    end
  end

  gradient
end