qrio 0.0.1

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.
@@ -0,0 +1,25 @@
1
+ |##|##|##|#| *| $|$$|.$|$_| #|##|##|##|
2
+ |# | | |#| *|$ |$$|..|_$| #| | | #|
3
+ |# |##|# |#| *| |__|.$|__| #| #|##| #|
4
+ |# |##|# |#| *| |_ |.$|_ | #| #|##| #|
5
+ |# |##|# |#| *|. |$$|_.|$ | #| #|##| #|
6
+ |# | | |#| *|$.|$$|__| $| #| | | #|
7
+ |##|##|##|#| %| %| %| %| %| #|##|##|##|
8
+ | | | | | *|..| |_$| | | | | |
9
+ |**|**|**|%|**|..| $|_$| $|**|**|**|**|
10
+ | $|$_| $| |$$| $|.$| $|__|$$|.$|__| |
11
+ |$ |$_|$ |%|__|$ |$$| |_$| |..|__|$ |
12
+ |$ |$_|$ | |$_| |..| $|__| |..|$_| |
13
+ | $|_ | |%|_ |$ |. |$$|_ |$$|_$|$_| |
14
+ |X |$ |. | |$$|_ | $|. | | |_$| |$$|
15
+ |XX|$ |$.|%| |$_|$$|..| $|..|__| |__|
16
+ |XX|$ |$.| |$ |__| |.$| |..|__|$ |__|
17
+ |XX| $|..|%| $|$_| $|$$| #|##|##| $|__|
18
+ | | | | | *| $|$_| $|$#| | #|__| $|
19
+ |##|##|##|#| *|$ |$$| |$#| #| #|__| |
20
+ |# | | |#| *| |__|$$|$#| | #|$_| |
21
+ |# |##|# |#| *| $|_ | |$#|##|##|$$| |
22
+ |# |##|# |#| *|. |$ |. |__|$$|$_| |$_|
23
+ |# |##|# |#| *|$.|$$|..|__|$.|_$| |__|
24
+ |# | | |#| *|..| |$$| $| |__| $|__|
25
+ |##|##|##|#| *|.$| $|..|$$| |__| |__|
@@ -0,0 +1,25 @@
1
+ |##|##|##|#| #| |# | |##| #|##|##|##|
2
+ |# | | |#| #| | #|# |##| #| | | #|
3
+ |# |##|# |#| #| #| #| | #| #| #|##| #|
4
+ |# |##|# |#| #|# |# |##|# | #| #|##| #|
5
+ |# |##|# |#| #| #|# | #|##| #| #|##| #|
6
+ |# | | |#| #| | #|# |##| #| | | #|
7
+ |##|##|##|#| #| #| #| #| #| #|##|##|##|
8
+ | | | | | #|# |# |##|# | | | | |
9
+ |##|##|##|#|##| #| | | |##|##|##|##|
10
+ | |##| | | #|##|##|##|# | #|##|# |# |
11
+ | | | |#| #|##|# | #| | #| #| #|##|
12
+ |##|##|##| | |# |# |##|# |# |# | |# |
13
+ |##|# |# |#| #|##| #|# | #|# | |##| #|
14
+ |##|##| #| | #|# |##|# |# |# |##|# | #|
15
+ | #| | |#| #|##|# | #| | #| #| #| #|
16
+ |# |##|##| | |# |# |##|# |# |# | |# |
17
+ | #|##|# |#| |##| |# | #|##|##| | #|
18
+ | | | | | #|##| |##| #| | #|# |##|
19
+ |##|##|##|#| #|##|# | #|##| #| #| #| #|
20
+ |# | | |#| #|# |# | #| #| | #| |# |
21
+ |# |##|# |#| #| | #| #|##|##|##|# | #|
22
+ |# |##|# |#| #|# | |# |# | #| |# | |
23
+ |# |##|# |#| #|##|# | #| #|##| | #| #|
24
+ |# | | |#| #|# |# | #|##|# |# |##|# |
25
+ |##|##|##|#| #| | | #|# | #| #| #| #|
@@ -0,0 +1,100 @@
1
+ 01000010
2
+ 11110110
3
+ 11110110
4
+ 11000110
5
+ 00000110
6
+ 01110110
7
+ 11010010
8
+ 11110010
9
+ 10000111
10
+ 10010111
11
+ 11110111
12
+ 11110111
13
+ 01000111
14
+ 01000110
15
+ 00100111
16
+ 00010111
17
+ 01000111
18
+ 10000111
19
+ 01010110
20
+ 00100110
21
+ 00000111
22
+ 01010110
23
+ 00100111
24
+ 10010110
25
+ 00110011
26
+ 00100010
27
+ 10010111
28
+ 11110000
29
+ 10100010
30
+ 11100110
31
+ 00110110
32
+ 11101100
33
+ 11110010
34
+ 00110110
35
+ 11110110
36
+ 00010001
37
+ 01010000
38
+ 01110010
39
+ 00010010
40
+ 00110100
41
+ 00100001
42
+ 11101101
43
+ 10001010
44
+ 00010011
45
+ 10001110
46
+ 11100110
47
+ 11000111
48
+ 00010001
49
+ 11000101
50
+ 10011011
51
+ 10101110
52
+ 00100101
53
+ 11011111
54
+ 00010101
55
+ 10111101
56
+ 11111111
57
+ 10111000
58
+ 00011111
59
+ 00010110
60
+ 01010000
61
+ 01111110
62
+ 10010101
63
+ 10010001
64
+ 10111100
65
+ 01011100
66
+ 10000011
67
+ 00001010
68
+ 11010010
69
+ 01100011
70
+ 11010011
71
+ 11110101
72
+ 11001001
73
+ 00000111
74
+ 01111111
75
+ 11011001
76
+ 01110011
77
+ 00000101
78
+ 10110001
79
+ 00111000
80
+ 10111110
81
+ 10111011
82
+ 01000010
83
+ 10100000
84
+ 10001100
85
+ 11001100
86
+ 11000100
87
+ 11100110
88
+ 00111110
89
+ 00011110
90
+ 11011100
91
+ 10001111
92
+ 01111010
93
+ 11110100
94
+ 00111111
95
+ 10010000
96
+ 10101010
97
+ 00100100
98
+ 11110100
99
+ 01011110
100
+ 11011101
@@ -0,0 +1,33 @@
1
+ xxxxxxx x x x x x xxxxxxx
2
+ x x x xxxxxx xxx x x x
3
+ x xxx x xx xxx xx xxxx x xxx x
4
+ x xxx x x x xx x x xx x xxx x
5
+ x xxx x xx xx x xxxx xx x xxx x
6
+ x x xxx x xxxx x x
7
+ xxxxxxx x x x x x x x x x xxxxxxx
8
+ xxx x x xxx xx
9
+ xx xx xx x xxx x x xx
10
+ xx x xx xx x xxxxx x xxx
11
+ xxx xx xxxxxxxx xx x xxx
12
+ xxx x x xx xx xxxx xxxxxx
13
+ x xxx xxx x x xx x x x x x
14
+ xx x x x xxxxx x x xx x x x
15
+ x xxx x x xx xx x xx
16
+ x xxx x x x xx xxxx x x x
17
+ x xx x x x x x x x xx xx x
18
+ x xx x x x x xxxx x
19
+ x x xxxx xxxx xxxx xx xxx xx x
20
+ x xx xxxx x x xxxx xxxx
21
+ x x x x xxx x x x x
22
+ xx x xx x x x xxx xx
23
+ x x x x x x x x xx xx xxx
24
+ x x x x xx x x xx xx xx xxx
25
+ xxxxx x xxx x xx xxxxx
26
+ xx x x x x xx xx x
27
+ xxxxxxx xxx xx xxxxxxxx x xx
28
+ x x xxx xx x x xx xxxx
29
+ x xxx x xxx xx xx xx xxxxxx x
30
+ x xxx x xxx x x x x x x
31
+ x xxx x x x x x x x xx x xx
32
+ x x x xx x x x xxxx
33
+ xxxxxxx x x x x x xxxx xx
@@ -0,0 +1,34 @@
1
+ require_relative '../lib/qrio'
2
+ require 'test/unit'
3
+
4
+ class TestHorizontalMatch < Test::Unit::TestCase
5
+ def test_adjacency_detection
6
+ hmatch1 = Qrio::HorizontalMatch.build(2, 0, 8)
7
+ hmatch2 = Qrio::HorizontalMatch.build(3, 0, 8)
8
+ hmatch3 = Qrio::HorizontalMatch.build(3, 5, 13)
9
+
10
+ assert hmatch1.origin_matches?(hmatch2)
11
+ assert hmatch1.terminus_matches?(hmatch2)
12
+ assert hmatch1.endpoints_match?(hmatch2)
13
+ assert hmatch1.offset_matches?(hmatch2)
14
+ assert hmatch1.adjacent?(hmatch2)
15
+
16
+ refute hmatch1.adjacent?(hmatch3)
17
+
18
+ # slice1 = @s.new(3, 26, 82, 39)
19
+ # slice2 = @s.new(3, 40, 81, 58)
20
+ # assert slice1.adjacent?(slice2)
21
+ end
22
+
23
+ def test_slice_sorting
24
+ input = [
25
+ [2, 0, 8],
26
+ [3, 1, 9],
27
+ [4, 0, 8]
28
+ ].map{|c| Qrio::HorizontalMatch.build(*c) }
29
+ output = input.sort
30
+
31
+ assert_equal [0, 1, 0], output.map{|s| s.left }
32
+ assert_equal [2, 3, 4], output.map{|s| s.top }
33
+ end
34
+ end
@@ -0,0 +1,66 @@
1
+ require_relative '../lib/qrio'
2
+ require 'test/unit'
3
+
4
+ class TestMatrix < Test::Unit::TestCase
5
+ def test_random_access
6
+ matrix = Qrio::Matrix.new([1, 1, 0, 0], 2, 2)
7
+ assert_equal 2, matrix.rows.length
8
+ assert_equal 2, matrix.columns.length
9
+
10
+ assert_equal [1, 1], matrix.rows[0]
11
+ assert_equal [0, 0], matrix.rows[1]
12
+ assert_equal [1, 0], matrix.columns[0]
13
+ assert_equal [1, 0], matrix.columns[1]
14
+
15
+ assert_equal 1, matrix[0, 0]
16
+ assert_equal 0, matrix[0, 1]
17
+ assert_equal 1, matrix[1, 0]
18
+ assert_equal 0, matrix[1, 1]
19
+ end
20
+
21
+ def test_rotation
22
+ matrix = Qrio::Matrix.new([1, 0, 1, 0, 0, 0, 0, 1, 0], 3, 3)
23
+ rotated = matrix.rotate
24
+
25
+ assert_equal [0, 0, 1], rotated.rows[0]
26
+ assert_equal [1, 0, 0], rotated.rows[1]
27
+ assert_equal [0, 0, 1], rotated.rows[2]
28
+ end
29
+
30
+ def test_extraction
31
+ matrix = Qrio::Matrix.new([
32
+ 1, 0, 0, 0,
33
+ 0, 1, 1, 0,
34
+ 0, 0, 1, 0,
35
+ 0, 0, 0, 1
36
+ ], 4, 4)
37
+
38
+ center = matrix.extract(1, 1, 2, 2)
39
+ assert_equal 2, center.width
40
+ assert_equal 2, center.height
41
+
42
+ assert_equal [1, 1], center.rows[0]
43
+ assert_equal [0, 1], center.rows[1]
44
+
45
+ extracted = matrix.extract(1, 1, 3, 2)
46
+ assert_equal 3, extracted.width
47
+ assert_equal 2, extracted.height
48
+
49
+ assert_equal [1, 1, 0], extracted.rows[0]
50
+ assert_equal [0, 1, 0], extracted.rows[1]
51
+ end
52
+
53
+ def test_set_bit
54
+ bits = Array.new(25, false)
55
+ matrix = Qrio::Matrix.new(bits, 5, 5)
56
+ refute matrix[4, 4]
57
+ refute matrix.rows.last.last
58
+ refute matrix.columns.last.last
59
+
60
+ matrix[4, 4] = true
61
+
62
+ assert matrix[4, 4]
63
+ assert matrix.rows.last.last
64
+ assert matrix.columns.last.last
65
+ end
66
+ end
@@ -0,0 +1,164 @@
1
+ require_relative '../lib/qrio'
2
+ require 'test/unit'
3
+
4
+ class TestQrMatrix < Test::Unit::TestCase
5
+ def setup
6
+ @bits, @qr = make_qr("block_test")
7
+ end
8
+
9
+ def test_to_s
10
+ assert_equal bits_to_string(@bits, @qr.width), @qr.to_s
11
+ end
12
+
13
+ def test_format_detection
14
+ @qr[1, 8] = false
15
+ assert_equal 'M', @qr.error_correction_level
16
+ end
17
+
18
+
19
+ def test_dimensions
20
+ assert_equal 25, @qr.width
21
+ assert_equal 25, @qr.height
22
+ end
23
+
24
+ def test_position_detection
25
+ assert @qr.in_finder_pattern?(0, 6)
26
+ assert @qr.in_finder_pattern?(0, 7)
27
+ assert @qr.in_finder_pattern?(0, 8)
28
+ refute @qr.in_finder_pattern?(0, 9)
29
+
30
+ assert @qr.in_finder_pattern?(6, 0)
31
+ assert @qr.in_finder_pattern?(7, 0)
32
+ assert @qr.in_finder_pattern?(8, 0)
33
+ refute @qr.in_finder_pattern?(9, 0)
34
+
35
+ assert @qr.in_finder_pattern?(8, 3)
36
+
37
+ assert @qr.in_alignment_line?(14, 6)
38
+ assert @qr.in_alignment_line?(6, 14)
39
+
40
+
41
+ assert_equal 2, @qr.version
42
+ assert @qr.in_alignment_pattern?(16, 16)
43
+ assert @qr.in_alignment_pattern?(18, 18)
44
+ assert @qr.in_alignment_pattern?(20, 20)
45
+
46
+ refute @qr.in_alignment_pattern?(15, 16)
47
+ refute @qr.in_alignment_pattern?(16, 15)
48
+
49
+ refute @qr.in_alignment_pattern?(21, 20)
50
+ refute @qr.in_alignment_pattern?(20, 21)
51
+ end
52
+
53
+ def test_alignment_pattern_detection_by_version
54
+ # version one has no alignment patterns
55
+ v1 = Qrio::QrMatrix.new(Array.new(441, false), 21, 21)
56
+ assert_equal 1, v1.version
57
+
58
+ (0...20).each do |c|
59
+ refute v1.in_alignment_pattern?(c, c)
60
+ end
61
+
62
+ # construct versions 2 - 10 and verify alignment patterns
63
+ [18, 22, 26, 30, 34, [22, 38], [24, 42], [26, 46], [28, 50]].each_with_index do |ap_centers, index|
64
+ version = index + 2
65
+ dimension = version * 4 + 17
66
+ bits = Array.new(dimension * dimension, false)
67
+
68
+ qr = Qrio::QrMatrix.new(bits, dimension, dimension)
69
+ assert_equal version, qr.version
70
+
71
+ qr.draw_alignment_patterns
72
+ verify_alignment_centers(qr, *ap_centers)
73
+ qr.raw_bytes.each do |byte|
74
+ assert_equal 0, byte
75
+ end
76
+ end
77
+ end
78
+
79
+ def test_read_raw_bytes
80
+ bytes = @qr.raw_bytes
81
+ bytes.each_with_index do |byte, index|
82
+ assert_equal index + 1, byte
83
+ end
84
+ end
85
+
86
+ def test_unmask
87
+ @qr[3,8] = false
88
+ assert_equal 0, @qr.mask_pattern
89
+
90
+ _, @masked = make_qr("masked0")
91
+ @qr.unmask
92
+
93
+ assert_equal @masked.raw_bytes, @qr.raw_bytes
94
+ end
95
+
96
+ def test_text
97
+ _, qrio = make_qr("qrio")
98
+ qrio.unmask
99
+ assert_equal fixture_content("qrio-codewords.txt").split("\n"),
100
+ qrio.raw_bytes.map{|b| b.to_s(2).rjust(8, '0') }
101
+
102
+ assert_equal 4, qrio.version
103
+ assert_equal 'H', qrio.error_correction_level
104
+ assert_equal 4, qrio.block_count
105
+ assert_equal 16, qrio.ecc_bytes_per_block
106
+
107
+ assert_equal "https://github.com/rubysolo/qrio", qrio.text
108
+ end
109
+
110
+ private
111
+
112
+ def verify_alignment_centers(qr, *centers)
113
+ cols = *centers.dup
114
+ rows = *centers.dup
115
+
116
+ refute qr.in_alignment_pattern? 6, 6
117
+ refute qr.in_alignment_pattern? qr.width - 7, 8
118
+ refute qr.in_alignment_pattern? 8, qr.height - 7
119
+
120
+ cols.each do |cy|
121
+ rows.each do |cx|
122
+ assert qr.in_alignment_pattern?(cx, cy), "(#{ cx }, #{ cy }) should be ap center (version #{ qr.version })"
123
+ assert qr.in_alignment_pattern?(cx - 2, cy - 2)
124
+ assert qr.in_alignment_pattern?(cx - 2, cy + 2)
125
+ assert qr.in_alignment_pattern?(cx + 2, cy - 2)
126
+ assert qr.in_alignment_pattern?(cx + 2, cy + 2)
127
+
128
+ refute qr.in_alignment_pattern?(cx - 3, cy - 2), "(#{ cx - 3}, #{ cy - 2}) should be outside alignment pattern (version #{ qr.version })"
129
+ refute qr.in_alignment_pattern?(cx - 2, cy - 3)
130
+ refute qr.in_alignment_pattern?(cx + 3, cy + 2)
131
+ refute qr.in_alignment_pattern?(cx + 2, cy + 3)
132
+ end
133
+ end
134
+ end
135
+
136
+ def fixture_content(filename)
137
+ IO.read(File.expand_path("../fixtures/#{ filename }", __FILE__))
138
+ end
139
+
140
+ def make_qr(which)
141
+ raw = fixture_content("#{ which }.qr")
142
+ data = raw.strip.gsub(/\|/, '').split(/\n/)
143
+
144
+ width = data.first.length
145
+ height = data.length
146
+ off = ' _.,'.split(//)
147
+
148
+ bits = data.join('').split(//).map{|s| ! off.include?(s) }
149
+ [bits, Qrio::QrMatrix.new(bits, width, height)]
150
+ end
151
+
152
+ def bits_to_string(bits, width)
153
+ chars = bits.map{|b| b ? '#' : ' ' }
154
+ string = []
155
+ while row = chars.slice!(0, width)
156
+ break if row.nil? || row.empty?
157
+ string << row.join
158
+ end
159
+ string << nil
160
+
161
+ string.join("\n")
162
+ end
163
+
164
+ end