pixelflut 0.2.0 → 0.2.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 +4 -4
- data/bin/pxf +132 -47
- 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 +14 -11
- 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,67 +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
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
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
|
17
23
|
end
|
18
24
|
|
19
|
-
|
20
|
-
$stderr.
|
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
|
21
85
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
26
117
|
end
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
args.key?('SCALE') ? args['SCALE'].to_f : nil,
|
36
|
-
args['IMAGE']
|
37
|
-
)
|
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)
|
38
126
|
end
|
39
127
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
data =
|
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
|
44
133
|
print("spawn #{data.size}")
|
45
134
|
data.size.times do |i|
|
46
135
|
next unless fork
|
47
|
-
Process.setproctitle(name
|
136
|
+
Process.setproctitle($name = format("#{$name}-%02d", i + 1))
|
48
137
|
data = data[i].join
|
49
138
|
GC.start
|
50
139
|
GC.disable
|
51
|
-
Pixelflut::Sender.send(address, data) { print('.') }
|
140
|
+
Pixelflut::Sender.send(Configuration.address, data) { print('.') }
|
52
141
|
end
|
53
|
-
rescue
|
54
|
-
error(
|
142
|
+
rescue ArgumentError => e
|
143
|
+
error(e)
|
55
144
|
rescue LoadError => e
|
56
|
-
error(
|
145
|
+
error(e, code: 4)
|
57
146
|
rescue Errno::ECONNREFUSED
|
58
|
-
error(
|
147
|
+
error('unable to connect', code: 2)
|
59
148
|
rescue Errno::EPIPE
|
60
|
-
error(
|
61
|
-
|
62
|
-
|
63
|
-
def create_data(opts)
|
64
|
-
data = Pixelflut.convert(**opts.to_h)
|
65
|
-
return Pixelflut.slices(data, count: opts.count) if opts.bytes.zero?
|
66
|
-
Pixelflut.packages(data, bytes: opts.bytes)
|
149
|
+
error('connection lost', code: 2)
|
150
|
+
rescue SocketError => e
|
151
|
+
error(e, code: 3)
|
67
152
|
end
|
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,14 +10,15 @@ 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
|
-
def
|
19
|
-
ret = [current = []]
|
20
|
-
size = 0
|
20
|
+
def junks(lines, bytes:)
|
21
|
+
size, ret = 0, [current = []]
|
21
22
|
lines.each do |line|
|
22
23
|
next current << line if (size += line.bytesize) < bytes
|
23
24
|
ret << (current = [line])
|
@@ -29,9 +30,11 @@ module Pixelflut
|
|
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'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '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'
|
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
|