rqrcode_core 0.1.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.
@@ -0,0 +1,252 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RQRCodeCore
4
+ class QRUtil
5
+ PATTERN_POSITION_TABLE = [
6
+ [],
7
+ [6, 18],
8
+ [6, 22],
9
+ [6, 26],
10
+ [6, 30],
11
+ [6, 34],
12
+ [6, 22, 38],
13
+ [6, 24, 42],
14
+ [6, 26, 46],
15
+ [6, 28, 50],
16
+ [6, 30, 54],
17
+ [6, 32, 58],
18
+ [6, 34, 62],
19
+ [6, 26, 46, 66],
20
+ [6, 26, 48, 70],
21
+ [6, 26, 50, 74],
22
+ [6, 30, 54, 78],
23
+ [6, 30, 56, 82],
24
+ [6, 30, 58, 86],
25
+ [6, 34, 62, 90],
26
+ [6, 28, 50, 72, 94],
27
+ [6, 26, 50, 74, 98],
28
+ [6, 30, 54, 78, 102],
29
+ [6, 28, 54, 80, 106],
30
+ [6, 32, 58, 84, 110],
31
+ [6, 30, 58, 86, 114],
32
+ [6, 34, 62, 90, 118],
33
+ [6, 26, 50, 74, 98, 122],
34
+ [6, 30, 54, 78, 102, 126],
35
+ [6, 26, 52, 78, 104, 130],
36
+ [6, 30, 56, 82, 108, 134],
37
+ [6, 34, 60, 86, 112, 138],
38
+ [6, 30, 58, 86, 114, 142],
39
+ [6, 34, 62, 90, 118, 146],
40
+ [6, 30, 54, 78, 102, 126, 150],
41
+ [6, 24, 50, 76, 102, 128, 154],
42
+ [6, 28, 54, 80, 106, 132, 158],
43
+ [6, 32, 58, 84, 110, 136, 162],
44
+ [6, 26, 54, 82, 110, 138, 166],
45
+ [6, 30, 58, 86, 114, 142, 170]
46
+ ]
47
+
48
+ G15 = 1 << 10 | 1 << 8 | 1 << 5 | 1 << 4 | 1 << 2 | 1 << 1 | 1 << 0
49
+ G18 = 1 << 12 | 1 << 11 | 1 << 10 | 1 << 9 | 1 << 8 | 1 << 5 | 1 << 2 | 1 << 0
50
+ G15_MASK = 1 << 14 | 1 << 12 | 1 << 10 | 1 << 4 | 1 << 1
51
+
52
+ DEMERIT_POINTS_1 = 3
53
+ DEMERIT_POINTS_2 = 3
54
+ DEMERIT_POINTS_3 = 40
55
+ DEMERIT_POINTS_4 = 10
56
+
57
+ BITS_FOR_MODE = {
58
+ QRMODE[:mode_number] => [10, 12, 14],
59
+ QRMODE[:mode_alpha_numk] => [9, 11, 13],
60
+ QRMODE[:mode_8bit_byte] => [8, 16, 16],
61
+ QRMODE[:mode_kanji] => [8, 10, 12],
62
+ }
63
+
64
+ def QRUtil.max_size
65
+ PATTERN_POSITION_TABLE.count
66
+ end
67
+
68
+ def QRUtil.get_bch_format_info( data )
69
+ d = data << 10
70
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15) >= 0
71
+ d ^= (G15 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G15)))
72
+ end
73
+ (( data << 10 ) | d) ^ G15_MASK
74
+ end
75
+
76
+ def QRUtil.get_bch_version(data)
77
+ d = data << 12
78
+ while QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18) >= 0
79
+ d ^= (G18 << (QRUtil.get_bch_digit(d) - QRUtil.get_bch_digit(G18)))
80
+ end
81
+ ( data << 12 ) | d
82
+ end
83
+
84
+ def QRUtil.get_bch_digit( data )
85
+ digit = 0
86
+
87
+ while data != 0
88
+ digit = digit + 1
89
+ data = (data).rszf(1)
90
+ end
91
+
92
+ digit
93
+ end
94
+
95
+ def QRUtil.get_pattern_positions(version)
96
+ PATTERN_POSITION_TABLE[version - 1]
97
+ end
98
+
99
+ def QRUtil.get_mask( mask_pattern, i, j )
100
+ if mask_pattern > QRMASKCOMPUTATIONS.size
101
+ raise QRCodeRunTimeError, "bad mask_pattern: #{mask_pattern}"
102
+ end
103
+
104
+ return QRMASKCOMPUTATIONS[mask_pattern].call(i, j)
105
+ end
106
+
107
+ def QRUtil.get_error_correct_polynomial( error_correct_length )
108
+ a = QRPolynomial.new( [1], 0 )
109
+
110
+ ( 0...error_correct_length ).each do |i|
111
+ a = a.multiply( QRPolynomial.new( [1, QRMath.gexp(i)], 0 ) )
112
+ end
113
+
114
+ a
115
+ end
116
+
117
+ def QRUtil.get_length_in_bits(mode, version)
118
+ if !QRMODE.value?(mode)
119
+ raise QRCodeRunTimeError, "Unknown mode: #{mode}"
120
+ end
121
+
122
+ if version > 40
123
+ raise QRCodeRunTimeError, "Unknown version: #{version}"
124
+ end
125
+
126
+ if version.between?(1, 9)
127
+ # 1 - 9
128
+ macro_version = 0
129
+ elsif version <= 26
130
+ # 10 - 26
131
+ macro_version = 1
132
+ elsif version <= 40
133
+ # 27 - 40
134
+ macro_version = 2
135
+ end
136
+
137
+ return BITS_FOR_MODE[mode][macro_version]
138
+ end
139
+
140
+ def QRUtil.get_lost_points(modules)
141
+ demerit_points = 0
142
+
143
+ demerit_points += QRUtil.demerit_points_1_same_color(modules)
144
+ demerit_points += QRUtil.demerit_points_2_full_blocks(modules)
145
+ demerit_points += QRUtil.demerit_points_3_dangerous_patterns(modules)
146
+ demerit_points += QRUtil.demerit_points_4_dark_ratio(modules)
147
+
148
+ return demerit_points
149
+ end
150
+
151
+ def QRUtil.demerit_points_1_same_color(modules)
152
+ demerit_points = 0
153
+ module_count = modules.size
154
+
155
+ # level1
156
+ (0...module_count).each do |row|
157
+ (0...module_count).each do |col|
158
+ same_count = 0
159
+ dark = modules[row][col]
160
+
161
+ ( -1..1 ).each do |r|
162
+ next if row + r < 0 || module_count <= row + r
163
+
164
+ ( -1..1 ).each do |c|
165
+ next if col + c < 0 || module_count <= col + c
166
+ next if r == 0 && c == 0
167
+ if dark == modules[row + r][col + c]
168
+ same_count += 1
169
+ end
170
+ end
171
+ end
172
+
173
+ if same_count > 5
174
+ demerit_points += (DEMERIT_POINTS_1 + same_count - 5)
175
+ end
176
+ end
177
+ end
178
+
179
+ return demerit_points
180
+ end
181
+
182
+ def QRUtil.demerit_points_2_full_blocks(modules)
183
+ demerit_points = 0
184
+ module_count = modules.size
185
+
186
+ # level 2
187
+ (0...(module_count - 1)).each do |row|
188
+ (0...(module_count - 1)).each do |col|
189
+ count = 0
190
+ count += 1 if modules[row][col]
191
+ count += 1 if modules[row + 1][col]
192
+ count += 1 if modules[row][col + 1]
193
+ count += 1 if modules[row + 1][col + 1]
194
+ if (count == 0 || count == 4)
195
+ demerit_points += DEMERIT_POINTS_2
196
+ end
197
+ end
198
+ end
199
+
200
+ return demerit_points
201
+ end
202
+
203
+ def QRUtil.demerit_points_3_dangerous_patterns(modules)
204
+ demerit_points = 0
205
+ module_count = modules.size
206
+
207
+ # level 3
208
+ modules.each do |row|
209
+ (module_count - 6).times do |col_idx|
210
+ if row[col_idx] &&
211
+ !row[col_idx + 1] &&
212
+ row[col_idx + 2] &&
213
+ row[col_idx + 3] &&
214
+ row[col_idx + 4] &&
215
+ !row[col_idx + 5] &&
216
+ row[col_idx + 6]
217
+ demerit_points += DEMERIT_POINTS_3
218
+ end
219
+ end
220
+ end
221
+
222
+ (0...module_count).each do |col|
223
+ (0...(module_count - 6)).each do |row|
224
+ if modules[row][col] &&
225
+ !modules[row + 1][col] &&
226
+ modules[row + 2][col] &&
227
+ modules[row + 3][col] &&
228
+ modules[row + 4][col] &&
229
+ !modules[row + 5][col] &&
230
+ modules[row + 6][col]
231
+ demerit_points += DEMERIT_POINTS_3
232
+ end
233
+ end
234
+ end
235
+
236
+ return demerit_points
237
+ end
238
+
239
+ def QRUtil.demerit_points_4_dark_ratio(modules)
240
+ # level 4
241
+ dark_count = modules.reduce(0) do |sum, col|
242
+ sum + col.count(true)
243
+ end
244
+
245
+ ratio = dark_count / (modules.size * modules.size)
246
+ ratio_delta = (100 * ratio - 50).abs / 5
247
+
248
+ demerit_points = ratio_delta * DEMERIT_POINTS_4
249
+ return demerit_points
250
+ end
251
+ end
252
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RQRCodeCore
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,32 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "rqrcode_core/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rqrcode_core"
8
+ spec.version = RQRCodeCore::VERSION
9
+ spec.platform = Gem::Platform::RUBY
10
+ spec.authors = ["Duncan Robertson"]
11
+ spec.email = ["duncan@whomwah.com"]
12
+
13
+ spec.summary = "A library to encode QR Codes"
14
+ spec.description = <<EOF
15
+ rqrcode_core is a Ruby library for encoding QR Codes. The simple
16
+ interface (with no runtime dependencies) allows you to create QR Code data structures.
17
+ EOF
18
+ spec.homepage = "https://github.com/whomwah/rqrcode_core"
19
+ spec.license = "MIT"
20
+
21
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = "exe"
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ["lib"]
27
+
28
+ spec.required_ruby_version = '~> 2.3'
29
+ spec.add_development_dependency "bundler", "~> 2.0"
30
+ spec.add_development_dependency "rake", "~> 10.0"
31
+ spec.add_development_dependency "minitest", "~> 5.0"
32
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rqrcode_core
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Duncan Robertson
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2019-07-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '2.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '2.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.0'
55
+ description: |
56
+ rqrcode_core is a Ruby library for encoding QR Codes. The simple
57
+ interface (with no runtime dependencies) allows you to create QR Code data structures.
58
+ email:
59
+ - duncan@whomwah.com
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - ".gitignore"
65
+ - Gemfile
66
+ - Gemfile.lock
67
+ - LICENSE.txt
68
+ - README.md
69
+ - Rakefile
70
+ - bin/console
71
+ - bin/setup
72
+ - lib/rqrcode_core.rb
73
+ - lib/rqrcode_core/core_ext.rb
74
+ - lib/rqrcode_core/core_ext/array.rb
75
+ - lib/rqrcode_core/core_ext/array/behavior.rb
76
+ - lib/rqrcode_core/core_ext/integer.rb
77
+ - lib/rqrcode_core/core_ext/integer/bitwise.rb
78
+ - lib/rqrcode_core/qrcode.rb
79
+ - lib/rqrcode_core/qrcode/qr_8bit_byte.rb
80
+ - lib/rqrcode_core/qrcode/qr_alphanumeric.rb
81
+ - lib/rqrcode_core/qrcode/qr_bit_buffer.rb
82
+ - lib/rqrcode_core/qrcode/qr_code.rb
83
+ - lib/rqrcode_core/qrcode/qr_math.rb
84
+ - lib/rqrcode_core/qrcode/qr_numeric.rb
85
+ - lib/rqrcode_core/qrcode/qr_polynomial.rb
86
+ - lib/rqrcode_core/qrcode/qr_rs_block.rb
87
+ - lib/rqrcode_core/qrcode/qr_util.rb
88
+ - lib/rqrcode_core/version.rb
89
+ - rqrcode_core.gemspec
90
+ homepage: https://github.com/whomwah/rqrcode_core
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.3'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubygems_version: 3.0.1
110
+ signing_key:
111
+ specification_version: 4
112
+ summary: A library to encode QR Codes
113
+ test_files: []