Class: Quadtone::Curve
- Inherits:
-
Object
- Object
- Quadtone::Curve
- Defined in:
- lib/quadtone/curve.rb
Constant Summary collapse
- DeltaETolerance =
1.0
- DeltaEMethod =
:density
Instance Attribute Summary collapse
-
#channel ⇒ Object
Returns the value of attribute channel.
-
#samples ⇒ Object
Returns the value of attribute samples.
Instance Method Summary collapse
- #dmax ⇒ Object
- #dmin ⇒ Object
- #draw_svg(svg, options = {}) ⇒ Object
- #dynamic_range ⇒ Object
- #grayscale(steps) ⇒ Object
-
#initialize(params = {}) ⇒ Curve
constructor
A new instance of Curve.
- #ink_limit(method = DeltaEMethod) ⇒ Object
- #input_for_output(output) ⇒ Object
- #normalize_inputs ⇒ Object
- #num_samples ⇒ Object
- #output_for_input(input) ⇒ Object
- #trim_to_limit ⇒ Object
- #verify_increasing_values ⇒ Object
Constructor Details
#initialize(params = {}) ⇒ Curve
Returns a new instance of Curve.
11 12 13 |
# File 'lib/quadtone/curve.rb', line 11 def initialize(params={}) params.each { |key, value| send("#{key}=", value) } end |
Instance Attribute Details
#channel ⇒ Object
Returns the value of attribute channel.
8 9 10 |
# File 'lib/quadtone/curve.rb', line 8 def channel @channel end |
#samples ⇒ Object
Returns the value of attribute samples.
9 10 11 |
# File 'lib/quadtone/curve.rb', line 9 def samples @samples end |
Instance Method Details
#dmax ⇒ Object
82 83 84 |
# File 'lib/quadtone/curve.rb', line 82 def dmax @samples.last.output_value end |
#dmin ⇒ Object
78 79 80 |
# File 'lib/quadtone/curve.rb', line 78 def dmin @samples.first.output_value end |
#draw_svg(svg, options = {}) ⇒ Object
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 |
# File 'lib/quadtone/curve.rb', line 90 def draw_svg(svg, ={}) size = [:size] || 500 # draw interpolated curve svg.g(fill: 'none', stroke: 'green', :'stroke-width' => 1) do samples = (0..1).step(1.0 / size).map do |n| [size * n, size * output_for_input(n)] end svg.polyline(points: samples.map { |pt| pt.join(',') }.join(' ')) end # draw markers for ink limits { density: 'gray', # cie76: 'red', # cie94: 'green', # cmclc: 'blue', }.each do |method, color| limit = ink_limit(method) x, y = size * limit.input_value, size * limit.output_value svg.g(stroke: color, :'stroke-width' => 3) do svg.line(x1: x, y1: y + 8, x2: x, y2: y - 8) end end # if (limit = ink_limit) # x, y = size * limit.input_value, size * limit.output_value # svg.g(stroke: 'black', :'stroke-width' => 3) do # svg.line(x1: x, y1: y + 15, x2: x, y2: y - 15) # end # end # draw individual samples @samples.each_with_index do |sample, i| svg.circle( cx: size * sample.input_value, cy: size * sample.output_value, r: 3, stroke: 'none', fill: "rgb(#{sample.output.to_rgb.to_a.join(',')})", title: sample.label) end svg.target! end |
#dynamic_range ⇒ Object
86 87 88 |
# File 'lib/quadtone/curve.rb', line 86 def dynamic_range [dmin, dmax] end |
#grayscale(steps) ⇒ Object
33 34 35 36 37 |
# File 'lib/quadtone/curve.rb', line 33 def grayscale(steps) spliner = Spliner::Spliner.new(Hash[ @samples.map { |s| [s.input.value, s.output.l] } ]) scale = (0 .. 1).step(1.0 / (steps - 1)) spliner[scale].map { |l| Color::Lab.new([l]) } end |
#ink_limit(method = DeltaEMethod) ⇒ Object
39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/quadtone/curve.rb', line 39 def ink_limit(method=DeltaEMethod) # ;;@samples.each { |s| warn "%s-%s: %.2f => %.2f" % [@channel, s.id, s.input.value, s.output.value] } @samples.each_with_index do |sample, i| if i > 0 previous_sample = @samples[i - 1] return previous_sample if sample.output_value < previous_sample.output_value return previous_sample if previous_sample.output.delta_e(sample.output, method) < DeltaETolerance end end @samples.last end |
#input_for_output(output) ⇒ Object
24 25 26 27 |
# File 'lib/quadtone/curve.rb', line 24 def input_for_output(output) @input_spliner ||= Spliner::Spliner.new(@samples.map(&:output_value), @samples.map(&:input_value)) @input_spliner[output] end |
#normalize_inputs ⇒ Object
59 60 61 62 63 64 65 |
# File 'lib/quadtone/curve.rb', line 59 def normalize_inputs scale = 1 / @samples.last.input.value @samples.each do |sample| sample.input = Color::Gray.new(k: sample.input.k * scale) end @input_spliner = @output_spliner = nil end |
#num_samples ⇒ Object
29 30 31 |
# File 'lib/quadtone/curve.rb', line 29 def num_samples @samples.length end |
#output_for_input(input) ⇒ Object
19 20 21 22 |
# File 'lib/quadtone/curve.rb', line 19 def output_for_input(input) @output_spliner ||= Spliner::Spliner.new(@samples.map(&:input_value), @samples.map(&:output_value)) @output_spliner[input] end |
#trim_to_limit ⇒ Object
51 52 53 54 55 56 57 |
# File 'lib/quadtone/curve.rb', line 51 def trim_to_limit limit = ink_limit i = @samples.index(limit) ;;warn "trimming curve #{@channel} to sample \##{i}: #{limit}" @samples.slice!(i + 1 .. -1) @input_spliner = @output_spliner = nil end |
#verify_increasing_values ⇒ Object
67 68 69 70 71 72 73 74 75 76 |
# File 'lib/quadtone/curve.rb', line 67 def verify_increasing_values @samples.each_with_index do |sample, i| if i > 0 previous_sample = @samples[i - 1] if sample.output_value < previous_sample.output_value raise "Samples not in increasing order (#{sample.label} [#{i}]: #{sample.output_value} < #{previous_sample.output_value})" end end end end |