lorraine 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in lorraine.gemspec
4
+ gemspec
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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
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
@@ -0,0 +1,3 @@
1
+ module Lorraine
2
+ VERSION = "0.0.2"
3
+ end
data/lib/lorraine.rb ADDED
@@ -0,0 +1,10 @@
1
+ require "lorraine/version"
2
+ require "lorraine/message"
3
+ require "lorraine/connection"
4
+ require "lorraine/image"
5
+ require "lorraine/server"
6
+ require_relative "../vendor/colorist/colorist"
7
+
8
+ module Lorraine
9
+ # Your code goes here...
10
+ end
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
@@ -0,0 +1,2 @@
1
+ require_relative 'colorist/color'
2
+ require_relative 'colorist/core_extensions'
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
+