mork 0.0.2 → 0.0.3

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
+ SHA1:
3
+ metadata.gz: cf9368eb34bdddb744f80f7baa1475ba03aedeab
4
+ data.tar.gz: 129f95cfa8329b81154186ec175f0b14a9ba3b72
5
+ SHA512:
6
+ metadata.gz: 82652798819ce990be08645e337199cc19ce8829bbda397212e958f17f6df3d865c62ab86d80eda12340250cd8f7ac09791b9c7f8a68c9ca060b13c88ff2e9c3
7
+ data.tar.gz: e733b22b1de5c615982da5c8725c04877654d297584a4677c5194aad2cf66c94074171abf4f7dd8a01ee82d5e62ef30c6d0c69f7b594667297ffd563cfde4a03
data/.gitignore CHANGED
@@ -1,6 +1,7 @@
1
1
  *.gem
2
2
  .bundle
3
3
  Gemfile.lock
4
+ quick.rb
4
5
  pkg/*
5
6
  tmp/*
6
7
  .rvmrc
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ mork
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.0.0-p451
data/Gemfile CHANGED
@@ -1,3 +1,3 @@
1
1
  source "http://rubygems.org"
2
- gem 'prawn', git: 'git://github.com/prawnpdf/prawn', submodules: true
2
+ # gem 'prawn', git: 'git://github.com/prawnpdf/prawn', submodules: true
3
3
  gemspec
data/README.md ADDED
@@ -0,0 +1,49 @@
1
+ Mork
2
+ ====
3
+
4
+ A ruby [optical mark recognition](http://en.wikipedia.org/wiki/Optical_mark_recognition) (OMR) library to accomplish two tasks:
5
+
6
+ 1. generating [response sheets](/spec/samples/sheet1.pdf) in PDF format (for tests, surveys, etc.)
7
+ 2. capturing the responses provided on the [printed sheet](/spec/samples/sheet1.jpg) by a human with a pen or a pencil.
8
+
9
+ Assumptions and limitations
10
+ ---------------------------
11
+ Mork is a low-level library, and very much work in progress. It is not, and will likely never be a complete OMR solution. While suggestions and contributions are more than welcome, for the time being several assumptions and restrictions to what the library is capable of apply.
12
+
13
+ - the generated PDF file is intended to be printed on regular printer paper, and the filled-out form to be acquired as a bitmap image by a normal optical scanner or camera (i.e., no specialized equipment is necessary)
14
+ - the [response sheet](/spec/samples/sheet1.pdf) contains the following items:
15
+ - registration marks at each page corner
16
+ - a bar code along the bottom margin to uniquely identify the sheet
17
+ - a header area to print arbitrary information
18
+ - a response area containing a list of numbered items (questions)
19
+ - each item contains an arbitrary number of choices, each marked with a capital letter (A, B, C, ...). In order to maximize contrast, choice "cells" are printed in red
20
+ - with some restrictions, the number of columns in the response area, the numer of items, the number of choices per item, the size and shape of the choice cells can be set by the user
21
+ - all items must fit within the allocated response area of a single sheet
22
+
23
+ Installing
24
+ ----------
25
+
26
+ Install the gem in your system:
27
+
28
+ $ gem install mork
29
+
30
+ If you are using bundler in your project, as you should, make sure your `Gemfile` contains the following, before running `bundle install`:
31
+
32
+ source 'http://rubygems.org'
33
+ gem 'mork'
34
+
35
+ Usage
36
+ -----
37
+
38
+ The layout of the response sheet is described in a YAML file
39
+
40
+ License
41
+ -------
42
+
43
+ Copyright (c) 2013 Giuseppe Bertini
44
+
45
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
46
+
47
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/config/grids.yml CHANGED
@@ -1,28 +1,32 @@
1
1
  default:
2
+ # units are millimiters
2
3
  page_size:
4
+ # this is A4
3
5
  width: 210.0
4
6
  height: 297.0
5
7
  header:
6
- name:
7
- top: 3
8
- left: 7.5
9
- width: 120
10
- size: 14
8
+ title:
9
+ top: 3
10
+ left: 7.5
11
+ width: 150
12
+ size: 12
11
13
  code:
12
14
  top: 3
13
15
  left: 170
14
16
  width: 25
15
17
  size: 12
16
- title:
17
- top: 12
18
- left: 7.5
19
- width: 180.0
20
- size: 12
21
- date:
22
- top: 18
23
- left: 7.5
24
- width: 180.0
25
- size: 12
18
+ name:
19
+ top: 15
20
+ left: 7.5
21
+ width: 112
22
+ size: 14
23
+ signature:
24
+ top: 15
25
+ left: 122
26
+ width: 70
27
+ height: 10
28
+ size: 7
29
+ box: true
26
30
  responses:
27
31
  columns: 4
28
32
  column_width: 50.0
data/cucu.jpg ADDED
Binary file
data/lib/mork/grid.rb CHANGED
@@ -164,13 +164,29 @@ module Mork
164
164
  ]
165
165
  end
166
166
 
167
+ def pdf_header_padding(k)
168
+ [
169
+ 1.mm,
170
+ pdf_header_height(k) - 1.mm
171
+ ]
172
+
173
+ end
174
+
167
175
  def pdf_header_width(k)
168
176
  header[k.to_s]["width"].to_f.mm
169
177
  end
170
178
 
179
+ def pdf_header_height(k)
180
+ header[k.to_s]["height"].to_f.mm
181
+ end
182
+
171
183
  def pdf_header_size(k)
172
184
  header[k.to_s]["size"].to_f
173
185
  end
186
+
187
+ def pdf_header_boxed?(k)
188
+ header[k.to_s]["box"] == true
189
+ end
174
190
 
175
191
  private
176
192
 
@@ -251,10 +267,10 @@ module Mork
251
267
  # ==============
252
268
  def code_cell_area(i)
253
269
  {
254
- x: (cx * code_cell_x(i) ).round,
255
- y: (cy * code_y ).round,
256
- w: (cx * CODE_WIDTH ).round,
257
- h: (cy * CODE_HEIGHT).round
270
+ x: (cx * code_cell_x(i)).round,
271
+ y: (cy * code_y ).round,
272
+ w: (cx * CODE_WIDTH ).round,
273
+ h: (cy * CODE_HEIGHT ).round
258
274
  }
259
275
  end
260
276
 
@@ -17,6 +17,8 @@ module Mork
17
17
  end
18
18
 
19
19
  def [] (i)
20
+ puts "I: #{i}"
21
+ puts @images[i].inspect
20
22
  Mimage.new @images[i]
21
23
  end
22
24
 
data/lib/mork/sheet.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  module Mork
2
2
  class Sheet
3
- def initialize(im, grid)
3
+ def initialize(im, grid=Grid.new)
4
4
  im = Mimage.new(im) if im.class == String
5
5
  raise "A new sheet requires either a Mimage or the name of the source image file" unless im.class == Mimage
6
- # grid = Grid.new(grid) if grid.class == String
7
- # raise "A new sheet requires either a Mimage or the name of the source image file" unless im.class == Mimage
8
6
  @grid = grid
7
+ # send page size to the grid, so that all later measurements can be done within the
8
+ # grid itself; this method assumes a 'stretch' strategy, i.e. where the image
9
+ # after registration has the same size in pixels as the original scanned file
10
+ @grid.set_page_size im.width, im.height
9
11
  @mimage = register(im)
10
12
  end
11
13
 
@@ -115,10 +117,6 @@ module Mork
115
117
  # ================
116
118
 
117
119
  def register(img)
118
- # send page size to the grid, so that all later measurements can be done within the
119
- # grid itself. WARNING: this method assumes a 'stretch' strategy, i.e. where the
120
- # image after registration has the same size in pixels as the original scanned file
121
- @grid.set_page_size img.width, img.height
122
120
  # find the XY coordinates of the 4 registration marks
123
121
  x1, y1 = reg_centroid_on(img, @grid.reg_mark_search_area(:top_left))
124
122
  x2, y2 = reg_centroid_on(img, @grid.reg_mark_search_area(:top_right))
@@ -42,9 +42,18 @@ module Mork
42
42
 
43
43
  def header
44
44
  @info[:header].each do |k,v|
45
- text_box v, at: @grid.pdf_header_xy(k),
46
- width: @grid.pdf_header_width(k),
47
- size: @grid.pdf_header_size(k) || 12
45
+ font_size @grid.pdf_header_size(k) do
46
+ if @grid.pdf_header_boxed?(k)
47
+ bounding_box @grid.pdf_header_xy(k), width: @grid.pdf_header_width(k), height: @grid.pdf_header_height(k) do
48
+ stroke_bounds
49
+ bounding_box @grid.pdf_header_padding(k), width: @grid.pdf_header_width(k) do
50
+ text v
51
+ end
52
+ end
53
+ else
54
+ text_box v, at: @grid.pdf_header_xy(k), width: @grid.pdf_header_width(k)
55
+ end
56
+ end
48
57
  end
49
58
  end
50
59
 
@@ -54,9 +63,9 @@ module Mork
54
63
  nquestions.times do |q|
55
64
  fill_color "000000"
56
65
  text_box "#{q+1}", at: @grid.pdf_qnum_xy(q),
57
- width: @grid.pdf_qnum_width,
58
- align: :right,
59
- size: Q_NUM_SIZE
66
+ width: @grid.pdf_qnum_width,
67
+ align: :right,
68
+ size: Q_NUM_SIZE
60
69
  stroke_color "ff0000"
61
70
  font_size CH_LETTER_SZ
62
71
  nchoices(q).times do |c|
@@ -73,7 +82,7 @@ module Mork
73
82
  render_file fn
74
83
  end
75
84
 
76
- private
85
+ private
77
86
  def nquestions
78
87
  @info[:choices].length
79
88
  end
data/lib/mork/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Mork
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
data/mork.gemspec CHANGED
@@ -17,15 +17,17 @@ Gem::Specification.new do |s|
17
17
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
18
  s.require_paths = ["lib"]
19
19
 
20
- # specify any dependencies here; for example:
20
+ # dependencies:
21
21
  s.add_dependency "narray"
22
22
  s.add_dependency "rmagick"
23
+ s.add_dependency "prawn"
23
24
  s.add_development_dependency 'rake'
24
25
  s.add_development_dependency "rspec"
25
26
  s.add_development_dependency "cucumber"
26
27
  s.add_development_dependency "guard-rspec"
27
28
  s.add_development_dependency "guard-shell"
28
29
  s.add_development_dependency "rb-fsevent"
30
+ s.add_development_dependency "awesome_print"
29
31
 
30
32
  # s.add_runtime_dependency "rest-client"
31
33
  end
@@ -7,27 +7,39 @@ module Mork
7
7
  code: 18446744073709551615,
8
8
  choices: [5] * 100,
9
9
  header: {
10
- name: "Bertini Giuseppe VR123456",
11
- title: "Esame di Fondamenti Morfologici e Funzionali della Vita",
10
+ name: "Bertini Giuseppe VR123456 Bertini Giuseppe VR123456",
11
+ title: "Esame di Fondamenti Morfologici e Funzionali della Vita - 18 gennaio 2013 Esame di Fondamenti Morfologici e Funzionali della Vita - 18 gennaio 2013",
12
12
  code: "119.27",
13
- date: "18 gennaio 2013"
13
+ signature: "Firma"
14
14
  }
15
15
  }
16
16
  s = SheetPDF.new(Grid.new(:default), info)
17
17
  s.save("tmp/f1.pdf")
18
18
 
19
19
  info = {
20
- code: 283764283738,
20
+ code: 17382938642823887837,
21
21
  choices: [5] * 100,
22
22
  header: {
23
23
  name: "Francesco Gagliardi VR765432",
24
- title: "Esame di Fondamenti Morfologici e Funzionali della Vita",
25
- code: "119.28",
26
- date: "18 gennaio 2013"
24
+ title: "Esame di Fondamenti Morfologici e Funzionali della Vita - 18 gennaio 2013",
25
+ code: "119.28"
27
26
  }
28
27
  }
29
28
  s = SheetPDF.new(Grid.new(:default), info)
30
29
  s.save("tmp/f2.pdf")
30
+
31
+ info = {
32
+ code: 8928348236,
33
+ choices: [5] * 160,
34
+ header: {
35
+ name: "G" * 60,
36
+ title: "E" * 100,
37
+ code: "119.28",
38
+ signature: "Firma"
39
+ }
40
+ }
41
+ s = SheetPDF.new(Grid.new(:default), info)
42
+ s.save("tmp/f3.pdf")
31
43
  end
32
44
  end
33
45
  end
Binary file
@@ -49,5 +49,5 @@ code_zero:
49
49
 
50
50
  two_pages:
51
51
  filename: spec/samples/two_pages.pdf
52
- code_int: 18446744073709551615
52
+ code_int: 17382938642823887837
53
53
 
Binary file