pixelflut 0.0.8 → 0.0.10

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 62efcd05717e96f42f60e21cbc7a569277fed6bb2e56d24d57d3fe11ff37cb1b
4
- data.tar.gz: 7c8fd4eb2542668dd25abd6b5cccc12818c790cf111f1b2a8e38bbda44527f4d
3
+ metadata.gz: 53fa839b0f1e655d481296ff80e16c50bcb14cb8b65002508a6cbdb6cf602d18
4
+ data.tar.gz: dc278f90adf043c2acfa484ea1beaadb04c12dd70e18e7ed2daa88db69ea1f28
5
5
  SHA512:
6
- metadata.gz: 94241373ff17f9e0cbbc1b1b2e51f55db1da4beb032c18f4985590e6c50a1ba1bd9313fc7858caa9be76f84593b8fc7374337226afc72641a1c40f767b7fa66a
7
- data.tar.gz: 00f6b49748585411187665ef9c2c3a519ca77641c7a3c7aa281b65f37a0c5b8fea7e53df82b49b58cc88401b72698f551b6752915c9d7177c9de5d2b1be9f3f3
6
+ metadata.gz: 1bbf4d13ed7bc852d20000103456680ececcfc4286225b0fb7be74afce25ad89dff6fdcb5e89120737c599645591400c5761e4c0172e632c742599975ee5a5da
7
+ data.tar.gz: 53368ac74848597f441952344f40e30744517da98db162405d7837f461d15096a66a37e0291763672d60119a8fe1d8266ee91c2ca7764bd7a2eef71620b3ec95
data/README.md CHANGED
@@ -29,14 +29,15 @@ $ pxf
29
29
  usage: pxf command [options]
30
30
 
31
31
  valid commands:
32
- convert Convert given IMAGE file to Pixelflut format.
32
+ convert Convert given IMAGE file to Pixelflut ASCII format.
33
33
  generate Execute given generator FILEs.
34
34
  help Print help for given COMMAND.
35
+ send Send given Pixelflut ASCII file to a server.
35
36
  server Start Pixelflut server.
36
37
  version Print version information.
37
38
  ```
38
39
 
39
- ### Start a server
40
+ ### Start a Sserver
40
41
 
41
42
  Starting the server on default port `1234` and open a drawing screen is quite simple:
42
43
 
@@ -56,21 +57,21 @@ With these options you can configure the server:
56
57
  -f, --[no-]fullscreen run in fullscreen mode
57
58
  ```
58
59
 
59
- ### Convert an image
60
+ ### Convert an Image
60
61
 
61
- There is a conversion command which can be used to convert a given image to the Pixelflut text format:
62
+ There is a conversion command which can be used to convert a given image to the Pixelflut ASCII text format:
62
63
 
63
64
  ```bash
64
65
  $ pxf convert image.png
65
66
  ```
66
67
 
67
- The result can directly send to a running server (sample assumes the server runs on localhost port 1234):
68
+ The result can send directly to a server (sample assumes the server runs on localhost port 1234):
68
69
 
69
70
  ```bash
70
- $ pxf convert image.png | netcat localhost 1234
71
+ $ pxf convert image.png | pxf send
71
72
  ```
72
73
 
73
- The converter can help you to resize and positioning the image and the servers canvas. These options are avail:
74
+ The converter can help you to resize and positioning the image at the servers canvas. These options are avail:
74
75
 
75
76
  ```
76
77
  -x, --transpose-x X transpose image X pixels
@@ -79,9 +80,22 @@ The converter can help you to resize and positioning the image and the servers c
79
80
  -h, --height HEIGHT resize the image to given HEIGHT
80
81
  ```
81
82
 
82
- It maybe faster to pre-process your image(s) and send later:
83
+ It maybe faster to pre-process your images and send them later:
83
84
 
84
85
  ```bash
85
- $ pxf convert -x 50 -y 100 --width 640 image.png > image.px
86
- $ cat image.px | netcat localhost 1234
86
+ $ pxf convert -x 50 -y 100 --width 100 image1.png > image1.px
87
+ $ pxf convert -x 150 --width 2100 image2.png > image2.px
88
+ $ pxf send -h pixel_host image1.px image2.px
87
89
  ```
90
+
91
+ ### Send Pixelflut ASCII Text
92
+
93
+ The `pxf send` command can be used to send given Pixelflut ASCII text files to a server. It uses several connections at the same time to fasten the transmission.
94
+
95
+ Next sample will send the Pixelflut ASCII text file named `pixels.px` to the server on port 1234 at address `pixelhost` using 12 connections:
96
+
97
+ ```bash
98
+ $ pxf send -h pixelhost -p 1234 -c 12 pixels.px
99
+ ```
100
+
101
+ If no file is given the STDIN will be read and send afterwards to the server.
data/TODO.md CHANGED
@@ -7,3 +7,4 @@
7
7
  - [ ] extend `pxf generate`
8
8
  - [x] add a pre-processor for images
9
9
  - [ ] mention the Gosu gem in the README
10
+ - [ ] add `pxf info` command to get some server information
@@ -8,8 +8,8 @@ def options(cfg)
8
8
  opts.banner = 'usage: pxf convert [options] IMAGE'
9
9
  opts.separator(nil)
10
10
  opts.separator('valid options:')
11
- opts.on('-x', '--transpose-x X', Integer, 'transpose image X pixels'){ |v| cfg[:x_offset] = v }
12
- opts.on('-y', '--transpose-y Y', Integer, 'transpose image Y pixels'){ |v| cfg[:y_offset] = v }
11
+ opts.on('-x', '--transpose-x X', Integer, 'transpose image X pixels'){ |v| cfg[:offset_x] = v }
12
+ opts.on('-y', '--transpose-y Y', Integer, 'transpose image Y pixels'){ |v| cfg[:offset_y] = v }
13
13
  opts.on('-w', '--width WIDTH', Integer, 'resize the image to given WIDTH'){ |v| cfg[:width] = v }
14
14
  opts.on('-h', '--height HEIGHT', Integer, 'resize the image to given HEIGHT'){ |v| cfg[:height] = v }
15
15
  end
@@ -27,25 +27,26 @@ def err(msg, code = 1)
27
27
  end
28
28
 
29
29
  def create_options
30
- cfg = {}
31
- options(cfg).parse!
32
- cfg
30
+ {}.tap{ |cfg| options(cfg).parse! }
33
31
  rescue OptionParser::ParseError => e
34
32
  err(e)
35
33
  end
36
34
 
37
35
  help(false) if '--help' == ARGV[0]
38
36
  help(true) if '--short-help' == ARGV[0]
39
- err('too few arguments') if ARGV.empty?
40
37
  options = create_options
38
+ err('too few arguments') if ARGV.empty?
41
39
  require File.realdirpath('../../lib/pixelflut/converter.rb', __FILE__)
40
+ err('unable to load library - RMagick') unless Pixelflut::Converter::AVAIL
41
+ require File.realdirpath('../../lib/pixelflut/canvas/streamed.rb', __FILE__)
42
42
  begin
43
+ canvas = Pixelflut::Canvas::Streamed.new($stdout)
44
+ canvas.offset_x = options[:offset_x] if options[:offset_x]
45
+ canvas.offset_y = options[:offset_y] if options[:offset_y]
43
46
  ARGV.each do |file_name|
44
47
  cvt = Pixelflut::Converter.new(file_name)
45
- cvt.x_offset = options[:x_offset] if options[:x_offset]
46
- cvt.y_offset = options[:y_offset] if options[:y_offset]
47
48
  cvt.resize_to(options[:width], options[:height]) if options[:width]
48
- cvt.each_line{ |line| puts(line) }
49
+ cvt.draw(canvas)
49
50
  end
50
51
  rescue Pixelflut::Converter::Error => e
51
52
  err(e.message, 2)
@@ -4,6 +4,7 @@
4
4
  def help(short)
5
5
  puts('usage: pxf help COMMAND', nil) unless short
6
6
  puts('Print help for given COMMAND.')
7
+ exit
7
8
  end
8
9
 
9
10
  def err(msg)
@@ -11,17 +12,12 @@ def err(msg)
11
12
  exit(1)
12
13
  end
13
14
 
14
- case ARGV[0]
15
- when '--help'
16
- help(false)
17
- when '--short-help'
18
- help(true)
19
- else
20
- root = File.realdirpath('../', __FILE__).freeze
21
- exec(File.join(root, 'pxf')) if ARGV.empty?
22
- ARGV.each do |cmd|
23
- fname = File.join(root, 'pxf-' + cmd)
24
- err("no such command - #{cmd}") unless File.executable?(fname)
25
- system(fname, '--help')
26
- end
15
+ help(false) if ARGV[0] == '--help'
16
+ help(true) if ARGV[0] == '--short-help'
17
+ root = File.realdirpath('../', __FILE__).freeze
18
+ exec(File.join(root, 'pxf')) if ARGV.empty?
19
+ ARGV.each do |cmd|
20
+ fname = File.join(root, 'pxf-' + cmd)
21
+ err("no such command - #{cmd}") unless File.executable?(fname)
22
+ system(fname, '--help')
27
23
  end
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ def options(cfg)
5
+ require 'optparse'
6
+ OptionParser.new do |opts|
7
+ opts.summary_indent = ' '
8
+ opts.banner = 'usage: pxf send [options] FILE'
9
+ opts.separator(nil)
10
+ opts.separator('valid options:')
11
+ opts.on('-h', '--host HOST', String, 'target host name (default localhost)'){ |v| cfg[:host] = v }
12
+ opts.on('-p', '--port PORT', Integer, 'target port (default 1234)'){ |v| cfg[:port] = v }
13
+ opts.on('-c', '--connections COUNT', Integer, 'count of connections (default 8)'){ |v| cfg[:count] = v }
14
+ end
15
+ end
16
+
17
+ def help(short)
18
+ puts(options(nil), nil) unless short
19
+ puts('Send given Pixelflut ASCII file to a server.')
20
+ exit
21
+ end
22
+
23
+ def err(msg, code = 1)
24
+ $stderr.puts("pxf: #{msg}")
25
+ exit(code)
26
+ end
27
+
28
+ def create_options
29
+ {port: 1234, count: 8}.tap{ |cfg| options(cfg).parse! }
30
+ rescue OptionParser::ParseError => e
31
+ err(e)
32
+ end
33
+
34
+ help(false) if '--help' == ARGV[0]
35
+ help(true) if '--short-help' == ARGV[0]
36
+ options = create_options
37
+ require File.realdirpath('../../lib/pixelflut/client.rb', __FILE__)
38
+ begin
39
+ Pixelflut::Client.new(options[:host], options[:port], ARGF.readlines, options[:count]).run
40
+ rescue SystemCallError => e
41
+ err(e.message, 2)
42
+ rescue Interrupt
43
+ exit
44
+ end
@@ -3,5 +3,6 @@ module Pixelflut
3
3
  autoload :App, File.join(LibDir, 'app.rb')
4
4
  autoload :Server, File.join(LibDir, 'server.rb')
5
5
  autoload :Canvas, File.join(LibDir, 'canvas.rb')
6
+ autoload :Converter, File.join(LibDir, 'converter.rb')
6
7
  autoload :VERSION, File.join(LibDir, 'version.rb')
7
8
  end
@@ -10,13 +10,11 @@ module Pixelflut
10
10
  end
11
11
 
12
12
  def each(&block)
13
- return to_enum(__method__) unless block
14
- @lines.each(&block)
15
- yield "QUIT\n"
13
+ block ? @lines.each(&block) : to_enum(__method__)
16
14
  end
17
15
 
18
16
  def to_s
19
- @lines.join + "QUIT\n"
17
+ @lines.join
20
18
  end
21
19
 
22
20
  private
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'client/socket'
4
+
5
+ module Pixelflut
6
+ class Client
7
+ def initialize(host, port, data, socket_count)
8
+ @sockets = create_sockets(Addrinfo.tcp(host, port), sliced(data, socket_count))
9
+ end
10
+
11
+ def run
12
+ loop{ break if call }
13
+ end
14
+
15
+ def call
16
+ @sockets.size == @sockets.count do |socket|
17
+ socket.call
18
+ socket.state == :closed
19
+ end
20
+ end
21
+
22
+ private
23
+
24
+ def sliced(data, count)
25
+ data = data.split("\n") if data.is_a?(String)
26
+ data = data.each_slice(data.size / count).to_a
27
+ data[-2] += data.pop unless (data.size % count).zero?
28
+ data.map!(&:join)
29
+ end
30
+
31
+ def create_sockets(address, slices)
32
+ slices.map{ |data| Socket.new(address, data) }
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'socket'
4
+
5
+ module Pixelflut
6
+ class Client
7
+ class Socket < ::Socket
8
+ attr_reader :state
9
+
10
+ def initialize(address, data)
11
+ super(address.ipv6? ? :INET6 : :INET, :STREAM)
12
+ configure
13
+ @addr = ::Socket.pack_sockaddr_in(address.ip_port, address.ip_address)
14
+ @data = data
15
+ @size = data.bytesize
16
+ @state = :not_connected
17
+ end
18
+
19
+ def call
20
+ case @state
21
+ when :not_connected
22
+ do_connect
23
+ when :wait_connect
24
+ do_wait_for_connect
25
+ when :write
26
+ do_write
27
+ else
28
+ close
29
+ @state = :closed
30
+ end
31
+ end
32
+
33
+ private
34
+
35
+ def do_connect
36
+ @state = :wait_writable === connect_nonblock(@addr, exception: false) ? :wait_connect : :write
37
+ end
38
+
39
+ def do_wait_for_connect
40
+ @state = :write unless wait_writable(0.1).nil?
41
+ end
42
+
43
+ def do_write
44
+ written = write_nonblock(@data, exception: false)
45
+ return if Symbol === written
46
+ @size -= written
47
+ return @state = :write_finished if @size <= 0
48
+ @data = @data.byteslice(written, @data.bytesize - written)
49
+ end
50
+
51
+ def configure
52
+ self.sync = true
53
+ setsockopt(:TCP, :NODELAY, 1)
54
+ setsockopt(:SOCKET, :KEEPALIVE, 0)
55
+ self.do_not_reverse_lookup = true
56
+ end
57
+ end
58
+ end
59
+ end
@@ -3,50 +3,44 @@
3
3
  module Pixelflut
4
4
  class Converter
5
5
  Error = Class.new(RuntimeError)
6
+ end
6
7
 
7
- attr_accessor :x_offset, :y_offset
8
+ begin
9
+ require 'rmagick'
8
10
 
9
- def initialize(file_name)
10
- load_rmagick
11
- @images = load_image(file_name)
12
- @x_offset = @y_offset = 0
13
- end
11
+ class Converter
12
+ AVAIL = true
14
13
 
15
- def resize_to(width, height = nil)
16
- @images.each{ |image| image.resize_to_fit!(width, height) }
17
- end
14
+ def initialize(file_name)
15
+ @images = load_images(file_name)
16
+ end
18
17
 
19
- def each_pixel
20
- return to_enum(__method__) unless block_given?
21
- @images.each do |image|
22
- image.each_pixel do |color, x, y|
23
- yield(
24
- x + @x_offset,
25
- y + @y_offset,
26
- color.to_color(Magick::AllCompliance, true, 8, true)[1, 8]
27
- ) unless 0xffff == color.opacity
28
- end
18
+ def resize_to(width, height = nil)
19
+ @images.each{ |image| image.resize_to_fit!(width, height) }
29
20
  end
30
- end
31
21
 
32
- def each_line
33
- return to_enum(__method__) unless block_given?
34
- each_pixel{ |x, y, rgba| yield "PX #{x} #{y} #{rgba}" }
35
- end
22
+ def each_pixel
23
+ return to_enum(__method__) unless block_given?
24
+ @images.each do |image|
25
+ image.each_pixel do |color, x, y|
26
+ yield(x, y, color.to_color(Magick::AllCompliance, true, 8, true)[1, 8]) unless 0xffff == color.opacity
27
+ end
28
+ end
29
+ end
36
30
 
37
- private
31
+ def draw(canvas)
32
+ each_pixel{ |x, y, rgba| canvas[x, y] = rgba }
33
+ end
38
34
 
39
- def load_image(file_name)
40
- Magick::ImageList.new(file_name)
41
- rescue Magick::ImageMagickError => e
42
- raise(Error, e.message)
43
- end
35
+ private
44
36
 
45
- def load_rmagick
46
- require 'rmagick'
47
- rescue LoadError
48
- raise(Error, 'unable to load gem - "RMagick" not installed')
37
+ def load_images(file_name)
38
+ Magick::ImageList.new(file_name)
39
+ rescue Magick::ImageMagickError => e
40
+ raise(Error, e.message)
41
+ end
49
42
  end
50
-
43
+ rescue LoadError
44
+ Converter::AVAIL = false
51
45
  end
52
46
  end
@@ -1,5 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'socket'
4
+
3
5
  module Pixelflut
4
6
  class Server
5
7
  class Connection
@@ -1,3 +1,3 @@
1
1
  module Pixelflut
2
- VERSION = '0.0.8'.freeze
2
+ VERSION = '0.0.10'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pixelflut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.8
4
+ version: 0.0.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mike Blumtritt
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-06 00:00:00.000000000 Z
11
+ date: 2018-03-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: gosu
@@ -62,6 +62,7 @@ executables:
62
62
  - pxf-server
63
63
  - pxf-convert
64
64
  - pxf-help
65
+ - pxf-send
65
66
  - pxf-version
66
67
  extensions: []
67
68
  extra_rdoc_files:
@@ -74,6 +75,7 @@ files:
74
75
  - bin/pxf-convert
75
76
  - bin/pxf-generate
76
77
  - bin/pxf-help
78
+ - bin/pxf-send
77
79
  - bin/pxf-server
78
80
  - bin/pxf-version
79
81
  - gems.rb
@@ -84,6 +86,8 @@ files:
84
86
  - lib/pixelflut/canvas/buffered.rb
85
87
  - lib/pixelflut/canvas/color.rb
86
88
  - lib/pixelflut/canvas/streamed.rb
89
+ - lib/pixelflut/client.rb
90
+ - lib/pixelflut/client/socket.rb
87
91
  - lib/pixelflut/converter.rb
88
92
  - lib/pixelflut/server.rb
89
93
  - lib/pixelflut/server/configuration.rb