pixelflut 0.0.13 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46bc6d8430a0a37a766f925558d1279fbf69457f859f9f6286c2fb4a3f3a9e81
4
- data.tar.gz: f634ffe53ec48385c8c9b42f032f3fa0e56d91155cf075a05b2b9c15794d8dbb
3
+ metadata.gz: b29b8ce88df1c1d08de27f9c87fae728d58d25759cbfc88c2f0c62865492f054
4
+ data.tar.gz: 55311c23772975543c15e74741a5bbb452e4a48eb0e4af4d351d28e9ed5cbfa3
5
5
  SHA512:
6
- metadata.gz: 53bb74856603e0d46563b707726cdb8d5d96f5192ebd641c00ebba463e45ba5165536f4b95ea60d28e0468f8735acb32d3439802541791faf9a2dcbe13b94dab
7
- data.tar.gz: 2f26150a3d40045e6030018cbcbf807dcbb1f415f193f156d1c45d8c4eea5e5c6d56e5205d764b701b6d644346d0892042f5fb1cdd9ce0d9cd6ee5ba4fbad099
6
+ metadata.gz: c078c2eb4b3dfe4c4faf5d0c3b9bc652c90d3b602c0166b89bcc5f6ccfe8c01e02e9ade0098d5b951f82beab9ef165a8e0bb9363542ebf93264f73d45985ef7e
7
+ data.tar.gz: 244d2e819a90182daf2883c49a73454e0367dc098a3ed3f50748846efec8605e14f34dff346f347f7df453d977de9e5b1bc1b9bf2eefbaf4bd36a24aea52d094
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # Pixelflut
2
2
 
3
- A Pixelflut server & client tool collection written in Ruby.
3
+ A Pixelflut client written in Ruby.
4
4
 
5
5
  ## Description
6
6
 
7
- Based on the idea of a simple server protocol to collaborate on a shared canvas named [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a Ruby version.
7
+ Based on the idea of a simple server protocol to collaborate on a shared canvas named [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a Ruby version of a client.
8
8
 
9
- This gem is an open experiment to write a fast server and canvas in Ruby. You are welcome to fork or create pull requests to find the fastest solution!
10
-
11
- The gem includes some tools to develop Pixelflut clients and pre-processors.
9
+ This gem is an open experiment. You are welcome to fork or create pull requests to find the fastest solution!
12
10
 
13
11
  ### Installation
14
12
 
@@ -26,76 +24,16 @@ You'll find some help on the command line:
26
24
 
27
25
  ```bash
28
26
  $ pxf
29
- usage: pxf command [options]
30
-
31
- valid commands:
32
- convert Convert given IMAGE file to Pixelflut ASCII format.
33
- generate Execute given generator FILEs.
34
- help Print help for given COMMAND.
35
- send Send given Pixelflut ASCII file to a server.
36
- server Start Pixelflut server.
37
- version Print version information.
38
- ```
27
+ Usage: pxf [options] IMAGE
39
28
 
40
- ### Start a Sserver
29
+ Options:
30
+ --host ADDRESS target host address
31
+ -p, --port NUMBER target port (default 1234)
32
+ -c, --connections COUNT count of connections (default 4)
33
+ -x, --transpose-x X transpose image X pixels
34
+ -y, --transpose-y Y transpose image Y pixels
35
+ -s, --scale FACTOR scale image by FACTOR
41
36
 
42
- Starting the server on default port `1234` and open a drawing screen is quite simple:
43
-
44
- ```bash
45
- $ pxf server
46
- ```
47
-
48
- With these options you can configure the server:
49
-
50
- ```
51
- -b, --bind ADDR bind to given address
52
- -p, --port PORT select port(default: 1234)
53
- -k, --keep-alive set maximum keep-alive time
54
- -r, --read_buffer SIZE set read buffer size (default: 1024)
55
- -w, --width WIDTH set canvas width (default: 800)
56
- -h, --height HEIGHT set canvas height (default: 600)
57
- -f, --[no-]fullscreen run in fullscreen mode
37
+ -h, --help print this help
38
+ -v, --version print version information
58
39
  ```
59
-
60
- ### Convert an Image
61
-
62
- There is a conversion command which can be used to convert a given image to the Pixelflut ASCII text format:
63
-
64
- ```bash
65
- $ pxf convert image.png
66
- ```
67
-
68
- The result can send directly to a server (sample assumes the server runs on localhost port 1234):
69
-
70
- ```bash
71
- $ pxf convert image.png | pxf send
72
- ```
73
-
74
- The converter can help you to resize and positioning the image at the servers canvas. These options are avail:
75
-
76
- ```
77
- -x, --transpose-x X transpose image X pixels
78
- -y, --transpose-y Y transpose image Y pixels
79
- -w, --width WIDTH resize the image to given WIDTH
80
- -h, --height HEIGHT resize the image to given HEIGHT
81
- ```
82
-
83
- It maybe faster to pre-process your images and send them later:
84
-
85
- ```bash
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
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/bin/pxf CHANGED
@@ -1,33 +1,84 @@
1
1
  #!/usr/bin/env ruby
2
2
  # frozen_string_literal: true
3
3
 
4
- def bin_root
5
- File.realdirpath('../', __FILE__).freeze
6
- end
4
+ Process.setproctitle($name = 'pxf')
5
+ $stderr.sync = $stdout.sync = true
6
+
7
+ require 'optparse'
8
+ require_relative '../lib/pixelflut'
7
9
 
8
- def find_commands
9
- Hash[Dir.glob(File.join(bin_root, 'pxf-*')).map!{ |cmd| [File.basename(cmd)[4..-1], cmd] }]
10
+ def err(msg, code = 1)
11
+ $stderr.puts("#{$name}: #{msg}")
12
+ exit(code)
10
13
  end
11
14
 
12
- def err(msg)
13
- $stderr.puts("pxf: #{msg}")
14
- exit 1
15
+ OPTS = Struct
16
+ .new(:host, :port, :count, :x, :y, :scale, :image)
17
+ .new('127.0.0.1', 1234, 4, 0, 0)
18
+
19
+ def parse(args)
20
+ OptionParser.new do |parser|
21
+ parser.summary_indent = ' '
22
+ parser.banner = 'Usage: pxf [options] IMAGE'
23
+ parser.separator(nil)
24
+ parser.separator('Options:')
25
+ parser.on(
26
+ '--host ADDRESS', 'target host address'
27
+ ){ |v| OPTS.host = v }
28
+ parser.on(
29
+ '-p', '--port NUMBER', Integer, 'target port (default 1234)'
30
+ ){ |v| OPTS.port = v }
31
+ parser.on(
32
+ '-c', '--connections COUNT', Integer, 'count of connections (default 4)'
33
+ ){ |v| OPTS.count = v }
34
+ parser.on(
35
+ '-x', '--transpose-x X', Integer, 'transpose image X pixels'
36
+ ){ |v| OPTS.x = v }
37
+ parser.on(
38
+ '-y', '--transpose-y Y', Integer, 'transpose image Y pixels'
39
+ ){ |v| OPTS.y = v }
40
+ parser.on(
41
+ '-s', '--scale FACTOR', OptionParser::DecimalNumeric, 'scale image by FACTOR'
42
+ ){ |v| OPTS.scale = v }
43
+ parser.separator(nil)
44
+ parser.on('-h', '--help', 'print this help') do
45
+ exit(!puts(parser))
46
+ end
47
+ parser.on('-v', '--version', 'print version information') do
48
+ require_relative '../lib/pixelflut/version'
49
+ exit(!puts("pxf-#{Pixelflut::VERSION}"))
50
+ end
51
+ end.parse!(args)
52
+ OPTS.image = args.first or err('image name expected')
53
+ OPTS
54
+ rescue OptionParser::ParseError => e
55
+ err(e)
15
56
  end
16
57
 
17
- def general_help
18
- puts('usage: pxf command [options]', nil, 'valid commands:')
19
- map = find_commands.transform_values!{ |cmd| %x(#{cmd} --short-help) }
20
- cmds = map.keys.sort!
21
- len = cmds.max_by(&:size).size + 3
22
- cmds.each do |cmd|
23
- print cmd.ljust(len)
24
- puts(map[cmd])
58
+ begin
59
+ parse(ARGV)
60
+ addr = Pixelflut::Sender.address(OPTS.host, OPTS.port)
61
+ slices = Pixelflut.as_slices(
62
+ source: OPTS.image,
63
+ count: OPTS.count,
64
+ x: OPTS.x,
65
+ y: OPTS.y,
66
+ scale: OPTS.scale
67
+ )
68
+ slices.size.times do |i|
69
+ next unless fork
70
+ Process.setproctitle($name = format('pxf-%02d', i + 1))
71
+ sender = Pixelflut::Sender.new(addr, slices[i].join)
72
+ slices.clear
73
+ puts "#{$name}: run"
74
+ sender.run
25
75
  end
26
- exit
76
+ rescue SocketError => e
77
+ err(e, 3)
78
+ rescue LoadError => e
79
+ err(e, 4)
80
+ rescue Errno::EPIPE
81
+ err('connection lost', 2)
82
+ rescue Interrupt
83
+ err('interrupted', 130)
27
84
  end
28
-
29
- general_help if ARGV.empty? || ARGV[0] == '--help' || ARGV[0] == '-h'
30
- cmd = ARGV.shift
31
- fname = File.join(bin_root, 'pxf-' + cmd)
32
- err("no such command - #{cmd}") unless File.executable?(fname)
33
- exec(fname, *ARGV)
@@ -1,8 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'pixelflut/image'
4
+ require_relative 'pixelflut/convert'
5
+ require_relative 'pixelflut/sender'
6
+
1
7
  module Pixelflut
2
- LIB_DIR = File.realdirpath('../pixelflut', __FILE__).freeze
3
- autoload :App, File.join(LIB_DIR, 'app.rb')
4
- autoload :Server, File.join(LIB_DIR, 'server.rb')
5
- autoload :Canvas, File.join(LIB_DIR, 'canvas.rb')
6
- autoload :Converter, File.join(LIB_DIR, 'converter.rb')
7
- autoload :VERSION, File.join(LIB_DIR, 'version.rb')
8
+ def self.converted(source, x = 0, y = 0, scale = nil)
9
+ image = Image.new(source)
10
+ image.scale(scale) if scale
11
+ Convert.each_line(image, x, y)
12
+ end
13
+
14
+ def self.as_slices(source:, count: 4, x: 0, y: 0, scale: nil)
15
+ image = Image.new(source)
16
+ image.scale(scale) if scale
17
+ Convert.as_slices(image, x, y, count)
18
+ end
8
19
  end
@@ -0,0 +1,28 @@
1
+ module Pixelflut
2
+ module Convert
3
+ def self.each_line0(image)
4
+ return to_enum(__method__, image) unless block_given?
5
+ image.each_pixel do |x, y, px|
6
+ px = px.to_color(Magick::AllCompliance, true, 8, true)[
7
+ 1, 255 == px.alpha ? 6 : 8
8
+ ]
9
+ yield("PX #{x} #{y} #{px}\n")
10
+ end
11
+ end
12
+
13
+ def self.each_line(image, dx, dy)
14
+ return to_enum(__method__, image, dx, dy) unless block_given?
15
+ image.each_pixel do |x, y, px|
16
+ px = px.to_color(Magick::AllCompliance, true, 8, true)[
17
+ 1, 255 == px.alpha ? 6 : 8
18
+ ]
19
+ yield("PX #{x + dx} #{y + dy} #{px}\n")
20
+ end
21
+ end
22
+
23
+ def self.as_slices(image, dx, dy, count)
24
+ ret = each_line(image, dx, dy).to_a.shuffle!
25
+ ret.each_slice(ret.size / count).to_a
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,32 @@
1
+ require 'rmagick'
2
+
3
+ module Pixelflut
4
+ class Image
5
+ def initialize(file_name)
6
+ @image = Magick::ImageList.new(file_name)[0]
7
+ rescue Magick::ImageMagickError => e
8
+ raise(LoadError, e.message, cause: e)
9
+ end
10
+
11
+ def width
12
+ @image.columns
13
+ end
14
+
15
+ def height
16
+ @image.rows
17
+ end
18
+
19
+ def resize_to(width, height = nil)
20
+ @image.resize_to_fit!(width, height)
21
+ end
22
+
23
+ def scale(factor)
24
+ @image.scale!(factor)
25
+ end
26
+
27
+ def each_pixel
28
+ return to_enum(__method__) unless block_given?
29
+ @image.each_pixel{ |px, x, y| 0 != px.alpha and yield(x, y, px) }
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,53 @@
1
+ require 'socket'
2
+
3
+ module Pixelflut
4
+ class Sender
5
+ def self.address(host, port)
6
+ Addrinfo.tcp(host, port)
7
+ end
8
+
9
+ def initialize(address, data)
10
+ @data = data.freeze
11
+ @addr = Socket.pack_sockaddr_in(address.ip_port, address.ip_address)
12
+ @socket = configure(Socket.new(address.ipv6? ? :INET6 : :INET, :STREAM))
13
+ end
14
+
15
+ def run
16
+ connect
17
+ send(@socket, @data)
18
+ @socket.close
19
+ end
20
+
21
+ private
22
+
23
+ def send(socket, data)
24
+ curr = String.new(data)
25
+ loop do
26
+ written = socket.write(curr)
27
+ curr =
28
+ if (size = curr.bytesize - written) > 0
29
+ curr.byteslice(written, size)
30
+ else
31
+ String.new(data)
32
+ end
33
+ end
34
+ end
35
+
36
+ def connect
37
+ loop do
38
+ (
39
+ :wait_writable == @socket.connect_nonblock(@addr, exception: false)
40
+ ) and break
41
+ end
42
+ loop{ @socket.wait_writable(10) and break }
43
+ end
44
+
45
+ def configure(socket)
46
+ socket.sync = true
47
+ socket.setsockopt(:TCP, :NODELAY, 1)
48
+ socket.setsockopt(:SOCKET, :KEEPALIVE, 0)
49
+ socket.do_not_reverse_lookup = true
50
+ socket
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,3 @@
1
1
  module Pixelflut
2
- VERSION = '0.0.13'.freeze
2
+ VERSION = '0.1.2'.freeze
3
3
  end
@@ -5,22 +5,23 @@ require_relative 'lib/pixelflut/version'
5
5
  GemSpec = Gem::Specification.new do |spec|
6
6
  spec.name = 'pixelflut'
7
7
  spec.version = Pixelflut::VERSION
8
- spec.summary = 'A Pixelflut server & client tool collection written in Ruby.'
8
+ spec.summary = 'A fast Pixelflut client written in Ruby.'
9
9
  spec.description = <<~DESCRIPTION
10
10
  Based on the idea of a simple server protocol to collaborate on a shared canvas named
11
- [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a Ruby version.
11
+ [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a fast Ruby client version.
12
12
  DESCRIPTION
13
13
  spec.author = 'Mike Blumtritt'
14
- spec.email = 'mike.blumtritt@invision.de'
14
+ spec.email = 'mike.blumtritt@pm.me'
15
15
  spec.homepage = 'https://github.com/mblumtritt/pixelflut'
16
16
  spec.metadata = {
17
- 'issue_tracker' => 'https://github.com/mblumtritt/pixelflut/issues'
17
+ 'source_code_uri' => 'https://github.com/mblumtritt/pixelflut',
18
+ 'bug_tracker_uri' => 'https://github.com/mblumtritt/pixelflut/issues'
18
19
  }
19
20
  spec.rubyforge_project = spec.name
20
21
 
21
- spec.add_runtime_dependency 'gosu', '>= 0.13.2'
22
- spec.add_development_dependency 'bundler', '>= 1.16.0'
23
- spec.add_development_dependency 'rake', '>= 12.3.0'
22
+ spec.add_runtime_dependency 'rmagick'
23
+ spec.add_development_dependency 'bundler'
24
+ spec.add_development_dependency 'rake'
24
25
 
25
26
  spec.platform = Gem::Platform::RUBY
26
27
  spec.required_rubygems_version = Gem::Requirement.new('>= 1.3.6')
metadata CHANGED
@@ -1,106 +1,83 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pixelflut
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.13
4
+ version: 0.1.2
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-12-26 00:00:00.000000000 Z
11
+ date: 2019-11-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: gosu
14
+ name: rmagick
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 0.13.2
19
+ version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 0.13.2
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: 1.16.0
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: 1.16.0
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 12.3.0
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 12.3.0
54
+ version: '0'
55
55
  description: |
56
56
  Based on the idea of a simple server protocol to collaborate on a shared canvas named
57
- [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a Ruby version.
58
- email: mike.blumtritt@invision.de
57
+ [Pixel Flut](https://cccgoe.de/wiki/Pixelflut) this gem implements a fast Ruby client version.
58
+ email: mike.blumtritt@pm.me
59
59
  executables:
60
60
  - pxf
61
- - pxf-generate
62
- - pxf-server
63
- - pxf-convert
64
- - pxf-help
65
- - pxf-send
66
- - pxf-version
67
- - pxf-info
68
61
  extensions: []
69
62
  extra_rdoc_files:
70
63
  - README.md
71
64
  files:
72
65
  - ".gitignore"
73
66
  - README.md
74
- - TODO.md
75
67
  - bin/pxf
76
- - bin/pxf-convert
77
- - bin/pxf-generate
78
- - bin/pxf-help
79
- - bin/pxf-info
80
- - bin/pxf-send
81
- - bin/pxf-server
82
- - bin/pxf-version
83
68
  - gems.rb
84
69
  - lib/pixelflut.rb
85
- - lib/pixelflut/app.rb
86
- - lib/pixelflut/canvas.rb
87
- - lib/pixelflut/canvas/base.rb
88
- - lib/pixelflut/canvas/buffered.rb
89
- - lib/pixelflut/canvas/streamed.rb
90
- - lib/pixelflut/client.rb
91
- - lib/pixelflut/client/socket.rb
92
- - lib/pixelflut/converter.rb
93
- - lib/pixelflut/server.rb
94
- - lib/pixelflut/server/configuration.rb
95
- - lib/pixelflut/server/connection.rb
96
- - lib/pixelflut/text_image.rb
70
+ - lib/pixelflut/convert.rb
71
+ - lib/pixelflut/image.rb
72
+ - lib/pixelflut/sender.rb
97
73
  - lib/pixelflut/version.rb
98
74
  - pixelflut.gemspec
99
75
  - rakefile.rb
100
76
  homepage: https://github.com/mblumtritt/pixelflut
101
77
  licenses: []
102
78
  metadata:
103
- issue_tracker: https://github.com/mblumtritt/pixelflut/issues
79
+ source_code_uri: https://github.com/mblumtritt/pixelflut
80
+ bug_tracker_uri: https://github.com/mblumtritt/pixelflut/issues
104
81
  post_install_message:
105
82
  rdoc_options: []
106
83
  require_paths:
@@ -116,8 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
116
93
  - !ruby/object:Gem::Version
117
94
  version: 1.3.6
118
95
  requirements: []
119
- rubygems_version: 3.0.1
96
+ rubygems_version: 3.0.6
120
97
  signing_key:
121
98
  specification_version: 4
122
- summary: A Pixelflut server & client tool collection written in Ruby.
99
+ summary: A fast Pixelflut client written in Ruby.
123
100
  test_files: []