mork 0.11.2 → 0.12.0
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 +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
|