lorraine 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/lorraine +15 -0
- data/lib/.DS_Store +0 -0
- data/lib/lorraine/command.rb +102 -0
- data/lib/lorraine/connection.rb +81 -0
- data/lib/lorraine/image.rb +62 -0
- data/lib/lorraine/message.rb +79 -0
- data/lib/lorraine/server.rb +41 -0
- data/lib/lorraine/test_connection.rb +20 -0
- data/lib/lorraine/version.rb +3 -0
- data/lib/lorraine.rb +10 -0
- data/lorraine.gemspec +27 -0
- data/vendor/colorist/colorist/color.rb +467 -0
- data/vendor/colorist/colorist/core_extensions.rb +26 -0
- data/vendor/colorist/colorist.rb +2 -0
- metadata +149 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Wil Gieseler
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# Lorraine
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'lorraine'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install lorraine
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/bin/lorraine
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
lib = File.expand_path(File.dirname(__FILE__) + '/../lib')
|
4
|
+
$LOAD_PATH.unshift(lib) if File.directory?(lib) && !$LOAD_PATH.include?(lib)
|
5
|
+
|
6
|
+
require 'lorraine'
|
7
|
+
require 'lorraine/command'
|
8
|
+
|
9
|
+
Lorraine::CommandLine.start
|
10
|
+
#
|
11
|
+
# args = ARGV.dup
|
12
|
+
# ARGV.clear
|
13
|
+
# command = args.shift.strip rescue nil
|
14
|
+
#
|
15
|
+
# Lorraine::Command.run(command, args)
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,102 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "thin"
|
5
|
+
|
6
|
+
class CommandLine < Thor
|
7
|
+
|
8
|
+
desc "testpattern", "Display a test pattern."
|
9
|
+
def testpattern
|
10
|
+
say "nice to meet you", :red
|
11
|
+
ask("What is your favorite Neopolitan flavor?", :limited_to => ["strawberry", "chocolate", "vanilla"])
|
12
|
+
|
13
|
+
|
14
|
+
puts "I'm a thor task!"
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "server <command>", "install one of the available apps"
|
18
|
+
method_option :port, type: :numeric, aliases: "-p", desc: "Port this server will be at.", default: 1964
|
19
|
+
def server(command)
|
20
|
+
puts "command: #{command}, options: #{options}"
|
21
|
+
if command.to_sym == :start
|
22
|
+
Lorraine::Server.start(options[:port])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "set <pixel> <r> <g> <b>", "light up a pixel. rgb values from 0.0 - 1.0"
|
27
|
+
method_option :remote, type: :boolean, aliases: "-r", desc: "Set the pixel over the network.", default: false
|
28
|
+
method_option :hostname, type: :string, aliases: "-h", desc: "Network hostname.", default: "localhost"
|
29
|
+
method_option :port, type: :numeric, aliases: "-h", desc: "Network port.", default: 1964
|
30
|
+
def set(pixel, r, g, b)
|
31
|
+
m = Lorraine::Message.new :set_pixel, pixel, (r * 4095).to_i, (g * 4095).to_i, (b * 4095).to_i
|
32
|
+
if options[:remote]
|
33
|
+
Lorraine::Client.send_message(m, options[:hostname], options[:port])
|
34
|
+
else
|
35
|
+
c = Lorraine::Connection.new
|
36
|
+
puts "Waiting 5 seconds..."
|
37
|
+
sleep 5
|
38
|
+
c.write_message(m)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
desc "debug", "Misc. debuggins"
|
43
|
+
def debug
|
44
|
+
c = Lorraine::Message.new :set_pixel, 2, 0, 0, 4095
|
45
|
+
j = c.to_json
|
46
|
+
puts "json: #{j}"
|
47
|
+
puts Lorraine::Message.from_json j
|
48
|
+
end
|
49
|
+
|
50
|
+
#
|
51
|
+
# def self.testpattern
|
52
|
+
# # puts "command: #{command}"
|
53
|
+
# # puts " args: #{args}"
|
54
|
+
# # puts "Starting connection... with serialort #{SerialPort::VERSION}"
|
55
|
+
#
|
56
|
+
# # Lorraine::Connection.new
|
57
|
+
# # c = Lorraine::Message.new :display_pixel, 2, 0, 0, 4095
|
58
|
+
# # puts "command: #{c}"
|
59
|
+
# # puts "binary: #{c.to_binary}"
|
60
|
+
# # puts "back in: #{Lorraine::Message.decode c.to_binary}"
|
61
|
+
#
|
62
|
+
# connection = Lorraine::Connection.new "/dev/tty.usbserial-A6008RQE"
|
63
|
+
# puts "Waiting 5 seconds..."
|
64
|
+
# sleep 5
|
65
|
+
# puts "Writing..."
|
66
|
+
#
|
67
|
+
#
|
68
|
+
# img = Lorraine::Image.new(5, 1)
|
69
|
+
# img2 = Lorraine::Image.new(5, 1)
|
70
|
+
#
|
71
|
+
# # img.clear!([1, 0, 0])
|
72
|
+
# img.rgb_pixels = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 1], [0.5, 1, 0.5]]
|
73
|
+
#
|
74
|
+
# img2.rgb_pixels = [[0, 0, 1], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
|
75
|
+
# # img2.clear!([0, 1, 0])
|
76
|
+
#
|
77
|
+
#
|
78
|
+
# # img.rgb_pixels = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 1, 1], [0.5, 1, 0.5]]
|
79
|
+
# # img.rgb_pixels = [[1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0], [1, 0, 0]]
|
80
|
+
#
|
81
|
+
# # full_colors = [[1, 0, 0], [0, 1, 0], [0, 0, 1], [0, 0, 0], [1, 1, 1]]
|
82
|
+
#
|
83
|
+
# connection.display_image img
|
84
|
+
#
|
85
|
+
# # i = 0
|
86
|
+
# while true
|
87
|
+
# # full_colors.rotate!
|
88
|
+
# # img.clear!(full_colors.first)
|
89
|
+
# # puts img.rgb_pixels.to_s
|
90
|
+
#
|
91
|
+
# connection.animate_to_image img2, 2, 200
|
92
|
+
# connection.animate_to_image img, 2, 200
|
93
|
+
# # i += 1
|
94
|
+
# end
|
95
|
+
# connection.sever!
|
96
|
+
#
|
97
|
+
#
|
98
|
+
# end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
class Connection
|
4
|
+
|
5
|
+
require "serialport"
|
6
|
+
|
7
|
+
attr_accessor :port
|
8
|
+
|
9
|
+
def initialize(port = Lorraine::Connection.first_available_port)
|
10
|
+
|
11
|
+
#simplest ruby program to read from arduino serial,
|
12
|
+
#using the SerialPort gem
|
13
|
+
#(http://rubygems.org/gems/serialport)
|
14
|
+
|
15
|
+
|
16
|
+
#params for serial port
|
17
|
+
port_str = port # may be different for you
|
18
|
+
baud_rate = 115200
|
19
|
+
# data_bits = 8
|
20
|
+
# stop_bits = 1
|
21
|
+
# parity = SerialPort::NONE
|
22
|
+
|
23
|
+
self.port = SerialPort.new port_str, baud_rate#, data_bits, stop_bits, parity
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.first_available_port
|
28
|
+
p = Dir.glob("/dev/tty.usb*").first
|
29
|
+
raise "No available ports." unless p
|
30
|
+
p
|
31
|
+
end
|
32
|
+
|
33
|
+
def write_binary_string(binary_string)
|
34
|
+
self.port.write binary_string
|
35
|
+
end
|
36
|
+
|
37
|
+
def write_message(msg)
|
38
|
+
puts "Writing message: #{msg}"
|
39
|
+
write_binary_string msg.to_binary
|
40
|
+
end
|
41
|
+
|
42
|
+
def display_pixels(pixel_array)
|
43
|
+
commands = []
|
44
|
+
pixel_array.each_with_index do |pixel, i|
|
45
|
+
commands << Lorraine::Message.new(:set_pixel, i, pixel[0], pixel[1], pixel[2])
|
46
|
+
end
|
47
|
+
commands << Lorraine::Message.new(:refresh)
|
48
|
+
commands.each do |command|
|
49
|
+
self.write_message command
|
50
|
+
#self.read_line
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def display_image(img)
|
55
|
+
@current_image = img
|
56
|
+
display_pixels img.rgb_pixels(4095)
|
57
|
+
end
|
58
|
+
|
59
|
+
def animate_to_image(other_image, duration = 1, fps = 24)
|
60
|
+
frame_time = duration.to_f / fps.to_f
|
61
|
+
frame_count = duration * fps
|
62
|
+
frames = Lorraine::Image.frames_between(@current_image, other_image, frame_count)
|
63
|
+
frames.each do |frame|
|
64
|
+
display_image frame
|
65
|
+
sleep frame_time
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def read_line
|
70
|
+
m = self.port.gets
|
71
|
+
puts "Lorraine::Connection Message: #{m}"
|
72
|
+
m
|
73
|
+
end
|
74
|
+
|
75
|
+
def sever!
|
76
|
+
self.port.close # see note 1
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
# require 'colorist'
|
4
|
+
|
5
|
+
|
6
|
+
class Image
|
7
|
+
|
8
|
+
attr_accessor :pixels
|
9
|
+
attr_accessor :width
|
10
|
+
attr_accessor :height
|
11
|
+
|
12
|
+
def self.frames_between(a, b, steps = 10)
|
13
|
+
raise "Different sized images for frames_between" if a.count != b.count
|
14
|
+
pixel_frames = []
|
15
|
+
a.pixels.each_with_index do |a_px, i|
|
16
|
+
b_px = b.pixels[i]
|
17
|
+
pixel_frames << a_px.gradient_to(b_px, steps)
|
18
|
+
end
|
19
|
+
pixel_frames.transpose.map do |frame|
|
20
|
+
img = Lorraine::Image.new(a.width, a.height)
|
21
|
+
img.pixels = frame
|
22
|
+
img
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(w, h)
|
27
|
+
self.width = w
|
28
|
+
self.height = h
|
29
|
+
end
|
30
|
+
|
31
|
+
def count
|
32
|
+
self.width * self.height
|
33
|
+
end
|
34
|
+
|
35
|
+
# 0.0 - 1.0
|
36
|
+
def rgb_pixels=(rgb, percent = true)
|
37
|
+
self.pixels = rgb.map{ |px| Colorist::Color.from_rgb(px[0], px[1], px[2], percent: percent) }
|
38
|
+
end
|
39
|
+
|
40
|
+
def clear!(rgb, percent = true)
|
41
|
+
px = []
|
42
|
+
count.times{ px << Colorist::Color.from_rgb(rgb[0], rgb[1], rgb[2], percent: percent) }
|
43
|
+
self.pixels = px
|
44
|
+
end
|
45
|
+
|
46
|
+
def rotate!
|
47
|
+
@pixels.rotate!
|
48
|
+
end
|
49
|
+
|
50
|
+
def rgb_pixels(upper_limit = 1)
|
51
|
+
self.pixels.map {|px| [px.r.to_f / 255.0 * upper_limit, px.g.to_f / 255.0 * upper_limit, px.b.to_f / 255.0 * upper_limit] }
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
class Pixel
|
57
|
+
|
58
|
+
attr_accessor :color
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
class Message
|
4
|
+
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
# Command ID - 16 bit unsigned integer (S)
|
8
|
+
# Address - 16 bit unsigned integer (S)
|
9
|
+
# Red value - 16 bit unsigned integer (S)
|
10
|
+
# Green value - 16 bit unsigned integer (S)
|
11
|
+
# Blue value - 16 bit unsigned integer (S)
|
12
|
+
|
13
|
+
def self.format
|
14
|
+
"nnnnn"
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(command = 0, pixel = 0, red = 0, green = 0, blue = 0)
|
18
|
+
self.command = command
|
19
|
+
self.pixel = pixel
|
20
|
+
self.red = red
|
21
|
+
self.green = green
|
22
|
+
self.blue = blue
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.decode(binary_string)
|
26
|
+
m = Lorraine::Message.new
|
27
|
+
m.command_id, m.pixel, m.red, m.green, m.blue = binary_string.unpack(Lorraine::Message.format)
|
28
|
+
m
|
29
|
+
end
|
30
|
+
|
31
|
+
attr_accessor :red
|
32
|
+
attr_accessor :green
|
33
|
+
attr_accessor :blue
|
34
|
+
attr_accessor :command
|
35
|
+
attr_accessor :pixel
|
36
|
+
|
37
|
+
COMMAND_IDS = {set_pixel: 1, refresh: 2}
|
38
|
+
|
39
|
+
def command_id
|
40
|
+
COMMAND_IDS[self.command]
|
41
|
+
end
|
42
|
+
|
43
|
+
def command_id=(id)
|
44
|
+
self.command = COMMAND_IDS.invert[id]
|
45
|
+
end
|
46
|
+
|
47
|
+
def packet
|
48
|
+
[self.command_id, self.pixel, self.red.to_i, self.green.to_i, self.blue.to_i]
|
49
|
+
end
|
50
|
+
|
51
|
+
def packet=(new_packet)
|
52
|
+
self.command_id, self.pixel, self.red, self.green, self.blue = new_packet
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.from_json(json)
|
56
|
+
Lorraine::Message.from_packet JSON.parse(json)
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.from_packet(p)
|
60
|
+
m = Lorraine::Message.new
|
61
|
+
m.packet = p
|
62
|
+
m
|
63
|
+
end
|
64
|
+
|
65
|
+
def to_json
|
66
|
+
self.packet.to_json
|
67
|
+
end
|
68
|
+
|
69
|
+
def to_binary
|
70
|
+
self.packet.pack(Lorraine::Message.format)
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
"#<Lorraine::Message command=#{command} pixel=#{pixel} r=#{red} g=#{green} b=#{blue} bytes=#{to_binary.length}>"
|
75
|
+
end
|
76
|
+
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
class Server
|
4
|
+
|
5
|
+
require 'faye'
|
6
|
+
require 'thin'
|
7
|
+
|
8
|
+
def self.start(port)
|
9
|
+
serial_connection = Lorraine::Connection.new
|
10
|
+
Thin::Server.start('0.0.0.0', port) do
|
11
|
+
Faye::WebSocket.load_adapter('thin')
|
12
|
+
faye_server = Faye::RackAdapter.new(:mount => '/faye', :timeout => 45)
|
13
|
+
faye_server.bind(:publish) do |client_id, channel, data|
|
14
|
+
# Process incoming things
|
15
|
+
m = Lorraine::Message.from_packet(data)
|
16
|
+
puts "Received message: #{m}"
|
17
|
+
serial_connection.write_message(m)
|
18
|
+
end
|
19
|
+
run faye_server
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
class Client
|
26
|
+
|
27
|
+
require 'json'
|
28
|
+
require 'httpclient'
|
29
|
+
|
30
|
+
def self.send_message(message, address = "localhost", port = "1964")
|
31
|
+
|
32
|
+
faye_json = {channel: "/illuminate", data: message.packet}.to_json
|
33
|
+
|
34
|
+
client = HTTPClient.new
|
35
|
+
puts client.post("http://#{address}:#{port}/faye", {message: faye_json})
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Lorraine
|
2
|
+
|
3
|
+
class FakeConnection < Connection
|
4
|
+
|
5
|
+
def initialize(port = nil)
|
6
|
+
nil
|
7
|
+
end
|
8
|
+
|
9
|
+
def write_message(msg)
|
10
|
+
puts "Writing message: #{msg}"
|
11
|
+
write_binary_string msg.to_binary
|
12
|
+
end
|
13
|
+
|
14
|
+
def sever!
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
data/lib/lorraine.rb
ADDED
data/lorraine.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/lorraine/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Wil Gieseler"]
|
6
|
+
gem.email = ["supapuerco@gmail.com"]
|
7
|
+
gem.description = %q{How else are you going to communicate with an LED wall?}
|
8
|
+
gem.summary = %q{How else are you going to communicate with an LED wall?}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "lorraine"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Lorraine::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('serialport', '>= 1.1.0')
|
19
|
+
gem.add_dependency('colorize')
|
20
|
+
gem.add_dependency('faye')
|
21
|
+
gem.add_dependency('thor')
|
22
|
+
gem.add_dependency('thin')
|
23
|
+
gem.add_dependency('json_pure')
|
24
|
+
gem.add_dependency('httpclient')
|
25
|
+
# gem.add_dependency('colorist')
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,467 @@
|
|
1
|
+
module Colorist
|
2
|
+
# Color is the general class for storing and manipulating a color with the
|
3
|
+
# Colorist gem. It provides methods to add, subtract, and calculate aspects
|
4
|
+
# of the color based on W3C and other standards.
|
5
|
+
class Color
|
6
|
+
attr_accessor :r, :g, :b
|
7
|
+
|
8
|
+
W3C_COLOR_NAMES = { "maroon" => 0x800000,
|
9
|
+
"red" => 0xff0000,
|
10
|
+
"orange" => 0xffa500,
|
11
|
+
"yellow" => 0xffff00,
|
12
|
+
"olive" => 0x808000,
|
13
|
+
"purple" => 0x800080,
|
14
|
+
"fuchsia" => 0xff00ff,
|
15
|
+
"white" => 0xffffff,
|
16
|
+
"lime" => 0x00ff00,
|
17
|
+
"green" => 0x008000,
|
18
|
+
"navy" => 0x000080,
|
19
|
+
"blue" => 0x0000ff,
|
20
|
+
"aqua" => 0x00ffff,
|
21
|
+
"teal" => 0x008080,
|
22
|
+
"black" => 0x000000,
|
23
|
+
"silver" => 0xc0c0c0,
|
24
|
+
"gray" => 0x808080 }
|
25
|
+
|
26
|
+
X11_COLOR_NAMES = { "alice_blue" => 0xf0f8ff,
|
27
|
+
"anthique_white" => 0xfaebd7,
|
28
|
+
"aqua" => 0x00ffff,
|
29
|
+
"auquamarine" => 0x7fffd4,
|
30
|
+
"azure" => 0xf0ffff,
|
31
|
+
"beige" => 0xf5f5dc,
|
32
|
+
"bisque" => 0xffe4c4,
|
33
|
+
"black" => 0x000000,
|
34
|
+
"blanched_almond" => 0xffebcd,
|
35
|
+
"blue" => 0x0000ff,
|
36
|
+
"blue_violet" => 0x8a2be2,
|
37
|
+
"brown" => 0xa52a2a,
|
38
|
+
"burly_wood" => 0xdeb887,
|
39
|
+
"cadet blue" => 0x5f9ea0,
|
40
|
+
"chartreuse" => 0x7fff00,
|
41
|
+
"chocolate" => 0xd2691e,
|
42
|
+
"coral" => 0xff7f50,
|
43
|
+
"cornflower" => 0x6495ed,
|
44
|
+
"cornslik" => 0xfff8dc,
|
45
|
+
"crimson" => 0xdc143c,
|
46
|
+
"cyan" => 0x00ffff,
|
47
|
+
"dark_blue" => 0x00008b,
|
48
|
+
"dark_cyan" => 0x008b8b,
|
49
|
+
"dark_goldenrod" => 0xb8860b,
|
50
|
+
"dark_gray" => 0xa9a9a9,
|
51
|
+
"dark_green" => 0x006400,
|
52
|
+
"dark_khaki" => 0xbdb76b,
|
53
|
+
"dark_magenta" => 0x8b008b,
|
54
|
+
"dark_olive_green" => 0x556b2f,
|
55
|
+
"dark_orange" => 0xff8c00,
|
56
|
+
"dark_orchid" => 0x9932cc,
|
57
|
+
"dark_red" => 0x8b0000,
|
58
|
+
"dark_salmon" => 0xe9967a,
|
59
|
+
"dark_sea_green" => 0x8fbc8f,
|
60
|
+
"dark_slate_blue" => 0x483d8b,
|
61
|
+
"dark_slate_gray" => 0x2f4f4f,
|
62
|
+
"dark_turquoise" => 0x00ced1,
|
63
|
+
"dark_violet" => 0x9400d3,
|
64
|
+
"deep_pink" => 0xff1493,
|
65
|
+
"deep_sky_blue" => 0x00bfff,
|
66
|
+
"dim_gray" => 0x696969,
|
67
|
+
"dodger_blue" => 0x1e90ff,
|
68
|
+
"firebrick" => 0xb22222,
|
69
|
+
"floral_white" => 0xfffaf0,
|
70
|
+
"forest_green" => 0x228b22,
|
71
|
+
"fuchsia" => 0xff00ff,
|
72
|
+
"gainsboro" => 0xdcdcdc,
|
73
|
+
"ghost_white" => 0xf8f8ff,
|
74
|
+
"gold" => 0xffd700,
|
75
|
+
"goldenrod" => 0xdaa520,
|
76
|
+
"gray" => 0xbebebe,
|
77
|
+
"green" => 0x008000,
|
78
|
+
"green_yellow" => 0xadff2f,
|
79
|
+
"honeydew" => 0xf0fff0,
|
80
|
+
"hot_pink" => 0xff69b4,
|
81
|
+
"indian_red" => 0xcd5c5c,
|
82
|
+
"indigo" => 0x4b0082,
|
83
|
+
"ivory" => 0xfffff0,
|
84
|
+
"khaki" => 0xf0e68c,
|
85
|
+
"lavender" => 0xe6e6fa,
|
86
|
+
"lavender_blush" => 0xfff0f5,
|
87
|
+
"lawn_green" => 0x7cfc00,
|
88
|
+
"lemon_chiffon" => 0xfffacd,
|
89
|
+
"light_blue" => 0xadd8e6,
|
90
|
+
"light_coral" => 0xf08080,
|
91
|
+
"light_cyan" => 0xe0ffff,
|
92
|
+
"light_goldenrod" => 0xfafad2,
|
93
|
+
"light_gray" => 0xd3d3d3,
|
94
|
+
"light_green" => 0x90ee90,
|
95
|
+
"light_pink" => 0xffb6c1,
|
96
|
+
"light_salmon" => 0xffa07a,
|
97
|
+
"light_sea_green" => 0x20b2aa,
|
98
|
+
"light_sky_blue" => 0x87cefa,
|
99
|
+
"light_slate_gray" => 0x778899,
|
100
|
+
"light_steel_blue" => 0xb0c4de,
|
101
|
+
"light_yellow" => 0xffffe0,
|
102
|
+
"lime" => 0x00ff00,
|
103
|
+
"lime_green" => 0x32cd32,
|
104
|
+
"linen" => 0xfaf0e6,
|
105
|
+
"magenta" => 0xff00ff,
|
106
|
+
"maroon" => 0xb03060,
|
107
|
+
"medium_aquamarine" => 0x66cdaa,
|
108
|
+
"medium_blue" => 0x0000cd,
|
109
|
+
"medium_orchid" => 0xba55d3,
|
110
|
+
"medium_purple" => 0x9370db,
|
111
|
+
"medium_sea_green" => 0x3cb371,
|
112
|
+
"medium_slate_blue" => 0x7b68ee,
|
113
|
+
"medium_spring_green" => 0x00fa9a,
|
114
|
+
"medium_turquoise" => 0x48d1cc,
|
115
|
+
"medium_violet_red" => 0xc71585,
|
116
|
+
"midnight_blue" => 0x191970,
|
117
|
+
"mint_cream" => 0xf5fffa,
|
118
|
+
"misty_rose" => 0xffe4e1,
|
119
|
+
"moccasin" => 0xffe4b5,
|
120
|
+
"navajo_white" => 0xffdead,
|
121
|
+
"navy" => 0x000080,
|
122
|
+
"old_lace" => 0xfdf5e6,
|
123
|
+
"olive" => 0x808000,
|
124
|
+
"olive_drab" => 0x6b8e23,
|
125
|
+
"orange" => 0xffa500,
|
126
|
+
"orange_red" => 0xff4500,
|
127
|
+
"orchid" => 0xda70d6,
|
128
|
+
"pale_goldenrod" => 0xeee8aa,
|
129
|
+
"pale_green" => 0x98fb98,
|
130
|
+
"pale_turquoise" => 0xafeeee,
|
131
|
+
"pale_violet_red" => 0xdb7093,
|
132
|
+
"papaya_whip" => 0xffefd5,
|
133
|
+
"peach_puff" => 0xffdab9,
|
134
|
+
"peru" => 0xcd853f,
|
135
|
+
"pink" => 0xffc0cb,
|
136
|
+
"plum" => 0xdda0dd,
|
137
|
+
"powder_blue" => 0xb0e0e6,
|
138
|
+
"purple" => 0xa020f0,
|
139
|
+
"red" => 0xff0000,
|
140
|
+
"rosy_brown" => 0xbc8f8f,
|
141
|
+
"royal_blue" => 0x4169e1,
|
142
|
+
"saddle_brown" => 0x8b4513,
|
143
|
+
"salmon" => 0xfa8072,
|
144
|
+
"sandy_brown" => 0xf4a460,
|
145
|
+
"sea_green" => 0x2e8b57,
|
146
|
+
"seashell" => 0xfff5ee,
|
147
|
+
"sienna" => 0xa0522d,
|
148
|
+
"sky_blue" => 0x87ceeb,
|
149
|
+
"slate_blue" => 0x6a5acd,
|
150
|
+
"slate_gray" => 0x708090,
|
151
|
+
"snow" => 0xfffafa,
|
152
|
+
"spring_green" => 0x00ff7f,
|
153
|
+
"steel_blue" => 0x4682b4,
|
154
|
+
"tan" => 0xd2b48c,
|
155
|
+
"teal" => 0x008080,
|
156
|
+
"thistle" => 0xd8bfd8,
|
157
|
+
"tomato" => 0xff6347,
|
158
|
+
"turquoise" => 0x40e0d0,
|
159
|
+
"violet" => 0xee82ee,
|
160
|
+
"wheat" => 0xf5deb3,
|
161
|
+
"white" => 0xffffff,
|
162
|
+
"white_smoke" => 0xf5f5f5,
|
163
|
+
"yellow" => 0xffff00 }
|
164
|
+
|
165
|
+
# Creates a new color with the hex color provided as a number (i.e. 0x112233)
|
166
|
+
def initialize(color=0x000000)
|
167
|
+
string = "%.6x" % color
|
168
|
+
@r = string[0..1].hex
|
169
|
+
@g = string[2..3].hex
|
170
|
+
@b = string[4..5].hex
|
171
|
+
end
|
172
|
+
|
173
|
+
# Initialize a color based on RGB values. By default, the values
|
174
|
+
# should be between 0 and 255. If you use the option <tt>:percent => true</tt>,
|
175
|
+
# the values should then be between 0.0 and 1.0.
|
176
|
+
def self.from_rgb(r,g,b,options={})
|
177
|
+
color = Colorist::Color.new
|
178
|
+
# convert from 0.0 to 1.0 to 0 to 255 if the :percent option is used
|
179
|
+
if options[:percent]
|
180
|
+
color.r, color.g, color.b = r * 255, g * 255, b * 255
|
181
|
+
else
|
182
|
+
color.r, color.g, color.b = r, g, b
|
183
|
+
end
|
184
|
+
color
|
185
|
+
end
|
186
|
+
|
187
|
+
# Initialize a colour based on HSV/HSB values. Hue should be between 0 and 360 (inclusive),
|
188
|
+
# while saturation and value should be from 0.0 to 1.0.
|
189
|
+
def self.from_hsv(hue, saturation, value)
|
190
|
+
saturation = 1 if saturation > 1
|
191
|
+
value = 1 if saturation > 1
|
192
|
+
|
193
|
+
# Conversion formula taken from wikipedia
|
194
|
+
|
195
|
+
f = (hue / 60.0) - (hue / 60)
|
196
|
+
|
197
|
+
p = value * (1 - saturation)
|
198
|
+
q = value * (1 - (saturation * f))
|
199
|
+
t = value * (1 - (saturation * (1 - f)))
|
200
|
+
|
201
|
+
case ((hue / 60) % 6).floor
|
202
|
+
when 0 then from_rgb(value, t, p, :percent => true)
|
203
|
+
when 1 then from_rgb(q, value, p, :percent => true)
|
204
|
+
when 2 then from_rgb(p, value, t, :percent => true)
|
205
|
+
when 3 then from_rgb(p, q, value, :percent => true)
|
206
|
+
when 4 then from_rgb(t, p, value, :percent => true)
|
207
|
+
when 5 then from_rgb(value, p, q, :percent => true)
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
# Converts a W3C hex string into a color. Works both with the
|
212
|
+
# full form (i.e. <tt>#ffffff</tt>) and the abbreviated form (<tt>#fff</tt>). Can
|
213
|
+
# also take any of the 16 named W3C colors.
|
214
|
+
# Specify a standard if you enter the key word as defined by the standard you use, the
|
215
|
+
# available standards are :
|
216
|
+
#
|
217
|
+
# * <tt>:w3c</tt> - Used by default, represent W3C colors specified in W3C_COLOR_NAMES constant
|
218
|
+
# * <tt>:x11</tt> - represent X11 standard colors specified in X11_COLOR_NAMES constant
|
219
|
+
#
|
220
|
+
# Examples :
|
221
|
+
#
|
222
|
+
# # Here we can ommit standard parameter (:w3c by default)
|
223
|
+
# color = Colorist::Color.from_string "gray" # => <Color #808080>
|
224
|
+
#
|
225
|
+
# # For X11 standard (gray hex value is different)
|
226
|
+
# color = Colorist::Color.from_string "gray", :x11 # => <Color #BEBEBE>
|
227
|
+
#
|
228
|
+
# # Other X11 color (case insensitive)
|
229
|
+
# color = Colorist::Color.from_string "Dark Olive Green", :x11 # => <Color #556B2F>
|
230
|
+
def self.from_string(some_string, standard=:w3c)
|
231
|
+
some_string = some_string.downcase.sub(/ /, "_")
|
232
|
+
if matched = some_string.match(/\A#([0-9a-f]{3})\z/i)
|
233
|
+
color = Colorist::Color.from_rgb(*matched[1].split(//).collect{|v| "#{v}#{v}".hex })
|
234
|
+
elsif matched = some_string.match(/\A#([0-9a-f]{6})\z/i)
|
235
|
+
color = Colorist::Color.new
|
236
|
+
color.r = matched[1][0..1].hex
|
237
|
+
color.g = matched[1][2..3].hex
|
238
|
+
color.b = matched[1][4..5].hex
|
239
|
+
elsif standard == :w3c
|
240
|
+
if W3C_COLOR_NAMES.key?(some_string)
|
241
|
+
color = Colorist::Color.new(W3C_COLOR_NAMES[some_string])
|
242
|
+
else
|
243
|
+
raise ArgumentError, "#{some_string} is not a valid W3C color.", caller
|
244
|
+
end
|
245
|
+
elsif standard == :x11
|
246
|
+
if X11_COLOR_NAMES.key?(some_string)
|
247
|
+
color = Colorist::Color.new(X11_COLOR_NAMES[some_string])
|
248
|
+
else
|
249
|
+
raise ArgumentError, "#{some_string} is not a valid X11 color.", caller
|
250
|
+
end
|
251
|
+
else
|
252
|
+
raise ArgumentError, "Must provide a valid W3C or X11 hex color or color name.", caller
|
253
|
+
end
|
254
|
+
color
|
255
|
+
end
|
256
|
+
|
257
|
+
# Create a new color from the provided object. Duplicates Color objects
|
258
|
+
# and attempts to call <tt>to_color</tt> on other objects. Will raise
|
259
|
+
# an ArgumentError if it is unable to coerce the color.
|
260
|
+
def self.from(some_entity)
|
261
|
+
case some_entity
|
262
|
+
when Colorist::Color
|
263
|
+
some_entity.dup
|
264
|
+
else
|
265
|
+
raise ArgumentError, "#{some_entity.class.to_s} cannot be coerced into a color.", caller unless some_entity.respond_to?(:to_color)
|
266
|
+
some_entity.to_color
|
267
|
+
end
|
268
|
+
end
|
269
|
+
|
270
|
+
# Create a duplicate of this color.
|
271
|
+
def dup
|
272
|
+
Colorist::Color.from_rgb(@r,@g,@b)
|
273
|
+
end
|
274
|
+
|
275
|
+
# Add the individual RGB values of two colors together. You
|
276
|
+
# may also use an equivalent numeric or string color representation.
|
277
|
+
#
|
278
|
+
# Examples:
|
279
|
+
#
|
280
|
+
# gray = Colorist::Color.new(0x333333)
|
281
|
+
# gray + "#300" # => <Color #663333>
|
282
|
+
# gray + 0x000000 # => <Color #333333>
|
283
|
+
# white = "white".to_color
|
284
|
+
# gray + white # => <Color #ffffff>
|
285
|
+
def +(other_color)
|
286
|
+
other_color = Colorist::Color.from(other_color)
|
287
|
+
color = self.dup
|
288
|
+
color.r += other_color.r
|
289
|
+
color.g += other_color.g
|
290
|
+
color.b += other_color.b
|
291
|
+
color
|
292
|
+
end
|
293
|
+
|
294
|
+
# Subtract the individual RGB values of the two colors together.
|
295
|
+
# You may also use an equivalent numeric or string color representation.
|
296
|
+
def -(other_color)
|
297
|
+
other_color = Colorist::Color.from(other_color)
|
298
|
+
color = self.dup
|
299
|
+
color.r -= other_color.r
|
300
|
+
color.g -= other_color.g
|
301
|
+
color.b -= other_color.b
|
302
|
+
color
|
303
|
+
end
|
304
|
+
|
305
|
+
# Compares colors based on brightness.
|
306
|
+
def <=>(other_color)
|
307
|
+
other_color = Colorist::Color.from(other_color)
|
308
|
+
brightness <=> other_color.brightness
|
309
|
+
end
|
310
|
+
|
311
|
+
# Compares colors based on brightness.
|
312
|
+
def < (other_color)
|
313
|
+
other_color = Colorist::Color.from(other_color)
|
314
|
+
brightness < other_color.brightness
|
315
|
+
end
|
316
|
+
|
317
|
+
# Compares colors based on brightness.
|
318
|
+
def > (other_color)
|
319
|
+
other_color = Colorist::Color.from(other_color)
|
320
|
+
brightness > other_color.brightness
|
321
|
+
end
|
322
|
+
|
323
|
+
# Equal if the red, green, and blue values are identical.
|
324
|
+
def ==(other_color)
|
325
|
+
other_color = Colorist::Color.from(other_color)
|
326
|
+
other_color.r == self.r && other_color.g == self.g && other_color.b == self.b
|
327
|
+
end
|
328
|
+
|
329
|
+
# Equal if the brightnesses of the two colors are identical.
|
330
|
+
def ===(other_color)
|
331
|
+
other_color = Colorist::Color.from(other_color)
|
332
|
+
other_color.brightness == brightness
|
333
|
+
end
|
334
|
+
|
335
|
+
def r=(value) #:nodoc:
|
336
|
+
@r = value; normalize; end
|
337
|
+
def g=(value) #:nodoc:
|
338
|
+
@g = value; normalize; end
|
339
|
+
def b=(value) #:nodoc:
|
340
|
+
@b = value; normalize; end
|
341
|
+
|
342
|
+
# Outputs a string representation of the color in the desired format.
|
343
|
+
# The available formats are:
|
344
|
+
#
|
345
|
+
# * <tt>:css</tt> - As a CSS hex string (i.e. <tt>#ffffff</tt>) (default)
|
346
|
+
# * <tt>:css_rgb</tt> - As a CSS RGB value string (i.e. <tt>rgb(255,255,255)</tt>)
|
347
|
+
# * <tt>:rgb</tt> - As an RGB triplet (i.e. <tt>1.0, 1.0, 1.0</tt>)
|
348
|
+
def to_s(format=:css)
|
349
|
+
case format
|
350
|
+
when :css
|
351
|
+
"#%.2x%.2x%.2x" % [r, g, b]
|
352
|
+
when :css_rgb
|
353
|
+
"rgb(%.2f,%.2f,%.2f)" % [r, g, b]
|
354
|
+
when :rgb
|
355
|
+
"%.3f, %.3f, %.3f" % [r / 255, g / 255, b / 255]
|
356
|
+
end
|
357
|
+
end
|
358
|
+
|
359
|
+
# Returns an array of the hue, saturation and value of the color.
|
360
|
+
# Hue will range from 0-359, hue and saturation will be between 0 and 1.
|
361
|
+
|
362
|
+
def to_hsv
|
363
|
+
red, green, blue = *[r, g, b].collect {|x| x / 255.0}
|
364
|
+
max = [red, green, blue].max
|
365
|
+
min = [red, green, blue].min
|
366
|
+
|
367
|
+
if min == max
|
368
|
+
hue = 0
|
369
|
+
elsif max == red
|
370
|
+
hue = 60 * ((green - blue) / (max - min))
|
371
|
+
elsif max == green
|
372
|
+
hue = 60 * ((blue - red) / (max - min)) + 120
|
373
|
+
elsif max == blue
|
374
|
+
hue = 60 * ((red - green) / (max - min)) + 240
|
375
|
+
end
|
376
|
+
|
377
|
+
saturation = (max == 0) ? 0 : (max - min) / max
|
378
|
+
[hue % 360, saturation, max]
|
379
|
+
end
|
380
|
+
|
381
|
+
def inspect
|
382
|
+
"#<Color #{to_s(:css)}>"
|
383
|
+
end
|
384
|
+
|
385
|
+
# Returns the perceived brightness of the provided color on a
|
386
|
+
# scale of 0.0 to 1.0 based on the formula provided. The formulas
|
387
|
+
# available are:
|
388
|
+
#
|
389
|
+
# * <tt>:w3c</tt> - <tt>((r * 299 + g * 587 + b * 114) / 1000 / 255</tt>
|
390
|
+
# * <tt>:standard</tt> - <tt>sqrt(0.241 * r^2 + 0.691 * g^2 + 0.068 * b^2) / 255</tt>
|
391
|
+
def brightness(formula=:w3c)
|
392
|
+
case formula
|
393
|
+
when :standard
|
394
|
+
Math.sqrt(0.241 * r**2 + 0.691 * g**2 + 0.068 * b**2) / 255
|
395
|
+
when :w3c
|
396
|
+
((r * 299 + g * 587 + b * 114) / 255000.0)
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
# Contrast this color with another color using the provided formula. The
|
401
|
+
# available formulas are:
|
402
|
+
#
|
403
|
+
# * <tt>:w3c</tt> - <tt>(max(r1 r2) - min(r1 r2)) + (max(g1 g2) - min(g1 g2)) + (max(b1 b2) - min(b1 b2))</tt>
|
404
|
+
def contrast_with(other_color, formula=:w3c)
|
405
|
+
other_color = Color.from(other_color)
|
406
|
+
case formula
|
407
|
+
when :w3c
|
408
|
+
(([self.r, other_color.r].max - [self.r, other_color.r].min) +
|
409
|
+
([self.g, other_color.g].max - [self.g, other_color.g].min) +
|
410
|
+
([self.b, other_color.b].max - [self.b, other_color.b].min)) / 765.0
|
411
|
+
end
|
412
|
+
end
|
413
|
+
|
414
|
+
# Returns the opposite of the current color.
|
415
|
+
def invert
|
416
|
+
Color.from_rgb(255 - r, 255 - g, 255 - b)
|
417
|
+
end
|
418
|
+
|
419
|
+
# Uses a naive formula to generate a gradient between this color and the given color.
|
420
|
+
# Returns the array of colors that make the gradient, including this color and the
|
421
|
+
# target color. By default will return 10 colors, but this can be changed by supplying
|
422
|
+
# an optional steps parameter.
|
423
|
+
def gradient_to(color, steps = 10)
|
424
|
+
color_to = Colorist::Color.from(color)
|
425
|
+
red = color_to.r - r
|
426
|
+
green = color_to.g - g
|
427
|
+
blue = color_to.b - b
|
428
|
+
|
429
|
+
result = (1..(steps - 3)).to_a.collect do |step|
|
430
|
+
percentage = step.to_f / (steps - 1)
|
431
|
+
Color.from_rgb(r + (red * percentage), g + (green * percentage), b + (blue * percentage))
|
432
|
+
end
|
433
|
+
|
434
|
+
# Add first and last colors to result, avoiding uneccessary calculation and rounding errors
|
435
|
+
|
436
|
+
result.unshift(self.dup)
|
437
|
+
result.push(color.dup)
|
438
|
+
result
|
439
|
+
end
|
440
|
+
|
441
|
+
# Converts the current color to grayscale using the brightness
|
442
|
+
# formula provided. See #brightness for a description of the
|
443
|
+
# available formulas.
|
444
|
+
def to_grayscale(formula=:w3c)
|
445
|
+
b = brightness(formula)
|
446
|
+
Color.from_rgb(255 * b, 255 * b, 255 * b)
|
447
|
+
end
|
448
|
+
|
449
|
+
# Returns an appropriate text color (either black or white) based on
|
450
|
+
# the brightness of this color. The +threshold+ specifies the brightness
|
451
|
+
# cutoff point.
|
452
|
+
def text_color(threshold=0.6, formula=:standard)
|
453
|
+
brightness(formula) > threshold ? Colorist::Color.new(0x000000) : Colorist::Color.new(0xffffff)
|
454
|
+
end
|
455
|
+
|
456
|
+
protected
|
457
|
+
|
458
|
+
def normalize #:nodoc:
|
459
|
+
@r = 255 if @r > 255
|
460
|
+
@g = 255 if @g > 255
|
461
|
+
@b = 255 if @b > 255
|
462
|
+
@r = 0 if @r < 0
|
463
|
+
@g = 0 if @g < 0
|
464
|
+
@b = 0 if @b < 0
|
465
|
+
end
|
466
|
+
end
|
467
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
class Integer
|
2
|
+
# Converts a hexadecimal number into a Color. Must be
|
3
|
+
# the equivalent of the full hexadecimal form (for example,
|
4
|
+
# <tt>0x123456</tt>).
|
5
|
+
def to_color
|
6
|
+
Colorist::Color.new(self)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Float
|
11
|
+
# Converts a number from 0.0 to 1.0 to the grayscale equivalent
|
12
|
+
# of that brightness value. Especially useful for adding percentages
|
13
|
+
# to a color.
|
14
|
+
def to_color
|
15
|
+
Colorist::Color.from_rgb(self * 255, self * 255, self * 255)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class String
|
20
|
+
# Converts a CSS-style color string to a Color. Can be
|
21
|
+
# in the full form (<tt>\#112233</tt>), the abbreviated form
|
22
|
+
# (<tt>\#123</tt>) or a CSS named color (<tt>"black"</tt> or <tt>"maroon"</tt>).
|
23
|
+
def to_color
|
24
|
+
Colorist::Color.from_string(self)
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lorraine
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.2
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Wil Gieseler
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2012-07-24 00:00:00 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: serialport
|
17
|
+
prerelease: false
|
18
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.1.0
|
24
|
+
type: :runtime
|
25
|
+
version_requirements: *id001
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: colorize
|
28
|
+
prerelease: false
|
29
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
type: :runtime
|
36
|
+
version_requirements: *id002
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: faye
|
39
|
+
prerelease: false
|
40
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ">="
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id003
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: thor
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: "0"
|
57
|
+
type: :runtime
|
58
|
+
version_requirements: *id004
|
59
|
+
- !ruby/object:Gem::Dependency
|
60
|
+
name: thin
|
61
|
+
prerelease: false
|
62
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ">="
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: "0"
|
68
|
+
type: :runtime
|
69
|
+
version_requirements: *id005
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: json_pure
|
72
|
+
prerelease: false
|
73
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
type: :runtime
|
80
|
+
version_requirements: *id006
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: httpclient
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: "0"
|
90
|
+
type: :runtime
|
91
|
+
version_requirements: *id007
|
92
|
+
description: How else are you going to communicate with an LED wall?
|
93
|
+
email:
|
94
|
+
- supapuerco@gmail.com
|
95
|
+
executables:
|
96
|
+
- lorraine
|
97
|
+
extensions: []
|
98
|
+
|
99
|
+
extra_rdoc_files: []
|
100
|
+
|
101
|
+
files:
|
102
|
+
- .gitignore
|
103
|
+
- Gemfile
|
104
|
+
- LICENSE
|
105
|
+
- README.md
|
106
|
+
- Rakefile
|
107
|
+
- bin/lorraine
|
108
|
+
- lib/.DS_Store
|
109
|
+
- lib/lorraine.rb
|
110
|
+
- lib/lorraine/command.rb
|
111
|
+
- lib/lorraine/connection.rb
|
112
|
+
- lib/lorraine/image.rb
|
113
|
+
- lib/lorraine/message.rb
|
114
|
+
- lib/lorraine/server.rb
|
115
|
+
- lib/lorraine/test_connection.rb
|
116
|
+
- lib/lorraine/version.rb
|
117
|
+
- lorraine.gemspec
|
118
|
+
- vendor/colorist/colorist.rb
|
119
|
+
- vendor/colorist/colorist/color.rb
|
120
|
+
- vendor/colorist/colorist/core_extensions.rb
|
121
|
+
homepage: ""
|
122
|
+
licenses: []
|
123
|
+
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
|
127
|
+
require_paths:
|
128
|
+
- lib
|
129
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
130
|
+
none: false
|
131
|
+
requirements:
|
132
|
+
- - ">="
|
133
|
+
- !ruby/object:Gem::Version
|
134
|
+
version: "0"
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ">="
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: "0"
|
141
|
+
requirements: []
|
142
|
+
|
143
|
+
rubyforge_project:
|
144
|
+
rubygems_version: 1.8.15
|
145
|
+
signing_key:
|
146
|
+
specification_version: 3
|
147
|
+
summary: How else are you going to communicate with an LED wall?
|
148
|
+
test_files: []
|
149
|
+
|