mork 0.11.2 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/mork/grid.rb +7 -8
- data/lib/mork/grid_const.rb +11 -0
- data/lib/mork/grid_omr.rb +11 -50
- data/lib/mork/grid_pdf.rb +21 -0
- data/lib/mork/magicko.rb +0 -34
- data/lib/mork/mimage.rb +24 -135
- data/lib/mork/npatch.rb +0 -30
- data/lib/mork/sheet_omr.rb +0 -130
- data/lib/mork/sheet_pdf.rb +17 -0
- data/lib/mork/version.rb +1 -1
- data/spec/mork/mimage_spec.rb +12 -0
- data/spec/mork/sheet_omr_spec.rb +7 -2
- data/spec/samples/base_layout.yml +9 -0
- metadata +2 -4
- data/lib/mork/mimage_list.rb +0 -32
- data/spec/mork/mimage_list_spec.rb +0 -37
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b30b33a147b248a73592bcea2dd9ff4d7952a4fb
|
4
|
+
data.tar.gz: e85ca2b34c0b579ec8bf7a3885331ac9ef74c62b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0649c313f2db3af8d358c03787c0c773c4962cd40ea245758b1bfcb40bec331568c05523371410e81dc4e845ab370d42028331bb685241538856c4875c213e57
|
7
|
+
data.tar.gz: 283fe8d57acd7451bca93920e1049218c1b6574c2944e5c8711dd43a2dbc25a096d802bf2929bcd91719c86efbfb44fe603043e1af60ac33a6375e9be54c2efa
|
data/lib/mork/grid.rb
CHANGED
@@ -65,14 +65,6 @@ module Mork
|
|
65
65
|
private
|
66
66
|
#====================#
|
67
67
|
|
68
|
-
# recursively turn hash keys into symbols. pasted from
|
69
|
-
# http://stackoverflow.com/questions/800122/best-way-to-convert-strings-to-symbols-in-hash
|
70
|
-
# def symbolize(obj)
|
71
|
-
# return obj.inject({}){|memo,(k,v)| memo[k.to_sym] = symbolize(v); memo} if obj.is_a? Hash
|
72
|
-
# return obj.inject([]){|memo,v | memo << symbolize(v); memo} if obj.is_a? Array
|
73
|
-
# return obj
|
74
|
-
# end
|
75
|
-
|
76
68
|
# cell_y(q)
|
77
69
|
#
|
78
70
|
# the distance from the registration frame to the top edge
|
@@ -129,5 +121,12 @@ module Mork
|
|
129
121
|
def page_height() @params[:page_size][:height].to_f end
|
130
122
|
def reg_margin() @params[:reg_marks][:margin].to_f end
|
131
123
|
def reg_radius() @params[:reg_marks][:radius].to_f end
|
124
|
+
def uid_digits() @params[:uid][:digits].to_i end
|
125
|
+
def uid_x() @params[:uid][:left].to_f end
|
126
|
+
def uid_y() @params[:uid][:top].to_f end
|
127
|
+
def uid_width() @params[:uid][:width].to_f end
|
128
|
+
def uid_height() @params[:uid][:height].to_f end
|
129
|
+
def uid_cell_width() @params[:uid][:cell_width].to_f end
|
130
|
+
def uid_cell_height() @params[:uid][:cell_height].to_f end
|
132
131
|
end
|
133
132
|
end
|
data/lib/mork/grid_const.rb
CHANGED
data/lib/mork/grid_omr.rb
CHANGED
@@ -26,8 +26,18 @@ module Mork
|
|
26
26
|
# ===========================================
|
27
27
|
# = Returning Coord sets for area locations =
|
28
28
|
# ===========================================
|
29
|
+
def choice_cell_areas
|
30
|
+
@choice_cell_areas ||= begin
|
31
|
+
max_questions.times.map do |q|
|
32
|
+
max_choices_per_question.times.map do |c|
|
33
|
+
coord cell_x(q,c), cell_y(q), cell_width, cell_height
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
29
39
|
def choice_cell_area(q, c)
|
30
|
-
|
40
|
+
choice_cell_areas[q][c]
|
31
41
|
end
|
32
42
|
|
33
43
|
def calibration_cell_areas
|
@@ -78,52 +88,3 @@ module Mork
|
|
78
88
|
end
|
79
89
|
end
|
80
90
|
end
|
81
|
-
|
82
|
-
# # the 4 values needed to locate a single registration mark
|
83
|
-
#
|
84
|
-
# def rm_search_area(corner, i)
|
85
|
-
# {
|
86
|
-
# x: (ppu_x * rmx(corner, i)).round,
|
87
|
-
# y: (ppu_y * rmy(corner, i)).round,
|
88
|
-
# w: (ppu_x * (reg_search + reg_radius * i)).round,
|
89
|
-
# h: (ppu_y * (reg_search + reg_radius * i)).round
|
90
|
-
# }
|
91
|
-
# end
|
92
|
-
|
93
|
-
# # finding the x position of the registration area based on iteration
|
94
|
-
# def rmx(corner, i)
|
95
|
-
# case corner
|
96
|
-
# when :tl; reg_off
|
97
|
-
# when :tr; page_width - reg_search - reg_off - reg_radius * i
|
98
|
-
# when :br; page_width - reg_search - reg_off - reg_radius * i
|
99
|
-
# when :bl; reg_off
|
100
|
-
# end
|
101
|
-
# end
|
102
|
-
|
103
|
-
# # finding the y position of the registration area based on iteration
|
104
|
-
# def rmy(corner, i)
|
105
|
-
# case corner
|
106
|
-
# when :tl; reg_off
|
107
|
-
# when :tr; reg_off
|
108
|
-
# when :br; page_height - reg_search - reg_off - reg_radius * i
|
109
|
-
# when :bl; page_height - reg_search - reg_off - reg_radius * i
|
110
|
-
# end
|
111
|
-
# end
|
112
|
-
|
113
|
-
# def rm_edgy_x() (ppu_x * reg_radius).round + 5 end
|
114
|
-
# def rm_edgy_y() (ppu_y * reg_radius).round + 5 end
|
115
|
-
# def rm_max_search_area_side() (ppu_x * page_width / 4).round end
|
116
|
-
|
117
|
-
# def cell_corner_size
|
118
|
-
# d = choice_cell_area(0,0)
|
119
|
-
# (d[:w]-d[:h]).abs
|
120
|
-
# end
|
121
|
-
|
122
|
-
# # GET RID OF THIS!
|
123
|
-
# def barcode_bit_areas(bitstring = '1' * barcode_bits)
|
124
|
-
# areas = []
|
125
|
-
# bitstring.reverse.each_char.with_index do |c, i|
|
126
|
-
# areas << barcode_bit_area(i+1) if c=='1'
|
127
|
-
# end
|
128
|
-
# areas
|
129
|
-
# end
|
data/lib/mork/grid_pdf.rb
CHANGED
@@ -70,6 +70,27 @@ module Mork
|
|
70
70
|
@cround ||= [width_of_cell, height_of_cell].min / 2
|
71
71
|
end
|
72
72
|
|
73
|
+
# UIDs
|
74
|
+
def width_of_uid
|
75
|
+
uid_cell_width.mm
|
76
|
+
end
|
77
|
+
|
78
|
+
def height_of_uid
|
79
|
+
uid_cell_height.mm
|
80
|
+
end
|
81
|
+
|
82
|
+
def uid_spacing_x
|
83
|
+
(uid_width / 11).mm
|
84
|
+
end
|
85
|
+
|
86
|
+
def uid_spacing_y
|
87
|
+
(uid_height / (uid_digits+1)).mm
|
88
|
+
end
|
89
|
+
|
90
|
+
def uround
|
91
|
+
@uround ||= [width_of_uid, height_of_uid].min / 2
|
92
|
+
end
|
93
|
+
|
73
94
|
def missing_header?(k)
|
74
95
|
@params[:header][k].nil?
|
75
96
|
end
|
data/lib/mork/magicko.rb
CHANGED
@@ -144,37 +144,3 @@ module Mork
|
|
144
144
|
end
|
145
145
|
end
|
146
146
|
end
|
147
|
-
|
148
|
-
# def patch(shape: nil, wid: width, hei: height)
|
149
|
-
# s = "|convert #{@path} #{shape} gray:-"
|
150
|
-
# bytes = IO.read(s).unpack 'C*'
|
151
|
-
# NPatch.new bytes, wid, hei
|
152
|
-
# end
|
153
|
-
|
154
|
-
# # raw_patch returns an array containing the pixels of the original image
|
155
|
-
# def raw_patch
|
156
|
-
# @raw_pixels ||= patch
|
157
|
-
# end
|
158
|
-
|
159
|
-
# def exec_mm_cmd(c, pp)
|
160
|
-
# c.distort(:perspective, pps(pp)) if pp
|
161
|
-
# @cmd.each { |cmd| c.send(*cmd) }
|
162
|
-
# end
|
163
|
-
|
164
|
-
# def highlight_cells(coords)
|
165
|
-
# @cmd << [:stroke, 'none']
|
166
|
-
# @cmd << [:fill, 'rgba(255, 255, 0, 0.3)']
|
167
|
-
# coords.each do |c|
|
168
|
-
# @cmd << [:draw, "roundrectangle #{c.choice_cell}"]
|
169
|
-
# end
|
170
|
-
# end
|
171
|
-
|
172
|
-
# def outline(coords)
|
173
|
-
# @cmd << [:stroke, 'green']
|
174
|
-
# @cmd << [:strokewidth, '2']
|
175
|
-
# @cmd << [:fill, 'none']
|
176
|
-
# coords.each do |c|
|
177
|
-
# @cmd << [:draw, "roundrectangle #{c.choice_cell}"]
|
178
|
-
# end
|
179
|
-
# end
|
180
|
-
|
data/lib/mork/mimage.rb
CHANGED
@@ -12,7 +12,8 @@ module Mork
|
|
12
12
|
def initialize(path, grom)
|
13
13
|
@mack = Magicko.new path
|
14
14
|
@grom = grom.set_page_size @mack.width, @mack.height
|
15
|
-
@choxq = [grom.max_choices_per_question] * grom.max_questions
|
15
|
+
# @choxq = [grom.max_choices_per_question] * grom.max_questions
|
16
|
+
@choxq = [(0...@grom.max_choices_per_question).to_a] * grom.max_questions
|
16
17
|
@rm = {} # registration mark centers
|
17
18
|
@valid = register
|
18
19
|
end
|
@@ -30,18 +31,24 @@ module Mork
|
|
30
31
|
}
|
31
32
|
end
|
32
33
|
|
33
|
-
def set_ch(
|
34
|
-
@choxq =
|
34
|
+
def set_ch(choxq)
|
35
|
+
@choxq = choxq.map { |ncho| (0...ncho).to_a }
|
35
36
|
# if set_ch is called more than once, discard memoization
|
36
|
-
@marked_choices = nil
|
37
|
+
@marked_choices = @choice_mean_darkness = nil
|
38
|
+
end
|
39
|
+
|
40
|
+
def choice_mean_darkness
|
41
|
+
@choice_mean_darkness ||= begin
|
42
|
+
itemator(@choxq) { |q,c| reg_pixels.average @grom.choice_cell_area(q, c) }
|
43
|
+
end
|
37
44
|
end
|
38
45
|
|
39
46
|
def marked
|
40
47
|
@marked_choices ||= begin
|
41
|
-
|
48
|
+
choice_mean_darkness.map do |cho|
|
42
49
|
[].tap do |choices|
|
43
|
-
|
44
|
-
choices << c if
|
50
|
+
cho.map.with_index do |drk, c|
|
51
|
+
choices << c if drk < choice_threshold
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
@@ -50,7 +57,7 @@ module Mork
|
|
50
57
|
|
51
58
|
def barcode_bits
|
52
59
|
@barcode_bits ||= begin
|
53
|
-
@grom.barcode_bits.times.
|
60
|
+
@grom.barcode_bits.times.map do |b|
|
54
61
|
reg_pixels.average(@grom.barcode_bit_area b+1) < barcode_threshold
|
55
62
|
end
|
56
63
|
end
|
@@ -65,10 +72,9 @@ module Mork
|
|
65
72
|
when :marked
|
66
73
|
choice_cell_areas marked
|
67
74
|
when :all
|
68
|
-
|
75
|
+
choice_cell_areas @choxq
|
69
76
|
when :max
|
70
|
-
|
71
|
-
# @grom.max_questions.times.map { |i| (0...@grom.max_choices_per_question).to_a }
|
77
|
+
@grom.choice_cell_areas.flatten
|
72
78
|
when Array
|
73
79
|
choice_cell_areas where
|
74
80
|
else
|
@@ -96,13 +102,9 @@ module Mork
|
|
96
102
|
private #
|
97
103
|
# ============================================================#
|
98
104
|
|
99
|
-
def itemator(
|
100
|
-
|
101
|
-
|
102
|
-
cho.times.map { |c| yield q, c }
|
103
|
-
else
|
104
|
-
cho.map { |c| yield q, c }
|
105
|
-
end
|
105
|
+
def itemator(cells)
|
106
|
+
cells.map.with_index do |cho, q|
|
107
|
+
cho.map { |c| yield q, c }
|
106
108
|
end
|
107
109
|
end
|
108
110
|
|
@@ -110,41 +112,24 @@ module Mork
|
|
110
112
|
itemator(cells) { |q,c| @grom.choice_cell_area q, c }.flatten
|
111
113
|
end
|
112
114
|
|
113
|
-
def all_choice_cell_areas
|
114
|
-
@all_choice_cell_areas ||= choice_cell_areas(@choxq)
|
115
|
-
end
|
116
|
-
|
117
115
|
def each_corner
|
118
116
|
[:tl, :tr, :br, :bl].each { |c| yield c }
|
119
117
|
end
|
120
118
|
|
121
|
-
def shade_of(q,c)
|
122
|
-
choice_cell_averages[q][c]
|
123
|
-
end
|
124
|
-
|
125
|
-
def choice_cell_averages
|
126
|
-
@choice_cell_averages ||= begin
|
127
|
-
itemator { |q, c| reg_pixels.average @grom.choice_cell_area(q, c) }
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
119
|
def choice_threshold
|
132
120
|
@choice_threshold ||= begin
|
133
|
-
|
121
|
+
dcm = choice_mean_darkness.flatten.min
|
122
|
+
(cal_cell_mean-dcm) * @grom.choice_threshold + dcm
|
134
123
|
end
|
135
124
|
end
|
136
125
|
|
137
|
-
def barcode_threshold
|
138
|
-
@barcode_threshold ||= (paper_white + ink_black) / 2
|
139
|
-
end
|
140
|
-
|
141
126
|
def cal_cell_mean
|
142
127
|
m = @grom.calibration_cell_areas.collect { |c| reg_pixels.average c }
|
143
128
|
m.inject(:+) / m.length.to_f
|
144
129
|
end
|
145
130
|
|
146
|
-
def
|
147
|
-
|
131
|
+
def barcode_threshold
|
132
|
+
@barcode_threshold ||= (paper_white + ink_black) / 2
|
148
133
|
end
|
149
134
|
|
150
135
|
def ink_black
|
@@ -159,12 +144,6 @@ module Mork
|
|
159
144
|
@reg_pixels ||= NPatch.new @mack.registered_bytes(@rm), @mack.width, @mack.height
|
160
145
|
end
|
161
146
|
|
162
|
-
def coordinates_of(cells)
|
163
|
-
cells.collect.each_with_index do |q, i|
|
164
|
-
q.collect { |c| @grom.choice_cell_area(i, c) }
|
165
|
-
end.flatten
|
166
|
-
end
|
167
|
-
|
168
147
|
# find the XY coordinates of the 4 registration marks,
|
169
148
|
# plus the stdev of the search area as quality control
|
170
149
|
def register
|
@@ -185,93 +164,3 @@ module Mork
|
|
185
164
|
end
|
186
165
|
end
|
187
166
|
end
|
188
|
-
|
189
|
-
# def corner
|
190
|
-
# @corner_size ||= @grom.cell_corner_size
|
191
|
-
# end
|
192
|
-
|
193
|
-
# 1000.times do |i|
|
194
|
-
# @rmsa[corner] = @grom.rm_search_area(corner, i)
|
195
|
-
# # puts "================================================================"
|
196
|
-
# # puts "Corner #{corner} - Iteration #{i} - Coo #{@rmsa[corner].inspect}"
|
197
|
-
# cx, cy = raw_pixels.dark_centroid @rmsa[corner]
|
198
|
-
# if cx.nil?
|
199
|
-
# status = :no_contrast
|
200
|
-
# elsif (cx < @grom.rm_edgy_x) or
|
201
|
-
# (cy < @grom.rm_edgy_y) or
|
202
|
-
# (cy > @rmsa[corner][:h] - @grom.rm_edgy_y) or
|
203
|
-
# (cx > @rmsa[corner][:w] - @grom.rm_edgy_x)
|
204
|
-
# status = :edgy
|
205
|
-
# else
|
206
|
-
# return {status: :ok, x: cx + @rmsa[corner][:x], y: cy + @rmsa[corner][:y]}
|
207
|
-
# end
|
208
|
-
# return {status: status, x: nil, y: nil} if @rmsa[corner][:w] > @grom.rm_max_search_area_side
|
209
|
-
# end
|
210
|
-
|
211
|
-
# TAKE OUT
|
212
|
-
# def highlight_reg_area
|
213
|
-
# @mack.highlight_rect [@rmsa[:tl], @rmsa[:tr], @rmsa[:br], @rmsa[:bl]]
|
214
|
-
# return unless valid?
|
215
|
-
# @mack.join [@rm[:tl], @rm[:tr], @rm[:br], @rm[:bl]]
|
216
|
-
# end
|
217
|
-
|
218
|
-
# def raw_pixels
|
219
|
-
# @mack.raw_patch
|
220
|
-
# end
|
221
|
-
|
222
|
-
# def outline(cells)
|
223
|
-
# return if cells.empty?
|
224
|
-
# @mack.outline coordinates_of(cells)
|
225
|
-
# end
|
226
|
-
|
227
|
-
# # highlight_cells(cells, roundedness)
|
228
|
-
# #
|
229
|
-
# # partially transparent yellow on top of choice cells
|
230
|
-
# def highlight_cells(cells)
|
231
|
-
# return if cells.empty?
|
232
|
-
# @mack.highlight_cells coordinates_of(cells)
|
233
|
-
# end
|
234
|
-
|
235
|
-
# def highlight_all_choices
|
236
|
-
# cells = (0...@grom.max_questions).collect { |i| (0...@grom.max_choices_per_question).to_a }
|
237
|
-
# highlight_cells cells
|
238
|
-
# end
|
239
|
-
|
240
|
-
# def highlight_barcode(bitstring)
|
241
|
-
# @mack.highlight_rect @grom.barcode_bit_areas bitstring
|
242
|
-
# end
|
243
|
-
|
244
|
-
# def highlight_rm_centers
|
245
|
-
# each_corner { |c| @mack.plus @rm[c][:x], @rm[c][:y], 20 }
|
246
|
-
# end
|
247
|
-
|
248
|
-
# def highlight_rm_areas
|
249
|
-
# each_corner { |c| @mack.highlight_area @grom.rm_crop_area(c) }
|
250
|
-
# end
|
251
|
-
|
252
|
-
# def cross(cells)
|
253
|
-
# return if cells.empty?
|
254
|
-
# cells = [cells] if cells.is_a? Hash
|
255
|
-
# @mack.cross coordinates_of(cells)
|
256
|
-
# end
|
257
|
-
|
258
|
-
# def barcode_bit?(i)
|
259
|
-
# reg_pixels.average(@grom.barcode_bit_area i+1) < barcode_threshold
|
260
|
-
# end
|
261
|
-
|
262
|
-
# puts "TL: #{@rm[:tl].inspect}"
|
263
|
-
# puts "TR: #{@rm[:tr].inspect}"
|
264
|
-
# puts "BR: #{@rm[:br].inspect}"
|
265
|
-
# puts "BL: #{@rm[:bl].inspect}"
|
266
|
-
|
267
|
-
# puts "REG #{@grom.rm_blur} - #{@grom.rm_dilate} - C #{c.inspect}"
|
268
|
-
|
269
|
-
# def marked_int
|
270
|
-
# marked.map do |q|
|
271
|
-
# [].tap do |choices|
|
272
|
-
# q.each_with_index do |choice, idx|
|
273
|
-
# choices << idx if choice
|
274
|
-
# end
|
275
|
-
# end
|
276
|
-
# end
|
277
|
-
# end
|
data/lib/mork/npatch.rb
CHANGED
@@ -27,33 +27,3 @@ module Mork
|
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
|
-
|
31
|
-
# def dark_centroid(c = nil)
|
32
|
-
# p = crop c
|
33
|
-
# sufficient_contrast?(p) or return
|
34
|
-
# xp = p.sum(1).to_a
|
35
|
-
# yp = p.sum(0).to_a
|
36
|
-
# # find the intensity trough
|
37
|
-
# ctr_x = xp.find_index(xp.min)
|
38
|
-
# ctr_y = yp.find_index(yp.min)
|
39
|
-
# # puts "Centroid: #{ctr_x}, #{ctr_y} - MinX #{xp.min/xp.length}, MaxX #{xp.max/xp.length}, MinY #{yp.min/yp.length}, MaxY #{yp.max/yp.length}"
|
40
|
-
# return ctr_x, ctr_y
|
41
|
-
# end
|
42
|
-
|
43
|
-
# def crop(c)
|
44
|
-
# raise "crop HELL" if c.nil?
|
45
|
-
# p = NArray.float c.w, c.h
|
46
|
-
# p[true,true] = @patch[c.x_rng, c.y_rng]
|
47
|
-
# p
|
48
|
-
# end
|
49
|
-
|
50
|
-
# def sufficient_contrast?(p)
|
51
|
-
# # puts "Contrast: #{p.stddev}"
|
52
|
-
# # tested with the few examples: spec/samples/rm0x.jpeg
|
53
|
-
# p.stddev > 20
|
54
|
-
# end
|
55
|
-
|
56
|
-
# def length
|
57
|
-
# # is this only going to be used for testing purposes?
|
58
|
-
# @patch.length
|
59
|
-
# end
|
data/lib/mork/sheet_omr.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
require 'mork/grid_omr'
|
2
2
|
require 'mork/mimage'
|
3
|
-
require 'mork/mimage_list'
|
4
3
|
|
5
4
|
module Mork
|
6
5
|
# Optical mark recognition of a response sheet that was: 1) generated
|
@@ -193,132 +192,3 @@ module Mork
|
|
193
192
|
end
|
194
193
|
end
|
195
194
|
end
|
196
|
-
|
197
|
-
|
198
|
-
# # write_raw(output_path_file_name)
|
199
|
-
# #
|
200
|
-
# # writes out a copy of the source image before registration;
|
201
|
-
# # the output image will also contain any previously applied overlays
|
202
|
-
# # if the argument is omitted, the image is created in-place,
|
203
|
-
# # i.e. the original source image is overwritten.
|
204
|
-
# def write_raw(fname=nil)
|
205
|
-
# @mim.write(fname, false)
|
206
|
-
# end
|
207
|
-
|
208
|
-
# # Array of arrays of marked choices.
|
209
|
-
# #
|
210
|
-
# # @param questions [Fixnum, Range, or Array] look for the first n questions
|
211
|
-
# # If the argument is omitted, all available choices are evaluated.
|
212
|
-
# # @return [Array] The list of marked choices as an array (one element per
|
213
|
-
# # question) of arrays (the indices of all marked choices for the question)
|
214
|
-
# def mark_array(questions = nil)
|
215
|
-
# return if not_registered
|
216
|
-
# x = question_range questions
|
217
|
-
# byebug
|
218
|
-
# x.collect do |q|
|
219
|
-
# [].tap do |cho|
|
220
|
-
# (0...@grom.max_choices_per_question).each do |c|
|
221
|
-
# cho << c if marked?(q, c)
|
222
|
-
# end
|
223
|
-
# end
|
224
|
-
# end
|
225
|
-
# end
|
226
|
-
|
227
|
-
# # Array of arrays of the characters corresponding to marked choices.
|
228
|
-
# # At this time, only the latin sequence 'A, B, C...' is supported.
|
229
|
-
# #
|
230
|
-
# # @param questions [Fixnum, Range, Array] same as for `mark_array`
|
231
|
-
# # @return [Array] The list of marked choices as an array (one element per
|
232
|
-
# # question) of arrays (the indices of all marked choices for the question)
|
233
|
-
# def mark_char_array(questions = nil)
|
234
|
-
# return if not_registered
|
235
|
-
# question_range(questions).collect do |q|
|
236
|
-
# [].tap do |cho|
|
237
|
-
# (0...@grom.max_choices_per_question).each do |c|
|
238
|
-
# cho << (65+c).chr if marked?(q, c)
|
239
|
-
# end
|
240
|
-
# end
|
241
|
-
# end
|
242
|
-
# end
|
243
|
-
|
244
|
-
# # Array of logical arrays of marked choices
|
245
|
-
# #
|
246
|
-
# # @param [Fixnum, Range, Array]
|
247
|
-
# def mark_logical_array(r = nil)
|
248
|
-
# return if not_registered
|
249
|
-
# question_range(r).collect do |q|
|
250
|
-
# (0...@grom.max_choices_per_question).collect {|c| marked?(q, c)}
|
251
|
-
# end
|
252
|
-
# end
|
253
|
-
|
254
|
-
# def question_range(r)
|
255
|
-
# # TODO: help text: although not API, people need to know this!
|
256
|
-
# if r.nil?
|
257
|
-
# (0...@nitems.length)
|
258
|
-
# elsif r.is_a? Fixnum
|
259
|
-
# (0...r)
|
260
|
-
# elsif r.is_a? Array
|
261
|
-
# r
|
262
|
-
# else
|
263
|
-
# raise "Invalid argument"
|
264
|
-
# end
|
265
|
-
# end
|
266
|
-
|
267
|
-
# def outline(cells)
|
268
|
-
# return if not_registered
|
269
|
-
# raise "Invalid ‘cells’ argument" unless cells.kind_of? Array
|
270
|
-
# @mim.outline cells
|
271
|
-
# end
|
272
|
-
|
273
|
-
# def cross(cells)
|
274
|
-
# return if not_registered
|
275
|
-
# raise "Invalid ‘cells’ argument" unless cells.kind_of? Array
|
276
|
-
# @mim.cross cells
|
277
|
-
# end
|
278
|
-
|
279
|
-
# def cross_marked
|
280
|
-
# return if not_registered
|
281
|
-
# @mim.cross mark_array
|
282
|
-
# end
|
283
|
-
|
284
|
-
# def highlight_all_choices
|
285
|
-
# return if not_registered
|
286
|
-
# @mim.highlight_all_choices
|
287
|
-
# end
|
288
|
-
|
289
|
-
# def highlight_marked
|
290
|
-
# return if not_registered
|
291
|
-
# @mim.highlight_cells mark_array
|
292
|
-
# end
|
293
|
-
|
294
|
-
# def highlight_barcode
|
295
|
-
# return if not_registered
|
296
|
-
# @mim.highlight_barcode barcode_string
|
297
|
-
# end
|
298
|
-
|
299
|
-
# def barcode_bit_string(i)
|
300
|
-
# @mim.barcode_bit?(i) ? "1" : "0"
|
301
|
-
# end
|
302
|
-
|
303
|
-
# def validate_choices(ch=nil)
|
304
|
-
# return false unless valid?
|
305
|
-
# cho = case ch
|
306
|
-
# when NilClass; [@mc] * @mq
|
307
|
-
# when Fixnum; [@mc] * [[ch, @mq].min, 1].max
|
308
|
-
# when Array; ch
|
309
|
-
# else raise ArgumentError, 'Invalid choice set'
|
310
|
-
# end
|
311
|
-
# @marked_choices = @mim.marked cho
|
312
|
-
# true
|
313
|
-
# end
|
314
|
-
|
315
|
-
# # Marked choices as boolean values
|
316
|
-
# #
|
317
|
-
# # @return [Array] an array of arrays of true/false values corresponding to
|
318
|
-
# # marked vs unmarked choice cells.
|
319
|
-
# def marked_logicals
|
320
|
-
# return if not_registered
|
321
|
-
# # this is the only marking function calling the mimage object
|
322
|
-
# @marked_choices ||= @mim.marked
|
323
|
-
# end
|
324
|
-
|
data/lib/mork/sheet_pdf.rb
CHANGED
@@ -145,6 +145,23 @@ module Mork
|
|
145
145
|
end
|
146
146
|
end
|
147
147
|
|
148
|
+
def create_uid_stamps
|
149
|
+
create_stamp('uid') do
|
150
|
+
10.times do |i|
|
151
|
+
offx = uid_spacing_x * i
|
152
|
+
stroke_rounded_rectangle [offx, 0],
|
153
|
+
@grip.width_of_uid,
|
154
|
+
@grip.height_of_uid,
|
155
|
+
@grip.uround
|
156
|
+
text_box i, at: [offx, 0],
|
157
|
+
width: @grip.width_of_uid,
|
158
|
+
height: @grip.height_of_uid,
|
159
|
+
align: :center,
|
160
|
+
valign: :center
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
148
165
|
def create_choice_stamps
|
149
166
|
ch_len.flatten.uniq.each do |t|
|
150
167
|
create_stamp("s#{t}") do
|
data/lib/mork/version.rb
CHANGED
data/spec/mork/mimage_spec.rb
CHANGED
@@ -8,6 +8,18 @@ module Mork
|
|
8
8
|
let(:img) { sample_img 'jdoe1' }
|
9
9
|
let(:fn) { File.basename(img.image_path) }
|
10
10
|
let(:mim) { Mimage.new img.image_path, GridOMR.new(img.grid_path) }
|
11
|
+
describe '#choice_mean_darkness' do
|
12
|
+
it 'returns all choices as darkness averaga' do
|
13
|
+
d = mim.choice_mean_darkness
|
14
|
+
d.each do |q|
|
15
|
+
p = q.map do |c|
|
16
|
+
c.round
|
17
|
+
end.join ' '
|
18
|
+
# puts p
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
11
23
|
describe 'basics' do
|
12
24
|
it 'should be valid' do
|
13
25
|
expect(mim.valid?).to be_truthy
|
data/spec/mork/sheet_omr_spec.rb
CHANGED
@@ -19,7 +19,7 @@ module Mork
|
|
19
19
|
|
20
20
|
describe '#set_choices' do
|
21
21
|
it 'returns true if all goes well' do
|
22
|
-
expect(omr.set_choices(10)).to be_truthy
|
22
|
+
expect(omr.set_choices([10])).to be_truthy
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
@@ -98,7 +98,7 @@ module Mork
|
|
98
98
|
|
99
99
|
it 'highlights all possible choice cells' do
|
100
100
|
omr.set_choices [5] * 30
|
101
|
-
|
101
|
+
omr.overlay :highlight, :max
|
102
102
|
omr.save "spec/out/highlight/max-#{fn}"
|
103
103
|
end
|
104
104
|
|
@@ -118,6 +118,11 @@ module Mork
|
|
118
118
|
omr.save "spec/out/mark/part-#{fn}"
|
119
119
|
end
|
120
120
|
|
121
|
+
it 'outlines arbitrary cells' do
|
122
|
+
omr.overlay :outline, [[1,2], [], [0,1,2,3,4], [3]]
|
123
|
+
omr.save "spec/out/outline/some-#{fn}"
|
124
|
+
end
|
125
|
+
|
121
126
|
it 'outlines and crosses marked cells' do
|
122
127
|
omr.overlay :outline, standard_mark_array(24)
|
123
128
|
omr.overlay :check
|
@@ -38,3 +38,12 @@ barcode:
|
|
38
38
|
width: 3 # width of each barcode bit
|
39
39
|
height: 3 # height of each barcode bit from the registration frame bottom side
|
40
40
|
spacing: 4 # horizontal distance between adjacent barcode bit centers
|
41
|
+
uid:
|
42
|
+
digits: 6
|
43
|
+
left: 150
|
44
|
+
top: 30
|
45
|
+
width: 50
|
46
|
+
height: 40
|
47
|
+
cell_width: 4
|
48
|
+
cell_height: 3
|
49
|
+
box: true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mork
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Giuseppe Bertini
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: narray
|
@@ -189,7 +189,6 @@ files:
|
|
189
189
|
- lib/mork/grid_pdf.rb
|
190
190
|
- lib/mork/magicko.rb
|
191
191
|
- lib/mork/mimage.rb
|
192
|
-
- lib/mork/mimage_list.rb
|
193
192
|
- lib/mork/npatch.rb
|
194
193
|
- lib/mork/sheet_omr.rb
|
195
194
|
- lib/mork/sheet_pdf.rb
|
@@ -200,7 +199,6 @@ files:
|
|
200
199
|
- spec/mork/grid_omr_spec.rb
|
201
200
|
- spec/mork/grid_spec.rb
|
202
201
|
- spec/mork/magicko_spec.rb
|
203
|
-
- spec/mork/mimage_list_spec.rb
|
204
202
|
- spec/mork/mimage_spec.rb
|
205
203
|
- spec/mork/npatch_spec.rb
|
206
204
|
- spec/mork/sheet_omr_spec.rb
|
data/lib/mork/mimage_list.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
# require 'RMagick'
|
2
|
-
|
3
|
-
module Mork
|
4
|
-
# @private
|
5
|
-
# The class MimageList, currently abandoned
|
6
|
-
class MimageList
|
7
|
-
def initialize(fname)
|
8
|
-
raise "Initializing a MimageList requires a string" unless fname.class == String
|
9
|
-
if File.extname(fname) == '.pdf'
|
10
|
-
@images = Magick::ImageList.new(fname) { self.density = 200 }
|
11
|
-
else
|
12
|
-
@images = Magick::ImageList.new(fname)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def shift
|
17
|
-
Mimage.new @images.shift
|
18
|
-
end
|
19
|
-
|
20
|
-
def [] (i)
|
21
|
-
# puts "I: #{i}"
|
22
|
-
# puts @images[i].inspect
|
23
|
-
Mimage.new @images[i]
|
24
|
-
end
|
25
|
-
|
26
|
-
def each
|
27
|
-
@images.each do |i|
|
28
|
-
yield Mimage.new i
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
module Mork
|
4
|
-
# describe MimageList do
|
5
|
-
# before(:all) do
|
6
|
-
# tpg = sample_img(:two_pages)
|
7
|
-
# @mlist = MimageList.new(tpg.filename)
|
8
|
-
# end
|
9
|
-
#
|
10
|
-
# describe ".new" do
|
11
|
-
# it "should raise an error unless called with a string" do
|
12
|
-
# lambda {
|
13
|
-
# MimageList.new(666)
|
14
|
-
# }.should raise_error
|
15
|
-
# end
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# describe "[]" do
|
19
|
-
# it "should return the 1st mimage in the stack" do
|
20
|
-
# @mlist[0].should be_a(Mimage)
|
21
|
-
# end
|
22
|
-
#
|
23
|
-
# it "should return the last mimage in the stack" do
|
24
|
-
# @mlist[1].should be_a(Mimage)
|
25
|
-
# end
|
26
|
-
# end
|
27
|
-
#
|
28
|
-
# describe "each" do
|
29
|
-
# it "should loop over all images" do
|
30
|
-
# @mlist.each do |m|
|
31
|
-
# puts m.inspect
|
32
|
-
# m.should be_a(Mimage)
|
33
|
-
# end
|
34
|
-
# end
|
35
|
-
# end
|
36
|
-
# end
|
37
|
-
end
|