mir_processing 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/mir +4 -0
- data/lib/mir/00_info_display.rb +37 -0
- data/lib/mir/00_version.rb +3 -0
- data/lib/mir/01_model.rb +153 -0
- data/lib/mir/01_runner.rb +63 -0
- data/lib/mir/02_viewer.rb +81 -0
- data/lib/mir.rb +6 -0
- metadata +64 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 89a5cadd98ec1b8041a0975fad823ada96957b9c5b600c8ed3c83a4503d7cb03
|
4
|
+
data.tar.gz: 4670d0ad67c51e9119642576f83accd8c9f60fd13c6f32e4c57f128c8d478ff2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 71f358287c53440cbfdd43ef7ab6e9e7df9a82966c0a84e85bcfa06e6c74ee33284d27799efef3bf1727dd4d0aa0025bb353a96f0be4f8d576a1830d093cdc6c
|
7
|
+
data.tar.gz: a193f81d97d3c0641a78cefeda37fb55ae2e1eab050d995ec2a043a445881aab1bf8b691162eb11adeaa82a6418946bfcc7d54c18096ce476cf04f82d8604a49
|
data/bin/mir
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module InfoDisplay
|
2
|
+
def info(level,str,other="")
|
3
|
+
case level
|
4
|
+
when 0
|
5
|
+
space_bar=""
|
6
|
+
when 1
|
7
|
+
space_bar=" |-"
|
8
|
+
else
|
9
|
+
space_bar=" "*3*(level-1)+" |-"
|
10
|
+
end
|
11
|
+
str="#{space_bar}[+] #{str}"
|
12
|
+
other="#{other}"
|
13
|
+
if other.size > 0
|
14
|
+
puts str.ljust(40,'.')+" #{other}"
|
15
|
+
else
|
16
|
+
puts str
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def hit_a_key str=""
|
21
|
+
puts str
|
22
|
+
puts "hit_a_key"
|
23
|
+
$stdin.gets
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
if $PROGRAM_NAME==__FILE__
|
28
|
+
include InfoDisplay
|
29
|
+
info 0,"I"
|
30
|
+
info 1,"A"
|
31
|
+
info 2,"1"
|
32
|
+
info 1,"B"
|
33
|
+
info 2,"1"
|
34
|
+
info 2,"2"
|
35
|
+
info 2,"3"
|
36
|
+
info 3,"a"
|
37
|
+
end
|
data/lib/mir/01_model.rb
ADDED
@@ -0,0 +1,153 @@
|
|
1
|
+
module Mir
|
2
|
+
Size=Struct.new(:x,:y)
|
3
|
+
|
4
|
+
# not used systematically...
|
5
|
+
Vect=Struct.new(:y,:x) do
|
6
|
+
def +(v)
|
7
|
+
Vect.new y+v.y,x+v.x
|
8
|
+
end
|
9
|
+
|
10
|
+
def scale fact
|
11
|
+
Vect.new y*fact,x*fact
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Rgb
|
16
|
+
attr_accessor :r,:g,:b
|
17
|
+
def initialize r,g,b
|
18
|
+
@r,@g,@b=r,g,b
|
19
|
+
end
|
20
|
+
|
21
|
+
def to_a
|
22
|
+
[self.r,self.g,self.b]
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_s
|
26
|
+
"(#{r.to_s.rjust(3)},#{g.to_s.rjust(3)},#{b.to_s.rjust(3)})"
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.random
|
30
|
+
Rgb.new rand(255),rand(255),rand(255)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Yuv
|
35
|
+
attr_accessor :y,:u,:v
|
36
|
+
def initialize y,u,v
|
37
|
+
@y,@u,@v=y,u,v
|
38
|
+
end
|
39
|
+
def to_a
|
40
|
+
[self.y,self.u,self.v]
|
41
|
+
end
|
42
|
+
def to_s
|
43
|
+
"(#{y.to_s.rjust(3)},#{u.to_s.rjust(3)},#{v.to_s.rjust(3)})"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
class Grid
|
48
|
+
attr_accessor :size
|
49
|
+
def initialize width,height
|
50
|
+
@size=Size.new(width,height)
|
51
|
+
@values=Array.new(height){Array.new(width)}
|
52
|
+
end
|
53
|
+
|
54
|
+
def [](y,x)
|
55
|
+
@values[y][x]
|
56
|
+
end
|
57
|
+
|
58
|
+
def []=(y,x,v)
|
59
|
+
@values[y][x]=v
|
60
|
+
end
|
61
|
+
|
62
|
+
def to_a
|
63
|
+
@values.flatten
|
64
|
+
end
|
65
|
+
|
66
|
+
def each &block
|
67
|
+
@values.each do |row|
|
68
|
+
row.each do |v|
|
69
|
+
yield v
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def fill_with v
|
75
|
+
@values.each_with_index do |row,y|
|
76
|
+
row.each_with_index do |pix,x|
|
77
|
+
self[y,x]=v
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def print
|
83
|
+
@values.each do |row|
|
84
|
+
puts row.map{|pix| pix.to_s.rjust(3)}.join(" ")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.from_a ary1d,sx,sy
|
89
|
+
ret=self.new(sx,sy)
|
90
|
+
sy.times do |y|
|
91
|
+
sx.times do |x|
|
92
|
+
index=y*(sx)+x
|
93
|
+
ret[y,x]=ary1d[index]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
ret
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.random sx,sy,klass
|
100
|
+
ret=self.new(sx,sy)
|
101
|
+
sy.times do |y|
|
102
|
+
sx.times do |x|
|
103
|
+
ret[y,x]=klass.random
|
104
|
+
end
|
105
|
+
end
|
106
|
+
ret
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class Image < Grid
|
111
|
+
include InfoDisplay
|
112
|
+
attr_accessor :name
|
113
|
+
def self.open(filename)
|
114
|
+
unless File.exist?(filename)
|
115
|
+
raise "file '#{filename}' not found"
|
116
|
+
end
|
117
|
+
image=nil
|
118
|
+
File.open(filename, 'r') do |f|
|
119
|
+
header=[]
|
120
|
+
begin
|
121
|
+
unless (line=f.gets.chomp).start_with?('#')
|
122
|
+
header << line
|
123
|
+
end
|
124
|
+
end until header.size==3
|
125
|
+
width, height = header[1].split.map {|n| n.to_i }
|
126
|
+
if header[0] != 'P6' or header[2] != '255' or width < 1 or height < 1
|
127
|
+
raise StandardError, "file '#{filename}' does not start with the expected header"
|
128
|
+
end
|
129
|
+
f.binmode
|
130
|
+
image = self.new(width, height)
|
131
|
+
|
132
|
+
height.times do |y|
|
133
|
+
width.times do |x|
|
134
|
+
# read 3 bytes
|
135
|
+
red, green, blue = f.read(3).unpack('C3')
|
136
|
+
image[y,x] = Rgb.new(red, green, blue)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
image.name=File.basename(filename)
|
141
|
+
image
|
142
|
+
end
|
143
|
+
|
144
|
+
def each_pixel &block
|
145
|
+
each &block
|
146
|
+
end
|
147
|
+
|
148
|
+
def Image.random sx,sy
|
149
|
+
ary=Grid.random(sx,sy,Rgb).to_a
|
150
|
+
Image.from_a ary,sx,sy
|
151
|
+
end
|
152
|
+
end
|
153
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "optparse"
|
2
|
+
|
3
|
+
module Mir
|
4
|
+
|
5
|
+
class Runner
|
6
|
+
|
7
|
+
def self.run *arguments
|
8
|
+
new.run(arguments)
|
9
|
+
end
|
10
|
+
|
11
|
+
def run arguments
|
12
|
+
options = args = parse_options(arguments)
|
13
|
+
begin
|
14
|
+
if filename=args[:file]
|
15
|
+
image=Mir::Image.open(filename)
|
16
|
+
viewer=ViewerApp.new(image)
|
17
|
+
viewer.run
|
18
|
+
else
|
19
|
+
raise "need a ppm file : mir [options] <file>"
|
20
|
+
end
|
21
|
+
rescue Exception => e
|
22
|
+
puts e unless options[:mute]
|
23
|
+
return false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def header
|
28
|
+
puts "Mir (#{VERSION}) - (c) JC Le Lann 2023"
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def parse_options(arguments)
|
33
|
+
|
34
|
+
parser = OptionParser.new
|
35
|
+
|
36
|
+
no_arguments=arguments.empty?
|
37
|
+
|
38
|
+
options = {}
|
39
|
+
|
40
|
+
parser.on("-h", "--help", "Show help message") do
|
41
|
+
puts parser
|
42
|
+
exit(true)
|
43
|
+
end
|
44
|
+
|
45
|
+
parser.on("-v", "--version", "Show version number") do
|
46
|
+
puts VERSION
|
47
|
+
exit(true)
|
48
|
+
end
|
49
|
+
|
50
|
+
parser.parse!(arguments)
|
51
|
+
|
52
|
+
header unless options[:mute]
|
53
|
+
|
54
|
+
options[:file]=arguments.shift #the remaining file
|
55
|
+
|
56
|
+
if no_arguments
|
57
|
+
puts parser
|
58
|
+
end
|
59
|
+
|
60
|
+
options
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require "gtk3"
|
2
|
+
|
3
|
+
module Mir
|
4
|
+
class PixelBoard < Gtk::DrawingArea
|
5
|
+
def initialize image
|
6
|
+
super()
|
7
|
+
@image=image
|
8
|
+
override_background_color(:normal, Gdk::RGBA.new(0, 0, 0, 1))
|
9
|
+
signal_connect "draw" do
|
10
|
+
on_expose
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def on_expose
|
15
|
+
cr = window.create_cairo_context
|
16
|
+
draw_pixels cr
|
17
|
+
end
|
18
|
+
|
19
|
+
def draw_pixels cr
|
20
|
+
@image.size.y.times do |y|
|
21
|
+
@image.size.x.times do |x|
|
22
|
+
pix=@image[y,x]
|
23
|
+
r,g,b=pix.to_a.map{|v| v/255.0}
|
24
|
+
xx,yy=x*3,y*3
|
25
|
+
cr.set_source_rgb r,g,b
|
26
|
+
cr.rectangle(x, y,1,1)
|
27
|
+
cr.stroke
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class ViewerWindow < Gtk::ApplicationWindow
|
34
|
+
def initialize app,image
|
35
|
+
super(app)
|
36
|
+
set_title image.name||"Mir::Viewer"
|
37
|
+
if image.size.x < 200
|
38
|
+
size=[200,100]
|
39
|
+
else
|
40
|
+
size=*image.size
|
41
|
+
end
|
42
|
+
set_default_size *size
|
43
|
+
set_window_position(:center)
|
44
|
+
signal_connect(:destroy){Gtk.main_quit}
|
45
|
+
# Create a box to hold the contents of the window
|
46
|
+
box = Gtk::Box.new(:vertical,0)
|
47
|
+
# Add a button to the window to quit the application
|
48
|
+
button = Gtk::Button.new(label: 'Quit')
|
49
|
+
button.signal_connect('clicked') { application.quit }
|
50
|
+
|
51
|
+
board = PixelBoard.new(image)
|
52
|
+
|
53
|
+
# Add the button to the box
|
54
|
+
box.pack_start(board, :expand => true, :fill => true, :padding => 0)
|
55
|
+
box.pack_start(button, :expand => false, :fill => true, :padding => 0)
|
56
|
+
|
57
|
+
# Add the box to the window
|
58
|
+
add(box)
|
59
|
+
show_all
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Viewer < Gtk::Application
|
64
|
+
def initialize image
|
65
|
+
super('com.Mir.viewer', :flags_none)
|
66
|
+
signal_connect(:activate){on_activate(image)}
|
67
|
+
end
|
68
|
+
|
69
|
+
def on_activate image
|
70
|
+
window = ViewerWindow.new(self,image)
|
71
|
+
window.present
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
if $PROGRAM_NAME==__FILE__
|
77
|
+
require_relative "../mir.rb"
|
78
|
+
image=Mir::Image.open ARGV.first
|
79
|
+
app = Mir::Viewer.new image
|
80
|
+
app.run
|
81
|
+
end
|
data/lib/mir.rb
ADDED
metadata
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mir_processing
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jean-Christophe Le Lann
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2023-12-15 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: colorize
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.8.1
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.8.1
|
27
|
+
description: MIR means 'Manipulations d'Images en Ruby
|
28
|
+
email: lelannje@ensta-bretagne.fr
|
29
|
+
executables:
|
30
|
+
- mir
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- bin/mir
|
35
|
+
- lib/mir.rb
|
36
|
+
- lib/mir/00_info_display.rb
|
37
|
+
- lib/mir/00_version.rb
|
38
|
+
- lib/mir/01_model.rb
|
39
|
+
- lib/mir/01_runner.rb
|
40
|
+
- lib/mir/02_viewer.rb
|
41
|
+
homepage: https://github.com/JC-LL/mir
|
42
|
+
licenses:
|
43
|
+
- MIT
|
44
|
+
metadata: {}
|
45
|
+
post_install_message: Thanks for installing ! Homepage :https://github.com/JC-LL/mir
|
46
|
+
rdoc_options: []
|
47
|
+
require_paths:
|
48
|
+
- lib
|
49
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 2.0.0
|
54
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: '0'
|
59
|
+
requirements: []
|
60
|
+
rubygems_version: 3.2.3
|
61
|
+
signing_key:
|
62
|
+
specification_version: 4
|
63
|
+
summary: Simple image manipulation in Ruby, for experimental purposes
|
64
|
+
test_files: []
|