pixelflut 0.2.1 → 0.2.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/pxf +136 -53
- data/lib/pixelflut/image.rb +3 -1
- data/lib/pixelflut/sender.rb +3 -1
- data/lib/pixelflut/version.rb +1 -1
- data/lib/pixelflut.rb +12 -9
- metadata +3 -49
- data/.gitignore +0 -3
- data/gems.rb +0 -3
- data/pixelflut.gemspec +0 -34
- data/rakefile.rb +0 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: accec3b9c3471899c3d8f9b9ff5b1e2f8f60506aa674acc9ff5e76dd8411ad15
|
4
|
+
data.tar.gz: ef229296c199b0e12dcd6f2f7a3c48a265c7d6dae9757b1518e299f117dfa01f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8634a2c74929588c18e9c1c7b391f0557811fcf342c7d1297511ab78ae1318fff00c49a4e398c99c6c7b576cfeafd9589543297ce5d1bca7a862a77434d9fac2
|
7
|
+
data.tar.gz: f7dbf586cf87531e11eca5938c3807cbd1a92d7881c21bde15d29b9f3b1301069b4c47de9cec7ae87a3b59049aded33169109f07a70d80f4d503e3a55c73b820
|
data/bin/pxf
CHANGED
@@ -1,69 +1,152 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
4
|
+
$stdout.sync = $stderr.sync = true
|
5
|
+
Process.setproctitle($name = 'pxf')
|
6
|
+
|
7
|
+
if ARGV.index('-h') || ARGV.index('--help')
|
8
|
+
puts <<~HELP
|
9
|
+
Usage: #{$name} <image> [options]
|
10
|
+
|
11
|
+
Options:
|
12
|
+
--host <address> target host address
|
13
|
+
-p, --port <port> target port (default 1234)
|
14
|
+
-c, --connections <count> count of connections (default 4)
|
15
|
+
-b, --bytes <bytes> send junks of <bytes> size
|
16
|
+
-x, --transpose-x <x> transpose image <x> pixels
|
17
|
+
-y, --transpose-y <y> transpose image <y> pixels
|
18
|
+
-s, --scale <scale> scale image by factor
|
19
|
+
-m, --pixel <mode> select pixel coding (RGBX | RGBA | RGB)
|
20
|
+
-h, --help print this help
|
21
|
+
HELP
|
22
|
+
exit
|
23
|
+
end
|
24
|
+
|
25
|
+
def error(msg, code: 1)
|
26
|
+
$stderr.puts("#{$name}-error: #{msg}")
|
27
|
+
exit(code)
|
28
|
+
end
|
29
|
+
|
30
|
+
error('Argument missing') if ARGV.empty?
|
31
|
+
|
32
|
+
Configuration =
|
33
|
+
Class
|
34
|
+
.new do
|
35
|
+
attr_reader :image
|
36
|
+
attr_reader :num_connections, :bytes
|
37
|
+
attr_reader :trans_x, :trans_y, :scale, :mode
|
38
|
+
|
39
|
+
def initialize
|
40
|
+
@address = '127.0.0.1'
|
41
|
+
@port = 1234
|
42
|
+
@num_connections = 4
|
43
|
+
@bytes = 0
|
44
|
+
@trans_x = 0
|
45
|
+
@trans_y = 0
|
46
|
+
@mode = :rgbx
|
47
|
+
end
|
48
|
+
|
49
|
+
def parse!(argv)
|
50
|
+
argv = Array.new(argv)
|
51
|
+
until argv.empty?
|
52
|
+
case arg = argv.shift
|
53
|
+
when '--host'
|
54
|
+
@address = as_str(argv.shift, 'host')
|
55
|
+
when '-p', '--port'
|
56
|
+
@port = as_uint(argv.shift, 'port')
|
57
|
+
when '-c', '--connections'
|
58
|
+
@num_connections = as_uint(argv.shift, 'connections')
|
59
|
+
when '-b', '--bytes'
|
60
|
+
@bytes = as_uint(argv.shift, 'bytes')
|
61
|
+
when '-x', '--transpose-x'
|
62
|
+
@trans_x = argv.shift.to_i
|
63
|
+
when '-y', '--transpose-y'
|
64
|
+
@trans_y = argv.shift.to_i
|
65
|
+
when '-s', '--scale'
|
66
|
+
@scale = as_float(argv.shift, 'scale')
|
67
|
+
when '-m', '--pixel'
|
68
|
+
@mode = as_mode(argv.shift, 'mode')
|
69
|
+
else
|
70
|
+
raise(ArgumentError, "Invalid option - #{arg}") if @image
|
71
|
+
@image = arg
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def address
|
77
|
+
Pixelflut::Sender.address(@address, @port)
|
78
|
+
end
|
79
|
+
|
80
|
+
def options
|
81
|
+
{ source: @image, x: @trans_x, y: @trans_y, scale: @scale, mode: @mode }
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def invalid(value, name)
|
87
|
+
raise(ArgumentError, "Value for #{name} missing") if value.nil?
|
88
|
+
raise(ArgumentError, "Invalid value for #{name} - '#{value}'")
|
89
|
+
end
|
90
|
+
|
91
|
+
def as_uint(value, name)
|
92
|
+
ret = value.to_i
|
93
|
+
ret.positive? ? ret : invalid(value, name)
|
94
|
+
end
|
95
|
+
|
96
|
+
def as_str(value, name)
|
97
|
+
value.nil? || value.empty? ? invalid(value, name) : value
|
98
|
+
end
|
99
|
+
|
100
|
+
def as_float(value, name)
|
101
|
+
ret = value.to_f
|
102
|
+
ret.positive? ? ret : invalid(value, name)
|
103
|
+
end
|
104
|
+
|
105
|
+
def as_mode(value, name)
|
106
|
+
case value.downcase
|
107
|
+
when 'rgbx'
|
108
|
+
:rgbx
|
109
|
+
when 'rgba'
|
110
|
+
:rgba
|
111
|
+
when 'rgb'
|
112
|
+
:rgb
|
113
|
+
else
|
114
|
+
invalid(value, name)
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
118
|
+
.new
|
119
|
+
|
120
|
+
def create_junks
|
121
|
+
lines = Pixelflut.convert(**Configuration.options)
|
122
|
+
if Configuration.bytes.zero?
|
123
|
+
return Pixelflut.slices(lines, count: Configuration.num_connections)
|
124
|
+
end
|
125
|
+
Pixelflut.junks(lines, bytes: Configuration.bytes)
|
14
126
|
end
|
15
127
|
|
16
|
-
|
17
|
-
|
128
|
+
begin
|
129
|
+
Configuration.parse!(ARGV)
|
130
|
+
require_relative('../lib/pixelflut')
|
131
|
+
data = create_junks
|
132
|
+
error("Too many subprocesses - #{data.size}") if data.size > 256
|
18
133
|
print("spawn #{data.size}")
|
19
134
|
data.size.times do |i|
|
20
135
|
next unless fork
|
21
|
-
Process.setproctitle(name
|
136
|
+
Process.setproctitle($name = format("#{$name}-%02d", i + 1))
|
22
137
|
data = data[i].join
|
23
138
|
GC.start
|
24
139
|
GC.disable
|
25
|
-
Pixelflut::Sender.send(
|
140
|
+
Pixelflut::Sender.send(Configuration.address, data) { print('.') }
|
26
141
|
end
|
27
|
-
rescue
|
28
|
-
error(
|
142
|
+
rescue ArgumentError => e
|
143
|
+
error(e)
|
29
144
|
rescue LoadError => e
|
30
|
-
error(
|
145
|
+
error(e, code: 4)
|
31
146
|
rescue Errno::ECONNREFUSED
|
32
|
-
error(
|
147
|
+
error('unable to connect', code: 2)
|
33
148
|
rescue Errno::EPIPE
|
34
|
-
error(
|
35
|
-
|
36
|
-
|
37
|
-
def create_junks(opts)
|
38
|
-
lines = Pixelflut.convert(**opts.to_h)
|
39
|
-
return Pixelflut.slices(lines, count: opts.count) if opts.bytes.zero?
|
40
|
-
Pixelflut.junks(lines, bytes: opts.bytes)
|
41
|
-
end
|
42
|
-
|
43
|
-
before do
|
44
|
-
$stderr.sync = $stdout.sync = true
|
45
|
-
Process.setproctitle(name)
|
46
|
-
require_relative('../lib/pixelflut')
|
47
|
-
end
|
48
|
-
|
49
|
-
parse_argv do |args|
|
50
|
-
Struct.new(:address, :count, :bytes, :x, :y, :mode, :scale, :source) do
|
51
|
-
def to_h
|
52
|
-
{ source: source, x: x, y: y, scale: scale, mode: mode }
|
53
|
-
end
|
54
|
-
end.new(
|
55
|
-
Pixelflut::Sender.address(
|
56
|
-
args['ADDRESS'] || '127.0.0.1',
|
57
|
-
(args['PORT'] || 1234).to_i
|
58
|
-
),
|
59
|
-
(args['CONN'] || 4).to_i,
|
60
|
-
args['BYTES'].to_i,
|
61
|
-
args['X'].to_i,
|
62
|
-
args['Y'].to_i,
|
63
|
-
{ 'RGBA' => :rgba, 'RGB' => :rgb }[args['MODE']] || :rgbx,
|
64
|
-
args.key?('SCALE') ? args['SCALE'].to_f : nil,
|
65
|
-
args['IMAGE']
|
66
|
-
)
|
149
|
+
error('connection lost', code: 2)
|
150
|
+
rescue SocketError => e
|
151
|
+
error(e, code: 3)
|
67
152
|
end
|
68
|
-
|
69
|
-
BEGIN { require('mini-cli') and include(MiniCli) }
|
data/lib/pixelflut/image.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rmagick'
|
2
4
|
|
3
5
|
module Pixelflut
|
4
6
|
class Image
|
5
7
|
def initialize(file_name)
|
6
|
-
@image = Magick::ImageList.new(file_name)
|
8
|
+
@image = Magick::ImageList.new(file_name).first
|
7
9
|
rescue Magick::ImageMagickError => e
|
8
10
|
raise(LoadError, e.message, cause: e)
|
9
11
|
end
|
data/lib/pixelflut/sender.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'socket'
|
2
4
|
|
3
5
|
module Pixelflut
|
@@ -16,7 +18,7 @@ module Pixelflut
|
|
16
18
|
Socket
|
17
19
|
.new(address.ipv6? ? :INET6 : :INET, :STREAM)
|
18
20
|
.tap do |socket|
|
19
|
-
socket.sync =
|
21
|
+
socket.sync = true
|
20
22
|
socket.setsockopt(:TCP, :NODELAY, 0)
|
21
23
|
socket.setsockopt(:SOCKET, :KEEPALIVE, 0)
|
22
24
|
socket.do_not_reverse_lookup = true
|
data/lib/pixelflut/version.rb
CHANGED
data/lib/pixelflut.rb
CHANGED
@@ -10,9 +10,11 @@ module Pixelflut
|
|
10
10
|
end
|
11
11
|
|
12
12
|
def slices(lines, count: 4)
|
13
|
-
Array
|
14
|
-
|
15
|
-
|
13
|
+
Array
|
14
|
+
.new(count) { [] }
|
15
|
+
.tap do |ret|
|
16
|
+
lines.each_with_index { |line, idx| ret[idx % count] << line }
|
17
|
+
end
|
16
18
|
end
|
17
19
|
|
18
20
|
def junks(lines, bytes:)
|
@@ -24,14 +26,15 @@ module Pixelflut
|
|
24
26
|
end
|
25
27
|
ret
|
26
28
|
end
|
27
|
-
alias packages junks # backward compatibility
|
28
29
|
|
29
30
|
private
|
30
31
|
|
31
32
|
def _convert(image, dx, dy)
|
32
|
-
image
|
33
|
-
|
34
|
-
|
33
|
+
image
|
34
|
+
.each_pixel
|
35
|
+
.to_a
|
36
|
+
.map! { |x, y, px| "PX #{x + dx} #{y + dy} #{yield(px)}\n" }
|
37
|
+
.shuffle!
|
35
38
|
end
|
36
39
|
|
37
40
|
def as_image(source, scale)
|
@@ -41,9 +44,9 @@ module Pixelflut
|
|
41
44
|
def as_cvt(mode)
|
42
45
|
case mode
|
43
46
|
when :rgb
|
44
|
-
|
47
|
+
->(px) { px.to_color(Magick::AllCompliance, false, 8, true)[1, 6] }
|
45
48
|
when :rgba
|
46
|
-
|
49
|
+
->(px) { px.to_color(Magick::AllCompliance, true, 8, true)[1, 8] }
|
47
50
|
else
|
48
51
|
lambda do |px|
|
49
52
|
px.to_color(Magick::AllCompliance, false, 8, true)[
|
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.2.
|
4
|
+
version: 0.2.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:
|
11
|
+
date: 2022-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rmagick
|
@@ -24,48 +24,6 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: mini-cli
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 0.4.0
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: 0.4.0
|
41
|
-
- !ruby/object:Gem::Dependency
|
42
|
-
name: bundler
|
43
|
-
requirement: !ruby/object:Gem::Requirement
|
44
|
-
requirements:
|
45
|
-
- - ">="
|
46
|
-
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
48
|
-
type: :development
|
49
|
-
prerelease: false
|
50
|
-
version_requirements: !ruby/object:Gem::Requirement
|
51
|
-
requirements:
|
52
|
-
- - ">="
|
53
|
-
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
55
|
-
- !ruby/object:Gem::Dependency
|
56
|
-
name: rake
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
58
|
-
requirements:
|
59
|
-
- - ">="
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
62
|
-
type: :development
|
63
|
-
prerelease: false
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
65
|
-
requirements:
|
66
|
-
- - ">="
|
67
|
-
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
69
27
|
description: |
|
70
28
|
Based on the idea of a simple server protocol to collaborate on a shared
|
71
29
|
canvas named [Pixelflut](https://cccgoe.de/wiki/Pixelflut) this gem
|
@@ -78,17 +36,13 @@ extensions: []
|
|
78
36
|
extra_rdoc_files:
|
79
37
|
- README.md
|
80
38
|
files:
|
81
|
-
- ".gitignore"
|
82
39
|
- README.md
|
83
40
|
- bin/pxf
|
84
41
|
- bin/pxf-info
|
85
|
-
- gems.rb
|
86
42
|
- lib/pixelflut.rb
|
87
43
|
- lib/pixelflut/image.rb
|
88
44
|
- lib/pixelflut/sender.rb
|
89
45
|
- lib/pixelflut/version.rb
|
90
|
-
- pixelflut.gemspec
|
91
|
-
- rakefile.rb
|
92
46
|
homepage: https://github.com/mblumtritt/pixelflut
|
93
47
|
licenses: []
|
94
48
|
metadata:
|
@@ -109,7 +63,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
109
63
|
- !ruby/object:Gem::Version
|
110
64
|
version: '0'
|
111
65
|
requirements: []
|
112
|
-
rubygems_version: 3.
|
66
|
+
rubygems_version: 3.3.7
|
113
67
|
signing_key:
|
114
68
|
specification_version: 4
|
115
69
|
summary: A fast Pixelflut client written in Ruby.
|
data/.gitignore
DELETED
data/gems.rb
DELETED
data/pixelflut.gemspec
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'lib/pixelflut/version'
|
4
|
-
|
5
|
-
Gem::Specification.new do |spec|
|
6
|
-
spec.name = 'pixelflut'
|
7
|
-
spec.version = Pixelflut::VERSION
|
8
|
-
spec.author = 'Mike Blumtritt'
|
9
|
-
|
10
|
-
spec.required_ruby_version = '>= 2.7.2'
|
11
|
-
|
12
|
-
spec.summary = 'A fast Pixelflut client written in Ruby.'
|
13
|
-
spec.description = <<~DESCRIPTION
|
14
|
-
Based on the idea of a simple server protocol to collaborate on a shared
|
15
|
-
canvas named [Pixelflut](https://cccgoe.de/wiki/Pixelflut) this gem
|
16
|
-
implements a fast Ruby client version.
|
17
|
-
DESCRIPTION
|
18
|
-
spec.homepage = 'https://github.com/mblumtritt/pixelflut'
|
19
|
-
|
20
|
-
spec.metadata['source_code_uri'] = 'https://github.com/mblumtritt/pixelflut'
|
21
|
-
spec.metadata['bug_tracker_uri'] =
|
22
|
-
'https://github.com/mblumtritt/pixelflut/issues'
|
23
|
-
|
24
|
-
spec.add_runtime_dependency 'rmagick'
|
25
|
-
spec.add_runtime_dependency 'mini-cli', '>= 0.4.0'
|
26
|
-
spec.add_development_dependency 'bundler'
|
27
|
-
spec.add_development_dependency 'rake'
|
28
|
-
|
29
|
-
spec.bindir = 'bin'
|
30
|
-
spec.executables = %w[pxf pxf-info]
|
31
|
-
|
32
|
-
spec.files = Dir.chdir(__dir__) { `git ls-files -z`.split(0.chr) }
|
33
|
-
spec.extra_rdoc_files = %w[README.md]
|
34
|
-
end
|