qr_reader 0.0.1 → 0.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.
@@ -0,0 +1,1084 @@
1
+ # frozen_string_literal: true
2
+
3
+ module QrReader
4
+ module Formats
5
+ module JPEG2000
6
+ # Tier-1 decoder (ITU-T T.800 Annex C and D): the MQ arithmetic
7
+ # decoder and the three coding passes of EBCOT (significance
8
+ # propagation, magnitude refinement, cleanup) with all code-block style
9
+ # options (selective arithmetic coding bypass, context reset,
10
+ # termination on each pass, vertically causal contexts, predictable
11
+ # termination, segmentation symbols).
12
+ #
13
+ # Coefficients are kept like OpenJPEG does: as signed integers scaled
14
+ # by two, so that the bit below the last decoded bit-plane can hold
15
+ # the reconstruction offset of one half.
16
+ #
17
+ # State flags: one Integer per column of a four-row stripe (with a
18
+ # border of one column and one stripe all around), laid out like
19
+ # OpenJPEG's t1 flags so that every context is one shift and one
20
+ # table lookup. For row r (0..3) of the stripe, bits 3r..3r+8 are the
21
+ # significance of its 3x3 neighbourhood (NW N NE W self E SW S SE);
22
+ # bits 18 + 3r' hold the signs, 20 + 3r "refined", 21 + 3r "visited
23
+ # in this bit-plane".
24
+ #
25
+ # The pass methods inline the MQ decoder (C.3.2) at every decision:
26
+ # this is the hottest code of the JPEG 2000 decoder and a method call
27
+ # per decision would cost more than the decision itself.
28
+ class Tier1
29
+ # Qe, next MPS, next LPS and switch flag of the 47 MQ states
30
+ # (Table C.2).
31
+ MQ_TABLE = [
32
+ [0x5601, 1, 1, 1], [0x3401, 2, 6, 0], [0x1801, 3, 9, 0], [0x0AC1, 4, 12, 0],
33
+ [0x0521, 5, 29, 0], [0x0221, 38, 33, 0], [0x5601, 7, 6, 1], [0x5401, 8, 14, 0],
34
+ [0x4801, 9, 14, 0], [0x3801, 10, 14, 0], [0x3001, 11, 17, 0], [0x2401, 12, 18, 0],
35
+ [0x1C01, 13, 20, 0], [0x1601, 29, 21, 0], [0x5601, 15, 14, 1], [0x5401, 16, 14, 0],
36
+ [0x5101, 17, 15, 0], [0x4801, 18, 16, 0], [0x3801, 19, 17, 0], [0x3401, 20, 18, 0],
37
+ [0x3001, 21, 19, 0], [0x2801, 22, 19, 0], [0x2401, 23, 20, 0], [0x2201, 24, 21, 0],
38
+ [0x1C01, 25, 22, 0], [0x1801, 26, 23, 0], [0x1601, 27, 24, 0], [0x1401, 28, 25, 0],
39
+ [0x1201, 29, 26, 0], [0x1101, 30, 27, 0], [0x0AC1, 31, 28, 0], [0x09C1, 32, 29, 0],
40
+ [0x08A1, 33, 30, 0], [0x0521, 34, 31, 0], [0x0441, 35, 32, 0], [0x02A1, 36, 33, 0],
41
+ [0x0221, 37, 34, 0], [0x0141, 38, 35, 0], [0x0111, 39, 36, 0], [0x0085, 40, 37, 0],
42
+ [0x0049, 41, 38, 0], [0x0025, 42, 39, 0], [0x0015, 43, 40, 0], [0x0009, 44, 41, 0],
43
+ [0x0005, 45, 42, 0], [0x0001, 45, 43, 0], [0x5601, 46, 46, 0]
44
+ ].freeze
45
+
46
+ # A context state is 2 * state index + MPS; these give its Qe and
47
+ # the state after an MPS or LPS decision (MPS switch included).
48
+ QE = Array.new(94) { |s| MQ_TABLE[s >> 1][0] }.freeze
49
+ NMPS = Array.new(94) { |s| (MQ_TABLE[s >> 1][1] << 1) | (s & 1) }.freeze
50
+ NLPS = Array.new(94) do |s|
51
+ row = MQ_TABLE[s >> 1]
52
+ (row[2] << 1) | (row[3] == 1 ? 1 - (s & 1) : s & 1)
53
+ end.freeze
54
+
55
+ # Initial context states (D.7, Table D.7): all 0 except the uniform
56
+ # context (state 46), run-length (state 3) and zero-coding 0 (state 4).
57
+ INITIAL_CONTEXTS = Array.new(19, 0).tap do |c|
58
+ c[18] = 92
59
+ c[17] = 6
60
+ c[0] = 8
61
+ end.freeze
62
+
63
+ CTX_RL = 17
64
+ CTX_UNI = 18
65
+
66
+ class << self
67
+ # Zero-coding context (Table D.1) of a 9-bit neighbourhood for
68
+ # subband orientation +orient+ (0 LL, 1 HL, 2 LH, 3 HH).
69
+ def zero_context(f, orient)
70
+ h = (f >> 3 & 1) + (f >> 5 & 1)
71
+ v = (f >> 1 & 1) + (f >> 7 & 1)
72
+ d = (f & 1) + (f >> 2 & 1) + (f >> 6 & 1) + (f >> 8 & 1)
73
+ h, v = v, h if orient == 1 # HL: horizontally high-pass
74
+ if orient == 3
75
+ hv = h + v
76
+ return [0, 1, 2][[hv, 2].min] if d.zero?
77
+ return [3, 4, 5][[hv, 2].min] if d == 1
78
+ return hv.zero? ? 6 : 7 if d == 2
79
+
80
+ 8
81
+ elsif h.zero?
82
+ return [0, 1, 2][[d, 2].min] if v.zero?
83
+
84
+ v == 1 ? 3 : 4
85
+ elsif h == 1
86
+ return d.zero? ? 5 : 6 if v.zero?
87
+
88
+ 7
89
+ else
90
+ 8
91
+ end
92
+ end
93
+
94
+ # [horizontal, vertical] sign contribution of a sign-context index
95
+ # (bits: 0 W sign, 1 N sig, 2 E sign, 3 W sig, 4 N sign, 5 E sig,
96
+ # 6 S sign, 7 S sig).
97
+ def sign_contributions(lu)
98
+ contribution = lambda do |sig_a, sgn_a, sig_b, sgn_b|
99
+ pos = [(lu[sig_a] == 1 && lu[sgn_a].zero? ? 1 : 0) + (lu[sig_b] == 1 && lu[sgn_b].zero? ? 1 : 0), 1].min
100
+ neg = [(lu[sig_a] == 1 && lu[sgn_a] == 1 ? 1 : 0) + (lu[sig_b] == 1 && lu[sgn_b] == 1 ? 1 : 0), 1].min
101
+ pos - neg
102
+ end
103
+ [contribution.call(5, 2, 3, 0), contribution.call(1, 4, 7, 6)]
104
+ end
105
+ end
106
+
107
+ # Zero-coding contexts: index (orient << 9) | neighbourhood.
108
+ ZC_LUT = Array.new(2048) { |i| zero_context(i & 0x1FF, i >> 9) }.freeze
109
+
110
+ # Sign-coding context (Table D.3) per sign-context index.
111
+ SC_LUT = Array.new(256) do |lu|
112
+ hc, vc = sign_contributions(lu)
113
+ hc, vc = -hc, -vc if hc.negative?
114
+ 9 + (hc.zero? ? (vc.zero? ? 0 : 1) : vc + 3)
115
+ end.freeze
116
+
117
+ # Sign prediction (the XOR bit of Table D.3) per sign-context index.
118
+ SPB_LUT = Array.new(256) do |lu|
119
+ hc, vc = sign_contributions(lu)
120
+ hc.negative? || (hc.zero? && vc.negative?) ? 1 : 0
121
+ end.freeze
122
+
123
+ # Bits of the flags words.
124
+ SIGMA_THIS = 0x10
125
+ NEIGHBOURS = 0x1EF
126
+ CHI_THIS_I = 19
127
+ MU_THIS = 1 << 20
128
+ PI_THIS = 1 << 21
129
+ UNVISITED_INSIGNIFICANT = PI_THIS | SIGMA_THIS
130
+ # Significance of the four rows of a stripe.
131
+ ANY_SIGNIFICANT = 0x2490
132
+ # Visited flags of the four rows.
133
+ PI_ALL = (1 << 21) | (1 << 24) | (1 << 27) | (1 << 30)
134
+
135
+ STYLE_BYPASS = 1
136
+ STYLE_RESET = 2
137
+ STYLE_VSC = 8
138
+ STYLE_SEGSYM = 0x20
139
+
140
+ # The coefficients of the last decoded code-block (w * h Integers,
141
+ # row-major, scaled by two).
142
+ attr_reader :data
143
+
144
+ def initialize
145
+ @data = []
146
+ @flags = []
147
+ @ctx = INITIAL_CONTEXTS.dup
148
+ end
149
+
150
+ # Decodes one code-block of +w+ x +h+ coefficients from +segments+
151
+ # ([[bytes, passes], ...]) with +numbps+ magnitude bit-planes, ROI
152
+ # shift +roishift+, subband +orient+ (0 LL, 1 HL, 2 LH, 3 HH) and
153
+ # code-block +style+ flags. Returns #data.
154
+ def decode(w, h, segments, numbps, roishift, orient, style)
155
+ n = w * h
156
+ data = @data
157
+ data.fill(0, 0, n)
158
+ stride = w + 2
159
+ @flags.fill(0, 0, stride * (((h + 3) >> 2) + 2))
160
+ @ctx.replace(INITIAL_CONTEXTS)
161
+ bpno = roishift + numbps
162
+ return data if bpno <= 0
163
+
164
+ passtype = 2
165
+ bypass = style & STYLE_BYPASS != 0
166
+ reset = style & STYLE_RESET != 0
167
+ vsc = style & STYLE_VSC != 0
168
+ segsym = style & STYLE_SEGSYM != 0
169
+ zoff = orient << 9
170
+ si = 0
171
+ while si < segments.size && bpno >= 1
172
+ bytes, passes = segments[si]
173
+ raw = bypass && passtype < 2 && bpno <= numbps - 4
174
+ raw ? init_raw(bytes) : init_mq(bytes)
175
+ passno = 0
176
+ while passno < passes && bpno >= 1
177
+ case passtype
178
+ when 0 then raw ? sigpass_raw(w, h, bpno, vsc) : sigpass(w, h, bpno, zoff, vsc)
179
+ when 1 then raw ? refpass_raw(w, h, bpno) : refpass(w, h, bpno)
180
+ else cleanup(w, h, bpno, zoff, vsc, segsym)
181
+ end
182
+ @ctx.replace(INITIAL_CONTEXTS) if reset && !raw
183
+ passtype += 1
184
+ if passtype == 3
185
+ passtype = 0
186
+ bpno -= 1
187
+ end
188
+ passno += 1
189
+ end
190
+ si += 1
191
+ end
192
+ data
193
+ end
194
+
195
+ # Writes the last code-block's coefficients (+w+ x +h+) into +rows+
196
+ # (an Array of row Arrays) at column +xo+, row +yo+: halved
197
+ # (reversible) when +step+ is nil, else multiplied by +step+. ROI
198
+ # coefficients (magnitude >= 2**roishift) are scaled down first.
199
+ # Rows of +rows+ that are nil (all zero so far) are created
200
+ # (+width+ zeros) when they receive a nonzero value.
201
+ def store(rows, xo, yo, w, h, roishift, step, width)
202
+ data = @data
203
+ apply_roi(w * h, roishift) if roishift.positive?
204
+ j = 0
205
+ di = 0
206
+ while j < h
207
+ # All-zero rows (counted at C speed) need no work.
208
+ unless data[di, w].count(0) == w
209
+ if step
210
+ store_row_scaled(data, rows, yo + j, di, xo, w, step, width)
211
+ else
212
+ store_row_halved(data, rows, yo + j, di, xo, w, width)
213
+ end
214
+ end
215
+ di += w
216
+ j += 1
217
+ end
218
+ end
219
+
220
+ private
221
+
222
+ def apply_roi(n, shift)
223
+ data = @data
224
+ thresh = 1 << (shift + 1)
225
+ i = 0
226
+ while i < n
227
+ v = data[i]
228
+ if v >= thresh
229
+ data[i] = v >> shift
230
+ elsif -v >= thresh
231
+ data[i] = -((-v) >> shift)
232
+ end
233
+ i += 1
234
+ end
235
+ end
236
+
237
+ def store_row_halved(data, rows, ri, di, x, w, width)
238
+ row = rows[ri]
239
+ stop = di + w
240
+ while di < stop
241
+ v = data[di]
242
+ if v != 0
243
+ row ||= (rows[ri] = Array.new(width, 0))
244
+ row[x] = v.negative? ? -((-v) >> 1) : v >> 1
245
+ end
246
+ di += 1
247
+ x += 1
248
+ end
249
+ end
250
+
251
+ def store_row_scaled(data, rows, ri, di, x, w, step, width)
252
+ row = rows[ri]
253
+ stop = di + w
254
+ while di < stop
255
+ v = data[di]
256
+ if v != 0
257
+ row ||= (rows[ri] = Array.new(width, 0.0))
258
+ row[x] = v * step
259
+ end
260
+ di += 1
261
+ x += 1
262
+ end
263
+ end
264
+
265
+ def init_mq(bytes)
266
+ buf = bytes + "\xFF\xFF".b
267
+ c = buf.getbyte(0) << 16
268
+ bp = 0
269
+ # BYTEIN (C.3.4) once, then INITDEC's shift by 7.
270
+ b = buf.getbyte(1)
271
+ if buf.getbyte(0) == 0xFF
272
+ if b > 0x8F
273
+ c += 0xFF00
274
+ ct = 8
275
+ else
276
+ bp = 1
277
+ c += b << 9
278
+ ct = 7
279
+ end
280
+ else
281
+ bp = 1
282
+ c += b << 8
283
+ ct = 8
284
+ end
285
+ @buf = buf
286
+ @bp = bp
287
+ @c = c << 7
288
+ @ct = ct - 7
289
+ @a = 0x8000
290
+ end
291
+
292
+ def init_raw(bytes)
293
+ @buf = bytes + "\xFF\xFF".b
294
+ @bp = 0
295
+ @c = 0
296
+ @ct = 0
297
+ end
298
+
299
+ # Significance propagation pass (D.3.1), MQ coded.
300
+ def sigpass(w, h, bpno, zoff, vsc)
301
+ fl = @flags
302
+ data = @data
303
+ ctx = @ctx
304
+ buf = @buf
305
+ bp = @bp
306
+ a = @a
307
+ c = @c
308
+ ct = @ct
309
+ one = 1 << bpno
310
+ oneplushalf = one | (one >> 1)
311
+ stride = w + 2
312
+ row_fi = stride + 1
313
+ k = 0
314
+ while k < h
315
+ nr = h - k
316
+ nr = 4 if nr > 4
317
+ fi = row_fi
318
+ col_di = k * w
319
+ stop = row_fi + w
320
+ while fi < stop
321
+ f = fl[fi]
322
+ if f != 0
323
+ ci = 0
324
+ di = col_di
325
+ while ci < nr
326
+ sh = 3 * ci
327
+ fs = f >> sh
328
+ if fs & UNVISITED_INSIGNIFICANT == 0 && fs & NEIGHBOURS != 0
329
+ cx = ZC_LUT[zoff | (fs & NEIGHBOURS)]
330
+ # --- MQ decode (cx) -> d
331
+ s = ctx[cx]
332
+ q = QE[s]
333
+ a -= q
334
+ if (c >> 16) < q
335
+ if a < q
336
+ d = s & 1
337
+ ctx[cx] = NMPS[s]
338
+ else
339
+ d = (s & 1) ^ 1
340
+ ctx[cx] = NLPS[s]
341
+ end
342
+ a = q
343
+ else
344
+ c -= q << 16
345
+ if a < 0x8000
346
+ if a < q
347
+ d = (s & 1) ^ 1
348
+ ctx[cx] = NLPS[s]
349
+ else
350
+ d = s & 1
351
+ ctx[cx] = NMPS[s]
352
+ end
353
+ else
354
+ d = s & 1
355
+ end
356
+ end
357
+ while a < 0x8000
358
+ if ct.zero?
359
+ if buf.getbyte(bp) == 0xFF
360
+ b = buf.getbyte(bp + 1)
361
+ if b > 0x8F
362
+ c += 0xFF00
363
+ ct = 8
364
+ else
365
+ bp += 1
366
+ c += b << 9
367
+ ct = 7
368
+ end
369
+ else
370
+ bp += 1
371
+ c += buf.getbyte(bp) << 8
372
+ ct = 8
373
+ end
374
+ end
375
+ a <<= 1
376
+ c <<= 1
377
+ ct -= 1
378
+ end
379
+ # ---
380
+ if d == 1
381
+ # Sign context (D.3.2).
382
+ lu = (fs & 0xAA) | ((fl[fi - 1] >> (CHI_THIS_I + sh)) & 1) |
383
+ ((fl[fi + 1] >> (CHI_THIS_I - 2 + sh)) & 4) |
384
+ ((fs >> 16) & 64)
385
+ lu |= ci.zero? ? (f >> 14) & 16 : (f >> (12 + sh)) & 16
386
+ cx = SC_LUT[lu]
387
+ # --- MQ decode (cx) -> d
388
+ s = ctx[cx]
389
+ q = QE[s]
390
+ a -= q
391
+ if (c >> 16) < q
392
+ if a < q
393
+ d = s & 1
394
+ ctx[cx] = NMPS[s]
395
+ else
396
+ d = (s & 1) ^ 1
397
+ ctx[cx] = NLPS[s]
398
+ end
399
+ a = q
400
+ else
401
+ c -= q << 16
402
+ if a < 0x8000
403
+ if a < q
404
+ d = (s & 1) ^ 1
405
+ ctx[cx] = NLPS[s]
406
+ else
407
+ d = s & 1
408
+ ctx[cx] = NMPS[s]
409
+ end
410
+ else
411
+ d = s & 1
412
+ end
413
+ end
414
+ while a < 0x8000
415
+ if ct.zero?
416
+ if buf.getbyte(bp) == 0xFF
417
+ b = buf.getbyte(bp + 1)
418
+ if b > 0x8F
419
+ c += 0xFF00
420
+ ct = 8
421
+ else
422
+ bp += 1
423
+ c += b << 9
424
+ ct = 7
425
+ end
426
+ else
427
+ bp += 1
428
+ c += buf.getbyte(bp) << 8
429
+ ct = 8
430
+ end
431
+ end
432
+ a <<= 1
433
+ c <<= 1
434
+ ct -= 1
435
+ end
436
+ # ---
437
+ sign = d ^ SPB_LUT[lu]
438
+ data[di] = sign == 1 ? -oneplushalf : oneplushalf
439
+ # Significance update of the neighbourhood.
440
+ fl[fi - 1] |= 0x20 << sh
441
+ f |= ((sign << CHI_THIS_I) | SIGMA_THIS) << sh
442
+ fl[fi + 1] |= 0x8 << sh
443
+ if ci.zero?
444
+ unless vsc
445
+ north = fi - stride
446
+ fl[north] |= (sign << 31) | 0x10000
447
+ fl[north - 1] |= 0x20000
448
+ fl[north + 1] |= 0x8000
449
+ end
450
+ elsif ci == 3
451
+ south = fi + stride
452
+ fl[south] |= (sign << 18) | 2
453
+ fl[south - 1] |= 4
454
+ fl[south + 1] |= 1
455
+ end
456
+ end
457
+ f |= PI_THIS << sh
458
+ end
459
+ ci += 1
460
+ di += w
461
+ end
462
+ fl[fi] = f
463
+ end
464
+ fi += 1
465
+ col_di += 1
466
+ end
467
+ k += 4
468
+ row_fi += stride
469
+ end
470
+ @bp = bp
471
+ @a = a
472
+ @c = c
473
+ @ct = ct
474
+ end
475
+
476
+ # Magnitude refinement pass (D.3.3), MQ coded.
477
+ def refpass(w, h, bpno)
478
+ fl = @flags
479
+ data = @data
480
+ ctx = @ctx
481
+ buf = @buf
482
+ bp = @bp
483
+ a = @a
484
+ c = @c
485
+ ct = @ct
486
+ poshalf = (1 << bpno) >> 1
487
+ stride = w + 2
488
+ row_fi = stride + 1
489
+ k = 0
490
+ while k < h
491
+ nr = h - k
492
+ nr = 4 if nr > 4
493
+ fi = row_fi
494
+ col_di = k * w
495
+ stop = row_fi + w
496
+ while fi < stop
497
+ f = fl[fi]
498
+ if f & ANY_SIGNIFICANT != 0
499
+ ci = 0
500
+ di = col_di
501
+ while ci < nr
502
+ sh = 3 * ci
503
+ fs = f >> sh
504
+ if fs & UNVISITED_INSIGNIFICANT == SIGMA_THIS
505
+ cx = if fs & MU_THIS != 0
506
+ 16
507
+ else
508
+ fs & NEIGHBOURS != 0 ? 15 : 14
509
+ end
510
+ # --- MQ decode (cx) -> d
511
+ s = ctx[cx]
512
+ q = QE[s]
513
+ a -= q
514
+ if (c >> 16) < q
515
+ if a < q
516
+ d = s & 1
517
+ ctx[cx] = NMPS[s]
518
+ else
519
+ d = (s & 1) ^ 1
520
+ ctx[cx] = NLPS[s]
521
+ end
522
+ a = q
523
+ else
524
+ c -= q << 16
525
+ if a < 0x8000
526
+ if a < q
527
+ d = (s & 1) ^ 1
528
+ ctx[cx] = NLPS[s]
529
+ else
530
+ d = s & 1
531
+ ctx[cx] = NMPS[s]
532
+ end
533
+ else
534
+ d = s & 1
535
+ end
536
+ end
537
+ while a < 0x8000
538
+ if ct.zero?
539
+ if buf.getbyte(bp) == 0xFF
540
+ b = buf.getbyte(bp + 1)
541
+ if b > 0x8F
542
+ c += 0xFF00
543
+ ct = 8
544
+ else
545
+ bp += 1
546
+ c += b << 9
547
+ ct = 7
548
+ end
549
+ else
550
+ bp += 1
551
+ c += buf.getbyte(bp) << 8
552
+ ct = 8
553
+ end
554
+ end
555
+ a <<= 1
556
+ c <<= 1
557
+ ct -= 1
558
+ end
559
+ # ---
560
+ v = data[di]
561
+ if v.negative?
562
+ data[di] = d == 1 ? v - poshalf : v + poshalf
563
+ else
564
+ data[di] = d == 1 ? v + poshalf : v - poshalf
565
+ end
566
+ f |= MU_THIS << sh
567
+ end
568
+ ci += 1
569
+ di += w
570
+ end
571
+ fl[fi] = f
572
+ end
573
+ fi += 1
574
+ col_di += 1
575
+ end
576
+ k += 4
577
+ row_fi += stride
578
+ end
579
+ @bp = bp
580
+ @a = a
581
+ @c = c
582
+ @ct = ct
583
+ end
584
+
585
+ # Cleanup pass (D.3.4) with run-length coding; resets the visited
586
+ # flags. Decodes the segmentation symbol when +segsym+.
587
+ def cleanup(w, h, bpno, zoff, vsc, segsym)
588
+ fl = @flags
589
+ data = @data
590
+ ctx = @ctx
591
+ buf = @buf
592
+ bp = @bp
593
+ a = @a
594
+ c = @c
595
+ ct = @ct
596
+ one = 1 << bpno
597
+ oneplushalf = one | (one >> 1)
598
+ stride = w + 2
599
+ row_fi = stride + 1
600
+ k = 0
601
+ while k < h
602
+ nr = h - k
603
+ nr = 4 if nr > 4
604
+ fi = row_fi
605
+ col_di = k * w
606
+ stop = row_fi + w
607
+ while fi < stop
608
+ f = fl[fi]
609
+ ci = 0
610
+ di = col_di
611
+ # Run-length mode: four insignificant coefficients without
612
+ # significant neighbours.
613
+ runlength = f.zero? && nr == 4
614
+ if runlength
615
+ cx = CTX_RL
616
+ # --- MQ decode (cx) -> d
617
+ s = ctx[cx]
618
+ q = QE[s]
619
+ a -= q
620
+ if (c >> 16) < q
621
+ if a < q
622
+ d = s & 1
623
+ ctx[cx] = NMPS[s]
624
+ else
625
+ d = (s & 1) ^ 1
626
+ ctx[cx] = NLPS[s]
627
+ end
628
+ a = q
629
+ else
630
+ c -= q << 16
631
+ if a < 0x8000
632
+ if a < q
633
+ d = (s & 1) ^ 1
634
+ ctx[cx] = NLPS[s]
635
+ else
636
+ d = s & 1
637
+ ctx[cx] = NMPS[s]
638
+ end
639
+ else
640
+ d = s & 1
641
+ end
642
+ end
643
+ while a < 0x8000
644
+ if ct.zero?
645
+ if buf.getbyte(bp) == 0xFF
646
+ b = buf.getbyte(bp + 1)
647
+ if b > 0x8F
648
+ c += 0xFF00
649
+ ct = 8
650
+ else
651
+ bp += 1
652
+ c += b << 9
653
+ ct = 7
654
+ end
655
+ else
656
+ bp += 1
657
+ c += buf.getbyte(bp) << 8
658
+ ct = 8
659
+ end
660
+ end
661
+ a <<= 1
662
+ c <<= 1
663
+ ct -= 1
664
+ end
665
+ # ---
666
+ if d.zero?
667
+ fi += 1
668
+ col_di += 1
669
+ next
670
+ end
671
+ # Two uniform-context symbols give the first significant row.
672
+ run = 0
673
+ rn = 0
674
+ while rn < 2
675
+ cx = CTX_UNI
676
+ # --- MQ decode (cx) -> d
677
+ s = ctx[cx]
678
+ q = QE[s]
679
+ a -= q
680
+ if (c >> 16) < q
681
+ if a < q
682
+ d = s & 1
683
+ ctx[cx] = NMPS[s]
684
+ else
685
+ d = (s & 1) ^ 1
686
+ ctx[cx] = NLPS[s]
687
+ end
688
+ a = q
689
+ else
690
+ c -= q << 16
691
+ if a < 0x8000
692
+ if a < q
693
+ d = (s & 1) ^ 1
694
+ ctx[cx] = NLPS[s]
695
+ else
696
+ d = s & 1
697
+ ctx[cx] = NMPS[s]
698
+ end
699
+ else
700
+ d = s & 1
701
+ end
702
+ end
703
+ while a < 0x8000
704
+ if ct.zero?
705
+ if buf.getbyte(bp) == 0xFF
706
+ b = buf.getbyte(bp + 1)
707
+ if b > 0x8F
708
+ c += 0xFF00
709
+ ct = 8
710
+ else
711
+ bp += 1
712
+ c += b << 9
713
+ ct = 7
714
+ end
715
+ else
716
+ bp += 1
717
+ c += buf.getbyte(bp) << 8
718
+ ct = 8
719
+ end
720
+ end
721
+ a <<= 1
722
+ c <<= 1
723
+ ct -= 1
724
+ end
725
+ # ---
726
+ run = (run << 1) | d
727
+ rn += 1
728
+ end
729
+ ci = run
730
+ di += run * w
731
+ end
732
+ while ci < nr
733
+ sh = 3 * ci
734
+ fs = f >> sh
735
+ if runlength
736
+ # The run's first significant coefficient: no zero coding.
737
+ runlength = false
738
+ d = 1
739
+ elsif fs & UNVISITED_INSIGNIFICANT == 0
740
+ cx = ZC_LUT[zoff | (fs & NEIGHBOURS)]
741
+ # --- MQ decode (cx) -> d
742
+ s = ctx[cx]
743
+ q = QE[s]
744
+ a -= q
745
+ if (c >> 16) < q
746
+ if a < q
747
+ d = s & 1
748
+ ctx[cx] = NMPS[s]
749
+ else
750
+ d = (s & 1) ^ 1
751
+ ctx[cx] = NLPS[s]
752
+ end
753
+ a = q
754
+ else
755
+ c -= q << 16
756
+ if a < 0x8000
757
+ if a < q
758
+ d = (s & 1) ^ 1
759
+ ctx[cx] = NLPS[s]
760
+ else
761
+ d = s & 1
762
+ ctx[cx] = NMPS[s]
763
+ end
764
+ else
765
+ d = s & 1
766
+ end
767
+ end
768
+ while a < 0x8000
769
+ if ct.zero?
770
+ if buf.getbyte(bp) == 0xFF
771
+ b = buf.getbyte(bp + 1)
772
+ if b > 0x8F
773
+ c += 0xFF00
774
+ ct = 8
775
+ else
776
+ bp += 1
777
+ c += b << 9
778
+ ct = 7
779
+ end
780
+ else
781
+ bp += 1
782
+ c += buf.getbyte(bp) << 8
783
+ ct = 8
784
+ end
785
+ end
786
+ a <<= 1
787
+ c <<= 1
788
+ ct -= 1
789
+ end
790
+ # ---
791
+ else
792
+ d = 0
793
+ end
794
+ if d == 1
795
+ lu = (fs & 0xAA) | ((fl[fi - 1] >> (CHI_THIS_I + sh)) & 1) |
796
+ ((fl[fi + 1] >> (CHI_THIS_I - 2 + sh)) & 4) |
797
+ ((fs >> 16) & 64)
798
+ lu |= ci.zero? ? (f >> 14) & 16 : (f >> (12 + sh)) & 16
799
+ cx = SC_LUT[lu]
800
+ # --- MQ decode (cx) -> d
801
+ s = ctx[cx]
802
+ q = QE[s]
803
+ a -= q
804
+ if (c >> 16) < q
805
+ if a < q
806
+ d = s & 1
807
+ ctx[cx] = NMPS[s]
808
+ else
809
+ d = (s & 1) ^ 1
810
+ ctx[cx] = NLPS[s]
811
+ end
812
+ a = q
813
+ else
814
+ c -= q << 16
815
+ if a < 0x8000
816
+ if a < q
817
+ d = (s & 1) ^ 1
818
+ ctx[cx] = NLPS[s]
819
+ else
820
+ d = s & 1
821
+ ctx[cx] = NMPS[s]
822
+ end
823
+ else
824
+ d = s & 1
825
+ end
826
+ end
827
+ while a < 0x8000
828
+ if ct.zero?
829
+ if buf.getbyte(bp) == 0xFF
830
+ b = buf.getbyte(bp + 1)
831
+ if b > 0x8F
832
+ c += 0xFF00
833
+ ct = 8
834
+ else
835
+ bp += 1
836
+ c += b << 9
837
+ ct = 7
838
+ end
839
+ else
840
+ bp += 1
841
+ c += buf.getbyte(bp) << 8
842
+ ct = 8
843
+ end
844
+ end
845
+ a <<= 1
846
+ c <<= 1
847
+ ct -= 1
848
+ end
849
+ # ---
850
+ sign = d ^ SPB_LUT[lu]
851
+ data[di] = sign == 1 ? -oneplushalf : oneplushalf
852
+ fl[fi - 1] |= 0x20 << sh
853
+ f |= ((sign << CHI_THIS_I) | SIGMA_THIS) << sh
854
+ fl[fi + 1] |= 0x8 << sh
855
+ if ci.zero?
856
+ unless vsc
857
+ north = fi - stride
858
+ fl[north] |= (sign << 31) | 0x10000
859
+ fl[north - 1] |= 0x20000
860
+ fl[north + 1] |= 0x8000
861
+ end
862
+ elsif ci == 3
863
+ south = fi + stride
864
+ fl[south] |= (sign << 18) | 2
865
+ fl[south - 1] |= 4
866
+ fl[south + 1] |= 1
867
+ end
868
+ end
869
+ ci += 1
870
+ di += w
871
+ end
872
+ fl[fi] = f & ~PI_ALL
873
+ fi += 1
874
+ col_di += 1
875
+ end
876
+ k += 4
877
+ row_fi += stride
878
+ end
879
+ @bp = bp
880
+ @a = a
881
+ @c = c
882
+ @ct = ct
883
+ segmentation_symbol if segsym
884
+ end
885
+
886
+ # Decodes (and ignores) the four segmentation symbols.
887
+ def segmentation_symbol
888
+ 4.times { mq_decode(CTX_UNI) }
889
+ end
890
+
891
+ # One MQ decision outside the hot loops.
892
+ def mq_decode(cx)
893
+ ctx = @ctx
894
+ buf = @buf
895
+ bp = @bp
896
+ a = @a
897
+ c = @c
898
+ ct = @ct
899
+ s = ctx[cx]
900
+ q = QE[s]
901
+ a -= q
902
+ if (c >> 16) < q
903
+ if a < q
904
+ d = s & 1
905
+ ctx[cx] = NMPS[s]
906
+ else
907
+ d = (s & 1) ^ 1
908
+ ctx[cx] = NLPS[s]
909
+ end
910
+ a = q
911
+ else
912
+ c -= q << 16
913
+ if a < 0x8000
914
+ if a < q
915
+ d = (s & 1) ^ 1
916
+ ctx[cx] = NLPS[s]
917
+ else
918
+ d = s & 1
919
+ ctx[cx] = NMPS[s]
920
+ end
921
+ else
922
+ d = s & 1
923
+ end
924
+ end
925
+ while a < 0x8000
926
+ if ct.zero?
927
+ if buf.getbyte(bp) == 0xFF
928
+ b = buf.getbyte(bp + 1)
929
+ if b > 0x8F
930
+ c += 0xFF00
931
+ ct = 8
932
+ else
933
+ bp += 1
934
+ c += b << 9
935
+ ct = 7
936
+ end
937
+ else
938
+ bp += 1
939
+ c += buf.getbyte(bp) << 8
940
+ ct = 8
941
+ end
942
+ end
943
+ a <<= 1
944
+ c <<= 1
945
+ ct -= 1
946
+ end
947
+ @bp = bp
948
+ @a = a
949
+ @c = c
950
+ @ct = ct
951
+ d
952
+ end
953
+
954
+ # One raw (bypass) bit (D.6).
955
+ def raw_bit
956
+ ct = @ct
957
+ if ct.zero?
958
+ if @c == 0xFF
959
+ b = @buf.getbyte(@bp)
960
+ if b > 0x8F
961
+ @c = 0xFF
962
+ ct = 8
963
+ else
964
+ @c = b
965
+ @bp += 1
966
+ ct = 7
967
+ end
968
+ else
969
+ @c = @buf.getbyte(@bp)
970
+ @bp += 1
971
+ ct = 8
972
+ end
973
+ end
974
+ ct -= 1
975
+ @ct = ct
976
+ (@c >> ct) & 1
977
+ end
978
+
979
+ # Significance propagation pass, raw coded (bypass mode).
980
+ def sigpass_raw(w, h, bpno, vsc)
981
+ fl = @flags
982
+ data = @data
983
+ one = 1 << bpno
984
+ oneplushalf = one | (one >> 1)
985
+ stride = w + 2
986
+ row_fi = stride + 1
987
+ k = 0
988
+ while k < h
989
+ nr = h - k
990
+ nr = 4 if nr > 4
991
+ fi = row_fi
992
+ col_di = k * w
993
+ stop = row_fi + w
994
+ while fi < stop
995
+ f = fl[fi]
996
+ if f != 0
997
+ ci = 0
998
+ di = col_di
999
+ while ci < nr
1000
+ sh = 3 * ci
1001
+ fs = f >> sh
1002
+ if fs & UNVISITED_INSIGNIFICANT == 0 && fs & NEIGHBOURS != 0
1003
+ if raw_bit == 1
1004
+ sign = raw_bit
1005
+ data[di] = sign == 1 ? -oneplushalf : oneplushalf
1006
+ fl[fi - 1] |= 0x20 << sh
1007
+ f |= ((sign << CHI_THIS_I) | SIGMA_THIS) << sh
1008
+ fl[fi + 1] |= 0x8 << sh
1009
+ if ci.zero?
1010
+ unless vsc
1011
+ north = fi - stride
1012
+ fl[north] |= (sign << 31) | 0x10000
1013
+ fl[north - 1] |= 0x20000
1014
+ fl[north + 1] |= 0x8000
1015
+ end
1016
+ elsif ci == 3
1017
+ south = fi + stride
1018
+ fl[south] |= (sign << 18) | 2
1019
+ fl[south - 1] |= 4
1020
+ fl[south + 1] |= 1
1021
+ end
1022
+ end
1023
+ f |= PI_THIS << sh
1024
+ end
1025
+ ci += 1
1026
+ di += w
1027
+ end
1028
+ fl[fi] = f
1029
+ end
1030
+ fi += 1
1031
+ col_di += 1
1032
+ end
1033
+ k += 4
1034
+ row_fi += stride
1035
+ end
1036
+ end
1037
+
1038
+ # Magnitude refinement pass, raw coded (bypass mode).
1039
+ def refpass_raw(w, h, bpno)
1040
+ fl = @flags
1041
+ data = @data
1042
+ poshalf = (1 << bpno) >> 1
1043
+ stride = w + 2
1044
+ row_fi = stride + 1
1045
+ k = 0
1046
+ while k < h
1047
+ nr = h - k
1048
+ nr = 4 if nr > 4
1049
+ fi = row_fi
1050
+ col_di = k * w
1051
+ stop = row_fi + w
1052
+ while fi < stop
1053
+ f = fl[fi]
1054
+ if f & ANY_SIGNIFICANT != 0
1055
+ ci = 0
1056
+ di = col_di
1057
+ while ci < nr
1058
+ sh = 3 * ci
1059
+ if (f >> sh) & UNVISITED_INSIGNIFICANT == SIGMA_THIS
1060
+ d = raw_bit
1061
+ v = data[di]
1062
+ if v.negative?
1063
+ data[di] = d == 1 ? v - poshalf : v + poshalf
1064
+ else
1065
+ data[di] = d == 1 ? v + poshalf : v - poshalf
1066
+ end
1067
+ f |= MU_THIS << sh
1068
+ end
1069
+ ci += 1
1070
+ di += w
1071
+ end
1072
+ fl[fi] = f
1073
+ end
1074
+ fi += 1
1075
+ col_di += 1
1076
+ end
1077
+ k += 4
1078
+ row_fi += stride
1079
+ end
1080
+ end
1081
+ end
1082
+ end
1083
+ end
1084
+ end