mir_processing 0.0.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 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: []