pixelflut 0.2.0 → 0.2.2

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: d060b7c6e1888c61141aa6f24fae4e2255f4335d8e63ff8dcf1a8710f6d749a4
4
- data.tar.gz: 81cb2846a78285887dab175ab3cb45bc9dcb4d9b0cf7d01add3d607431d537c5
3
+ metadata.gz: accec3b9c3471899c3d8f9b9ff5b1e2f8f60506aa674acc9ff5e76dd8411ad15
4
+ data.tar.gz: ef229296c199b0e12dcd6f2f7a3c48a265c7d6dae9757b1518e299f117dfa01f
5
5
  SHA512:
6
- metadata.gz: d30c42ab6b714404eff2f5dfb3c861c96010266086a497ba2684acb7e6c8ca2b3d79999e41fc10b44fb89a62c1375ed0b68b6da74afa79dfe40cc775c0031d47
7
- data.tar.gz: 58ab45066aeff1c2b1162ff225ba24498a966a7a75caae0219f849695c1cf7d1b997ddbfba605ed118ffea2c9a72a222e666525b2936a618c6563b083b8f4208
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
- require 'mini-cli'
5
- include MiniCli
6
-
7
- help <<~end, 'IMAGE'
8
- --host ADDRESS target host address
9
- -p, --port PORT target port (default 1234)
10
- -c, --connections CONN count of connections (default 4)
11
- -b, --bytes BYTES send junks of BYTES size
12
- -x, --transpose-x X transpose image X pixels
13
- -y, --transpose-y Y transpose image Y pixels
14
- -s, --scale SCALE scale image by SCALE factor
15
- -m, --pixel MODE select pixel coding (RGBX | RGBA | RGB)
16
- -h, --help print this help
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
- Process.setproctitle(name)
20
- $stderr.sync = $stdout.sync = true
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
- parse_argv do |args|
23
- Struct.new(:host, :port, :count, :bytes, :x, :y, :mode, :scale, :source) do
24
- def to_h
25
- { source: source, x: x, y: y, scale: scale, mode: mode }
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
- end.new(
28
- args['ADDRESS'] || '127.0.0.1',
29
- (args['PORT'] || 1234).to_i,
30
- (args['CONN'] || 4).to_i,
31
- args['BYTES'].to_i,
32
- args['X'].to_i,
33
- args['Y'].to_i,
34
- { 'RGBA' => :rgba, 'RGB' => :rgb }[args['MODE']] || :rgbx,
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
- main do |opts|
41
- require_relative '../lib/pixelflut'
42
- address = Pixelflut::Sender.address(opts.host, opts.port)
43
- data = create_data(opts)
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(format("#{name}-%02d", i + 1)))
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 SocketError => e
54
- error(3, e)
142
+ rescue ArgumentError => e
143
+ error(e)
55
144
  rescue LoadError => e
56
- error(4, e)
145
+ error(e, code: 4)
57
146
  rescue Errno::ECONNREFUSED
58
- error(2, 'unable to connect')
147
+ error('unable to connect', code: 2)
59
148
  rescue Errno::EPIPE
60
- error(2, 'connection lost')
61
- end
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
@@ -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)[0]
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
@@ -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 = false
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Pixelflut
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.2'
5
5
  end
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.new(count) { [] }.tap do |ret|
14
- lines.each_with_index { |line, idx| ret[idx % count] << line }
15
- end
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 packages(lines, bytes:)
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.each_pixel.to_a.map! do |x, y, px|
33
- "PX #{x + dx} #{y + dy} #{yield(px)}\n"
34
- end.shuffle!
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
- lambda { |px| px.to_color(Magick::AllCompliance, false, 8, true)[1, 6] }
47
+ ->(px) { px.to_color(Magick::AllCompliance, false, 8, true)[1, 6] }
45
48
  when :rgba
46
- lambda { |px| px.to_color(Magick::AllCompliance, true, 8, true)[1, 8] }
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.0
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: 2021-03-14 00:00:00.000000000 Z
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.2.9
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
@@ -1,3 +0,0 @@
1
- tmp/
2
- pkg/
3
- gems.locked
data/gems.rb DELETED
@@ -1,3 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source('https://rubygems.org') { gemspec }
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
data/rakefile.rb DELETED
@@ -1,7 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
-
5
- $stdout.sync = $stderr.sync = true
6
-
7
- task(:default) { exec 'rake --tasks' }