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 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
+