termin-ansicolor 1.3.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,161 @@
1
+ module Termin
2
+ module ANSIColor
3
+ module RGBColorMetricsHelpers
4
+ module WeightedEuclideanDistance
5
+ def weighted_euclidean_distance_to(other, weights = [ 1.0 ] * values.size)
6
+ sum = 0.0
7
+ values.zip(other.values, weights) do |s, o, w|
8
+ sum += w * (s - o) ** 2
9
+ end
10
+ Math.sqrt(sum)
11
+ end
12
+ end
13
+
14
+ module NormalizeRGBTriple
15
+ private
16
+
17
+ def normalize(v)
18
+ v /= 255.0
19
+ if v <= 0.04045
20
+ v / 12
21
+ else
22
+ ( (v + 0.055) / 1.055) ** 2.4
23
+ end
24
+ end
25
+
26
+ def normalize_rgb_triple(rgb_triple)
27
+ [
28
+ rgb_triple.red,
29
+ rgb_triple.green,
30
+ rgb_triple.blue
31
+ ].map { |v| normalize(v) }
32
+ end
33
+ end
34
+ end
35
+
36
+ module RGBColorMetrics
37
+ def self.metric(name)
38
+ metric?(name) or raise ArgumentError, "unknown metric #{name.inspect}"
39
+ end
40
+
41
+ def self.metric?(name)
42
+ if const_defined?(name)
43
+ const_get name
44
+ end
45
+ end
46
+
47
+ def self.metrics
48
+ constants.map(&:to_sym)
49
+ end
50
+
51
+ # Implements color distance how the old greeks and most donkeys would…
52
+ module Euclidean
53
+ def self.distance(rgb1, rgb2)
54
+ rgb1.weighted_euclidean_distance_to rgb2
55
+ end
56
+ end
57
+
58
+ # Implements color distance the best way everybody knows…
59
+ module NTSC
60
+ def self.distance(rgb1, rgb2)
61
+ rgb1.weighted_euclidean_distance_to rgb2, [ 0.299, 0.587, 0.114 ]
62
+ end
63
+ end
64
+
65
+ # Implements color distance as given in:
66
+ # http://www.compuphase.com/cmetric.htm
67
+ module CompuPhase
68
+ def self.distance(rgb1, rgb2)
69
+ rmean = (rgb1.red + rgb2.red) / 2
70
+ rgb1.weighted_euclidean_distance_to rgb2,
71
+ [ 2 + (rmean >> 8), 4, 2 + ((255 - rmean) >> 8) ]
72
+ end
73
+ end
74
+
75
+ module YUV
76
+ class YUVTriple < Struct.new(:y, :u, :v)
77
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
78
+
79
+ def self.from_rgb_triple(rgb_triple)
80
+ r, g, b = rgb_triple.red, rgb_triple.green, rgb_triple.blue
81
+ y = (0.299 * r + 0.587 * g + 0.114 * b).round
82
+ u = ((b - y) * 0.492).round
83
+ v = ((r - y) * 0.877).round
84
+ new(y, u, v)
85
+ end
86
+ end
87
+
88
+ def self.distance(rgb1, rgb2)
89
+ yuv1 = YUVTriple.from_rgb_triple(rgb1)
90
+ yuv2 = YUVTriple.from_rgb_triple(rgb2)
91
+ yuv1.weighted_euclidean_distance_to yuv2
92
+ end
93
+ end
94
+
95
+ module CIEXYZ
96
+ class CIEXYZTriple < Struct.new(:x, :y, :z)
97
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
98
+ extend RGBColorMetricsHelpers::NormalizeRGBTriple
99
+
100
+ def self.from_rgb_triple(rgb_triple)
101
+ r, g, b = normalize_rgb_triple rgb_triple
102
+
103
+ x = 0.436052025 * r + 0.385081593 * g + 0.143087414 * b
104
+ y = 0.222491598 * r + 0.71688606 * g + 0.060621486 * b
105
+ z = 0.013929122 * r + 0.097097002 * g + 0.71418547 * b
106
+
107
+ x *= 255
108
+ y *= 255
109
+ z *= 255
110
+
111
+ new(x.round, y.round, z.round)
112
+ end
113
+ end
114
+
115
+ def self.distance(rgb1, rgb2)
116
+ xyz1 = CIEXYZTriple.from_rgb_triple(rgb1)
117
+ xyz2 = CIEXYZTriple.from_rgb_triple(rgb2)
118
+ xyz1.weighted_euclidean_distance_to xyz2
119
+ end
120
+ end
121
+
122
+ module CIELab
123
+ class CIELabTriple < Struct.new(:l, :a, :b)
124
+ include RGBColorMetricsHelpers::WeightedEuclideanDistance
125
+ extend RGBColorMetricsHelpers::NormalizeRGBTriple
126
+
127
+ def self.from_rgb_triple(rgb_triple)
128
+ r, g, b = normalize_rgb_triple rgb_triple
129
+
130
+ x = 0.436052025 * r + 0.385081593 * g + 0.143087414 * b
131
+ y = 0.222491598 * r + 0.71688606 * g + 0.060621486 * b
132
+ z = 0.013929122 * r + 0.097097002 * g + 0.71418547 * b
133
+
134
+ xr = x / 0.964221
135
+ yr = y
136
+ zr = z / 0.825211
137
+
138
+ eps = 216.0 / 24389
139
+ k = 24389.0 / 27
140
+
141
+ fx = xr > eps ? xr ** (1.0 / 3) : (k * xr + 16) / 116
142
+ fy = yr > eps ? yr ** (1.0 / 3) : (k * yr + 16) / 116
143
+ fz = zr > eps ? zr ** (1.0 / 3) : (k * zr + 16) / 116
144
+
145
+ l = 2.55 * ((116 * fy) - 16)
146
+ a = 500 * (fx - fy)
147
+ b = 200 * (fy - fz)
148
+
149
+ new(l.round, a.round, b.round)
150
+ end
151
+ end
152
+
153
+ def self.distance(rgb1, rgb2)
154
+ lab1 = CIELabTriple.from_rgb_triple(rgb1)
155
+ lab2 = CIELabTriple.from_rgb_triple(rgb2)
156
+ lab1.weighted_euclidean_distance_to lab2
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,121 @@
1
+ require 'termin/ansicolor/rgb_color_metrics'
2
+
3
+ module Termin
4
+ module ANSIColor
5
+ class RGBTriple
6
+ include Termin::ANSIColor::RGBColorMetricsHelpers::WeightedEuclideanDistance
7
+
8
+ def self.convert_value(color)
9
+ color.nil? and raise ArgumentError, "missing color value"
10
+ color = Integer(color)
11
+ (0..0xff) === color or raise ArgumentError,
12
+ "color value #{color.inspect} not between 0 and 255"
13
+ color
14
+ end
15
+
16
+ private_class_method :convert_value
17
+
18
+ def self.from_html(html)
19
+ case html
20
+ when /\A#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})\z/i
21
+ new(*$~.captures.map { |c| convert_value(c.to_i(16)) })
22
+ when /\A#([0-9a-f])([0-9a-f])([0-9a-f])\z/i
23
+ new(*$~.captures.map { |c| convert_value(c.to_i(16) << 4) })
24
+ end
25
+ end
26
+
27
+ def self.from_hash(options)
28
+ new(
29
+ convert_value(options[:red]),
30
+ convert_value(options[:green]),
31
+ convert_value(options[:blue])
32
+ )
33
+ end
34
+
35
+ def self.from_array(array)
36
+ new(*array)
37
+ end
38
+
39
+ def self.[](thing)
40
+ case
41
+ when thing.respond_to?(:to_rgb_triple) then thing
42
+ when thing.respond_to?(:to_ary) then RGBTriple.from_array(thing.to_ary)
43
+ when thing.respond_to?(:to_str) then RGBTriple.from_html(thing.to_str.sub(/\Aon_/, '')) # XXX somewhat hacky
44
+ when thing.respond_to?(:to_hash) then RGBTriple.from_hash(thing.to_hash)
45
+ else raise ArgumentError, "cannot convert #{thing.inspect} into #{self}"
46
+ end
47
+ end
48
+
49
+ def initialize(red, green, blue)
50
+ @values = [ red, green, blue ]
51
+ end
52
+
53
+ def red
54
+ @values[0]
55
+ end
56
+
57
+ def green
58
+ @values[1]
59
+ end
60
+
61
+ def blue
62
+ @values[2]
63
+ end
64
+
65
+ def gray?
66
+ red != 0 && red != 0xff && red == green && green == blue && blue == red
67
+ end
68
+
69
+ def html
70
+ s = '#'
71
+ @values.each { |c| s << '%02x' % c }
72
+ s
73
+ end
74
+
75
+ def to_rgb_triple
76
+ self
77
+ end
78
+
79
+ attr_reader :values
80
+ protected :values
81
+
82
+ def to_a
83
+ @values.dup
84
+ end
85
+
86
+ def ==(other)
87
+ @values == other.values
88
+ end
89
+
90
+ def distance_to(other, options = {})
91
+ options[:metric] ||= RGBColorMetrics::CIELab
92
+ options[:metric].distance(self, other)
93
+ end
94
+
95
+ def initialize_copy(other)
96
+ r = super
97
+ other.instance_variable_set :@values, @values.dup
98
+ r
99
+ end
100
+
101
+ def gradient_to(other, options = {})
102
+ options[:steps] ||= 16
103
+ steps = options[:steps].to_i
104
+ steps < 2 and raise ArgumentError, 'at least 2 steps are required'
105
+ changes = other.values.zip(@values).map { |x, y| x - y }
106
+ current = self
107
+ gradient = [ current.dup ]
108
+ s = steps - 1
109
+ while s > 1
110
+ current = current.dup
111
+ gradient << current
112
+ 3.times do |i|
113
+ current.values[i] += changes[i] / (steps - 1)
114
+ end
115
+ s -= 1
116
+ end
117
+ gradient << other
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,8 @@
1
+ module Termin::ANSIColor
2
+ # Termin::ANSIColor version
3
+ VERSION = '1.3.0'
4
+ VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end
@@ -0,0 +1,41 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: term-ansicolor 1.3.0 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "termin-ansicolor"
6
+ s.version = "1.3.0.2"
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib"]
10
+ s.authors = ["Florian Frank"]
11
+ s.date = "2014-02-06"
12
+ s.description = "This library uses ANSI escape sequences to control the attributes of terminal output. Termin Ansicolor is the clone of term-ansicolor gem with fixed bug. This gem is needed until merging pull request on official repo."
13
+ s.email = "flori@ping.de"
14
+ s.executables = ["cdiff", "decolor", "colortab", "term_mandel", "term_display"]
15
+ s.extra_rdoc_files = ["README.rdoc", "lib/termin/ansicolor.rb", "lib/termin/ansicolor/attribute.rb", "lib/termin/ansicolor/ppm_reader.rb", "lib/termin/ansicolor/rgb_color_metrics.rb", "lib/termin/ansicolor/rgb_triple.rb", "lib/termin/ansicolor/version.rb"]
16
+ s.files = [".gitignore", ".travis.yml", "CHANGES", "COPYING", "Gemfile", "README.rdoc", "Rakefile", "VERSION", "bin/cdiff", "bin/colortab", "bin/decolor", "bin/term_display", "bin/term_mandel", "examples/ColorTest.gif", "examples/Mona_Lisa.jpg", "examples/Stilleben.jpg", "examples/example.rb", "examples/lambda-red-plain.ppm", "examples/lambda-red.png", "examples/lambda-red.ppm", "examples/pacman.jpg", "examples/smiley.png", "examples/wool.jpg", "lib/termin/ansicolor.rb", "lib/termin/ansicolor/.keep", "lib/termin/ansicolor/attribute.rb", "lib/termin/ansicolor/ppm_reader.rb", "lib/termin/ansicolor/rgb_color_metrics.rb", "lib/termin/ansicolor/rgb_triple.rb", "lib/termin/ansicolor/version.rb", "term-ansicolor.gemspec", "tests/ansicolor_test.rb", "tests/attribute_test.rb", "tests/ppm_reader_test.rb", "tests/rgb_color_metrics_test.rb", "tests/rgb_triple_test.rb", "tests/test_helper.rb"]
17
+ s.homepage = "http://flori.github.com/term-ansicolor"
18
+ s.licenses = ["GPL-2"]
19
+ s.rdoc_options = ["--title", "Term-ansicolor - Ruby library that colors strings using ANSI escape sequences", "--main", "README.rdoc"]
20
+ s.rubygems_version = "2.2.2"
21
+ s.summary = "Ruby library that colors strings using ANSI escape sequences"
22
+ s.test_files = ["tests/ansicolor_test.rb", "tests/attribute_test.rb", "tests/ppm_reader_test.rb", "tests/rgb_color_metrics_test.rb", "tests/rgb_triple_test.rb", "tests/test_helper.rb"]
23
+
24
+ if s.respond_to? :specification_version then
25
+ s.specification_version = 4
26
+
27
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
28
+ s.add_development_dependency(%q<gem_hadar>, ["~> 1.0.0"])
29
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
30
+ s.add_runtime_dependency(%q<tins>, ["~> 1.0"])
31
+ else
32
+ s.add_dependency(%q<gem_hadar>, ["~> 1.0.0"])
33
+ s.add_dependency(%q<simplecov>, [">= 0"])
34
+ s.add_dependency(%q<tins>, ["~> 1.0"])
35
+ end
36
+ else
37
+ s.add_dependency(%q<gem_hadar>, ["~> 1.0.0"])
38
+ s.add_dependency(%q<simplecov>, [">= 0"])
39
+ s.add_dependency(%q<tins>, ["~> 1.0"])
40
+ end
41
+ end
@@ -0,0 +1,133 @@
1
+ require 'test_helper'
2
+
3
+ class String
4
+ include Termin::ANSIColor
5
+ end
6
+
7
+ class Color
8
+ extend Termin::ANSIColor
9
+ end
10
+
11
+ class StringLike
12
+ def initialize(string)
13
+ @string = string
14
+ end
15
+
16
+ def to_str
17
+ @string
18
+ end
19
+ end
20
+
21
+ class ANSIColorTest < Test::Unit::TestCase
22
+ include Termin::ANSIColor
23
+
24
+ def setup
25
+ @string = "red"
26
+ @string_red = "\e[31mred\e[0m"
27
+ @string_red_on_green = "\e[42m\e[31mred\e[0m\e[0m"
28
+ @string_like = StringLike.new(@string)
29
+ @string_like_red = StringLike.new(@string_red)
30
+ end
31
+
32
+ attr_reader :string, :string_red, :string_red_on_green, :string_like, :string_like_red
33
+
34
+ def test_red
35
+ assert_equal string_red, string.red
36
+ assert_equal string_red, Color.red(string)
37
+ assert_equal string_red, Color.red { string }
38
+ assert_equal string_red, Termin::ANSIColor.red { string }
39
+ assert_equal string_red, red { string }
40
+ end
41
+
42
+ def test_red_on_green
43
+ assert_equal string_red_on_green, string.red.on_green
44
+ assert_equal string_red_on_green, Color.on_green(Color.red(string))
45
+ assert_equal string_red_on_green, Color.on_green { Color.red { string } }
46
+ assert_equal string_red_on_green,
47
+ Termin::ANSIColor.on_green { Termin::ANSIColor.red { string } }
48
+ assert_equal string_red_on_green, on_green { red { string } }
49
+ end
50
+
51
+ def test_color
52
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(:color128, "foo")
53
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(:color128)
54
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128, "foo")
55
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(:color128) { "foo" }
56
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(:color128) { "foo" }
57
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128) { "foo" }
58
+ assert_equal "\e[38;5;128mfoo\e[0m", color(:color128) + "foo" + color(:reset)
59
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(128, "foo")
60
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(128)
61
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128, "foo")
62
+ assert_equal "\e[38;5;128mfoo\e[0m", Color.color(128) { "foo" }
63
+ assert_equal "\e[38;5;128mfoo\e[0m", "foo".color(128) { "foo" }
64
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128) { "foo" }
65
+ assert_equal "\e[38;5;128mfoo\e[0m", color(128) + "foo" + color(:reset)
66
+ end
67
+
68
+ def test_on_color
69
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(:color128, "foo")
70
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(:color128)
71
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128, "foo")
72
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(:color128) { "foo" }
73
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(:color128) { "foo" }
74
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128) { "foo" }
75
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(:color128) + "foo" + color(:reset)
76
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(128, "foo")
77
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(128)
78
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128, "foo")
79
+ assert_equal "\e[48;5;128mfoo\e[0m", Color.on_color(128) { "foo" }
80
+ assert_equal "\e[48;5;128mfoo\e[0m", "foo".on_color(128) { "foo" }
81
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128) { "foo" }
82
+ assert_equal "\e[48;5;128mfoo\e[0m", on_color(128) + "foo" + color(:reset)
83
+ end
84
+
85
+ def test_uncolor
86
+ assert_equal string, string_red.uncolor
87
+ assert_equal string, Color.uncolor(string_red)
88
+ assert_equal string, Color.uncolor(string_like_red)
89
+ assert_equal string, Color.uncolor { string_red }
90
+ assert_equal string, Color.uncolor { string_like_red }
91
+ assert_equal string, Termin::ANSIColor.uncolor { string_red }
92
+ assert_equal string, Termin::ANSIColor.uncolor { string_like_red }
93
+ assert_equal string, uncolor { string }
94
+ assert_equal string, uncolor { string_like_red }
95
+ assert_equal "", uncolor(Object.new)
96
+ for index in 0..255
97
+ assert_equal "foo", Color.uncolor(Color.color("color#{index}", "foo"))
98
+ assert_equal "foo", Color.uncolor(Color.on_color("color#{index}", "foo"))
99
+ end
100
+ end
101
+
102
+ def test_attributes
103
+ foo = 'foo'
104
+ for a in Termin::ANSIColor.attributes
105
+ # skip clear for Ruby 1.9 which implements String#clear to empty the string
106
+ if a != :clear || Termin::ANSIColor.support?(:clear)
107
+ assert_not_equal foo, foo_colored = foo.__send__(a)
108
+ assert_equal foo, foo_colored.uncolor
109
+ end
110
+ assert_not_equal foo, foo_colored = Color.__send__(a, foo)
111
+ assert_equal foo, Color.uncolor(foo_colored)
112
+ assert_not_equal foo, foo_colored = Color.__send__(a) { foo }
113
+ assert_equal foo, Color.uncolor { foo_colored }
114
+ assert_not_equal foo, foo_colored = Termin::ANSIColor.__send__(a) { foo }
115
+ assert_equal foo, Termin::ANSIColor.uncolor { foo_colored }
116
+ assert_not_equal foo, foo_colored = __send__(a) { foo }
117
+ assert_equal foo, uncolor { foo_colored }
118
+ end
119
+ assert_equal Termin::ANSIColor.attributes, 'foo'.attributes
120
+ end
121
+
122
+ def test_coloring_string_like
123
+ assert_equal "\e[31mred\e[0m", red(string_like)
124
+ end
125
+
126
+ def test_frozen
127
+ string = 'foo'
128
+ red = string.red
129
+ string.extend(Termin::ANSIColor).freeze
130
+ assert string.frozen?
131
+ assert_equal red, string.red
132
+ end
133
+ end