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 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' }