coloryze 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
File without changes
data/bin/coloryze ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+ # exec ruby -w -x $0 ${1+"$@"} # -*- ruby -*-
3
+ #!ruby -w
4
+ # vim: set filetype=ruby : set sw=2
5
+
6
+ dir = File.dirname(File.dirname(File.expand_path(__FILE__)))
7
+
8
+ libpath = dir + "/lib"
9
+ $:.unshift libpath
10
+
11
+ require 'color/coloryze'
12
+
13
+ Log.output = $stderr
14
+
15
+ col = Coloryze.new(ARGV, $stdout)
16
+ exit(col.exit_status)
data/lib/color.rb ADDED
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ $:.unshift(File.dirname(__FILE__)) unless
5
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
6
+
7
+ module Color
8
+ VERSION = '0.0.1'
9
+ end
10
+
11
+ rbfiles = Dir[File.dirname(__FILE__) + "/color/**/*.rb"]
12
+
13
+ rbfiles.sort.each do |rbfile|
14
+ rootname = rbfile.match(%r{.*/(\w+)\.rb})[1]
15
+ require "color/" + rootname
16
+ end
@@ -0,0 +1,225 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'color/rgb'
5
+ require 'color/hsb'
6
+ require 'color/full_palette'
7
+ require 'color/sample_palette'
8
+ require 'color/scheme'
9
+
10
+ require 'rubygems'
11
+ require 'riel'
12
+
13
+ Log.level = Log::WARN
14
+
15
+ class SchemeOption
16
+
17
+ attr_accessor :stype, :desc, :cls, :option, :re, :args, :params
18
+
19
+ def initialize(stype, desc, cls, *params)
20
+ @stype = stype
21
+ @desc = desc
22
+ @cls = cls
23
+ @params = params
24
+ @option = '--' + stype + "=" + params.collect { |arg| arg.to_s.upcase }.join(',')
25
+ restr = '^' + '--' + stype + "=" + params.collect { |arg| arg == :hue ? '(\#?\w+)' : '(\d+)' }.join(',') + '$' # '$
26
+ @re = Regexp.new(restr)
27
+ @args = Array.new
28
+ end
29
+
30
+ def set_args(args)
31
+ (0 ... args.length).each do |idx|
32
+ if @params[idx] == :hue
33
+ @args << create_hue(args[idx])
34
+ else
35
+ @args << args[idx].to_i
36
+ end
37
+ end
38
+ end
39
+
40
+ def create_hue(val)
41
+ if Color::RGB.matches_rgb_string?(val)
42
+ Color::RGB.new(val).to_hsb.hue
43
+ elsif md = %r{^\d+$}.match(val)
44
+ val.to_i
45
+ else
46
+ raise RuntimeErro.new("invalid value for hue: #{val}")
47
+ end
48
+ end
49
+
50
+ def to_s
51
+ [ @stype, @desc, @cls, @re ].join(" ")
52
+ end
53
+ end
54
+
55
+ class Coloryze
56
+ include Loggable
57
+
58
+ VERSION = "2.0.0"
59
+
60
+ attr_reader :exit_status
61
+
62
+ def initialize(args, outio = $stdout, errio = $stderr)
63
+ info "args: #{args}"
64
+
65
+ @exit_status = 0
66
+ @scheme_options = Array.new
67
+
68
+ _add_option("monochromatic", "display one hue", Color::Monochromatic, :hue)
69
+ _add_option("split-complementary", "display hue and two complements near 180 degrees", Color::SplitComplementary, :hue, :deg)
70
+ _add_option("double-complementary", "display two hues and their two complements", Color::DoubleComplementary, :hue, :hue)
71
+ _add_option("complementary", "display hues at 180 degrees from each other", Color::Complementary, :hue)
72
+ _add_option("analogous", "display three hues near each other", Color::Analogous, :hue, :deg)
73
+ _add_option("triadic", "display three equidistant hues", Color::Triadic, :hue)
74
+ _add_option("hues", "display colors for the generated hues (no scheme applied)", Color::Hues, :start, :end, :int)
75
+
76
+ output_type = :html
77
+ sample = nil
78
+ total_sample = nil
79
+
80
+ @scheme_options.each do |sopt|
81
+ # info "sopt: #{sopt}"
82
+ end
83
+
84
+ sopt = nil
85
+ scheme_args = Array.new
86
+
87
+ params = {
88
+ :background => nil,
89
+ :saturation_start => nil,
90
+ :saturation_end => nil,
91
+ :saturation_step => nil,
92
+ :brightness_start => nil,
93
+ :brightness_end => nil,
94
+ :brightness_step => nil,
95
+ }
96
+
97
+ args.each do |arg|
98
+ info "arg: #{arg}"
99
+
100
+ case arg
101
+ when %r{--(saturation|brightness)=(\d+),(\d+),(\d+)}
102
+ md = Regexp.last_match
103
+ fieldname = md[1]
104
+ %w{ _start _end _step }.each_with_index do |fieldsuffix, idx|
105
+ field = (fieldname + fieldsuffix).intern
106
+ params[field] = md[idx + 2].to_i
107
+ end
108
+ # not supported
109
+ # when %r{--background}
110
+ # args[:background] = md[1]
111
+ when %r{--output=(\w+)}
112
+ md = Regexp.last_match
113
+ output_type = md[1].intern
114
+ when "--version"
115
+ show_version(outio)
116
+ @exit_status = 0
117
+ return
118
+ when "--verbose"
119
+ Log.level = Log::DEBUG
120
+ when %r{--sample=(\d+)}
121
+ md = Regexp.last_match
122
+ sample = md[1].to_i
123
+ when %r{--total-sample=(\d+)}
124
+ md = Regexp.last_match
125
+ total_sample = md[1].to_i
126
+ when "--help", "--usage"
127
+ show_usage(outio)
128
+ @exit_status = 0
129
+ return
130
+ else
131
+ md = nil
132
+ if sopt
133
+ $stderr.puts "error: invalid argument: #{arg}"
134
+ @sxit_status = 1
135
+ elsif sopt = @scheme_options.detect { |so| md = so.re.match(arg) }
136
+ sopt.set_args(md[1 .. -1])
137
+ scheme_args.concat(md[1 .. -1])
138
+
139
+ # add process for scheme without the right parameters
140
+ end
141
+ end
142
+ end
143
+
144
+ unless sopt
145
+ # check for invalid scheme parameters
146
+
147
+ args.each do |arg|
148
+ @scheme_options.each do |so|
149
+ if arg.index("--" + so.stype)
150
+ info "matched #{so}"
151
+ errio.puts "error: scheme '#{so.stype}' requires " + so.params.collect { |p| p.to_s }.join(",")
152
+ @exit_status = 1
153
+ return
154
+ end
155
+ end
156
+ end
157
+ end
158
+
159
+ unless sopt
160
+ show_usage(outio)
161
+ @exit_status = 1
162
+ return
163
+ end
164
+
165
+ info "sopt: #{sopt}"
166
+ info "scheme_args: #{scheme_args}"
167
+
168
+ hues = sopt.cls.new(*sopt.args).hues
169
+
170
+ info "hues: #{hues}"
171
+ info "params: #{params}"
172
+
173
+ info "sample: #{sample}"
174
+ info "total_sample: #{total_sample}"
175
+
176
+ palette_cls = if sample || total_sample
177
+ # yes, a mismatch between *sample and *samples ... legacy option.
178
+ params[:samples] = sample
179
+ params[:total_samples] = total_sample
180
+ Color::SamplePalette
181
+ else
182
+ Color::FullPalette
183
+ end
184
+
185
+ palette = palette_cls.new(hues, params)
186
+ info "palette: #{palette}"
187
+ if output_type == :html
188
+ palette.print_as_html(outio)
189
+ else
190
+ palette.print_as_text(outio)
191
+ end
192
+ end
193
+
194
+ def show_version(io)
195
+ io.puts "coloryze, version #{VERSION}"
196
+ io.puts "Written by Jeff Pace (jpace@incava.org)"
197
+ io.puts "Released under the GNU Public License."
198
+ end
199
+
200
+ def show_usage(io)
201
+ io.puts "usage: coloryze [options]"
202
+ io.puts "options:"
203
+ options = Array.new
204
+ options << [ "--help, --usage", "display this help message" ]
205
+ @scheme_options.each do |sopt|
206
+ options << [ sopt.option, sopt.desc ]
207
+ end
208
+ options << [ "--sample=NUM", "select only NUM colors per hue, chosen randomly" ]
209
+ options << [ "--total-sample=NUM", "select only NUM total colors, chosen randomly" ]
210
+ options << [ "--saturation=START,END,INT", "set the saturation start, end, and interval" ]
211
+ options << [ "--brightness=START,END,INT", "set the brightness start, end, and interval" ]
212
+ options << [ "--output=TYPE", "set the output type, \"text\" (the default) or \"html\"" ]
213
+ options << [ "--verbose", "produce debugging output" ]
214
+ options << [ "--version", "display the version and exit"]
215
+
216
+ options.each do |opt|
217
+ io.printf " %-30s %s\n", *opt
218
+ end
219
+ end
220
+
221
+ def _add_option(stype, desc, cls, *params)
222
+ @scheme_options << SchemeOption.new(stype, desc, cls, *params)
223
+ end
224
+
225
+ end
@@ -0,0 +1,158 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'color/hsb'
5
+ require 'color/rgb'
6
+ require 'color/util'
7
+ require 'color/palette'
8
+
9
+ # shows a set of colors, in text and html
10
+
11
+ module Color
12
+
13
+ class FullPalette < Palette
14
+
15
+ def initialize(hues, args = Hash.new)
16
+ super(args)
17
+
18
+ # hue => saturation => brightness => rgb
19
+ @colors = Array.new
20
+
21
+ hues.each do |hue|
22
+ (saturation_start .. saturation_end).step(saturation_step) do |sat|
23
+ (brightness_start .. brightness_end).step(brightness_step) do |brt|
24
+ hsb = HSB.new hue, sat / 100.0, brt / 100.0
25
+ @colors << hsb
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ def colors
32
+ @colors
33
+ end
34
+
35
+ def puts_indented(io, level, msg)
36
+ io.puts((' ' * (4 * level)) + msg)
37
+ end
38
+
39
+ def print_html_tables(io = $stdout)
40
+ n_columns = 1 + (@brightness_end - @brightness_start) / @brightness_step
41
+
42
+ # want the output to be:
43
+
44
+ # +-------------------------------------------------------+
45
+ # + hue[0] +
46
+ # + +-----------------------------------------------------+
47
+ # + + sat[0] +
48
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
49
+ # + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b +
50
+ # + + + + + + + + + + + + + + +
51
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
52
+ # + + sat[1] +
53
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
54
+ # + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b +
55
+ # + + + + + + + + + + + + + + +
56
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
57
+ # +-------------------------------------------------------+
58
+ # + hue[1] +
59
+ # + +-----------------------------------------------------+
60
+ # + + sat[0] +
61
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
62
+ # + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b +
63
+ # + + + + + + + + + + + + + + +
64
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
65
+ # + + sat[1] +
66
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
67
+ # + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b + + r/b +
68
+ # + + + + + + + + + + + + + + +
69
+ # + +-----+ +-----+ +-----+ +-----+ +-----+ +-----+ +-----+
70
+ # +-------------------------------------------------------+
71
+
72
+ cellwidth = 100 / n_columns
73
+
74
+ level = 1
75
+
76
+ colors_by_hue.sort.each do |hue, by_saturation|
77
+ puts_indented io, 1, '<table width="100%">'
78
+
79
+ puts_indented io, 2, '<tr>'
80
+
81
+ textcolor = @background.nil? || @background.index(%r{[A-Z]\w}) ? "000000" : "FFFFFF"
82
+ puts_indented io, 3, "<td style=\"color: \##{textcolor};\">hue #{hue} &deg;</td>"
83
+
84
+ puts_indented io, 2, '</tr>'
85
+
86
+ by_saturation.sort.each do |sat, by_brightness|
87
+ puts_indented io, 2, '<tr>'
88
+ puts_indented io, 3, '<td>'
89
+
90
+ puts_indented io, 4, '<table width="100%">'
91
+ puts_indented io, 5, '<tr>'
92
+ puts_indented io, 6, "<td colspan=#{n_columns}>"
93
+
94
+ puts_indented io, 7, "saturation: #{sat}"
95
+
96
+ puts_indented io, 6, '</td>'
97
+ puts_indented io, 5, '</tr>'
98
+
99
+ puts_indented io, 5, '<tr>'
100
+
101
+ by_brightness.sort.reverse.each do |brt, hsb|
102
+ rgbstr = sprintf("%06x", hsb.to_rgb)
103
+
104
+ puts_indented io, 6, "<td style=\"width: #{cellwidth}%; vertical-align: bottom; border:2px outset; border-collapse:collapse;\">"
105
+
106
+ puts_indented io, 7, "<table width=\"100%\" border=\"0\" border-width=\"4px\">"
107
+
108
+ stylestr = @background ? " style=\"color: \##{rgbstr};\"" : ""
109
+
110
+ text = sprintf "\#%s; b: %3.2f", rgbstr, brt
111
+
112
+ puts_indented io, 8, '<tr><td' + stylestr + '>' + text + '</td></tr'
113
+
114
+ puts_indented io, 8, "<tr><td style=\"background-color: \##{rgbstr}; vertical-align: bottom;\"><br>&nbsp;</td></tr>"
115
+
116
+ puts_indented io, 7, "</table>"
117
+ puts_indented io, 6, "</td>"
118
+ end
119
+
120
+ puts_indented io, 5, '</tr>'
121
+
122
+ puts_indented io, 4, '</table>'
123
+
124
+ puts_indented io, 3, '</td>'
125
+ puts_indented io, 2, '</tr>'
126
+
127
+ end
128
+
129
+ puts_indented io, 1, '</table>'
130
+ end
131
+
132
+ return nil if true
133
+
134
+
135
+ colors_by_hue.sort.each do |hue, by_saturation|
136
+ print_html_hue_line(io, hue, n_columns)
137
+
138
+ io.puts "<table width=\"100%\">"
139
+ io.puts " <tr>"
140
+
141
+ by_saturation.sort.each do |sat, by_brightness|
142
+ by_brightness.sort.reverse.each do |brt, hsb|
143
+ io.puts " <tr>"
144
+
145
+ # this is one color per row, for now
146
+ print_html_color(io, sat, brt, hsb.to_rgb, 100 / n_columns)
147
+
148
+ io.puts " </tr>"
149
+ end
150
+ end
151
+ io.puts "</table>"
152
+ io.puts "<br/>"
153
+ end
154
+ end
155
+
156
+ end
157
+
158
+ end
data/lib/color/hsb.rb ADDED
@@ -0,0 +1,107 @@
1
+ #!/usr/bin/ruby -w
2
+ # -*- ruby -*-
3
+
4
+ require 'color/rgb'
5
+ require 'color/util'
6
+
7
+ module Color
8
+
9
+ class HSB
10
+ attr_accessor :hue, :saturation, :brightness
11
+
12
+ def initialize(hue, saturation, brightness)
13
+ Color::check_constraint(hue, "hue", 0, 360)
14
+ Color::check_constraint(saturation, "saturation", 0, 1)
15
+ Color::check_constraint(brightness, "brightness", 0, 1)
16
+
17
+ @hue = hue
18
+ @saturation = saturation
19
+ @brightness = brightness
20
+ end
21
+
22
+ def to_s
23
+ "hue: #{hue}; saturation: #{saturation}; brightness: #{brightness}"
24
+ end
25
+
26
+ def inspect
27
+ to_s
28
+ end
29
+
30
+ def equal?(other)
31
+ $stderr.puts "*******"
32
+
33
+ hue.equal?(other.hue) &&
34
+ if cmp == 0
35
+ cmp = saturation <=> other.saturation
36
+ if cmp == 0
37
+ cmp = brightness <=> other.brightness
38
+ end
39
+ end
40
+
41
+ puts "returning: #{cmp}"
42
+ cmp
43
+ end
44
+
45
+ def <=>(other)
46
+ cmp = hue <=> other.hue
47
+ if cmp == 0
48
+ cmp = saturation <=> other.saturation
49
+ if cmp == 0
50
+ cmp = brightness <=> other.brightness
51
+ end
52
+ end
53
+
54
+ cmp
55
+ end
56
+
57
+ def floats_equal?(a, b, threshold)
58
+ (a - b).abs < 0.0001
59
+ end
60
+
61
+ def ==(other)
62
+ threshold = 0.0001
63
+ floats_equal?(hue, other.hue, threshold) && floats_equal?(saturation, other.saturation, threshold) && floats_equal?(brightness, other.brightness, threshold)
64
+ end
65
+
66
+ # Converts HSB (HSV) to RGB. Hue is expected as 0-360; saturation
67
+ # and brightness (value) as 0.0-1.0. Returns an RGB object.
68
+ def to_rgb
69
+ red = green = blue = nil
70
+
71
+ if saturation == 0
72
+ red = green = blue = brightness * 255
73
+ else
74
+ hi = (hue / 60.0).to_i
75
+ f = (hue / 60.0) - hi
76
+ p = brightness * (1 - saturation)
77
+ q = brightness * (1 - saturation * f)
78
+ t = brightness * (1 - saturation * (1 - f))
79
+
80
+ red, green, blue = case hi
81
+ when 0
82
+ [ brightness, t, p ]
83
+ when 1
84
+ [ q, brightness, p ]
85
+ when 2
86
+ [ p, brightness, t ]
87
+ when 3
88
+ [ p, q, brightness ]
89
+ when 4
90
+ [ t, p, brightness ]
91
+ when 5
92
+ [ brightness, p, q ]
93
+ else
94
+ raise "error: hue: #{hue}; hi: #{hi}"
95
+ end
96
+
97
+ red *= 255
98
+ green *= 255
99
+ blue *= 255
100
+ end
101
+
102
+ RGB.new red, green, blue
103
+ end
104
+
105
+ end
106
+
107
+ end