pixelflut 0.2.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +14 -13
- data/bin/pxf +99 -118
- data/lib/pixelflut/sender.rb +17 -17
- data/lib/pixelflut/version.rb +1 -1
- data/lib/pixelflut.rb +79 -40
- metadata +5 -7
- data/bin/pxf-info +0 -32
- data/lib/pixelflut/image.rb +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b91c341d7ba55f35b968b3a35c31cb4e676b2055c2f86bd6a94e3f5a4847c788
|
4
|
+
data.tar.gz: 700e3fae41c985852236339eca7381f05d383e55c74e9948b2f7935b2f7bf69e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 68bbebdd53d083cf10e6bc5c76a18b81ac43347f929166d61493a4e8a54b07263f7ae18c1b23eb5c26317a8d02a33aea18f26740c0cb3f9f387338bb4322a2f5
|
7
|
+
data.tar.gz: c045bd205847f450c924c2e0f2485737af956f6f419e99b78dadd7b8ab101972f0b251bd09eb62bd39024f60c4f00b34830ccf367a718e71395d037696f735ea
|
data/README.md
CHANGED
@@ -12,8 +12,8 @@ This gem is an open experiment. You are welcome to fork or create pull requests
|
|
12
12
|
|
13
13
|
Use [Bundler](http://gembundler.com/) to install the gem:
|
14
14
|
|
15
|
-
```
|
16
|
-
|
15
|
+
```sh
|
16
|
+
gem install pixelflut
|
17
17
|
```
|
18
18
|
|
19
19
|
Now the `pxf` command offers the complete functionality.
|
@@ -22,18 +22,19 @@ Now the `pxf` command offers the complete functionality.
|
|
22
22
|
|
23
23
|
You'll find some help on the command line:
|
24
24
|
|
25
|
-
```
|
25
|
+
```
|
26
26
|
$ pxf
|
27
|
-
Usage: pxf [
|
27
|
+
Usage: pxf [options] <image>
|
28
28
|
|
29
29
|
Options:
|
30
|
-
|
31
|
-
-p, --port
|
32
|
-
-c, --connections
|
33
|
-
-
|
34
|
-
-
|
35
|
-
-
|
36
|
-
-
|
37
|
-
-
|
38
|
-
-
|
30
|
+
--host <address> target host address (default 127.0.0.1)
|
31
|
+
-p, --port <port> target port (default 1337)
|
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
|
+
-m, --mode <mode> select pixel encoding (TEXT | BIN)
|
36
|
+
-t, --threads use threads instead of processes
|
37
|
+
-h, --help print this help
|
38
|
+
-v, --version print version information
|
39
|
+
|
39
40
|
```
|
data/bin/pxf
CHANGED
@@ -2,151 +2,132 @@
|
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
4
|
$stdout.sync = $stderr.sync = true
|
5
|
-
|
5
|
+
$name = Process.setproctitle(File.basename(Process.argv0))
|
6
6
|
|
7
7
|
if ARGV.index('-h') || ARGV.index('--help')
|
8
8
|
puts <<~HELP
|
9
|
-
Usage: #{$name}
|
9
|
+
Usage: #{$name} [options] <png_image>
|
10
10
|
|
11
11
|
Options:
|
12
|
-
--host <address> target host address
|
12
|
+
--host <address> target host address (default 127.0.0.1)
|
13
13
|
-p, --port <port> target port (default 1234)
|
14
14
|
-c, --connections <count> count of connections (default 4)
|
15
|
-
-
|
15
|
+
-m, --mode <mode> select pixel encoding (TEXT | BIN)
|
16
|
+
-t, --threads use threads instead of processes
|
16
17
|
-x, --transpose-x <x> transpose image <x> pixels
|
17
18
|
-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
19
|
-h, --help print this help
|
20
|
+
-v, --version print version information
|
21
21
|
HELP
|
22
22
|
exit
|
23
23
|
end
|
24
24
|
|
25
|
-
|
26
|
-
|
25
|
+
if ARGV.index('-v') || ARGV.index('--version')
|
26
|
+
require_relative('../lib/pixelflut/version')
|
27
|
+
puts("#{$name} - Pixelflut v#{Pixelflut::VERSION}")
|
28
|
+
exit
|
29
|
+
end
|
30
|
+
|
31
|
+
def die!(msg, code: 1)
|
32
|
+
$stderr.puts("#{$name}: #{msg}")
|
27
33
|
exit(code)
|
28
34
|
end
|
29
35
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
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
|
36
|
+
die!('argument missing') if ARGV.empty?
|
37
|
+
|
38
|
+
require_relative('../lib/pixelflut')
|
39
|
+
|
40
|
+
module Configuration
|
41
|
+
class << self
|
42
|
+
attr_reader :use_threads
|
43
|
+
|
44
|
+
def address
|
45
|
+
require_relative('../lib/pixelflut/sender')
|
46
|
+
Pixelflut::Sender.as_address(@host || '127.0.0.1', @port || 1234)
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def invalid(value, name)
|
52
|
+
die!("value for #{name} missing") if value.nil?
|
53
|
+
die!("invalid value for #{name} - '#{value}'")
|
54
|
+
end
|
55
|
+
|
56
|
+
def as_str(value, name)
|
57
|
+
value.nil? || value.empty? ? invalid(value, name) : value
|
58
|
+
end
|
59
|
+
|
60
|
+
def as_uint(value, name)
|
61
|
+
(ret = value.to_i).positive? ? ret : invalid(value, name)
|
62
|
+
end
|
63
|
+
|
64
|
+
def as_mode(value, name)
|
65
|
+
%w[text bin].include?(v = value.downcase) ? v : invalid(value, name)
|
117
66
|
end
|
118
|
-
|
67
|
+
end
|
119
68
|
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
69
|
+
until ARGV.empty?
|
70
|
+
case arg = ARGV.shift
|
71
|
+
when '--host'
|
72
|
+
@host = as_str(ARGV.shift, 'host')
|
73
|
+
when '-p', '--port'
|
74
|
+
@port = as_uint(ARGV.shift, 'port')
|
75
|
+
when '-c', '--connections'
|
76
|
+
Pixelflut.count = as_uint(ARGV.shift, 'connections')
|
77
|
+
die!("too many connections - #{Pixelflut.count}") if Pixelflut.count > 255
|
78
|
+
when '-m', '--mode', '--pixel'
|
79
|
+
Pixelflut.mode = as_mode(ARGV.shift, 'mode')
|
80
|
+
when '-t', '--use-threads'
|
81
|
+
@use_threads = true
|
82
|
+
when '-x', '--transpose-x'
|
83
|
+
Pixelflut.delta_x = ARGV.shift.to_i
|
84
|
+
when '-y', '--transpose-y'
|
85
|
+
Pixelflut.delta_y = ARGV.shift.to_i
|
86
|
+
else
|
87
|
+
die!("invalid option - #{arg}") if Pixelflut.file_name
|
88
|
+
Pixelflut.file_name = arg
|
89
|
+
end
|
124
90
|
end
|
125
|
-
|
91
|
+
|
92
|
+
die!('<image> missing') unless Pixelflut.file_name
|
126
93
|
end
|
127
94
|
|
128
|
-
|
129
|
-
|
130
|
-
require_relative('../lib/pixelflut')
|
131
|
-
data = create_junks
|
132
|
-
error("Too many subprocesses - #{data.size}") if data.size > 256
|
133
|
-
print("spawn #{data.size}")
|
95
|
+
def use_processes(address, data)
|
96
|
+
puts("#{$name}: start #{data.size} processes for #{data.sum(&:size)} bytes")
|
134
97
|
data.size.times do |i|
|
135
98
|
next unless fork
|
136
|
-
|
137
|
-
data = data[i].join
|
99
|
+
data = data[i]
|
138
100
|
GC.start
|
139
|
-
|
140
|
-
Pixelflut::Sender.send(
|
101
|
+
$name = Process.setproctitle("#{$name}-#{'0' if i < 9}#{i + 1}")
|
102
|
+
Pixelflut::Sender.send(address, data) do |size|
|
103
|
+
puts("#{$name}: #{size} bytes")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def use_threads(address, data)
|
109
|
+
puts("#{$name}: start #{data.size} threads for #{data.sum(&:size)} bytes")
|
110
|
+
Thread.report_on_exception = false
|
111
|
+
data.map! { |slice| Thread.start { Pixelflut::Sender.send(address, slice) } }
|
112
|
+
GC.start
|
113
|
+
data.each(&:join)
|
114
|
+
end
|
115
|
+
|
116
|
+
begin
|
117
|
+
if Configuration.use_threads
|
118
|
+
use_threads(Configuration.address, Pixelflut.data)
|
119
|
+
else
|
120
|
+
use_processes(Configuration.address, Pixelflut.data)
|
141
121
|
end
|
142
|
-
rescue ArgumentError => e
|
143
|
-
error(e)
|
144
|
-
rescue LoadError => e
|
145
|
-
error(e, code: 4)
|
146
122
|
rescue Errno::ECONNREFUSED
|
147
|
-
|
123
|
+
die!('unable to connect', code: 2)
|
148
124
|
rescue Errno::EPIPE
|
149
|
-
|
125
|
+
die!('connection lost', code: 2)
|
150
126
|
rescue SocketError => e
|
151
|
-
|
127
|
+
die!(e, code: 3)
|
128
|
+
rescue LoadError => e
|
129
|
+
die!(e, code: 4)
|
130
|
+
rescue Interrupt
|
131
|
+
print("\b\b") if $stdout.tty?
|
132
|
+
die!('aborted', code: 130)
|
152
133
|
end
|
data/lib/pixelflut/sender.rb
CHANGED
@@ -1,31 +1,31 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'socket'
|
4
|
-
|
5
3
|
module Pixelflut
|
6
4
|
module Sender
|
7
|
-
def self.
|
8
|
-
|
5
|
+
def self.as_address(host, port)
|
6
|
+
require('socket') unless defined?(Addrinfo)
|
7
|
+
info = Addrinfo.tcp(host, port)
|
8
|
+
Address.new(
|
9
|
+
Socket.pack_sockaddr_in(info.ip_port, info.ip_address),
|
10
|
+
info.ipv6? ? :INET6 : :INET
|
11
|
+
)
|
9
12
|
end
|
10
13
|
|
11
14
|
def self.send(address, data)
|
12
15
|
socket = create_socket(address)
|
13
|
-
yield(
|
14
|
-
|
16
|
+
yield(data.bytesize) if block_given?
|
17
|
+
socket.write(data) while true
|
15
18
|
end
|
16
19
|
|
17
20
|
def self.create_socket(address)
|
18
|
-
Socket
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
socket.do_not_reverse_lookup = true
|
25
|
-
socket.connect(
|
26
|
-
Socket.pack_sockaddr_in(address.ip_port, address.ip_address)
|
27
|
-
)
|
28
|
-
end
|
21
|
+
socket = Socket.new(address.type, :STREAM)
|
22
|
+
socket.connect(address.sockaddr_in)
|
23
|
+
socket.setsockopt(:TCP, :NODELAY, 1)
|
24
|
+
socket.setsockopt(:SOCKET, :KEEPALIVE, 0)
|
25
|
+
socket.sync = socket.do_not_reverse_lookup = true
|
26
|
+
socket
|
29
27
|
end
|
28
|
+
|
29
|
+
Address = Struct.new(:sockaddr_in, :type)
|
30
30
|
end
|
31
31
|
end
|
data/lib/pixelflut/version.rb
CHANGED
data/lib/pixelflut.rb
CHANGED
@@ -1,60 +1,99 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require_relative 'pixelflut/image'
|
4
|
-
require_relative 'pixelflut/sender'
|
5
|
-
|
6
3
|
module Pixelflut
|
7
4
|
class << self
|
8
|
-
|
9
|
-
|
5
|
+
attr_accessor :file_name, :count, :mode, :delta_x, :delta_y
|
6
|
+
|
7
|
+
def data
|
8
|
+
sliced(convert(*load).shuffle!, @count).map!(&:join)
|
10
9
|
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
private
|
12
|
+
|
13
|
+
def load
|
14
|
+
require('chunky_png') unless defined?(ChunkyPNG)
|
15
|
+
image = ChunkyPNG::Canvas.from_file(@file_name)
|
16
|
+
[image.width, image.height, image.pixels.pack("N#{image.pixels.size}")]
|
17
|
+
rescue Errno::ENOENT => e
|
18
|
+
raise(LoadError, e.message, cause: e)
|
18
19
|
end
|
19
20
|
|
20
|
-
def
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
21
|
+
# def load_rmagick
|
22
|
+
# require('rmagick') unless defined?(Magick)
|
23
|
+
# image = Magick::Image.read(@file_name).first
|
24
|
+
# image.scale!(@scale) if @scale
|
25
|
+
# [
|
26
|
+
# image.columns,
|
27
|
+
# image.rows,
|
28
|
+
# image.export_pixels_to_str(0, 0, image.columns, image.rows, 'rgba')
|
29
|
+
# ]
|
30
|
+
# rescue Magick::ImageMagickError => e
|
31
|
+
# raise(LoadError, e.message, cause: e)
|
32
|
+
# end
|
33
|
+
|
34
|
+
def sliced(array, number)
|
35
|
+
division = array.size / number
|
36
|
+
modulo = array.size % number
|
37
|
+
pos = 0
|
38
|
+
Array.new(number) do |index|
|
39
|
+
length = division + (modulo > 0 && modulo > index ? 1 : 0)
|
40
|
+
slice = array.slice(pos, length)
|
41
|
+
pos += length
|
42
|
+
slice
|
26
43
|
end
|
27
|
-
ret
|
28
44
|
end
|
29
45
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
.map! { |x, y, px| "PX #{x + dx} #{y + dy} #{yield(px)}\n" }
|
37
|
-
.shuffle!
|
46
|
+
def convert(width, height, blob)
|
47
|
+
if @mode == 'bin'
|
48
|
+
to_bin_format(width, height, blob)
|
49
|
+
else
|
50
|
+
to_text_format(width, height, blob)
|
51
|
+
end
|
38
52
|
end
|
39
53
|
|
40
|
-
def
|
41
|
-
|
54
|
+
def to_text_format(width, height, blob)
|
55
|
+
ret = []
|
56
|
+
pos = -1
|
57
|
+
height.times do |y|
|
58
|
+
width.times do |x|
|
59
|
+
next if (a = blob.getbyte(pos += 4)) == 0
|
60
|
+
ret << format(
|
61
|
+
(
|
62
|
+
if a == 255
|
63
|
+
"PX %d %d %02x%02x%02x\n"
|
64
|
+
else
|
65
|
+
"PX %d %d %02x%02x%02x%02x\n"
|
66
|
+
end
|
67
|
+
),
|
68
|
+
x + @delta_x,
|
69
|
+
y + @delta_y,
|
70
|
+
blob.getbyte(pos - 3),
|
71
|
+
blob.getbyte(pos - 2),
|
72
|
+
blob.getbyte(pos - 1),
|
73
|
+
a
|
74
|
+
)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
ret
|
42
78
|
end
|
43
79
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
1,
|
54
|
-
px.alpha >= 65_535 ? 6 : 8
|
55
|
-
]
|
80
|
+
def to_bin_format(width, height, blob)
|
81
|
+
ret = []
|
82
|
+
pos = 0
|
83
|
+
height.times do |y|
|
84
|
+
width.times do |x|
|
85
|
+
if blob[pos + 3] != "\x0"
|
86
|
+
ret << "PB#{[x + @delta_x, y + @delta_y].pack('v2')}#{blob[pos, 4]}"
|
87
|
+
end
|
88
|
+
pos += 4
|
56
89
|
end
|
57
90
|
end
|
91
|
+
ret
|
58
92
|
end
|
59
93
|
end
|
94
|
+
|
95
|
+
@count = ENV['TC'].to_i
|
96
|
+
@count = 4 unless @count.positive?
|
97
|
+
@mode = 'text'
|
98
|
+
@delta_x = @delta_y = 0
|
60
99
|
end
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pixelflut
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
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: 2023-12-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: chunky_png
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -31,16 +31,13 @@ description: |
|
|
31
31
|
email:
|
32
32
|
executables:
|
33
33
|
- pxf
|
34
|
-
- pxf-info
|
35
34
|
extensions: []
|
36
35
|
extra_rdoc_files:
|
37
36
|
- README.md
|
38
37
|
files:
|
39
38
|
- README.md
|
40
39
|
- bin/pxf
|
41
|
-
- bin/pxf-info
|
42
40
|
- lib/pixelflut.rb
|
43
|
-
- lib/pixelflut/image.rb
|
44
41
|
- lib/pixelflut/sender.rb
|
45
42
|
- lib/pixelflut/version.rb
|
46
43
|
homepage: https://github.com/mblumtritt/pixelflut
|
@@ -48,6 +45,7 @@ licenses: []
|
|
48
45
|
metadata:
|
49
46
|
source_code_uri: https://github.com/mblumtritt/pixelflut
|
50
47
|
bug_tracker_uri: https://github.com/mblumtritt/pixelflut/issues
|
48
|
+
rubygems_mfa_required: 'true'
|
51
49
|
post_install_message:
|
52
50
|
rdoc_options: []
|
53
51
|
require_paths:
|
@@ -63,7 +61,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
63
61
|
- !ruby/object:Gem::Version
|
64
62
|
version: '0'
|
65
63
|
requirements: []
|
66
|
-
rubygems_version: 3.
|
64
|
+
rubygems_version: 3.4.22
|
67
65
|
signing_key:
|
68
66
|
specification_version: 4
|
69
67
|
summary: A fast Pixelflut client written in Ruby.
|
data/bin/pxf-info
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
#! /bin/sh
|
2
|
-
|
3
|
-
set -e
|
4
|
-
|
5
|
-
if [ "$1" = '--help' ]
|
6
|
-
then
|
7
|
-
echo "Usage: ${0##*/} [-p|--port PORT] ADDRESS
|
8
|
-
|
9
|
-
Requests screen size of Pixelflut server at ADDRESS.
|
10
|
-
"
|
11
|
-
exit 0
|
12
|
-
fi
|
13
|
-
|
14
|
-
PORT="1234"
|
15
|
-
ADDRESS=""
|
16
|
-
|
17
|
-
while [ $# -gt 0 ]
|
18
|
-
do
|
19
|
-
key="$1"
|
20
|
-
case $key in
|
21
|
-
-p|--port)
|
22
|
-
PORT="$2"
|
23
|
-
shift; shift
|
24
|
-
;;
|
25
|
-
*)
|
26
|
-
ADDRESS="$key"
|
27
|
-
shift
|
28
|
-
;;
|
29
|
-
esac
|
30
|
-
done
|
31
|
-
|
32
|
-
echo "SIZE\nQUIT\n" | nc "$ADDRESS" "$PORT"
|
data/lib/pixelflut/image.rb
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require 'rmagick'
|
4
|
-
|
5
|
-
module Pixelflut
|
6
|
-
class Image
|
7
|
-
def initialize(file_name)
|
8
|
-
@image = Magick::ImageList.new(file_name).first
|
9
|
-
rescue Magick::ImageMagickError => e
|
10
|
-
raise(LoadError, e.message, cause: e)
|
11
|
-
end
|
12
|
-
|
13
|
-
def width
|
14
|
-
@image.columns
|
15
|
-
end
|
16
|
-
|
17
|
-
def height
|
18
|
-
@image.rows
|
19
|
-
end
|
20
|
-
|
21
|
-
def resize_to(width, height = nil)
|
22
|
-
@image.resize_to_fit!(width, height)
|
23
|
-
end
|
24
|
-
|
25
|
-
def scale(factor)
|
26
|
-
@image.scale!(factor)
|
27
|
-
end
|
28
|
-
|
29
|
-
def each_pixel
|
30
|
-
return to_enum(__method__) unless block_given?
|
31
|
-
@image.each_pixel { |px, x, y| 0 != px.alpha and yield(x, y, px) }
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|