qrest 1.0.0 → 1.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 28f37a9b5e5fb20a07f781323ce9f2381ecadd873bec290b5b65811849adb563
4
- data.tar.gz: 7ba9b8e971a1e76bb5869455a15f0973f29575a82a11d671656070a16ae1cfe0
3
+ metadata.gz: 2490fb27884f2ab7c5172782a898c7b20f4c77709a3c1846a8af68c6d6133cb3
4
+ data.tar.gz: b80229455a23a9176cd0c4f0b34c0cc56fd95c5e91303f881d08b8310ae2495d
5
5
  SHA512:
6
- metadata.gz: 5d592804716c69561ceb2cd556c7581302a485c7925c6908d956ebeeb7277011da21cf07867af837942813073d7e0307b7af27e74f7911180b8bbf1a8c11ff23
7
- data.tar.gz: 72830cd5baadaefc25cade7df5a7a82af010a79ecb78f54e576c90551b09a2e072f943c42306f31e8fd873befaba0d63fdb495b26cb4188f9cbca3234b8c0e30
6
+ metadata.gz: e803f95b2ca0fbb93f21b5f00e750dca32672ee4fd7f658cac78feebf178b839984f6fcf4483bef180e5f89650b0472faa0b5e174e78da3cc8fbdbdd5c9ee18e
7
+ data.tar.gz: 3c41ee417fbd90787886ee4f492f8737f06f63c71d7b6f0333133c5675313dcbb9d7d6f8773dd47ae50528564ab14eb3abd79fd51ac341800c7f1715fa13cfe4
data/lib/qrest/bch.rb CHANGED
@@ -24,9 +24,9 @@ module QRest
24
24
 
25
25
  end
26
26
 
27
- G15 = 0b000010100110111
28
- G15_MASK = 0b101010000010010
29
- G18 = 0b001111100100101
27
+ G15 = 0b0_0000_0101_0011_0111
28
+ G15_MASK = 0b0_0101_0100_0001_0010
29
+ G18 = 0b0_0001_1111_0010_0101
30
30
 
31
31
  G15D = digit G15
32
32
  G18D = digit G18
@@ -34,19 +34,19 @@ module QRest
34
34
  class <<self
35
35
 
36
36
  def format_info data
37
- d = data << 10
37
+ d = e = data << 10
38
38
  until (m = (digit d) - G15D) < 0 do
39
39
  d ^= G15 << m
40
40
  end
41
- ((data << 10) | d) ^ G15_MASK
41
+ (e | d) ^ G15_MASK
42
42
  end
43
43
 
44
44
  def version data
45
- d = data << 12
45
+ d = e = data << 12
46
46
  until (m = (digit d) - G18D) < 0 do
47
47
  d ^= G18 << m
48
48
  end
49
- (data << 12) | d
49
+ e | d
50
50
  end
51
51
 
52
52
  end
@@ -16,7 +16,8 @@ module QRest
16
16
  def total **weigths
17
17
  weigths.inject 0 do |sum,(k,v)|
18
18
  e = ([*(send k)].zip [*v]).inject 0 do |s,(r,f)| s += r*f end
19
- sum += e.round
19
+ puts [k, v, e.class, e, e.round].inspect
20
+ sum + e.round
20
21
  end
21
22
  end
22
23
 
@@ -107,6 +108,7 @@ module QRest
107
108
 
108
109
 
109
110
  def dark_ratio
111
+ puts @fields.inspect
110
112
  dark = @fields.sum do |col| col.count true end
111
113
  all = @fields.size*@fields.size
112
114
  (dark.to_f / all - 0.5).abs * 100
data/lib/qrest/modules.rb CHANGED
@@ -12,6 +12,8 @@ module QRest
12
12
 
13
13
  class Modules
14
14
 
15
+ VERSIONS = 1..40
16
+
15
17
  POSITIONPATTERNLENGTH = (7 + 1) * 2 + 1
16
18
 
17
19
  ERRORCORRECTLEVEL = { l: 1, m: 0, q: 3, h: 2 }
@@ -38,7 +40,7 @@ module QRest
38
40
  proc { |i,j| ((i * j) % 3 + (i + j) % 2) % 2 },
39
41
  ]
40
42
 
41
- attr_reader :version, :count, :fields, :demerits
43
+ attr_reader :version, :count, :fields
42
44
 
43
45
  class <<self
44
46
 
@@ -49,31 +51,30 @@ module QRest
49
51
  dark_ratio: 2,
50
52
  }
51
53
 
52
- def create_best data, version, error_correct_level
53
- demerits, pattern = nil, 0
54
+ def create_best data
55
+ demerits, pattern = nil, nil
54
56
  MASK_PATTERNS.length.times { |i|
55
- test = new data, version, error_correct_level, true, i
56
- d = test.demerits.total **WEIGHTS
57
- demerits, pattern = d, i if not demerits or demerits > d
57
+ t = ModulesTest.new data, i
58
+ d = t.demerits.total **WEIGHTS
59
+ demerits, pattern = d, i if not pattern or demerits > d
58
60
  }
59
- new data, version, error_correct_level, false, pattern
61
+ new data, pattern
60
62
  end
61
63
 
62
64
  end
63
65
 
64
- def initialize data, version, ecl, test, mask_pattern
65
- count = version * 4 + POSITIONPATTERNLENGTH
66
+ def initialize data, mask_pattern
67
+ count = data.version * 4 + POSITIONPATTERNLENGTH
66
68
  @fields = Array.new count do Array.new count end
67
69
  place_position_probe_pattern 0, 0
68
70
  place_position_probe_pattern @fields.size - 7, 0
69
71
  place_position_probe_pattern 0, @fields.size - 7
70
- place_position_adjust_pattern version
72
+ place_position_adjust_pattern @fields.size
71
73
  place_timing_pattern
72
- place_format_info test, (ERRORCORRECTLEVEL[ecl]<<3) | mask_pattern
73
- place_version_info version, test if version >= 7
74
- bs = BitStream.new data
74
+ place_format_info (ERRORCORRECTLEVEL[data.error_correct_level]<<3) | mask_pattern
75
+ place_version_info data.version
76
+ bs = BitStream.new data.data
75
77
  walk_fields mask_pattern do bs.get end
76
- @demerits = Demerits.new @fields if test
77
78
  end
78
79
 
79
80
  def inspect
@@ -165,58 +166,47 @@ module QRest
165
166
  end
166
167
  end
167
168
 
168
- PATTERN_POSITION_TABLE = [
169
- [],
170
- [6, 18],
171
- [6, 22],
172
- [6, 26],
173
- [6, 30],
174
- [6, 34],
175
- [6, 22, 38],
176
- [6, 24, 42],
177
- [6, 26, 46],
178
- [6, 28, 50],
179
- [6, 30, 54],
180
- [6, 32, 58],
181
- [6, 34, 62],
182
- [6, 26, 46, 66],
183
- [6, 26, 48, 70],
184
- [6, 26, 50, 74],
185
- [6, 30, 54, 78],
186
- [6, 30, 56, 82],
187
- [6, 30, 58, 86],
188
- [6, 34, 62, 90],
189
- [6, 28, 50, 72, 94],
190
- [6, 26, 50, 74, 98],
191
- [6, 30, 54, 78, 102],
192
- [6, 28, 54, 80, 106],
193
- [6, 32, 58, 84, 110],
194
- [6, 30, 58, 86, 114],
195
- [6, 34, 62, 90, 118],
196
- [6, 26, 50, 74, 98, 122],
197
- [6, 30, 54, 78, 102, 126],
198
- [6, 26, 52, 78, 104, 130],
199
- [6, 30, 56, 82, 108, 134],
200
- [6, 34, 60, 86, 112, 138],
201
- [6, 30, 58, 86, 114, 142],
202
- [6, 34, 62, 90, 118, 146],
203
- [6, 30, 54, 78, 102, 126, 150],
204
- [6, 24, 50, 76, 102, 128, 154],
205
- [6, 28, 54, 80, 106, 132, 158],
206
- [6, 32, 58, 84, 110, 136, 162],
207
- [6, 26, 54, 82, 110, 138, 166],
208
- [6, 30, 58, 86, 114, 142, 170]
209
- ]
210
169
 
211
- MAX_VERSION = PATTERN_POSITION_TABLE.size
170
+ @adjust_pattern = {}
171
+
172
+ class <<self
173
+
174
+ ADJUST_FIRST = 6
175
+ def adjust_pattern_pos size
176
+ @adjust_pattern[ size] ||= begin
177
+ s = size - ADJUST_FIRST*2 - 1
178
+ if s < ADJUST_FIRST*2 then
179
+ []
180
+ else
181
+ kat = (s-1)/28
182
+ ds = [ 0]
183
+ case kat
184
+ when 0 then ds.push s
185
+ when 1 then h = s / 2 ; ds.push h, h
186
+ else
187
+ 28.step 20, -2 do |h|
188
+ m = s - kat*h
189
+ if m > h - [kat,3].max*2 then
190
+ ds.push m, *([ h] * kat)
191
+ break
192
+ end
193
+ end
194
+ end
195
+ p = ADJUST_FIRST
196
+ ds.map { |e| p += e }
197
+ end
198
+ end
199
+ end
200
+
201
+ end
212
202
 
213
203
  R_22 = -2..2
214
204
 
215
- def place_position_adjust_pattern version
216
- positions = PATTERN_POSITION_TABLE[ version - 1]
205
+ def place_position_adjust_pattern size
206
+ ps = Modules.adjust_pattern_pos size
217
207
  rd = R_22.minmax
218
- positions.each do |row|
219
- positions.each do |col|
208
+ ps.each do |row|
209
+ ps.each do |col|
220
210
  next unless @fields[ row][ col].nil?
221
211
  R_22.each do |r|
222
212
  pr = row + r
@@ -231,39 +221,45 @@ module QRest
231
221
 
232
222
  def place_timing_pattern
233
223
  (8...@fields.size-8).each do |i|
224
+ next unless @fields[ i][ 6].nil?
234
225
  @fields[ i][ 6] = @fields[ 6][ i] = i.even?
235
226
  end
236
227
  end
237
228
 
238
- def place_format_info test, ecl
229
+ def set_bit n
230
+ n.odd?
231
+ end
232
+
233
+ def place_format_info ecl
239
234
  bits = Bch.format_info ecl
240
235
  15.times do |i|
241
- mod = !test && bits.odd?
236
+ m = set_bit bits
242
237
  r =
243
238
  case i
244
239
  when ...6 then 0
245
240
  when ...8 then 1
246
241
  else @fields.size - 15
247
242
  end
248
- @fields[ r+i][ 8] = mod
243
+ @fields[ r + i][ 8] = m
249
244
  c =
250
245
  case i
251
246
  when ...8 then @fields.size
252
247
  when ...9 then 16
253
248
  else 15
254
249
  end
255
- @fields[ 8][ c - i - 1] = mod
250
+ @fields[ 8][ c - i - 1] = m
256
251
  bits >>= 1
257
252
  end
258
- @fields[ @fields.size - 8][ 8] = !test
253
+ @fields[ @fields.size - 8][ 8] = set_bit 1
259
254
  end
260
255
 
261
- def place_version_info version, test
256
+ def place_version_info version
257
+ return if version < 7
262
258
  bits = Bch.version version
263
259
  18.times do |i|
264
260
  id, im = i.divmod 3
265
261
  im += @fields.size - 8 - 3
266
- @fields[ id][ im] = @fields[ im][ id] = !test && (bits & 1) == 1
262
+ @fields[ id][ im] = @fields[ im][ id] = set_bit bits
267
263
  bits >>= 1
268
264
  end
269
265
  end
@@ -271,7 +267,8 @@ module QRest
271
267
  def walk_fields mask_pattern
272
268
  # An image says more than a thousand statements:
273
269
  # <https://en.wikipedia.org/wiki/QR_code#Message_placement>
274
- mp = MASK_PATTERNS[ mask_pattern] or raise ArgumentError, "Bad mask_pattern: #{mask_pattern}"
270
+ mp = MASK_PATTERNS[ mask_pattern] or
271
+ raise ArgumentError, "Bad mask_pattern: #{mask_pattern}"
275
272
  row = c2 = @fields.size - 1
276
273
  inc = -1
277
274
  loop do
@@ -296,5 +293,18 @@ module QRest
296
293
 
297
294
  end
298
295
 
296
+ class ModulesTest < Modules
297
+
298
+ attr_reader :demerits
299
+
300
+ def initialize data, mask_pattern
301
+ super
302
+ @demerits = Demerits.new @fields
303
+ end
304
+
305
+ def set_bit _ ; false ; end
306
+
307
+ end
308
+
299
309
  end
300
310
 
@@ -18,7 +18,7 @@ module QRest
18
18
  if error_correct_length > 0 then
19
19
  e = error_correct_length - 1
20
20
  ge = new [1, 0]
21
- ge.gexp! 1, e
21
+ ge.gfexp! 1, e
22
22
  (error_correct e).multiply ge
23
23
  else
24
24
  new [1]
@@ -57,55 +57,61 @@ module QRest
57
57
  @num.unshift 0 until @num.length >= n
58
58
  end
59
59
 
60
- def first_glog
61
- Polynomial.glog @num.first
60
+ def first_gflog
61
+ Polynomial.gflog @num.first
62
62
  end
63
63
 
64
- def each_glog
64
+ def each_gflog
65
65
  @num.each_with_index { |n,i|
66
- yield (Polynomial.glog n), i
66
+ yield (Polynomial.gflog n), i
67
67
  }
68
68
  end
69
69
 
70
- def gexp! i, n
71
- @num[ i] ^= Polynomial.gexp n
70
+ def gfexp! i, n
71
+ @num[ i] ^= Polynomial.gfexp n
72
72
  end
73
73
 
74
74
  def multiply e
75
75
  r = Polynomial.zeroes length + e.length - 1
76
- each_glog { |gi,i|
77
- e.each_glog { |gj,j|
78
- r.gexp! i + j, gi + gj
76
+ each_gflog { |gi,i|
77
+ e.each_gflog { |gj,j|
78
+ r.gfexp! i + j, gi + gj
79
79
  }
80
80
  }
81
81
  r
82
82
  end
83
83
 
84
84
  def error_mod error_count
85
- e = Polynomial.error_correct error_count
86
- ef = e.first_glog
87
85
  p = dup
88
- p.extend! error_count
86
+ p.error_mod! error_count
87
+ end
88
+
89
+ def error_mod! error_count
90
+ e = Polynomial.error_correct error_count
91
+ extend! error_count
89
92
  loop do
90
- p.norm!
91
- break if p.length < e.length
92
- ratio = p.first_glog - ef
93
- e.each_glog { |gi,i|
94
- p.gexp! i, ratio + gi
93
+ norm!
94
+ break if length < e.length
95
+ f = first_gflog
96
+ e.each_gflog { |gi,i|
97
+ gfexp! i, gi + f
95
98
  }
96
99
  end
97
- p.grow! error_count
98
- p
100
+ grow! error_count
101
+ self
99
102
  end
100
103
 
101
104
 
102
- EXP_TABLE = []
103
- (0...8).each do |i|
104
- EXP_TABLE.push 1 << i
105
- end
106
- (8...256).each do |i|
107
- EXP_TABLE.push EXP_TABLE[i-4] ^ EXP_TABLE[i-5] ^ EXP_TABLE[i-6] ^ EXP_TABLE[i-8]
105
+ EXP_TABLE = [1]
106
+ loop do
107
+ x = x_ = EXP_TABLE.last << 1
108
+ x &= 0xff
109
+ x ^= 0x1d if x != x_
110
+ break if x == EXP_TABLE.first
111
+ EXP_TABLE.push x
108
112
  end
113
+ EXP_TABLE
114
+
109
115
 
110
116
  LOG_TABLE = [nil] * 256
111
117
  255.times do |i|
@@ -117,15 +123,12 @@ module QRest
117
123
 
118
124
  class <<self
119
125
 
120
- def glog n
121
- n >= 1 or raise Error, "Internal error: glog(#{n})."
122
- LOG_TABLE[n]
126
+ def gflog n
127
+ LOG_TABLE[n] or raise ArgumentError, "Argument is out of domain: gflog(#{n})."
123
128
  end
124
129
 
125
- def gexp n
126
- while n < 0 do n += 255 end
127
- while n >= 256 do n -= 255 end
128
- EXP_TABLE[n]
130
+ def gfexp n
131
+ EXP_TABLE[n % 255]
129
132
  end
130
133
 
131
134
  end
@@ -9,134 +9,143 @@ require "qrest/polynomial"
9
9
 
10
10
  module QRest
11
11
 
12
- class RSBlocks
12
+ class RSData
13
13
 
14
- class Block
14
+ attr_reader :version, :error_correct_level, :data
15
15
 
16
- attr_reader :data_count, :total_count
17
-
18
- def initialize total_count, data_count
19
- @total_count, @data_count = total_count, data_count
20
- end
16
+ def initialize version, error_correct_level, input
17
+ @version, @error_correct_level = version, error_correct_level
18
+ b = Blocks.new @version, @error_correct_level
19
+ @data = b.create_data input, version
20
+ end
21
21
 
22
- def error_count ; total_count - data_count ; end
22
+ class Blocks
23
23
 
24
- end
24
+ class Block
25
+ attr_reader :data_count, :total_count
26
+ def initialize total_count, data_count
27
+ @total_count, @data_count = total_count, data_count
28
+ end
29
+ def error_count ; total_count - data_count ; end
30
+ end
25
31
 
26
- def initialize version, bs
27
- @version = version
28
- @list = bs.map { |num,total,data| [ num, (Block.new total, data)] }
29
- end
32
+ def initialize version, error_correct_level
33
+ @list = self.class.blocks[ version][ error_correct_level].map { |num,total,data|
34
+ [ num, (Block.new total, data)]
35
+ }
36
+ end
30
37
 
31
- def each ; @list.each { |(n,b)| n.times { yield b } } ; end
32
- def sum sym ; @list.map { |(n,b)| n * (b.send sym) }.sum ; end
33
- def max sym ; @list.map { |(_,b)| (b.send sym) }.max ; end
38
+ def each ; @list.each { |(n,b)| n.times { yield b } } ; end
39
+ def sum sym ; @list.map { |(n,b)| n * (b.send sym) }.sum ; end
40
+ def max sym ; @list.map { |(_,b)| (b.send sym) }.max ; end
34
41
 
35
- def create_data data
36
- l = sum :data_count
37
- b = BitBuffer.build l do |buf| data.write buf, @version end
38
- create_bytes b
39
- end
42
+ def create_data input, version
43
+ dcdata, ecdata = create_blocks input, version
44
+ data = []
45
+ (max :data_count).times do |j|
46
+ dcdata.each do |dc|
47
+ data.push dc[j] if j < dc.size
48
+ end
49
+ end
50
+ (max :error_count).times do |j|
51
+ ecdata.each do |ec|
52
+ data.push ec[j] if j < ec.size
53
+ end
54
+ end
55
+ data.length == (sum :total_count) or
56
+ raise Error, "Internal error. Please consider a report."
57
+ data
58
+ end
40
59
 
41
- private
60
+ private
42
61
 
43
- def create_bytes buffer
44
- dcdata, ecdata = [], []
45
- i = 0
46
- each do |rs|
47
- p = Polynomial.new buffer[ i, rs.data_count]
48
- i += rs.data_count
49
- dcdata.push p.num
50
- ecdata.push (p.error_mod rs.error_count).num
62
+ def build_buffer input, version
63
+ l = sum :data_count
64
+ BitBuffer.build l do |buf| input.write_to buf, version end
51
65
  end
52
- data = []
53
- (max :data_count).times do |j|
54
- dcdata.each do |dc|
55
- data.push dc[j] if j < dc.size
66
+
67
+ def create_blocks input, version
68
+ buffer = build_buffer input, version
69
+ dcdata, ecdata = [], []
70
+ i = 0
71
+ each do |rs|
72
+ p = Polynomial.new buffer[ i, rs.data_count]
73
+ i += rs.data_count
74
+ dcdata.push p.num.dup
75
+ p.error_mod! rs.error_count
76
+ ecdata.push p.num
56
77
  end
78
+ [ dcdata, ecdata]
57
79
  end
58
- (max :error_count).times do |j|
59
- ecdata.each do |ec|
60
- data.push ec[j] if j < ec.size
61
- end
80
+
81
+ class <<self
82
+ attr_reader :blocks
62
83
  end
63
- data.length == (sum :total_count) or
64
- raise Error, "Internal error. Please consider a report."
65
- data
66
- end
67
84
 
68
- @blocks = Hash.new { |h,k|
69
- v = nil
70
- RS_BLOCK_TABLE.each_line { |l|
71
- n, l = l.split nil, 2
72
- if n.to_i == k then
73
- v = {}
74
- while l =~ /([a-z])\b([ 0-9,]+)/ do
75
- n, b, l = $1, $2, $'
76
- b.rstrip!
77
- v[ n.to_sym] = (b.split /,/).map { |t| t.split.map { |i| i.to_i } }
85
+ @blocks = Hash.new { |h,k|
86
+ v = nil
87
+ RS_BLOCK_TABLE.each_line { |l|
88
+ n, l = l.split nil, 2
89
+ if n.to_i == k then
90
+ v = {}
91
+ while l =~ /([a-z])\b([ 0-9,]+)/ do
92
+ n, b, l = $1, $2, $'
93
+ b.rstrip!
94
+ v[ n.to_sym] = (b.split /,/).map { |t| t.split.map { |i| i.to_i } }
95
+ end
96
+ break
78
97
  end
79
- break
80
- end
98
+ }
99
+ v or raise ArgumentError, "No RS block for version #{k}"
100
+ h[k] = v
81
101
  }
82
- h[k] = v
83
- }
84
-
85
- class <<self
86
102
 
87
- private :new
88
-
89
- def get version, error_correct_level
90
- v = @blocks[version] or raise ArgumentError, "No RS block for version #{version}"
91
- new version, v[error_correct_level]
92
- end
103
+ # http://www.thonky.com/qr-code-tutorial/error-correction-table/
104
+ RS_BLOCK_TABLE = <<~EOT
105
+ 1 l 1 26 19, m 1 26 16, q 1 26 13, h 1 26 9,
106
+ 2 l 1 44 34, m 1 44 28, q 1 44 22, h 1 44 16,
107
+ 3 l 1 70 55, m 1 70 44, q 2 35 17, h 2 35 13,
108
+ 4 l 1 100 80, m 2 50 32, q 2 50 24, h 4 25 9,
109
+ 5 l 1 134 108, m 2 67 43, q 2 33 15, 2 34 16, h 2 33 11, 2 34 12,
110
+ 6 l 2 86 68, m 4 43 27, q 4 43 19, h 4 43 15,
111
+ 7 l 2 98 78, m 4 49 31, q 2 32 14, 4 33 15, h 4 39 13, 1 40 14,
112
+ 8 l 2 121 97, m 2 60 38, 2 61 39, q 4 40 18, 2 41 19, h 4 40 14, 2 41 15,
113
+ 9 l 2 146 116, m 3 58 36, 2 59 37, q 4 36 16, 4 37 17, h 4 36 12, 4 37 13,
114
+ 10 l 2 86 68, 2 87 69, m 4 69 43, 1 70 44, q 6 43 19, 2 44 20, h 6 43 15, 2 44 16,
115
+ 11 l 4 101 81, m 1 80 50, 4 81 51, q 4 50 22, 4 51 23, h 3 36 12, 8 37 13,
116
+ 12 l 2 116 92, 2 117 93, m 6 58 36, 2 59 37, q 4 46 20, 6 47 21, h 7 42 14, 4 43 15,
117
+ 13 l 4 133 107, m 8 59 37, 1 60 38, q 8 44 20, 4 45 21, h 12 33 11, 4 34 12,
118
+ 14 l 3 145 115, 1 146 116, m 4 64 40, 5 65 41, q 11 36 16, 5 37 17, h 11 36 12, 5 37 13,
119
+ 15 l 5 109 87, 1 110 88, m 5 65 41, 5 66 42, q 5 54 24, 7 55 25, h 11 36 12, 7 37 13,
120
+ 16 l 5 122 98, 1 123 99, m 7 73 45, 3 74 46, q 15 43 19, 2 44 20, h 3 45 15, 13 46 16,
121
+ 17 l 1 135 107, 5 136 108, m 10 74 46, 1 75 47, q 1 50 22, 15 51 23, h 2 42 14, 17 43 15,
122
+ 18 l 5 150 120, 1 151 121, m 9 69 43, 4 70 44, q 17 50 22, 1 51 23, h 2 42 14, 19 43 15,
123
+ 19 l 3 141 113, 4 142 114, m 3 70 44, 11 71 45, q 17 47 21, 4 48 22, h 9 39 13, 16 40 14,
124
+ 20 l 3 135 107, 5 136 108, m 3 67 41, 13 68 42, q 15 54 24, 5 55 25, h 15 43 15, 10 44 16,
125
+ 21 l 4 144 116, 4 145 117, m 17 68 42, q 17 50 22, 6 51 23, h 19 46 16, 6 47 17,
126
+ 22 l 2 139 111, 7 140 112, m 17 74 46, q 7 54 24, 16 55 25, h 34 37 13,
127
+ 23 l 4 151 121, 5 152 122, m 4 75 47, 14 76 48, q 11 54 24, 14 55 25, h 16 45 15, 14 46 16,
128
+ 24 l 6 147 117, 4 148 118, m 6 73 45, 14 74 46, q 11 54 24, 16 55 25, h 30 46 16, 2 47 17,
129
+ 25 l 8 132 106, 4 133 107, m 8 75 47, 13 76 48, q 7 54 24, 22 55 25, h 22 45 15, 13 46 16,
130
+ 26 l 10 142 114, 2 143 115, m 19 74 46, 4 75 47, q 28 50 22, 6 51 23, h 33 46 16, 4 47 17,
131
+ 27 l 8 152 122, 4 153 123, m 22 73 45, 3 74 46, q 8 53 23, 26 54 24, h 12 45 15, 28 46 16,
132
+ 28 l 3 147 117, 10 148 118, m 3 73 45, 23 74 46, q 4 54 24, 31 55 25, h 11 45 15, 31 46 16,
133
+ 29 l 7 146 116, 7 147 117, m 21 73 45, 7 74 46, q 1 53 23, 37 54 24, h 19 45 15, 26 46 16,
134
+ 30 l 5 145 115, 10 146 116, m 19 75 47, 10 76 48, q 15 54 24, 25 55 25, h 23 45 15, 25 46 16,
135
+ 31 l 13 145 115, 3 146 116, m 2 74 46, 29 75 47, q 42 54 24, 1 55 25, h 23 45 15, 28 46 16,
136
+ 32 l 17 145 115, m 10 74 46, 23 75 47, q 10 54 24, 35 55 25, h 19 45 15, 35 46 16,
137
+ 33 l 17 145 115, 1 146 116, m 14 74 46, 21 75 47, q 29 54 24, 19 55 25, h 11 45 15, 46 46 16,
138
+ 34 l 13 145 115, 6 146 116, m 14 74 46, 23 75 47, q 44 54 24, 7 55 25, h 59 46 16, 1 47 17,
139
+ 35 l 12 151 121, 7 152 122, m 12 75 47, 26 76 48, q 39 54 24, 14 55 25, h 22 45 15, 41 46 16,
140
+ 36 l 6 151 121, 14 152 122, m 6 75 47, 34 76 48, q 46 54 24, 10 55 25, h 2 45 15, 64 46 16,
141
+ 37 l 17 152 122, 4 153 123, m 29 74 46, 14 75 47, q 49 54 24, 10 55 25, h 24 45 15, 46 46 16,
142
+ 38 l 4 152 122, 18 153 123, m 13 74 46, 32 75 47, q 48 54 24, 14 55 25, h 42 45 15, 32 46 16,
143
+ 39 l 20 147 117, 4 148 118, m 40 75 47, 7 76 48, q 43 54 24, 22 55 25, h 10 45 15, 67 46 16,
144
+ 40 l 19 148 118, 6 149 119, m 18 75 47, 31 76 48, q 34 54 24, 34 55 25, h 20 45 15, 61 46 16,
145
+ EOT
93
146
 
94
147
  end
95
148
 
96
- # http://www.thonky.com/qr-code-tutorial/error-correction-table/
97
- RS_BLOCK_TABLE = <<~EOT
98
- 1 l 1 26 19, m 1 26 16, q 1 26 13, h 1 26 9,
99
- 2 l 1 44 34, m 1 44 28, q 1 44 22, h 1 44 16,
100
- 3 l 1 70 55, m 1 70 44, q 2 35 17, h 2 35 13,
101
- 4 l 1 100 80, m 2 50 32, q 2 50 24, h 4 25 9,
102
- 5 l 1 134 108, m 2 67 43, q 2 33 15, 2 34 16, h 2 33 11, 2 34 12,
103
- 6 l 2 86 68, m 4 43 27, q 4 43 19, h 4 43 15,
104
- 7 l 2 98 78, m 4 49 31, q 2 32 14, 4 33 15, h 4 39 13, 1 40 14,
105
- 8 l 2 121 97, m 2 60 38, 2 61 39, q 4 40 18, 2 41 19, h 4 40 14, 2 41 15,
106
- 9 l 2 146 116, m 3 58 36, 2 59 37, q 4 36 16, 4 37 17, h 4 36 12, 4 37 13,
107
- 10 l 2 86 68, 2 87 69, m 4 69 43, 1 70 44, q 6 43 19, 2 44 20, h 6 43 15, 2 44 16,
108
- 11 l 4 101 81, m 1 80 50, 4 81 51, q 4 50 22, 4 51 23, h 3 36 12, 8 37 13,
109
- 12 l 2 116 92, 2 117 93, m 6 58 36, 2 59 37, q 4 46 20, 6 47 21, h 7 42 14, 4 43 15,
110
- 13 l 4 133 107, m 8 59 37, 1 60 38, q 8 44 20, 4 45 21, h 12 33 11, 4 34 12,
111
- 14 l 3 145 115, 1 146 116, m 4 64 40, 5 65 41, q 11 36 16, 5 37 17, h 11 36 12, 5 37 13,
112
- 15 l 5 109 87, 1 110 88, m 5 65 41, 5 66 42, q 5 54 24, 7 55 25, h 11 36 12, 7 37 13,
113
- 16 l 5 122 98, 1 123 99, m 7 73 45, 3 74 46, q 15 43 19, 2 44 20, h 3 45 15, 13 46 16,
114
- 17 l 1 135 107, 5 136 108, m 10 74 46, 1 75 47, q 1 50 22, 15 51 23, h 2 42 14, 17 43 15,
115
- 18 l 5 150 120, 1 151 121, m 9 69 43, 4 70 44, q 17 50 22, 1 51 23, h 2 42 14, 19 43 15,
116
- 19 l 3 141 113, 4 142 114, m 3 70 44, 11 71 45, q 17 47 21, 4 48 22, h 9 39 13, 16 40 14,
117
- 20 l 3 135 107, 5 136 108, m 3 67 41, 13 68 42, q 15 54 24, 5 55 25, h 15 43 15, 10 44 16,
118
- 21 l 4 144 116, 4 145 117, m 17 68 42, q 17 50 22, 6 51 23, h 19 46 16, 6 47 17,
119
- 22 l 2 139 111, 7 140 112, m 17 74 46, q 7 54 24, 16 55 25, h 34 37 13,
120
- 23 l 4 151 121, 5 152 122, m 4 75 47, 14 76 48, q 11 54 24, 14 55 25, h 16 45 15, 14 46 16,
121
- 24 l 6 147 117, 4 148 118, m 6 73 45, 14 74 46, q 11 54 24, 16 55 25, h 30 46 16, 2 47 17,
122
- 25 l 8 132 106, 4 133 107, m 8 75 47, 13 76 48, q 7 54 24, 22 55 25, h 22 45 15, 13 46 16,
123
- 26 l 10 142 114, 2 143 115, m 19 74 46, 4 75 47, q 28 50 22, 6 51 23, h 33 46 16, 4 47 17,
124
- 27 l 8 152 122, 4 153 123, m 22 73 45, 3 74 46, q 8 53 23, 26 54 24, h 12 45 15, 28 46 16,
125
- 28 l 3 147 117, 10 148 118, m 3 73 45, 23 74 46, q 4 54 24, 31 55 25, h 11 45 15, 31 46 16,
126
- 29 l 7 146 116, 7 147 117, m 21 73 45, 7 74 46, q 1 53 23, 37 54 24, h 19 45 15, 26 46 16,
127
- 30 l 5 145 115, 10 146 116, m 19 75 47, 10 76 48, q 15 54 24, 25 55 25, h 23 45 15, 25 46 16,
128
- 31 l 13 145 115, 3 146 116, m 2 74 46, 29 75 47, q 42 54 24, 1 55 25, h 23 45 15, 28 46 16,
129
- 32 l 17 145 115, m 10 74 46, 23 75 47, q 10 54 24, 35 55 25, h 19 45 15, 35 46 16,
130
- 33 l 17 145 115, 1 146 116, m 14 74 46, 21 75 47, q 29 54 24, 19 55 25, h 11 45 15, 46 46 16,
131
- 34 l 13 145 115, 6 146 116, m 14 74 46, 23 75 47, q 44 54 24, 7 55 25, h 59 46 16, 1 47 17,
132
- 35 l 12 151 121, 7 152 122, m 12 75 47, 26 76 48, q 39 54 24, 14 55 25, h 22 45 15, 41 46 16,
133
- 36 l 6 151 121, 14 152 122, m 6 75 47, 34 76 48, q 46 54 24, 10 55 25, h 2 45 15, 64 46 16,
134
- 37 l 17 152 122, 4 153 123, m 29 74 46, 14 75 47, q 49 54 24, 10 55 25, h 24 45 15, 46 46 16,
135
- 38 l 4 152 122, 18 153 123, m 13 74 46, 32 75 47, q 48 54 24, 14 55 25, h 42 45 15, 32 46 16,
136
- 39 l 20 147 117, 4 148 118, m 40 75 47, 7 76 48, q 43 54 24, 22 55 25, h 10 45 15, 67 46 16,
137
- 40 l 19 148 118, 6 149 119, m 18 75 47, 31 76 48, q 34 54 24, 34 55 25, h 20 45 15, 61 46 16,
138
- EOT
139
-
140
149
  end
141
150
 
142
151
  end
data/lib/qrest/segment.rb CHANGED
@@ -13,8 +13,8 @@ module QRest
13
13
  @data = data
14
14
  end
15
15
 
16
- def write buffer, version
17
- buffer.put 1<<self.class::ID, 4
16
+ def write_to buffer, version
17
+ buffer.put self.class::ID, 4
18
18
  buffer.put @data.bytesize, (get_length_in_bits version)
19
19
  end
20
20
 
@@ -62,10 +62,13 @@ module QRest
62
62
  type or raise ArgumentError, "Not a valid segment type: #{mode}"
63
63
  type.new data
64
64
  else
65
+ r = nil
65
66
  @sub.each do |t|
66
- break t.new data
67
- rescue ArgumentError, NotImplementedError
67
+ r = t.new data
68
+ break
69
+ rescue ArgumentError, NotImplementedError, EncodingError
68
70
  end
71
+ r or raise "No appropriate segment type possible."
69
72
  end
70
73
  when Array then
71
74
  Multi.new data
@@ -94,8 +97,8 @@ module QRest
94
97
  }
95
98
  end
96
99
 
97
- def write buffer, version
98
- @segs.each { |s| s.write buffer, version }
100
+ def write_to buffer, version
101
+ @segs.each { |s| s.write_to buffer, version }
99
102
  end
100
103
 
101
104
  def size version
@@ -108,7 +111,7 @@ module QRest
108
111
  class Numeric < Segment
109
112
 
110
113
  NAME = "number"
111
- ID = 0
114
+ ID = 1
112
115
  BITS_FOR_MODE = [10, 12, 14]
113
116
 
114
117
  def initialize data
@@ -118,7 +121,7 @@ module QRest
118
121
 
119
122
  NUMBER_LENGTH = { 3 => 10, 2 => 7, 1 => 4 }
120
123
 
121
- def write buffer, version
124
+ def write_to buffer, version
122
125
  super
123
126
  @data.scan /\d{1,3}/ do |chars|
124
127
  buffer.put chars.to_i, NUMBER_LENGTH[ chars.length]
@@ -132,7 +135,7 @@ module QRest
132
135
  class Alphanumeric < Segment
133
136
 
134
137
  NAME = "alphanumeric"
135
- ID = 1
138
+ ID = 2
136
139
  BITS_FOR_MODE = [ 9, 11, 13]
137
140
 
138
141
  ALPHANUMERIC, = [
@@ -146,7 +149,7 @@ module QRest
146
149
  super
147
150
  end
148
151
 
149
- def write buffer, version
152
+ def write_to buffer, version
150
153
  super
151
154
  @data.scan /(.)(.)?/ do |c,d|
152
155
  val = ALPHANUMERIC[ c]
@@ -166,7 +169,7 @@ module QRest
166
169
  class Kanji < Segment
167
170
 
168
171
  NAME = "kanji"
169
- ID = nil # ???
172
+ ID = 8
170
173
  BITS_FOR_MODE = [ 8, 10, 12]
171
174
 
172
175
  def initialize data
@@ -174,7 +177,7 @@ module QRest
174
177
  not_implemented
175
178
  end
176
179
 
177
- def write buffer, version
180
+ def write_to buffer, version
178
181
  super
179
182
  not_implemented
180
183
  end
@@ -192,10 +195,20 @@ module QRest
192
195
  class Bytes < Segment
193
196
 
194
197
  NAME = "8bit"
195
- ID = 2
198
+ ID = 4
196
199
  BITS_FOR_MODE = [ 8, 16, 16]
197
200
 
198
- def write buffer, version
201
+ @strict = false
202
+ class <<self
203
+ attr_accessor :strict
204
+ end
205
+
206
+ def initialize data
207
+ data = data.encode Encoding::ISO8859_1 if self.class.strict
208
+ super
209
+ end
210
+
211
+ def write_to buffer, version
199
212
  super
200
213
  @data.each_byte do |b|
201
214
  buffer.put b, 8
data/lib/qrest/version.rb CHANGED
@@ -6,7 +6,7 @@
6
6
  module QRest
7
7
 
8
8
  NAME = "qrest"
9
- VERSION = "1.0.0"
9
+ VERSION = "1.0.2"
10
10
 
11
11
  end
12
12
 
data/lib/qrest.rb CHANGED
@@ -27,26 +27,24 @@ module QRest
27
27
  Modules::ERRORCORRECTLEVEL[error_correct_level] or
28
28
  raise ArgumentError, "Unknown error correction level: #{level}"
29
29
  if version then
30
- version <= Modules::MAX_VERSION or
31
- raise ArgumentError, "Requested version exceeds maximum of #{Modules::MAX_VERSION}"
30
+ Modules::VERSIONS.include? version or
31
+ raise ArgumentError, "Requested version not in #{Modules::VERSIONS}"
32
32
  else
33
33
  if max_version then
34
- max_version <= Modules::MAX_VERSION or
35
- raise ArgumentError, "Maximum posible version is #{Modules::MAX_VERSION}"
34
+ Modules::VERSIONS.include? max_version or
35
+ raise ArgumentError, "Maximum version mot in #{Modules::VERSIONS}"
36
36
  else
37
- max_version = Modules::MAX_VERSION
37
+ max_version = Modules::VERSIONS.end
38
38
  end
39
39
  mb = Modules::MAXBITS[error_correct_level]
40
- version = 0
41
- begin
42
- version += 1
43
- version <= max_version or
44
- raise Error, "Data length exceeds maximum capacity of version #{max_version}"
45
- end until (input.size version) <= mb[version - 1]
40
+ version = Modules::VERSIONS.find { |v|
41
+ v <= max_version or
42
+ raise Error, "Data length exceeds requested maximum version of #{max_version}"
43
+ (input.size v) <= mb[ v - 1]
44
+ }
46
45
  end
47
-
48
- data = (RSBlocks.get version, error_correct_level).create_data input
49
- @modules = Modules.create_best data, version, error_correct_level
46
+ data = RSData.new version, error_correct_level, input
47
+ @modules = Modules.create_best data
50
48
  end
51
49
 
52
50
  def to_s dark: nil, light: nil, quiet_size: nil
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: qrest
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bertram Scharpf
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-03-16 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
11
  dependencies: []
12
12
  description: |
13
13
  A Ruby library that generates QR Codes
@@ -50,7 +50,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
50
50
  - !ruby/object:Gem::Version
51
51
  version: '0'
52
52
  requirements: []
53
- rubygems_version: 3.6.4
53
+ rubygems_version: 3.7.1
54
54
  specification_version: 4
55
55
  summary: Generate QR Codes
56
56
  test_files: []