pixelflut 0.0.8 → 0.0.10

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