mir_processing 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/mir'
4
+ Mir::Runner.run(*ARGV)
@@ -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
@@ -0,0 +1,3 @@
1
+ module Mir
2
+ VERSION="0.0.2"
3
+ end
@@ -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
@@ -0,0 +1,6 @@
1
+ require "gtk3"
2
+ require_relative "./mir/00_info_display.rb"
3
+ require_relative "./mir/00_version.rb"
4
+ require_relative "./mir/01_model.rb"
5
+ require_relative "./mir/01_runner.rb"
6
+ require_relative "./mir/02_viewer.rb"
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: []