qr_reader 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.
Files changed (58) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +16 -0
  3. data/LICENSE.txt +21 -0
  4. data/NOTICE +14 -0
  5. data/README.md +222 -0
  6. data/exe/qr_reader +66 -0
  7. data/lib/qr_reader/binarizer.rb +170 -0
  8. data/lib/qr_reader/bit_matrix.rb +120 -0
  9. data/lib/qr_reader/decoder/bitstream_parser.rb +307 -0
  10. data/lib/qr_reader/decoder/character_set.rb +163 -0
  11. data/lib/qr_reader/decoder/codewords.rb +164 -0
  12. data/lib/qr_reader/decoder/data_mask.rb +57 -0
  13. data/lib/qr_reader/decoder/format_reader.rb +204 -0
  14. data/lib/qr_reader/decoder/function_patterns.rb +62 -0
  15. data/lib/qr_reader/decoder/galois_field.rb +69 -0
  16. data/lib/qr_reader/decoder/reed_solomon.rb +312 -0
  17. data/lib/qr_reader/decoder.rb +241 -0
  18. data/lib/qr_reader/detector/alignment_grid.rb +127 -0
  19. data/lib/qr_reader/detector/alignment_pattern_finder.rb +191 -0
  20. data/lib/qr_reader/detector/candidate/dimension.rb +237 -0
  21. data/lib/qr_reader/detector/candidate/strokes.rb +126 -0
  22. data/lib/qr_reader/detector/candidate.rb +436 -0
  23. data/lib/qr_reader/detector/finder_pattern.rb +63 -0
  24. data/lib/qr_reader/detector/finder_pattern_finder.rb +199 -0
  25. data/lib/qr_reader/detector/geometry.rb +118 -0
  26. data/lib/qr_reader/detector/grid_sampler.rb +350 -0
  27. data/lib/qr_reader/detector/pattern_sets.rb +235 -0
  28. data/lib/qr_reader/detector/perspective_transform.rb +117 -0
  29. data/lib/qr_reader/detector/pure_detector.rb +197 -0
  30. data/lib/qr_reader/detector.rb +215 -0
  31. data/lib/qr_reader/errors.rb +14 -0
  32. data/lib/qr_reader/format_information.rb +79 -0
  33. data/lib/qr_reader/formats/bmp.rb +434 -0
  34. data/lib/qr_reader/formats/ccitt.rb +81 -0
  35. data/lib/qr_reader/formats/gif.rb +272 -0
  36. data/lib/qr_reader/formats/jpeg.rb +152 -0
  37. data/lib/qr_reader/formats/pdf.rb +2935 -0
  38. data/lib/qr_reader/formats/png.rb +311 -0
  39. data/lib/qr_reader/formats/pnm.rb +286 -0
  40. data/lib/qr_reader/formats/tiff.rb +1345 -0
  41. data/lib/qr_reader/formats.rb +279 -0
  42. data/lib/qr_reader/image.rb +231 -0
  43. data/lib/qr_reader/kernels/binarizer.rb +475 -0
  44. data/lib/qr_reader/kernels/ccitt.rb +554 -0
  45. data/lib/qr_reader/kernels/detector.rb +587 -0
  46. data/lib/qr_reader/kernels/image.rb +65 -0
  47. data/lib/qr_reader/kernels/jpeg.rb +3421 -0
  48. data/lib/qr_reader/kernels/lzw.rb +173 -0
  49. data/lib/qr_reader/kernels/pixels.rb +116 -0
  50. data/lib/qr_reader/kernels/png.rb +1138 -0
  51. data/lib/qr_reader/kernels.rb +14 -0
  52. data/lib/qr_reader/native_kernels.rb +130 -0
  53. data/lib/qr_reader/reader.rb +348 -0
  54. data/lib/qr_reader/result.rb +49 -0
  55. data/lib/qr_reader/symbol_version.rb +173 -0
  56. data/lib/qr_reader/version.rb +5 -0
  57. data/lib/qr_reader.rb +77 -0
  58. metadata +103 -0
@@ -0,0 +1,3421 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "../errors"
4
+
5
+ # JPEG kernels: a luminance-only JPEG decoder in the Ruby subset that Spinel
6
+ # compiles (see DESIGN.md, "Kernels"); QrReader::Formats::JPEG wraps it.
7
+ #
8
+ # Supported: baseline (SOF0), extended sequential Huffman (SOF1) and
9
+ # progressive (SOF2) 8-bit JPEGs with any sampling factors, restart
10
+ # intervals, 8/16-bit quantisation tables, 1 component (gray), 3 components
11
+ # (YCbCr, or RGB via Adobe APP14 / component ids "RGB") and 4 components
12
+ # (Adobe CMYK and YCCK). Arithmetic coding, lossless, hierarchical, 12-bit
13
+ # and JPEG-LS files raise UnsupportedImageError. The output matches
14
+ # libjpeg-turbo's default "islow" IDCT exactly (as built with SIMD, which
15
+ # saturates out-of-range samples), including the reduced IDCTs,
16
+ # per-component DCT scaling and upsampling used for scale 2, 4 and 8.
17
+ # Truncated scan data decodes what is present (missing blocks stay
18
+ # mid-gray); damaged restart intervals are resynchronised by their marker
19
+ # numbers; other corruption raises ImageError.
20
+ #
21
+ # How it stays fast in pure Ruby:
22
+ # * For YCbCr only Y is reconstructed (Y is the luminance). Chroma blocks
23
+ # are entropy-decoded and dropped; chroma-only progressive scans (and
24
+ # AC scans at scale 8) are skipped without decoding.
25
+ # * Byte stuffing and restart markers are removed per scan at C speed, so
26
+ # the bit reader (32 bits per refill) never checks for markers.
27
+ # * Huffman lookahead tables also carry the run length and sign-extended
28
+ # coefficient, so most coefficients cost a single table lookup.
29
+ # * Coefficients are decoded into one Array per block row (65 entries per
30
+ # block: 64 dequantised coefficients in natural order, then the zigzag
31
+ # index of the last nonzero one), which selects a DC-only fill or an IDCT
32
+ # specialised for the inputs that can be nonzero (derived from libjpeg's
33
+ # formulas). Rows are IDCT'd, packed and cleared once per MCU row.
34
+ # * Hot loops live in methods called per MCU, block row or block, so YJIT
35
+ # (which compiles a method once it has been called 30 times) kicks in
36
+ # during the first decode.
37
+ # * Samples are collected four to an Array element (32-bit words) per MCU
38
+ # row and packed to bytes at C speed.
39
+ #
40
+ # Memory stays proportional to the output: sequential scans keep one MCU
41
+ # row of coefficients; progressive scans keep every coefficient of the
42
+ # needed components as packed 16-bit Strings (one per block row, allocated
43
+ # only where data arrives); nothing is allocated per pixel or coefficient
44
+ # for a whole image.
45
+ #
46
+ # Two resolutions for about the price of one decode: jpeg_luma_keep also
47
+ # returns a compact store of the luminance (see JpegDecoder#store), from
48
+ # which jpeg_render produces any other scale. For sequential JPEGs it holds
49
+ # the scan data and, per luminance block, where its AC coefficients start
50
+ # and its DC (8 bytes per block), so rendering skips the chroma blocks and
51
+ # all DC decoding; for progressive JPEGs the coefficients themselves.
52
+ module QrReaderKernels
53
+ # [width, height] from the frame header (the height from a DNL marker
54
+ # when the header gives 0), without decoding.
55
+ # spinel-sample: QrReaderKernels.jpeg_info("\xFF\xD8".b)
56
+ def self.jpeg_info(bytes)
57
+ JpegDecoder.new(bytes, 1, false).info
58
+ end
59
+
60
+ # Luminance at 1/+scale+ (1, 2, 4 or 8) of the size, ceil(width / scale)
61
+ # x ceil(height / scale) bytes, row-major.
62
+ # spinel-sample: QrReaderKernels.jpeg_luma("\xFF\xD8".b, 1)
63
+ def self.jpeg_luma(bytes, scale)
64
+ JpegDecoder.new(bytes, scale, false).decode
65
+ end
66
+
67
+ # Like jpeg_luma, but also returns a store of the luminance component
68
+ # for jpeg_render: [luma, store]. The store is empty when the luminance
69
+ # is not a single component (RGB, CMYK) or too large for scale 1.
70
+ # spinel-sample: QrReaderKernels.jpeg_luma_keep("\xFF\xD8".b, 4)
71
+ def self.jpeg_luma_keep(bytes, scale)
72
+ decoder = JpegDecoder.new(bytes, scale, true)
73
+ luma = decoder.decode
74
+ [luma, decoder.store]
75
+ end
76
+
77
+ # Luminance at 1/+scale+ from a store made by jpeg_luma_keep: the same
78
+ # bytes as jpeg_luma at that scale, without decoding chroma or DCs.
79
+ # spinel-sample: QrReaderKernels.jpeg_render("\x00".b, 1)
80
+ def self.jpeg_render(store, scale)
81
+ JpegDecoder.new(store, scale, false).render_store
82
+ end
83
+
84
+ # Unsigned little-endian 32-bit Integer at data[off, 4], or -1 if the
85
+ # data ends before.
86
+ def self.jpeg_u32(data, off)
87
+ return -1 if off < 0 || off + 4 > data.bytesize
88
+
89
+ data.getbyte(off) | (data.getbyte(off + 1) << 8) | (data.getbyte(off + 2) << 16) | (data.getbyte(off + 3) << 24)
90
+ end
91
+
92
+ # --- Tables -------------------------------------------------------------
93
+
94
+ # Lookahead bits of the Huffman fast tables.
95
+ JPEG_FAST_BITS = 10
96
+ JPEG_FAST_MASK = (1 << JPEG_FAST_BITS) - 1
97
+
98
+ # Run used for end-of-block in the AC fast tables: it pushes the
99
+ # coefficient index past 63, ending the block loop without a branch.
100
+ # A block loop that ended at k > JPEG_EOB_RUN had its EOB at k - EOB_RUN - 1.
101
+ JPEG_EOB_RUN = 100
102
+
103
+ # Zigzag index -> natural (row-major) index.
104
+ JPEG_ZIGZAG = [
105
+ 0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5,
106
+ 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28,
107
+ 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51,
108
+ 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63
109
+ ].freeze
110
+
111
+ # JPEG_ZIGZAG extended for corrupt runs past 63 (clamped to 63 like
112
+ # libjpeg) and for the end-of-block pseudo run (slot 64 of the block,
113
+ # which is overwritten with the block's last nonzero index afterwards).
114
+ JPEG_ZIGZAG_EXT = (JPEG_ZIGZAG + Array.new(16, 63) + Array.new(JPEG_EOB_RUN + 4 - 16, 64)).freeze
115
+
116
+ # Entries per block of a coefficient row: 64 coefficients in natural
117
+ # order and, at index 64, the zigzag index of the last nonzero one.
118
+ JPEG_BLOCK_STRIDE = 65
119
+
120
+ # Decoded samples are buffered as packed little-endian words (first
121
+ # sample in the low byte: "V*" packs faster than "N*"). By output block
122
+ # size (8 / scale): samples per word, words per block row, the factor
123
+ # that repeats a sample over a word, and the pack directive.
124
+ JPEG_SAMPLES_PER_WORD = [0, 1, 2, 0, 4, 0, 0, 0, 4].freeze
125
+ JPEG_WORDS = [0, 1, 1, 0, 1, 0, 0, 0, 2].freeze
126
+ JPEG_SPREAD = [0, 1, 0x0101, 0, 0x01010101, 0, 0, 0, 0x01010101].freeze
127
+ JPEG_PACK = ["", "C*", "v*", "", "V*", "", "", "", "V*"].freeze
128
+
129
+ # Largest supported output (64 Mi pixels, e.g. 8192 x 8192); bigger
130
+ # images need a larger scale. Guards against absurd header sizes.
131
+ JPEG_MAX_PIXELS = 1 << 26
132
+
133
+ # Most bytes the coefficients of a progressive JPEG may take (2 per
134
+ # coefficient): enough for one needed component of a MAX_PIXELS image,
135
+ # and for all four of a CMYK image of a quarter of that size.
136
+ JPEG_MAX_COEFFICIENT_BYTES = 160 << 20
137
+
138
+ # Block visits (blocks covered by decoded scans) per block of the needed
139
+ # components after which the rest of a file is ignored: real progressive
140
+ # files make about 3 to 10, but crafted ones could repeat cheap scans
141
+ # (e.g. end-of-band runs over the whole image).
142
+ JPEG_MAX_VISITS = 64
143
+
144
+ # Decoded scans after which the rest of a file is ignored: crafted files
145
+ # with endless refinement scans could otherwise take very long (real
146
+ # progressive files have about 6 to 20 scans).
147
+ JPEG_MAX_SCANS = 256
148
+
149
+ # Colour spaces of the stored components.
150
+ JPEG_GRAY = 0
151
+ JPEG_YCBCR = 1
152
+ JPEG_RGB = 2
153
+ JPEG_CMYK = 3
154
+ JPEG_YCCK = 4
155
+ JPEG_OTHER = 5
156
+
157
+ # Standard Huffman tables (ITU T.81 Annex K.3), used when a scan refers
158
+ # to an undefined table 0 or 1 (Motion-JPEG frames omit them), like
159
+ # libjpeg-turbo does: code counts per length and symbols.
160
+ JPEG_STD_DC_COUNTS = [
161
+ [0, 1, 5, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], [0, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
162
+ ].freeze
163
+ JPEG_STD_DC_SYMBOLS = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].freeze
164
+ JPEG_STD_AC_COUNTS = [
165
+ [0, 2, 1, 3, 3, 2, 4, 3, 5, 5, 4, 4, 0, 0, 1, 0x7d], [0, 2, 1, 2, 4, 4, 3, 4, 7, 5, 4, 4, 0, 1, 2, 0x77]
166
+ ].freeze
167
+ JPEG_STD_AC_SYMBOLS = [
168
+ [
169
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
170
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
171
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
172
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
173
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
174
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
175
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
176
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
177
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
178
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
179
+ 0xf9, 0xfa
180
+ ],
181
+ [
182
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
183
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
184
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
185
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
186
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
187
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
188
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
189
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
190
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
191
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
192
+ 0xf9, 0xfa
193
+ ]
194
+ ].freeze
195
+
196
+
197
+ # Post-IDCT range limiting of libjpeg-turbo's 8x8, 4x4 and 2x2 IDCTs,
198
+ # whose SIMD versions (used on x86 and ARM) saturate: indexed by
199
+ # (sample + 128) & 0xFFFF, clamps samples within +-32767 to 0..255.
200
+ def self.jpeg_clamp_table
201
+ t = Array.new(65_536, 0)
202
+ i = 0
203
+ while i < 32_896
204
+ t[i] = i < 256 ? i : 255
205
+ i += 1
206
+ end
207
+ t
208
+ end
209
+
210
+ # libjpeg's C range-limit table (used by its 1x1 IDCT at scale 8),
211
+ # indexed by (sample + 128) & 1023: clamps to 0..255 near the valid range
212
+ # but wraps far out-of-range samples around.
213
+ def self.jpeg_range_limit_table
214
+ t = Array.new(1024, 0)
215
+ i = 0
216
+ while i < 1024
217
+ c = (i - 128) & 1023
218
+ t[i] = if c < 128 then c + 128
219
+ elsif c < 512 then 255
220
+ elsif c < 896 then 0
221
+ else c - 896
222
+ end
223
+ i += 1
224
+ end
225
+ t
226
+ end
227
+
228
+ # libjpeg's YCbCr -> RGB tables (jdcolor.c, 16-bit fixed point), indexed
229
+ # by the Cb/Cr sample: Cr -> R, Cb -> B, Cr -> G and Cb -> G (+ rounding).
230
+ def self.jpeg_color_table(kind)
231
+ t = Array.new(256, 0)
232
+ i = 0
233
+ while i < 256
234
+ x = i - 128
235
+ t[i] = if kind == 0 then (91_881 * x + 32_768) >> 16
236
+ elsif kind == 1 then (116_130 * x + 32_768) >> 16
237
+ elsif kind == 2 then -46_802 * x
238
+ else -22_554 * x + 32_768
239
+ end
240
+ i += 1
241
+ end
242
+ t
243
+ end
244
+
245
+ JPEG_CLAMP = jpeg_clamp_table.freeze
246
+ JPEG_RANGE_LIMIT = jpeg_range_limit_table.freeze
247
+ JPEG_CR_R = jpeg_color_table(0).freeze
248
+ JPEG_CB_B = jpeg_color_table(1).freeze
249
+ JPEG_CR_G = jpeg_color_table(2).freeze
250
+ JPEG_CB_G = jpeg_color_table(3).freeze
251
+
252
+ # A shared empty Integer Array: "not defined" tables, unused slots.
253
+ JPEG_NONE = Array.new(0, 0).freeze
254
+ # Huffman code counts of an undefined table.
255
+ JPEG_NO_COUNTS = Array.new(16, 0).freeze
256
+
257
+ JPEG_FF = "\xFF".b.freeze
258
+ JPEG_DNL_MARKER = "\xFF\xDC\x00\x04".b.freeze
259
+ # Zero bytes appended to a scan: more than one MCU can consume, so a
260
+ # truncated MCU never reads past the end of the data.
261
+ JPEG_TAIL_PADDING = ("\0" * 4096).b.freeze
262
+
263
+ # First Integer of a store made by jpeg_luma_keep ("JPK3"), and its kinds.
264
+ JPEG_STORE_MAGIC = 0x334B_504A
265
+ JPEG_STORE_SEQUENTIAL = 1
266
+ JPEG_STORE_PROGRESSIVE = 2
267
+ # Integers in a store header (before the kind's own data).
268
+ JPEG_STORE_HEAD = 77
269
+ # Bytes per block of a raw progressive coefficient row, and the offset of
270
+ # the block's last nonzero zigzag index in it.
271
+ JPEG_RAW_BLOCK = JPEG_BLOCK_STRIDE * 2
272
+ JPEG_RAW_KM = 128
273
+
274
+ # Name of an unsupported frame type (SOF marker code).
275
+ def self.jpeg_sof_name(code)
276
+ if code == 0xC3 then "lossless"
277
+ elsif code == 0xC5 then "hierarchical"
278
+ elsif code == 0xC6 then "hierarchical progressive"
279
+ elsif code == 0xC7 then "hierarchical lossless"
280
+ elsif code == 0xC9 then "arithmetic-coded"
281
+ elsif code == 0xCA then "arithmetic-coded progressive"
282
+ elsif code == 0xCB then "arithmetic-coded lossless"
283
+ elsif code == 0xCD then "arithmetic-coded hierarchical"
284
+ elsif code == 0xCE then "arithmetic-coded hierarchical progressive"
285
+ elsif code == 0xCF then "arithmetic-coded hierarchical lossless"
286
+ else "JPEG-LS"
287
+ end
288
+ end
289
+
290
+ # Raised internally when the data ends early; decoding then finishes with
291
+ # what was decoded so far.
292
+ class JpegTruncated < QrReader::ImageError; end
293
+
294
+ # A Huffman table with FAST_BITS lookahead tables.
295
+ #
296
+ # +look+ maps the next FAST_BITS bits to (code length << 8 | symbol), or 0
297
+ # for longer codes (see #decode_long). +fast+ also folds in the extra
298
+ # bits: (value << 16) | (run << 8) | (total bit length), or 0 when code
299
+ # and extra bits do not fit in FAST_BITS. Zero-valued AC entries are the
300
+ # end-of-block (run JPEG_EOB_RUN) and ZRL (run 15) symbols.
301
+ class JpegHuffman
302
+ attr_reader :fast, :look, :counts, :symbols
303
+
304
+ # +counts+: number of codes of each length 1..16; +symbols+ in code order.
305
+ def initialize(counts, symbols, ac)
306
+ @fast = Array.new(1 << JPEG_FAST_BITS, 0)
307
+ @look = Array.new(1 << JPEG_FAST_BITS, 0)
308
+ @maxcode = Array.new(18, 0)
309
+ @valoff = Array.new(17, 0)
310
+ @counts = counts
311
+ @symbols = symbols
312
+ code = 0
313
+ index = 0
314
+ len = 1
315
+ while len <= 16
316
+ n = counts[len - 1]
317
+ @valoff[len] = index - code
318
+ i = 0
319
+ while i < n
320
+ sym = symbols[index]
321
+ raise QrReader::ImageError, "corrupt JPEG: bad DC Huffman symbol #{sym}" if !ac && sym > 15
322
+
323
+ add_entries(code, len, sym, ac) if len <= JPEG_FAST_BITS
324
+ code += 1
325
+ index += 1
326
+ i += 1
327
+ end
328
+ # Codes must fit in len bits and may not be all ones (like libjpeg).
329
+ raise QrReader::ImageError, "corrupt JPEG: bad Huffman table" if n > 0 && code >= (1 << len)
330
+
331
+ @maxcode[len] = code << (16 - len)
332
+ code <<= 1
333
+ len += 1
334
+ end
335
+ @maxcode[17] = 1 << 17
336
+ end
337
+
338
+ # Decodes a code longer than FAST_BITS from the next 16 bits. Returns
339
+ # (length << 8) | symbol; an invalid code yields symbol 0 and length 16
340
+ # ("fake a zero", like libjpeg).
341
+ def decode_long(window)
342
+ len = JPEG_FAST_BITS + 1
343
+ len += 1 while window >= @maxcode[len]
344
+ return 16 << 8 if len > 16
345
+
346
+ (len << 8) | @symbols[(window >> (16 - len)) + @valoff[len]]
347
+ end
348
+
349
+ private
350
+
351
+ def add_entries(code, len, sym, ac)
352
+ shift = JPEG_FAST_BITS - len
353
+ base = code << shift
354
+ @look.fill((len << 8) | sym, base, 1 << shift)
355
+ run = 0
356
+ size = sym
357
+ if ac
358
+ run = sym >> 4
359
+ size = sym & 15
360
+ end
361
+ if size == 0
362
+ # DC: difference 0. AC: ZRL, or end of block (libjpeg treats every
363
+ # other zero-size symbol in sequential scans as EOB).
364
+ run = JPEG_EOB_RUN if ac && run != 15
365
+ @fast.fill((run << 8) | len, base, 1 << shift)
366
+ elsif size <= shift
367
+ rest = shift - size
368
+ count = 1 << rest
369
+ head = (run << 8) | (len + size)
370
+ half = 1 << (size - 1)
371
+ offset = (1 << size) - 1
372
+ v = 0
373
+ while v <= offset
374
+ value = v < half ? v - offset : v
375
+ @fast.fill((value << 16) | head, base | (v << rest), count)
376
+ v += 1
377
+ end
378
+ end
379
+ nil
380
+ end
381
+ end
382
+
383
+ # A placeholder table (no codes).
384
+ JPEG_EMPTY_HUFFMAN = JpegHuffman.new(JPEG_NO_COUNTS, JPEG_NONE, false)
385
+
386
+ # Frame component state.
387
+ class JpegComponent
388
+ attr_reader :index, :id, :h, :v, :tq, :plane, :raw, :marks, :sdata
389
+ # Sample size at full scale, blocks covered by a non-interleaved scan,
390
+ # allocated block grid (padded to whole MCUs) and plane size in samples.
391
+ attr_accessor :cw, :ch, :bw, :bh, :abw, :abh, :pw, :ph
392
+ # Whether the component contributes to the luminance output.
393
+ attr_accessor :needed
394
+ # Output size of its blocks (libjpeg's DCT_scaled_size: 8, 4, 2 or 1)
395
+ # and the IDCT producing them.
396
+ attr_accessor :bs, :idct
397
+ # Progressive JPEGs: Integers per block of the raw coefficient rows
398
+ # (JPEG_BLOCK_STRIDE, or 1 when only DCs are needed).
399
+ attr_accessor :stride
400
+ # Latched dequantisation table, indexed by (extended) zigzag position.
401
+ attr_accessor :qz
402
+
403
+ def initialize(index, id, h, v, tq)
404
+ @index = index
405
+ @id = id
406
+ @h = h
407
+ @v = v
408
+ @tq = tq
409
+ @cw = 0
410
+ @ch = 0
411
+ @bw = 0
412
+ @bh = 0
413
+ @abw = 0
414
+ @abh = 0
415
+ @pw = 0
416
+ @ph = 0
417
+ @needed = false
418
+ @bs = 8
419
+ @idct = JpegIDCT.new(8)
420
+ # Output plane (binary String, pw x ph, filled row by row).
421
+ @plane = "".b
422
+ # Progressive JPEGs: raw coefficients (not dequantised) as packed
423
+ # signed 16-bit Strings, one per block row ("" until data arrives).
424
+ @raw = []
425
+ @stride = JPEG_BLOCK_STRIDE
426
+ @qz = JPEG_NONE
427
+ # Store (see JpegDecoder#store) of a sequential decode: per block of
428
+ # the allocated grid, the bit position of its AC data in the scan and
429
+ # its DC, as (position << 16) | (DC & 0xFFFF), or -1 without data.
430
+ @marks = JPEG_NONE
431
+ # Store of a progressive decode: the raw coefficient rows.
432
+ @sdata = "".b
433
+ end
434
+
435
+ # Starts an empty output plane for pw x ph samples.
436
+ def start_plane
437
+ @plane = String.new(capacity: @pw * @ph, encoding: Encoding::BINARY)
438
+ nil
439
+ end
440
+
441
+ # Appends sample rows to the plane (nothing beyond its size).
442
+ def append_plane(rows)
443
+ @plane << rows if @plane.bytesize + rows.bytesize <= @pw * @ph
444
+ nil
445
+ end
446
+
447
+ # Pads the plane with mid-gray rows up to its full size.
448
+ def finish_plane
449
+ gray = @pw * @ph - @plane.bytesize
450
+ @plane << ("\x80".b * gray) if gray > 0
451
+ nil
452
+ end
453
+
454
+ # Starts the progressive coefficient rows (all empty).
455
+ def start_raw
456
+ @raw = Array.new(@abh, "".b)
457
+ nil
458
+ end
459
+
460
+ # Raw coefficient row +r+, allocated (all zero) on first use.
461
+ def raw_row(r)
462
+ row = @raw[r]
463
+ if row.empty?
464
+ row = "\0".b * (@abw * @stride * 2)
465
+ @raw[r] = row
466
+ end
467
+ row
468
+ end
469
+
470
+ # Frees raw coefficient row +r+.
471
+ def release_raw(r)
472
+ @raw[r] = "".b
473
+ nil
474
+ end
475
+
476
+ # Starts the block marks of a sequential decode with a store.
477
+ def start_marks
478
+ @marks = Array.new(@abw * @abh, -1)
479
+ nil
480
+ end
481
+
482
+ # Appends raw coefficient row +raw+ ("" for an all-zero row) to the
483
+ # store of a progressive decode.
484
+ def store_raw(raw)
485
+ if raw.empty?
486
+ @sdata << ("\0".b * (@abw * JPEG_RAW_BLOCK))
487
+ else
488
+ @sdata << raw
489
+ end
490
+ nil
491
+ end
492
+ end
493
+
494
+ # Inverse DCTs, bit-exact with libjpeg's jidctint.c ("islow", 8x8 output)
495
+ # and jidctred.c (4x4 and 2x2 output for scaled decoding).
496
+ #
497
+ # The idct<size>_<n> methods are libjpeg's 1-D kernels specialised for
498
+ # blocks whose nonzero coefficients lie in the top-left n x n corner
499
+ # (dropping zero terms changes nothing in integer arithmetic). Rounding
500
+ # and the +128 level shift are folded into the DC term of each pass.
501
+ #
502
+ # Input: dequantised coefficients in natural order at c[base, 64].
503
+ # Output: a bs x bs block written to the Array +out+ as packed
504
+ # little-endian words (JPEG_WORDS[bs] per block row) at word offset
505
+ # +off+ with row stride +stride+ (in words). Writing four samples per
506
+ # Array element instead of one is markedly faster under YJIT.
507
+ #
508
+ # One instance (with a fixed set of instance variables, which keeps
509
+ # YJIT's code monomorphic) serves a whole decode.
510
+ class JpegIDCT
511
+ attr_reader :bs
512
+
513
+ # +bs+: output block size 8, 4, 2 or 1 (1 needs no IDCT, only #fill).
514
+ def initialize(bs)
515
+ @bs = bs
516
+ @ws = Array.new(64, 0)
517
+ end
518
+
519
+ # IDCT of the block at c[base, 64] whose last nonzero coefficient has
520
+ # zigzag index +km+ (> 0; DC-only blocks are filled by callers).
521
+ def transform(c, base, km, out, off, stride)
522
+ bs = @bs
523
+ if bs == 8
524
+ if km <= 2 then idct8_2(c, base, out, off, stride)
525
+ elsif km <= 9 then idct8_4(c, base, out, off, stride)
526
+ elsif km <= 20 then idct8_6(c, base, out, off, stride)
527
+ else idct8_8(c, base, out, off, stride)
528
+ end
529
+ elsif bs == 4
530
+ if km <= 2 then idct4_2(c, base, out, off, stride)
531
+ elsif km <= 9 then idct4_4(c, base, out, off, stride)
532
+ else idct4_8(c, base, out, off, stride)
533
+ end
534
+ elsif km <= 2
535
+ idct2_2(c, base, out, off, stride)
536
+ else
537
+ idct2_8(c, base, out, off, stride)
538
+ end
539
+ nil
540
+ end
541
+
542
+ # Sample of a DC-only block (the same for every IDCT size, except that
543
+ # libjpeg-turbo's 1x1 IDCT wraps instead of saturating).
544
+ def dc_sample(dequantised_dc)
545
+ if @bs == 1
546
+ JPEG_RANGE_LIMIT[((dequantised_dc + 1028) >> 3) & 1023]
547
+ else
548
+ JPEG_CLAMP[((dequantised_dc + 1028) >> 3) & 0xFFFF]
549
+ end
550
+ end
551
+
552
+ # Fills a bs x bs block of +out+ (packed words) with sample +value+.
553
+ def fill(out, off, stride, value)
554
+ bs = @bs
555
+ v = value * JPEG_SPREAD[bs]
556
+ r = 0
557
+ if bs == 8
558
+ while r < 8
559
+ out[off] = v
560
+ out[off + 1] = v
561
+ off += stride
562
+ r += 1
563
+ end
564
+ else
565
+ while r < bs
566
+ out[off] = v
567
+ off += stride
568
+ r += 1
569
+ end
570
+ end
571
+ nil
572
+ end
573
+
574
+ # IDCTs the +n+ blocks of a coefficient row (JPEG_BLOCK_STRIDE entries
575
+ # per block: dequantised coefficients in natural order, then the zigzag
576
+ # index of the last nonzero one) into +out+ at word offset +off+.
577
+ def render_row(row, n, out, off, stride)
578
+ step = JPEG_WORDS[@bs]
579
+ dc_only = @bs == 1
580
+ base = 0
581
+ x = 0
582
+ while x < n
583
+ km = row[base + 64]
584
+ if km == 0 || dc_only
585
+ fill(out, off, stride, dc_sample(row[base]))
586
+ else
587
+ transform(row, base, km, out, off, stride)
588
+ end
589
+ base += JPEG_BLOCK_STRIDE
590
+ off += step
591
+ x += 1
592
+ end
593
+ nil
594
+ end
595
+
596
+ def idct8_2(c, base, out, off, stride)
597
+ rl = JPEG_CLAMP
598
+ ws = @ws
599
+ i = 0
600
+ ci = base
601
+ while i <= 1
602
+ d0 = c[ci]
603
+ d1 = c[ci + 8]
604
+ if d1 == 0
605
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = ws[i + 32] = ws[i + 40] = ws[i + 48] = ws[i + 56] = d0 << 2
606
+ else
607
+ t0 = (d0 << 13) + 1024
608
+ o3 = d1 * 11_363
609
+ o2 = d1 * 9633
610
+ o1 = d1 * 6437
611
+ o0 = d1 * 2260
612
+ ws[i] = (t0 + o3) >> 11
613
+ ws[i + 8] = (t0 + o2) >> 11
614
+ ws[i + 16] = (t0 + o1) >> 11
615
+ ws[i + 24] = (t0 + o0) >> 11
616
+ ws[i + 32] = (t0 - o0) >> 11
617
+ ws[i + 40] = (t0 - o1) >> 11
618
+ ws[i + 48] = (t0 - o2) >> 11
619
+ ws[i + 56] = (t0 - o3) >> 11
620
+ end
621
+ i += 1
622
+ ci = base + i
623
+ end
624
+ i = 0
625
+ while i < 64
626
+ d0 = ws[i]
627
+ d1 = ws[i + 1]
628
+ if d1 == 0
629
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
630
+ out[off] = v
631
+ out[off + 1] = v
632
+ else
633
+ t0 = (d0 + 4112) << 13
634
+ o3 = d1 * 11_363
635
+ o2 = d1 * 9633
636
+ o1 = d1 * 6437
637
+ o0 = d1 * 2260
638
+ out[off] = rl[((t0 + o3) >> 18) & 0xFFFF] | (rl[((t0 + o2) >> 18) & 0xFFFF] << 8) | (rl[((t0 + o1) >> 18) & 0xFFFF] << 16) | (rl[((t0 + o0) >> 18) & 0xFFFF] << 24)
639
+ out[off + 1] = rl[((t0 - o0) >> 18) & 0xFFFF] | (rl[((t0 - o1) >> 18) & 0xFFFF] << 8) | (rl[((t0 - o2) >> 18) & 0xFFFF] << 16) | (rl[((t0 - o3) >> 18) & 0xFFFF] << 24)
640
+ end
641
+ off += stride
642
+ i += 8
643
+ end
644
+ nil
645
+ end
646
+
647
+ def idct8_4(c, base, out, off, stride)
648
+ rl = JPEG_CLAMP
649
+ ws = @ws
650
+ i = 0
651
+ ci = base
652
+ while i <= 3
653
+ d0 = c[ci]
654
+ d1 = c[ci + 8]
655
+ d2 = c[ci + 16]
656
+ d3 = c[ci + 24]
657
+ if d1 == 0 && d2 == 0 && d3 == 0
658
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = ws[i + 32] = ws[i + 40] = ws[i + 48] = ws[i + 56] = d0 << 2
659
+ else
660
+ t0 = (d0 << 13) + 1024
661
+ t2 = d2 * 4433
662
+ t3 = d2 * 10_703
663
+ t10 = t0 + t3
664
+ t13 = t0 - t3
665
+ t11 = t0 + t2
666
+ t12 = t0 - t2
667
+ o0 = d1 * 2260 - d3 * 6436
668
+ o1 = d1 * 6437 - d3 * 11_362
669
+ o2 = d1 * 9633 - d3 * 2259
670
+ o3 = d1 * 11_363 + d3 * 9633
671
+ ws[i] = (t10 + o3) >> 11
672
+ ws[i + 8] = (t11 + o2) >> 11
673
+ ws[i + 16] = (t12 + o1) >> 11
674
+ ws[i + 24] = (t13 + o0) >> 11
675
+ ws[i + 32] = (t13 - o0) >> 11
676
+ ws[i + 40] = (t12 - o1) >> 11
677
+ ws[i + 48] = (t11 - o2) >> 11
678
+ ws[i + 56] = (t10 - o3) >> 11
679
+ end
680
+ i += 1
681
+ ci = base + i
682
+ end
683
+ i = 0
684
+ while i < 64
685
+ d0 = ws[i]
686
+ d1 = ws[i + 1]
687
+ d2 = ws[i + 2]
688
+ d3 = ws[i + 3]
689
+ if d1 == 0 && d2 == 0 && d3 == 0
690
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
691
+ out[off] = v
692
+ out[off + 1] = v
693
+ else
694
+ t0 = (d0 + 4112) << 13
695
+ t2 = d2 * 4433
696
+ t3 = d2 * 10_703
697
+ t10 = t0 + t3
698
+ t13 = t0 - t3
699
+ t11 = t0 + t2
700
+ t12 = t0 - t2
701
+ o0 = d1 * 2260 - d3 * 6436
702
+ o1 = d1 * 6437 - d3 * 11_362
703
+ o2 = d1 * 9633 - d3 * 2259
704
+ o3 = d1 * 11_363 + d3 * 9633
705
+ out[off] = rl[((t10 + o3) >> 18) & 0xFFFF] | (rl[((t11 + o2) >> 18) & 0xFFFF] << 8) | (rl[((t12 + o1) >> 18) & 0xFFFF] << 16) | (rl[((t13 + o0) >> 18) & 0xFFFF] << 24)
706
+ out[off + 1] = rl[((t13 - o0) >> 18) & 0xFFFF] | (rl[((t12 - o1) >> 18) & 0xFFFF] << 8) | (rl[((t11 - o2) >> 18) & 0xFFFF] << 16) | (rl[((t10 - o3) >> 18) & 0xFFFF] << 24)
707
+ end
708
+ off += stride
709
+ i += 8
710
+ end
711
+ nil
712
+ end
713
+
714
+ def idct8_6(c, base, out, off, stride)
715
+ rl = JPEG_CLAMP
716
+ ws = @ws
717
+ i = 0
718
+ ci = base
719
+ while i <= 5
720
+ d0 = c[ci]
721
+ d1 = c[ci + 8]
722
+ d2 = c[ci + 16]
723
+ d3 = c[ci + 24]
724
+ d4 = c[ci + 32]
725
+ d5 = c[ci + 40]
726
+ if d1 == 0 && d2 == 0 && d3 == 0 && d4 == 0 && d5 == 0
727
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = ws[i + 32] = ws[i + 40] = ws[i + 48] = ws[i + 56] = d0 << 2
728
+ else
729
+ t0 = ((d0 + d4) << 13) + 1024
730
+ t1 = ((d0 - d4) << 13) + 1024
731
+ t2 = d2 * 4433
732
+ t3 = d2 * 10_703
733
+ t10 = t0 + t3
734
+ t13 = t0 - t3
735
+ t11 = t1 + t2
736
+ t12 = t1 - t2
737
+ s2 = d5 + d3
738
+ s4 = d5 + d1
739
+ z5 = (s4 + d3) * 9633
740
+ z1 = d1 * -7373
741
+ z2 = s2 * -20_995
742
+ z3 = d3 * -16_069 + z5
743
+ z4 = s4 * -3196 + z5
744
+ o0 = z1 + z3
745
+ o1 = d5 * 16_819 + z2 + z4
746
+ o2 = d3 * 25_172 + z2 + z3
747
+ o3 = d1 * 12_299 + z1 + z4
748
+ ws[i] = (t10 + o3) >> 11
749
+ ws[i + 8] = (t11 + o2) >> 11
750
+ ws[i + 16] = (t12 + o1) >> 11
751
+ ws[i + 24] = (t13 + o0) >> 11
752
+ ws[i + 32] = (t13 - o0) >> 11
753
+ ws[i + 40] = (t12 - o1) >> 11
754
+ ws[i + 48] = (t11 - o2) >> 11
755
+ ws[i + 56] = (t10 - o3) >> 11
756
+ end
757
+ i += 1
758
+ ci = base + i
759
+ end
760
+ i = 0
761
+ while i < 64
762
+ d0 = ws[i]
763
+ d1 = ws[i + 1]
764
+ d2 = ws[i + 2]
765
+ d3 = ws[i + 3]
766
+ d4 = ws[i + 4]
767
+ d5 = ws[i + 5]
768
+ if d1 == 0 && d2 == 0 && d3 == 0 && d4 == 0 && d5 == 0
769
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
770
+ out[off] = v
771
+ out[off + 1] = v
772
+ else
773
+ t0 = ((d0 + d4) + 4112) << 13
774
+ t1 = ((d0 - d4) + 4112) << 13
775
+ t2 = d2 * 4433
776
+ t3 = d2 * 10_703
777
+ t10 = t0 + t3
778
+ t13 = t0 - t3
779
+ t11 = t1 + t2
780
+ t12 = t1 - t2
781
+ s2 = d5 + d3
782
+ s4 = d5 + d1
783
+ z5 = (s4 + d3) * 9633
784
+ z1 = d1 * -7373
785
+ z2 = s2 * -20_995
786
+ z3 = d3 * -16_069 + z5
787
+ z4 = s4 * -3196 + z5
788
+ o0 = z1 + z3
789
+ o1 = d5 * 16_819 + z2 + z4
790
+ o2 = d3 * 25_172 + z2 + z3
791
+ o3 = d1 * 12_299 + z1 + z4
792
+ out[off] = rl[((t10 + o3) >> 18) & 0xFFFF] | (rl[((t11 + o2) >> 18) & 0xFFFF] << 8) | (rl[((t12 + o1) >> 18) & 0xFFFF] << 16) | (rl[((t13 + o0) >> 18) & 0xFFFF] << 24)
793
+ out[off + 1] = rl[((t13 - o0) >> 18) & 0xFFFF] | (rl[((t12 - o1) >> 18) & 0xFFFF] << 8) | (rl[((t11 - o2) >> 18) & 0xFFFF] << 16) | (rl[((t10 - o3) >> 18) & 0xFFFF] << 24)
794
+ end
795
+ off += stride
796
+ i += 8
797
+ end
798
+ nil
799
+ end
800
+
801
+ def idct8_8(c, base, out, off, stride)
802
+ rl = JPEG_CLAMP
803
+ ws = @ws
804
+ i = 0
805
+ ci = base
806
+ while i <= 7
807
+ d0 = c[ci]
808
+ d1 = c[ci + 8]
809
+ d2 = c[ci + 16]
810
+ d3 = c[ci + 24]
811
+ d4 = c[ci + 32]
812
+ d5 = c[ci + 40]
813
+ d6 = c[ci + 48]
814
+ d7 = c[ci + 56]
815
+ if d1 == 0 && d2 == 0 && d3 == 0 && d4 == 0 && d5 == 0 && d6 == 0 && d7 == 0
816
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = ws[i + 32] = ws[i + 40] = ws[i + 48] = ws[i + 56] = d0 << 2
817
+ else
818
+ z1 = (d2 + d6) * 4433
819
+ t2 = z1 - d6 * 15_137
820
+ t3 = z1 + d2 * 6270
821
+ t0 = ((d0 + d4) << 13) + 1024
822
+ t1 = ((d0 - d4) << 13) + 1024
823
+ t10 = t0 + t3
824
+ t13 = t0 - t3
825
+ t11 = t1 + t2
826
+ t12 = t1 - t2
827
+ s1 = d7 + d1
828
+ s2 = d5 + d3
829
+ s3 = d7 + d3
830
+ s4 = d5 + d1
831
+ z5 = (s3 + s4) * 9633
832
+ z1 = s1 * -7373
833
+ z2 = s2 * -20_995
834
+ z3 = s3 * -16_069 + z5
835
+ z4 = s4 * -3196 + z5
836
+ o0 = d7 * 2446 + z1 + z3
837
+ o1 = d5 * 16_819 + z2 + z4
838
+ o2 = d3 * 25_172 + z2 + z3
839
+ o3 = d1 * 12_299 + z1 + z4
840
+ ws[i] = (t10 + o3) >> 11
841
+ ws[i + 8] = (t11 + o2) >> 11
842
+ ws[i + 16] = (t12 + o1) >> 11
843
+ ws[i + 24] = (t13 + o0) >> 11
844
+ ws[i + 32] = (t13 - o0) >> 11
845
+ ws[i + 40] = (t12 - o1) >> 11
846
+ ws[i + 48] = (t11 - o2) >> 11
847
+ ws[i + 56] = (t10 - o3) >> 11
848
+ end
849
+ i += 1
850
+ ci = base + i
851
+ end
852
+ i = 0
853
+ while i < 64
854
+ d0 = ws[i]
855
+ d1 = ws[i + 1]
856
+ d2 = ws[i + 2]
857
+ d3 = ws[i + 3]
858
+ d4 = ws[i + 4]
859
+ d5 = ws[i + 5]
860
+ d6 = ws[i + 6]
861
+ d7 = ws[i + 7]
862
+ if d1 == 0 && d2 == 0 && d3 == 0 && d4 == 0 && d5 == 0 && d6 == 0 && d7 == 0
863
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
864
+ out[off] = v
865
+ out[off + 1] = v
866
+ else
867
+ z1 = (d2 + d6) * 4433
868
+ t2 = z1 - d6 * 15_137
869
+ t3 = z1 + d2 * 6270
870
+ t0 = ((d0 + d4) + 4112) << 13
871
+ t1 = ((d0 - d4) + 4112) << 13
872
+ t10 = t0 + t3
873
+ t13 = t0 - t3
874
+ t11 = t1 + t2
875
+ t12 = t1 - t2
876
+ s1 = d7 + d1
877
+ s2 = d5 + d3
878
+ s3 = d7 + d3
879
+ s4 = d5 + d1
880
+ z5 = (s3 + s4) * 9633
881
+ z1 = s1 * -7373
882
+ z2 = s2 * -20_995
883
+ z3 = s3 * -16_069 + z5
884
+ z4 = s4 * -3196 + z5
885
+ o0 = d7 * 2446 + z1 + z3
886
+ o1 = d5 * 16_819 + z2 + z4
887
+ o2 = d3 * 25_172 + z2 + z3
888
+ o3 = d1 * 12_299 + z1 + z4
889
+ out[off] = rl[((t10 + o3) >> 18) & 0xFFFF] | (rl[((t11 + o2) >> 18) & 0xFFFF] << 8) | (rl[((t12 + o1) >> 18) & 0xFFFF] << 16) | (rl[((t13 + o0) >> 18) & 0xFFFF] << 24)
890
+ out[off + 1] = rl[((t13 - o0) >> 18) & 0xFFFF] | (rl[((t12 - o1) >> 18) & 0xFFFF] << 8) | (rl[((t11 - o2) >> 18) & 0xFFFF] << 16) | (rl[((t10 - o3) >> 18) & 0xFFFF] << 24)
891
+ end
892
+ off += stride
893
+ i += 8
894
+ end
895
+ nil
896
+ end
897
+
898
+ def idct4_2(c, base, out, off, stride)
899
+ rl = JPEG_CLAMP
900
+ ws = @ws
901
+ i = 0
902
+ ci = base
903
+ while i <= 1
904
+ d0 = c[ci]
905
+ d1 = c[ci + 8]
906
+ if d1 == 0
907
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = d0 << 2
908
+ else
909
+ t0 = (d0 << 14) + 2048
910
+ t2 = 0
911
+ t10 = t0 + t2
912
+ t12 = t0 - t2
913
+ o0 = d1 * 8697
914
+ o2 = d1 * 20_995
915
+ ws[i] = (t10 + o2) >> 12
916
+ ws[i + 8] = (t12 + o0) >> 12
917
+ ws[i + 16] = (t12 - o0) >> 12
918
+ ws[i + 24] = (t10 - o2) >> 12
919
+ end
920
+ i += 1
921
+ ci = base + i
922
+ end
923
+ i = 0
924
+ while i < 32
925
+ d0 = ws[i]
926
+ d1 = ws[i + 1]
927
+ if d1 == 0
928
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
929
+ out[off] = v
930
+ else
931
+ t0 = (d0 + 4112) << 14
932
+ t2 = 0
933
+ t10 = t0 + t2
934
+ t12 = t0 - t2
935
+ o0 = d1 * 8697
936
+ o2 = d1 * 20_995
937
+ out[off] = rl[((t10 + o2) >> 19) & 0xFFFF] | (rl[((t12 + o0) >> 19) & 0xFFFF] << 8) | (rl[((t12 - o0) >> 19) & 0xFFFF] << 16) | (rl[((t10 - o2) >> 19) & 0xFFFF] << 24)
938
+ end
939
+ off += stride
940
+ i += 8
941
+ end
942
+ nil
943
+ end
944
+
945
+ def idct4_4(c, base, out, off, stride)
946
+ rl = JPEG_CLAMP
947
+ ws = @ws
948
+ i = 0
949
+ ci = base
950
+ while i <= 3
951
+ d0 = c[ci]
952
+ d1 = c[ci + 8]
953
+ d2 = c[ci + 16]
954
+ d3 = c[ci + 24]
955
+ if d1 == 0 && d2 == 0 && d3 == 0
956
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = d0 << 2
957
+ else
958
+ t0 = (d0 << 14) + 2048
959
+ t2 = d2 * 15_137
960
+ t10 = t0 + t2
961
+ t12 = t0 - t2
962
+ o0 = d3 * -17_799 + d1 * 8697
963
+ o2 = d3 * 7373 + d1 * 20_995
964
+ ws[i] = (t10 + o2) >> 12
965
+ ws[i + 8] = (t12 + o0) >> 12
966
+ ws[i + 16] = (t12 - o0) >> 12
967
+ ws[i + 24] = (t10 - o2) >> 12
968
+ end
969
+ i += 1
970
+ ci = base + i
971
+ end
972
+ i = 0
973
+ while i < 32
974
+ d0 = ws[i]
975
+ d1 = ws[i + 1]
976
+ d2 = ws[i + 2]
977
+ d3 = ws[i + 3]
978
+ if d1 == 0 && d2 == 0 && d3 == 0
979
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
980
+ out[off] = v
981
+ else
982
+ t0 = (d0 + 4112) << 14
983
+ t2 = d2 * 15_137
984
+ t10 = t0 + t2
985
+ t12 = t0 - t2
986
+ o0 = d3 * -17_799 + d1 * 8697
987
+ o2 = d3 * 7373 + d1 * 20_995
988
+ out[off] = rl[((t10 + o2) >> 19) & 0xFFFF] | (rl[((t12 + o0) >> 19) & 0xFFFF] << 8) | (rl[((t12 - o0) >> 19) & 0xFFFF] << 16) | (rl[((t10 - o2) >> 19) & 0xFFFF] << 24)
989
+ end
990
+ off += stride
991
+ i += 8
992
+ end
993
+ nil
994
+ end
995
+
996
+ def idct4_8(c, base, out, off, stride)
997
+ rl = JPEG_CLAMP
998
+ ws = @ws
999
+ i = 0
1000
+ ci = base
1001
+ while i <= 7
1002
+ d0 = c[ci]
1003
+ d1 = c[ci + 8]
1004
+ d2 = c[ci + 16]
1005
+ d3 = c[ci + 24]
1006
+ d5 = c[ci + 40]
1007
+ d6 = c[ci + 48]
1008
+ d7 = c[ci + 56]
1009
+ if d1 == 0 && d2 == 0 && d3 == 0 && d5 == 0 && d6 == 0 && d7 == 0
1010
+ ws[i] = ws[i + 8] = ws[i + 16] = ws[i + 24] = d0 << 2
1011
+ else
1012
+ t0 = (d0 << 14) + 2048
1013
+ t2 = d2 * 15_137 + d6 * -6270
1014
+ t10 = t0 + t2
1015
+ t12 = t0 - t2
1016
+ o0 = d7 * -1730 + d5 * 11_893 + d3 * -17_799 + d1 * 8697
1017
+ o2 = d7 * -4176 + d5 * -4926 + d3 * 7373 + d1 * 20_995
1018
+ ws[i] = (t10 + o2) >> 12
1019
+ ws[i + 8] = (t12 + o0) >> 12
1020
+ ws[i + 16] = (t12 - o0) >> 12
1021
+ ws[i + 24] = (t10 - o2) >> 12
1022
+ end
1023
+ i += (i == 3 ? 2 : 1)
1024
+ ci = base + i
1025
+ end
1026
+ i = 0
1027
+ while i < 32
1028
+ d0 = ws[i]
1029
+ d1 = ws[i + 1]
1030
+ d2 = ws[i + 2]
1031
+ d3 = ws[i + 3]
1032
+ d5 = ws[i + 5]
1033
+ d6 = ws[i + 6]
1034
+ d7 = ws[i + 7]
1035
+ if d1 == 0 && d2 == 0 && d3 == 0 && d5 == 0 && d6 == 0 && d7 == 0
1036
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x1010101
1037
+ out[off] = v
1038
+ else
1039
+ t0 = (d0 + 4112) << 14
1040
+ t2 = d2 * 15_137 + d6 * -6270
1041
+ t10 = t0 + t2
1042
+ t12 = t0 - t2
1043
+ o0 = d7 * -1730 + d5 * 11_893 + d3 * -17_799 + d1 * 8697
1044
+ o2 = d7 * -4176 + d5 * -4926 + d3 * 7373 + d1 * 20_995
1045
+ out[off] = rl[((t10 + o2) >> 19) & 0xFFFF] | (rl[((t12 + o0) >> 19) & 0xFFFF] << 8) | (rl[((t12 - o0) >> 19) & 0xFFFF] << 16) | (rl[((t10 - o2) >> 19) & 0xFFFF] << 24)
1046
+ end
1047
+ off += stride
1048
+ i += 8
1049
+ end
1050
+ nil
1051
+ end
1052
+
1053
+ def idct2_2(c, base, out, off, stride)
1054
+ rl = JPEG_CLAMP
1055
+ ws = @ws
1056
+ i = 0
1057
+ ci = base
1058
+ while i <= 1
1059
+ d0 = c[ci]
1060
+ d1 = c[ci + 8]
1061
+ if d1 == 0
1062
+ ws[i] = ws[i + 8] = d0 << 2
1063
+ else
1064
+ t10 = (d0 << 15) + 4096
1065
+ t0 = d1 * 29_692
1066
+ ws[i] = (t10 + t0) >> 13
1067
+ ws[i + 8] = (t10 - t0) >> 13
1068
+ end
1069
+ i += 1
1070
+ ci = base + i
1071
+ end
1072
+ i = 0
1073
+ while i < 16
1074
+ d0 = ws[i]
1075
+ d1 = ws[i + 1]
1076
+ if d1 == 0
1077
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x101
1078
+ out[off] = v
1079
+ else
1080
+ t10 = (d0 + 4112) << 15
1081
+ t0 = d1 * 29_692
1082
+ out[off] = rl[((t10 + t0) >> 20) & 0xFFFF] | (rl[((t10 - t0) >> 20) & 0xFFFF] << 8)
1083
+ end
1084
+ off += stride
1085
+ i += 8
1086
+ end
1087
+ nil
1088
+ end
1089
+
1090
+ def idct2_8(c, base, out, off, stride)
1091
+ rl = JPEG_CLAMP
1092
+ ws = @ws
1093
+ i = 0
1094
+ ci = base
1095
+ while i <= 7
1096
+ d0 = c[ci]
1097
+ d1 = c[ci + 8]
1098
+ d3 = c[ci + 24]
1099
+ d5 = c[ci + 40]
1100
+ d7 = c[ci + 56]
1101
+ if d1 == 0 && d3 == 0 && d5 == 0 && d7 == 0
1102
+ ws[i] = ws[i + 8] = d0 << 2
1103
+ else
1104
+ t10 = (d0 << 15) + 4096
1105
+ t0 = d7 * -5906 + d5 * 6967 + d3 * -10_426 + d1 * 29_692
1106
+ ws[i] = (t10 + t0) >> 13
1107
+ ws[i + 8] = (t10 - t0) >> 13
1108
+ end
1109
+ i += (i == 1 || i == 3 || i == 5 ? 2 : 1)
1110
+ ci = base + i
1111
+ end
1112
+ i = 0
1113
+ while i < 16
1114
+ d0 = ws[i]
1115
+ d1 = ws[i + 1]
1116
+ d3 = ws[i + 3]
1117
+ d5 = ws[i + 5]
1118
+ d7 = ws[i + 7]
1119
+ if d1 == 0 && d3 == 0 && d5 == 0 && d7 == 0
1120
+ v = rl[((d0 + 4112) >> 5) & 0xFFFF] * 0x101
1121
+ out[off] = v
1122
+ else
1123
+ t10 = (d0 + 4112) << 15
1124
+ t0 = d7 * -5906 + d5 * 6967 + d3 * -10_426 + d1 * 29_692
1125
+ out[off] = rl[((t10 + t0) >> 20) & 0xFFFF] | (rl[((t10 - t0) >> 20) & 0xFFFF] << 8)
1126
+ end
1127
+ off += stride
1128
+ i += 8
1129
+ end
1130
+ nil
1131
+ end
1132
+ end
1133
+
1134
+ # Decoder state for one JPEG stream, or for rendering a coefficient store.
1135
+ class JpegDecoder
1136
+ # Restart interval, MCU grid and whether to keep a coefficient store.
1137
+ attr_reader :restart_interval, :mcux, :mcuy, :keep
1138
+
1139
+ # +bytes+: the JPEG (or a coefficient store for #render_store).
1140
+ def initialize(bytes, scale, keep)
1141
+ @data = bytes
1142
+ @scale = scale
1143
+ @bs = 8 / scale
1144
+ @keep = keep
1145
+ @qt = [JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE]
1146
+ # Huffman table definitions and built tables: DC 0..3, AC 4..7.
1147
+ @hcounts = [JPEG_NO_COUNTS, JPEG_NO_COUNTS, JPEG_NO_COUNTS, JPEG_NO_COUNTS,
1148
+ JPEG_NO_COUNTS, JPEG_NO_COUNTS, JPEG_NO_COUNTS, JPEG_NO_COUNTS]
1149
+ @hsymbols = [JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE, JPEG_NONE]
1150
+ @hdefined = [0, 0, 0, 0, 0, 0, 0, 0]
1151
+ empty = JPEG_EMPTY_HUFFMAN
1152
+ @htables = [empty, empty, empty, empty, empty, empty, empty, empty]
1153
+ @hbuilt = [0, 0, 0, 0, 0, 0, 0, 0]
1154
+ @restart_interval = 0
1155
+ @jfif = false
1156
+ @adobe_transform = -1
1157
+ # (Object lists are built from a literal with their first element,
1158
+ # which lets Spinel compile them as typed object arrays.)
1159
+ @components = []
1160
+ @scans_decoded = 0
1161
+ @marker_end = 0
1162
+ @precision = 0
1163
+ @width = 0
1164
+ @height = 0
1165
+ @progressive = false
1166
+ @frame_end = 0
1167
+ @hmax = 0
1168
+ @vmax = 0
1169
+ @mcux = 0
1170
+ @mcuy = 0
1171
+ @out_w = 0
1172
+ @out_h = 0
1173
+ @color = JPEG_GRAY
1174
+ @scanned = [0]
1175
+ @visits = 0
1176
+ @max_visits = 0
1177
+ # The current scan's entropy-coded data (see #entropy_data).
1178
+ @scan = "".b
1179
+ @starts = JPEG_NONE
1180
+ @ends = JPEG_NONE
1181
+ # Store of a sequential decode: the scan with the luminance blocks
1182
+ # and their AC Huffman table.
1183
+ @keep_scan = "".b
1184
+ @keep_table = empty
1185
+ end
1186
+
1187
+ def info
1188
+ begin
1189
+ parse(true)
1190
+ rescue JpegTruncated
1191
+ raise QrReader::ImageError, "truncated JPEG header"
1192
+ end
1193
+ raise QrReader::ImageError, "JPEG has no frame header" if @components.empty?
1194
+
1195
+ begin
1196
+ resolve_height
1197
+ rescue JpegTruncated
1198
+ raise QrReader::ImageError, "truncated JPEG header"
1199
+ end
1200
+ [@width, @height]
1201
+ end
1202
+
1203
+ def decode
1204
+ begin
1205
+ parse(false)
1206
+ rescue QrReader::UnsupportedImageError => e
1207
+ raise e
1208
+ rescue JpegTruncated
1209
+ # Truncation after complete scans: keep what was decoded.
1210
+ raise QrReader::ImageError, "truncated JPEG" if @scans_decoded == 0
1211
+ rescue QrReader::ImageError => e
1212
+ # Corruption after complete scans: keep what was decoded.
1213
+ raise e if @scans_decoded == 0
1214
+ end
1215
+ raise QrReader::ImageError, "JPEG has no image data" if @scans_decoded == 0
1216
+
1217
+ finish
1218
+ end
1219
+
1220
+ def huffman_table(ac, id)
1221
+ slot = ac ? id + 4 : id
1222
+ return @htables[slot] if @hbuilt[slot] == 1
1223
+
1224
+ counts = @hcounts[slot]
1225
+ symbols = @hsymbols[slot]
1226
+ if @hdefined[slot] == 0
1227
+ raise QrReader::ImageError, "corrupt JPEG: missing Huffman table" if id > 1
1228
+
1229
+ counts = ac ? JPEG_STD_AC_COUNTS[id] : JPEG_STD_DC_COUNTS[id]
1230
+ symbols = ac ? JPEG_STD_AC_SYMBOLS[id] : JPEG_STD_DC_SYMBOLS
1231
+ end
1232
+ table = JpegHuffman.new(counts, symbols, ac)
1233
+ @htables[slot] = table
1234
+ @hbuilt[slot] = 1
1235
+ table
1236
+ end
1237
+
1238
+ # Latches the component's quantisation table (as libjpeg does at the
1239
+ # component's first scan), indexed by extended zigzag position.
1240
+ def latch_quant(comp)
1241
+ return nil unless comp.qz.empty?
1242
+
1243
+ q = @qt[comp.tq]
1244
+ raise QrReader::ImageError, "corrupt JPEG: missing quantisation table #{comp.tq}" if q.empty?
1245
+
1246
+ comp.qz = q + Array.new(16, q[63]) + Array.new(JPEG_ZIGZAG_EXT.size - 80, 0)
1247
+ nil
1248
+ end
1249
+
1250
+ # The store of a decode with +keep+ (a binary String; empty when nothing
1251
+ # was kept), from which #render_store renders the luminance at any
1252
+ # scale.
1253
+ #
1254
+ # Layout: little-endian unsigned 32-bit Integers - magic, kind
1255
+ # (JPEG_STORE_SEQUENTIAL or JPEG_STORE_PROGRESSIVE), width, height,
1256
+ # colour space, hmax, vmax, component count, the stored (luminance)
1257
+ # component's index, h, v, abw and abh, and its 64 quantisation values
1258
+ # (zigzag order) - followed by the kind's data:
1259
+ # * sequential: the luminance blocks' AC Huffman table (16 code counts,
1260
+ # the symbol count and the symbols, as Integers), the scan data size;
1261
+ # per block of the abw x abh grid two Integers, the bit position of its
1262
+ # AC coefficients in the scan data (0xFFFFFFFF: no data, mid-gray) and
1263
+ # its DC (raw, 16-bit); then the scan data (see #entropy_data).
1264
+ # * progressive: abh raw coefficient rows (JpegComponent#raw_row).
1265
+ def store
1266
+ return "".b unless @keep
1267
+
1268
+ c = @components[0]
1269
+ i = 0
1270
+ while i < @components.size
1271
+ c = @components[i] if @components[i].needed
1272
+ i += 1
1273
+ end
1274
+ head = [JPEG_STORE_MAGIC, @progressive ? JPEG_STORE_PROGRESSIVE : JPEG_STORE_SEQUENTIAL, @width, @height,
1275
+ @color, @hmax, @vmax, @components.size, c.index, c.h, c.v, c.abw, c.abh]
1276
+ k = 0
1277
+ while k < 64
1278
+ head << (c.qz.empty? ? 0 : c.qz[k])
1279
+ k += 1
1280
+ end
1281
+ unless @progressive
1282
+ table = @keep_table
1283
+ k = 0
1284
+ while k < 16
1285
+ head << table.counts[k]
1286
+ k += 1
1287
+ end
1288
+ head << table.symbols.size
1289
+ k = 0
1290
+ while k < table.symbols.size
1291
+ head << table.symbols[k]
1292
+ k += 1
1293
+ end
1294
+ head << @keep_scan.bytesize
1295
+ end
1296
+ out = String.new(capacity: head.size * 4 + c.abw * c.abh * 8 + @keep_scan.bytesize + c.sdata.bytesize,
1297
+ encoding: Encoding::BINARY)
1298
+ i = 0
1299
+ while i < head.size
1300
+ v = head[i]
1301
+ out << (v & 255) << ((v >> 8) & 255) << ((v >> 16) & 255) << ((v >> 24) & 255)
1302
+ i += 1
1303
+ end
1304
+ if @progressive
1305
+ out << c.sdata
1306
+ else
1307
+ marks = c.marks
1308
+ n = c.abw
1309
+ r = 0
1310
+ while r < c.abh
1311
+ out << mark_bytes(marks, r * n, n)
1312
+ r += 1
1313
+ end
1314
+ out << @keep_scan
1315
+ end
1316
+ out
1317
+ end
1318
+
1319
+ # Luminance at this decoder's scale from the store in @data.
1320
+ def render_store
1321
+ data = @data
1322
+ size = data.bytesize
1323
+ kind = QrReaderKernels.jpeg_u32(data, 4)
1324
+ if QrReaderKernels.jpeg_u32(data, 0) != JPEG_STORE_MAGIC || size < JPEG_STORE_HEAD * 4 ||
1325
+ (kind != JPEG_STORE_SEQUENTIAL && kind != JPEG_STORE_PROGRESSIVE)
1326
+ raise QrReader::ImageError, "not a JPEG store"
1327
+ end
1328
+
1329
+ @progressive = kind == JPEG_STORE_PROGRESSIVE
1330
+ @width = QrReaderKernels.jpeg_u32(data, 8)
1331
+ @height = QrReaderKernels.jpeg_u32(data, 12)
1332
+ @color = QrReaderKernels.jpeg_u32(data, 16)
1333
+ @hmax = QrReaderKernels.jpeg_u32(data, 20)
1334
+ @vmax = QrReaderKernels.jpeg_u32(data, 24)
1335
+ ncomp = QrReaderKernels.jpeg_u32(data, 28)
1336
+ index = QrReaderKernels.jpeg_u32(data, 32)
1337
+ c = JpegComponent.new(index, index, QrReaderKernels.jpeg_u32(data, 36), QrReaderKernels.jpeg_u32(data, 40), 0)
1338
+ c.abw = QrReaderKernels.jpeg_u32(data, 44)
1339
+ c.abh = QrReaderKernels.jpeg_u32(data, 48)
1340
+ if @width < 1 || @width > 65_535 || @height < 1 || @height > 65_535 || @hmax < 1 || @hmax > 4 ||
1341
+ @vmax < 1 || @vmax > 4 || ncomp < 1 || ncomp > 10 || index >= ncomp || @color > JPEG_OTHER ||
1342
+ c.h < 1 || c.h > @hmax || c.v < 1 || c.v > @vmax
1343
+ raise QrReader::ImageError, "corrupt JPEG store"
1344
+ end
1345
+
1346
+ mcux = (@width + 8 * @hmax - 1) / (8 * @hmax)
1347
+ mcuy = (@height + 8 * @vmax - 1) / (8 * @vmax)
1348
+ raise QrReader::ImageError, "corrupt JPEG store" if c.abw < 1 || c.abw > mcux * c.h || c.abh < 1 || c.abh > mcuy * c.v
1349
+
1350
+ comps = [index == 0 ? c : JpegComponent.new(0, 0, 1, 1, 0)]
1351
+ i = 1
1352
+ while i < ncomp
1353
+ comps << (i == index ? c : JpegComponent.new(i, i, 1, 1, 0))
1354
+ i += 1
1355
+ end
1356
+ @components = comps
1357
+ setup_output
1358
+ q = Array.new(64, 0)
1359
+ k = 0
1360
+ while k < 64
1361
+ q[k] = QrReaderKernels.jpeg_u32(data, 52 + 4 * k)
1362
+ k += 1
1363
+ end
1364
+ c.qz = q + Array.new(16, q[63]) + Array.new(JPEG_ZIGZAG_EXT.size - 80, 0)
1365
+ c.needed = true
1366
+ c.bs = scaled_block_size(c)
1367
+ c.idct = JpegIDCT.new(c.bs)
1368
+ c.pw = c.abw * c.bs
1369
+ c.ph = c.abh * c.bs
1370
+ p = JPEG_STORE_HEAD * 4
1371
+ if @progressive
1372
+ raise QrReader::ImageError, "corrupt JPEG store" if p + c.abh * c.abw * JPEG_RAW_BLOCK > size
1373
+
1374
+ render_stored_raw(c, p)
1375
+ else
1376
+ counts = Array.new(16, 0)
1377
+ total = 0
1378
+ k = 0
1379
+ while k < 16
1380
+ counts[k] = QrReaderKernels.jpeg_u32(data, p + 4 * k)
1381
+ total += counts[k]
1382
+ k += 1
1383
+ end
1384
+ nsym = QrReaderKernels.jpeg_u32(data, p + 64)
1385
+ raise QrReader::ImageError, "corrupt JPEG store" if nsym != total || nsym > 256
1386
+
1387
+ symbols = Array.new(nsym, 0)
1388
+ k = 0
1389
+ while k < nsym
1390
+ symbols[k] = QrReaderKernels.jpeg_u32(data, p + 68 + 4 * k)
1391
+ k += 1
1392
+ end
1393
+ p += 68 + 4 * nsym
1394
+ scan_size = QrReaderKernels.jpeg_u32(data, p)
1395
+ marks = p + 4
1396
+ scan = marks + c.abw * c.abh * 8
1397
+ # (No scan data if the luminance scan could not be decoded.)
1398
+ raise QrReader::ImageError, "corrupt JPEG store" if scan + scan_size != size
1399
+
1400
+ render_marked(c, marks, scan, scan_size, JpegHuffman.new(counts, symbols, true))
1401
+ end
1402
+ output
1403
+ end
1404
+
1405
+ private
1406
+
1407
+ # ---------------------------------------------------------------
1408
+ # Marker parsing
1409
+
1410
+ def parse(header_only)
1411
+ data = @data
1412
+ raise QrReader::ImageError, "not a JPEG file" unless data.getbyte(0) == 0xFF && data.getbyte(1) == 0xD8
1413
+
1414
+ pos = 2
1415
+ while (code = next_marker(pos)) >= 0
1416
+ pos = @marker_end
1417
+ if code >= 0xC0 && code <= 0xC2
1418
+ pos = read_frame(pos, code)
1419
+ return nil if header_only
1420
+ elsif code == 0xC3 || (code >= 0xC5 && code <= 0xC7) || (code >= 0xC9 && code <= 0xCB) ||
1421
+ (code >= 0xCD && code <= 0xCF) || code == 0xF7
1422
+ raise QrReader::UnsupportedImageError, "#{QrReaderKernels.jpeg_sof_name(code)} JPEG is not supported" unless header_only
1423
+
1424
+ read_frame(pos, code)
1425
+ return nil
1426
+ elsif code == 0xC4
1427
+ pos = read_dht(pos)
1428
+ elsif code == 0xDB
1429
+ pos = read_dqt(pos)
1430
+ elsif code == 0xDD
1431
+ pos = read_dri(pos)
1432
+ elsif code == 0xDA
1433
+ raise QrReader::ImageError, "corrupt JPEG: scan before frame header" if header_only
1434
+
1435
+ pos = read_scan(pos)
1436
+ elsif code == 0xD9
1437
+ return nil
1438
+ elsif code == 0xE0
1439
+ pos = read_app0(pos)
1440
+ elsif code == 0xEE
1441
+ pos = read_app14(pos)
1442
+ elsif (code >= 0xD0 && code <= 0xD8) || code == 0x01
1443
+ # markers without payload
1444
+ elsif code == 0xDE || code == 0xDF
1445
+ raise QrReader::UnsupportedImageError, "hierarchical JPEG is not supported"
1446
+ elsif code >= 0x02 && code <= 0xBF
1447
+ raise QrReader::ImageError, "corrupt JPEG: unknown marker 0x#{code.to_s(16).upcase}"
1448
+ else
1449
+ pos = segment_end(pos)
1450
+ end
1451
+ end
1452
+ nil
1453
+ end
1454
+
1455
+ # Finds the next marker at or after +pos+, skipping junk and fill bytes.
1456
+ # Returns its code (and sets @marker_end to the position after it), or
1457
+ # -1 at the end of the data.
1458
+ def next_marker(pos)
1459
+ data = @data
1460
+ size = data.bytesize
1461
+ while pos < size
1462
+ f = data.byteindex(JPEG_FF, pos)
1463
+ return -1 unless f
1464
+
1465
+ pos = f + 1
1466
+ pos += 1 while pos < size && data.getbyte(pos) == 0xFF
1467
+ return -1 if pos >= size
1468
+
1469
+ code = data.getbyte(pos)
1470
+ if code != 0
1471
+ @marker_end = pos + 1
1472
+ return code
1473
+ end
1474
+ end
1475
+ -1
1476
+ end
1477
+
1478
+ def u16(pos)
1479
+ raise JpegTruncated, "truncated JPEG" if pos < 0 || pos + 2 > @data.bytesize
1480
+
1481
+ (@data.getbyte(pos) << 8) | @data.getbyte(pos + 1)
1482
+ end
1483
+
1484
+ def byte(pos)
1485
+ raise JpegTruncated, "truncated JPEG" if pos < 0 || pos >= @data.bytesize
1486
+
1487
+ @data.getbyte(pos)
1488
+ end
1489
+
1490
+ # Position after the marker segment whose length field is at +pos+.
1491
+ def segment_end(pos)
1492
+ len = u16(pos)
1493
+ raise QrReader::ImageError, "corrupt JPEG: bad marker length" if len < 2
1494
+ raise JpegTruncated, "truncated JPEG" if pos + len > @data.bytesize
1495
+
1496
+ pos + len
1497
+ end
1498
+
1499
+ def read_frame(pos, code)
1500
+ stop = segment_end(pos)
1501
+ raise QrReader::ImageError, "corrupt JPEG: duplicate frame header" unless @components.empty?
1502
+
1503
+ @precision = byte(pos + 2)
1504
+ @height = u16(pos + 3)
1505
+ @width = u16(pos + 5)
1506
+ count = byte(pos + 7)
1507
+ raise QrReader::ImageError, "corrupt JPEG: bad image width" if @width == 0
1508
+ raise QrReader::ImageError, "corrupt JPEG: bad component count" if count < 1 || count > 10
1509
+ raise QrReader::ImageError, "corrupt JPEG: bad frame header length" if stop - pos != 8 + 3 * count
1510
+
1511
+ @progressive = code == 0xC2
1512
+ comps = [frame_component(pos, 0)]
1513
+ i = 1
1514
+ while i < count
1515
+ comps << frame_component(pos, i)
1516
+ i += 1
1517
+ end
1518
+ @components = comps
1519
+ @frame_end = stop
1520
+ stop
1521
+ end
1522
+
1523
+ # Component +i+ of the frame header whose length field is at +pos+.
1524
+ def frame_component(pos, i)
1525
+ p = pos + 8 + 3 * i
1526
+ hv = byte(p + 1)
1527
+ h = hv >> 4
1528
+ v = hv & 15
1529
+ tq = byte(p + 2)
1530
+ raise QrReader::ImageError, "corrupt JPEG: bad sampling factors" if h < 1 || h > 4 || v < 1 || v > 4
1531
+ raise QrReader::ImageError, "corrupt JPEG: bad quantisation table id" if tq > 3
1532
+
1533
+ JpegComponent.new(i, byte(p), h, v, tq)
1534
+ end
1535
+
1536
+ def read_dht(pos)
1537
+ stop = segment_end(pos)
1538
+ p = pos + 2
1539
+ while p < stop
1540
+ info = byte(p)
1541
+ klass = info >> 4
1542
+ id = info & 15
1543
+ raise QrReader::ImageError, "corrupt JPEG: bad Huffman table id" if klass > 1 || id > 3
1544
+
1545
+ counts = Array.new(16, 0)
1546
+ total = 0
1547
+ i = 0
1548
+ while i < 16
1549
+ n = byte(p + 1 + i)
1550
+ counts[i] = n
1551
+ total += n
1552
+ i += 1
1553
+ end
1554
+ raise QrReader::ImageError, "corrupt JPEG: bad Huffman table" if total > 256 || p + 17 + total > stop
1555
+
1556
+ symbols = Array.new(total, 0)
1557
+ i = 0
1558
+ while i < total
1559
+ symbols[i] = @data.getbyte(p + 17 + i)
1560
+ i += 1
1561
+ end
1562
+ slot = klass == 0 ? id : id + 4
1563
+ @hcounts[slot] = counts
1564
+ @hsymbols[slot] = symbols
1565
+ @hdefined[slot] = 1
1566
+ @hbuilt[slot] = 0
1567
+ p += 17 + total
1568
+ end
1569
+ stop
1570
+ end
1571
+
1572
+ def read_dqt(pos)
1573
+ stop = segment_end(pos)
1574
+ p = pos + 2
1575
+ while p < stop
1576
+ info = byte(p)
1577
+ precision = info >> 4
1578
+ id = info & 15
1579
+ size = precision == 0 ? 64 : 128
1580
+ raise QrReader::ImageError, "corrupt JPEG: bad quantisation table" if precision > 1 || id > 3 || p + 1 + size > stop
1581
+
1582
+ q = Array.new(64, 0)
1583
+ i = 0
1584
+ while i < 64
1585
+ q[i] = precision == 0 ? @data.getbyte(p + 1 + i) : (@data.getbyte(p + 1 + 2 * i) << 8) | @data.getbyte(p + 2 + 2 * i)
1586
+ i += 1
1587
+ end
1588
+ @qt[id] = q
1589
+ p += 1 + size
1590
+ end
1591
+ stop
1592
+ end
1593
+
1594
+ def read_dri(pos)
1595
+ stop = segment_end(pos)
1596
+ raise QrReader::ImageError, "corrupt JPEG: bad DRI marker" if stop - pos != 4
1597
+
1598
+ @restart_interval = u16(pos + 2)
1599
+ stop
1600
+ end
1601
+
1602
+ def read_app0(pos)
1603
+ stop = segment_end(pos)
1604
+ @jfif = true if stop - pos >= 16 && @data.byteslice(pos + 2, 5) == "JFIF\0"
1605
+ stop
1606
+ end
1607
+
1608
+ def read_app14(pos)
1609
+ stop = segment_end(pos)
1610
+ @adobe_transform = byte(pos + 13) if stop - pos >= 14 && @data.byteslice(pos + 2, 5) == "Adobe"
1611
+ stop
1612
+ end
1613
+
1614
+ # Height 0 in the frame header means it is given by a DNL marker after
1615
+ # the first scan (0xFF 0xDC cannot occur inside scan data).
1616
+ def resolve_height
1617
+ return nil if @height != 0
1618
+
1619
+ at = @data.byteindex(JPEG_DNL_MARKER, @frame_end)
1620
+ raise QrReader::ImageError, "corrupt JPEG: zero image height" unless at
1621
+
1622
+ @height = u16(at + 4)
1623
+ raise QrReader::ImageError, "corrupt JPEG: zero image height" if @height == 0
1624
+
1625
+ nil
1626
+ end
1627
+
1628
+ # ---------------------------------------------------------------
1629
+ # Frame setup (at the first scan, when all header markers are known)
1630
+
1631
+ def setup_frame
1632
+ return nil if @hmax > 0
1633
+
1634
+ if @precision != 8
1635
+ if @precision == 12 || @precision == 16
1636
+ raise QrReader::UnsupportedImageError, "#{@precision}-bit JPEG is not supported"
1637
+ end
1638
+
1639
+ raise QrReader::ImageError, "corrupt JPEG: bad sample precision #{@precision}"
1640
+ end
1641
+ resolve_height
1642
+ comps = @components
1643
+ @color = color_space
1644
+ nneeded = 1
1645
+ nneeded = 3 if @color == JPEG_RGB
1646
+ nneeded = 4 if @color == JPEG_CMYK || @color == JPEG_YCCK
1647
+ # A coefficient store only for single-component luminance that can be
1648
+ # rendered at full size.
1649
+ @keep = false if nneeded > 1 || @width * @height > JPEG_MAX_PIXELS
1650
+ hmax = 0
1651
+ vmax = 0
1652
+ i = 0
1653
+ while i < comps.size
1654
+ c = comps[i]
1655
+ hmax = c.h if c.h > hmax
1656
+ vmax = c.v if c.v > vmax
1657
+ i += 1
1658
+ end
1659
+ @hmax = hmax
1660
+ @vmax = vmax
1661
+ setup_output
1662
+ @mcux = (@width + 8 * hmax - 1) / (8 * hmax)
1663
+ @mcuy = (@height + 8 * vmax - 1) / (8 * vmax)
1664
+ idcts = [JpegIDCT.new(1), JpegIDCT.new(1), JpegIDCT.new(2), JpegIDCT.new(1), JpegIDCT.new(4),
1665
+ JpegIDCT.new(1), JpegIDCT.new(1), JpegIDCT.new(1), JpegIDCT.new(8)]
1666
+ single = comps.size == 1
1667
+ blocks = 0
1668
+ i = 0
1669
+ while i < comps.size
1670
+ c = comps[i]
1671
+ c.bs = scaled_block_size(c)
1672
+ c.idct = idcts[c.bs]
1673
+ setup_component(c, i < nneeded, single)
1674
+ blocks += c.abw * c.abh if c.needed
1675
+ i += 1
1676
+ end
1677
+ check_coefficient_memory if @progressive
1678
+ @scanned = Array.new(comps.size, 0)
1679
+ @visits = 0
1680
+ @max_visits = JPEG_MAX_VISITS * blocks + 65_536
1681
+ nil
1682
+ end
1683
+
1684
+ # Output size at this decoder's scale (checked against MAX_PIXELS).
1685
+ def setup_output
1686
+ w = @width
1687
+ h = @height
1688
+ @out_w = (w + @scale - 1) / @scale
1689
+ @out_h = (h + @scale - 1) / @scale
1690
+ raise QrReader::UnsupportedImageError, "JPEG too large (#{w}x#{h})" if @out_w * @out_h > JPEG_MAX_PIXELS
1691
+
1692
+ nil
1693
+ end
1694
+
1695
+ # libjpeg's per-component DCT scaling: at reduced scales a subsampled
1696
+ # component gets a larger IDCT where that replaces upsampling.
1697
+ def scaled_block_size(c)
1698
+ size = @bs
1699
+ while size < 8 && ((@hmax * @bs) % (c.h * size * 2)) == 0 && ((@vmax * @bs) % (c.v * size * 2)) == 0
1700
+ size += size
1701
+ end
1702
+ size
1703
+ end
1704
+
1705
+ # Progressive JPEGs keep all coefficients of the needed components (2
1706
+ # bytes each): refuse sizes whose storage would be excessive.
1707
+ def check_coefficient_memory
1708
+ bytes = 0
1709
+ i = 0
1710
+ while i < @components.size
1711
+ c = @components[i]
1712
+ bytes += c.abw * c.abh * c.stride * 2 if c.needed
1713
+ i += 1
1714
+ end
1715
+ return nil if bytes <= JPEG_MAX_COEFFICIENT_BYTES
1716
+
1717
+ raise QrReader::UnsupportedImageError, "progressive JPEG too large to decode at scale #{@scale} " \
1718
+ "(#{@width}x#{@height}, #{@components.size} components)"
1719
+ end
1720
+
1721
+ def setup_component(c, needed, single)
1722
+ c.cw = (@width * c.h + @hmax - 1) / @hmax
1723
+ c.ch = (@height * c.v + @vmax - 1) / @vmax
1724
+ c.bw = (c.cw + 7) / 8
1725
+ c.bh = (c.ch + 7) / 8
1726
+ c.abw = single ? c.bw : @mcux * c.h
1727
+ c.abh = single ? c.bh : @mcuy * c.v
1728
+ c.pw = c.abw * c.bs
1729
+ c.ph = c.abh * c.bs
1730
+ c.needed = needed
1731
+ return nil unless needed
1732
+
1733
+ if @progressive
1734
+ # Only the DC is kept when it is all that is rendered.
1735
+ c.stride = c.bs == 1 && !@keep ? 1 : JPEG_BLOCK_STRIDE
1736
+ c.start_raw
1737
+ else
1738
+ c.start_plane
1739
+ c.start_marks if @keep
1740
+ end
1741
+ nil
1742
+ end
1743
+
1744
+ # Colour space of the stored components, following libjpeg's rules.
1745
+ def color_space
1746
+ comps = @components
1747
+ n = comps.size
1748
+ if n == 1
1749
+ JPEG_GRAY
1750
+ elsif n == 3
1751
+ if @jfif then JPEG_YCBCR
1752
+ elsif @adobe_transform >= 0 then @adobe_transform == 0 ? JPEG_RGB : JPEG_YCBCR
1753
+ elsif comps[0].id == 82 && comps[1].id == 71 && comps[2].id == 66 then JPEG_RGB # "RGB"
1754
+ else JPEG_YCBCR
1755
+ end
1756
+ elsif n == 4
1757
+ @adobe_transform <= 0 ? JPEG_CMYK : JPEG_YCCK
1758
+ else
1759
+ JPEG_OTHER
1760
+ end
1761
+ end
1762
+
1763
+ # ---------------------------------------------------------------
1764
+ # Scans
1765
+
1766
+ def read_scan(pos)
1767
+ raise QrReader::ImageError, "corrupt JPEG: scan before frame header" if @components.empty?
1768
+
1769
+ stop = segment_end(pos)
1770
+ count = byte(pos + 2)
1771
+ raise QrReader::ImageError, "corrupt JPEG: bad scan header" if count < 1 || count > 4 || stop - pos != 6 + 2 * count
1772
+
1773
+ taken = []
1774
+ dcs = []
1775
+ acs = []
1776
+ i = 0
1777
+ while i < count
1778
+ id = byte(pos + 3 + 2 * i)
1779
+ tables = byte(pos + 4 + 2 * i)
1780
+ comp = scan_component(id, taken)
1781
+ raise QrReader::ImageError, "corrupt JPEG: bad scan component" if comp < 0
1782
+ raise QrReader::ImageError, "corrupt JPEG: bad Huffman table id" if (tables >> 4) > 3 || (tables & 15) > 3
1783
+
1784
+ taken << comp
1785
+ dcs << (tables >> 4)
1786
+ acs << (tables & 15)
1787
+ i += 1
1788
+ end
1789
+ comps = [@components[taken[0]]]
1790
+ i = 1
1791
+ while i < count
1792
+ comps << @components[taken[i]]
1793
+ i += 1
1794
+ end
1795
+ ss = byte(stop - 3)
1796
+ se = byte(stop - 2)
1797
+ ah = byte(stop - 1) >> 4
1798
+ al = byte(stop - 1) & 15
1799
+
1800
+ setup_frame
1801
+ raise QrReader::ImageError, "corrupt JPEG: too many blocks per MCU" if count > 1 && mcu_blocks(comps) > 10
1802
+
1803
+ validate_progression(count, ss, se, ah, al) if @progressive
1804
+ seg_end = scan_extent(stop)
1805
+ if decode_scan?(comps, ss)
1806
+ # Crafted files could repeat cheap scans that each visit every block.
1807
+ @visits += count == 1 ? comps[0].bw * comps[0].bh : @mcux * @mcuy * mcu_blocks(comps)
1808
+ raise QrReader::ImageError, "corrupt JPEG: too many scans" if @scans_decoded >= JPEG_MAX_SCANS || @visits > @max_visits
1809
+
1810
+ entropy_data(stop, seg_end)
1811
+ @scans_decoded += 1
1812
+ if @progressive
1813
+ JpegProgressive.new(self, comps, dcs, ss, se, ah, al, acs[0], @scan, @starts, @ends).run
1814
+ else
1815
+ JpegSequential.new(self, comps, dcs, acs, @scan, @starts, @ends).run
1816
+ keep_scan(comps, acs) if @keep
1817
+ end
1818
+ @scan = "".b
1819
+ end
1820
+ seg_end
1821
+ end
1822
+
1823
+ # Keeps the scan data and AC table of the needed component's (only)
1824
+ # sequential scan for the store.
1825
+ def keep_scan(comps, acs)
1826
+ # (Bit positions in the store are 32-bit.)
1827
+ @keep = false if @scan.bytesize >= (1 << 28)
1828
+ i = 0
1829
+ while i < comps.size
1830
+ if comps[i].needed
1831
+ @keep_scan = @scan
1832
+ @keep_table = huffman_table(true, acs[i])
1833
+ end
1834
+ i += 1
1835
+ end
1836
+ nil
1837
+ end
1838
+
1839
+ # Index of the first component with this id not yet in the scan (whose
1840
+ # indices are +taken+; some encoders write duplicate ids, libjpeg-turbo
1841
+ # matches them so), or -1.
1842
+ def scan_component(id, taken)
1843
+ i = 0
1844
+ while i < @components.size
1845
+ if @components[i].id == id
1846
+ free = true
1847
+ j = 0
1848
+ while j < taken.size
1849
+ free = false if taken[j] == i
1850
+ j += 1
1851
+ end
1852
+ return i if free
1853
+ end
1854
+ i += 1
1855
+ end
1856
+ -1
1857
+ end
1858
+
1859
+ # Blocks per MCU of an interleaved scan.
1860
+ def mcu_blocks(comps)
1861
+ n = 0
1862
+ i = 0
1863
+ while i < comps.size
1864
+ n += comps[i].h * comps[i].v
1865
+ i += 1
1866
+ end
1867
+ n
1868
+ end
1869
+
1870
+ def validate_progression(count, ss, se, ah, al)
1871
+ bad = ss == 0 ? se != 0 : ss > se || se > 63 || count != 1
1872
+ bad ||= ah != 0 && al != ah - 1
1873
+ bad ||= al > 13
1874
+ raise QrReader::ImageError, "corrupt JPEG: bad progressive scan parameters" if bad
1875
+
1876
+ nil
1877
+ end
1878
+
1879
+ # Whether a scan contributes to the output: scans without needed
1880
+ # components, progressive AC scans of components decoded DC-only (block
1881
+ # size 1, without a coefficient store) and repeated sequential scans
1882
+ # are skipped.
1883
+ def decode_scan?(comps, ss)
1884
+ unless @progressive
1885
+ # A component has a single sequential scan: repeats are ignored,
1886
+ # and so are scans of components the output does not need.
1887
+ fresh = false
1888
+ i = 0
1889
+ while i < comps.size
1890
+ c = comps[i]
1891
+ fresh = true if c.needed && @scanned[c.index] == 0
1892
+ @scanned[c.index] = 1
1893
+ i += 1
1894
+ end
1895
+ return fresh
1896
+ end
1897
+ if ss == 0
1898
+ i = 0
1899
+ while i < comps.size
1900
+ return true if comps[i].needed
1901
+
1902
+ i += 1
1903
+ end
1904
+ return false
1905
+ end
1906
+ c = comps[0]
1907
+ c.needed && c.stride > 1
1908
+ end
1909
+
1910
+ # End of the entropy-coded data starting at +pos+: the first 0xFF that
1911
+ # is neither stuffing nor a restart marker. Fill bytes (0xFF runs)
1912
+ # before stuffing or RST are allowed. With restart intervals, reserved
1913
+ # marker codes (corrupt data) do not end the scan either: like libjpeg,
1914
+ # decoding resumes at the next RST.
1915
+ def scan_extent(pos)
1916
+ data = @data
1917
+ size = data.bytesize
1918
+ resync = @restart_interval > 0
1919
+ while pos < size
1920
+ e = data.byteindex(JPEG_FF, pos)
1921
+ return size unless e
1922
+
1923
+ r = e + 1
1924
+ return size if r >= size
1925
+
1926
+ c = data.getbyte(r)
1927
+ if c == 0xFF
1928
+ r += 1 while r < size && data.getbyte(r) == 0xFF
1929
+ return e if r >= size
1930
+
1931
+ c = data.getbyte(r)
1932
+ return e unless c == 0 || (c >= 0xD0 && c <= 0xD7) || (resync && c < 0xC0)
1933
+ elsif c != 0 && (c < 0xD0 || c > 0xD7)
1934
+ return e if !resync || c >= 0xC0
1935
+ end
1936
+ pos = r + 1
1937
+ end
1938
+ size
1939
+ end
1940
+
1941
+ # The entropy-coded segment [pos, stop) without byte stuffing, its
1942
+ # restart intervals concatenated, as @scan (followed by zero padding).
1943
+ # @starts[i] is the byte offset of interval i, @ends[i] the bit
1944
+ # position just after its data.
1945
+ def entropy_data(pos, stop)
1946
+ data = @data
1947
+ stop -= 1 if stop > pos && data.getbyte(stop - 1) == 0xFF # dangling half of a stuffed byte
1948
+ resync = @restart_interval > 0
1949
+ buf = String.new(capacity: stop - pos + JPEG_TAIL_PADDING.bytesize, encoding: Encoding::BINARY)
1950
+ piece_start = []
1951
+ piece_end = []
1952
+ marks = []
1953
+ cur = 0
1954
+ cut = false # the interval's data ended at a reserved marker (corrupt data)
1955
+ p = pos
1956
+ while p < stop
1957
+ f = data.byteindex(JPEG_FF, p)
1958
+ if f.nil? || f >= stop
1959
+ buf << data.byteslice(p, stop - p) unless cut
1960
+ break
1961
+ end
1962
+ buf << data.byteslice(p, f - p) if !cut && f > p
1963
+ q = f + 1
1964
+ q += 1 while q < stop && data.getbyte(q) == 0xFF # fill bytes
1965
+ if q >= stop
1966
+ buf << data.byteslice(f, stop - f) unless cut
1967
+ break
1968
+ end
1969
+ c = data.getbyte(q)
1970
+ if c == 0
1971
+ buf << JPEG_FF unless cut
1972
+ elsif c >= 0xD0 && c <= 0xD7
1973
+ break unless resync # a stray RST ends the data, like in libjpeg
1974
+
1975
+ piece_start << cur
1976
+ piece_end << buf.bytesize
1977
+ marks << c
1978
+ cur = buf.bytesize
1979
+ cut = false
1980
+ else
1981
+ # Reserved marker: fill bytes before it stay, the interval ends.
1982
+ buf << data.byteslice(f, q - 1 - f) if !cut && q - 1 > f
1983
+ cut = true
1984
+ end
1985
+ p = q + 1
1986
+ end
1987
+ if marks.empty?
1988
+ @starts = [0]
1989
+ @ends = [buf.bytesize << 3]
1990
+ buf << JPEG_TAIL_PADDING
1991
+ @scan = buf
1992
+ return nil
1993
+ end
1994
+
1995
+ piece_start << cur
1996
+ piece_end << buf.bytesize
1997
+ # The intervals in order, each starting on a 4-byte boundary (an empty
1998
+ # one where the next begins).
1999
+ order = restart_intervals(marks)
2000
+ out = String.new(capacity: buf.bytesize + 4 * order.size + JPEG_TAIL_PADDING.bytesize, encoding: Encoding::BINARY)
2001
+ starts = []
2002
+ ends = []
2003
+ i = 0
2004
+ while i < order.size
2005
+ j = order[i]
2006
+ start = out.bytesize
2007
+ len = j < 0 ? 0 : piece_end[j] - piece_start[j]
2008
+ out << buf.byteslice(piece_start[j], len) << JPEG_TAIL_PADDING.byteslice(0, -len & 3) if len > 0
2009
+ starts << start
2010
+ ends << ((start + len) << 3)
2011
+ i += 1
2012
+ end
2013
+ out << JPEG_TAIL_PADDING
2014
+ @scan = out
2015
+ @starts = starts
2016
+ @ends = ends
2017
+ nil
2018
+ end
2019
+
2020
+ # The data pieces of a scan split at restart markers (piece 0 before
2021
+ # the first marker, piece j + 1 after marks[j]) in restart interval
2022
+ # order, assigned by the markers' numbers (modulo 8), -1 for an empty
2023
+ # interval. A marker without the
2024
+ # expected number is judged by the next one: if that one continues from
2025
+ # the expected number, this marker is corrupt and counts as expected; if
2026
+ # it continues from this marker, intervals were lost (up to five; they
2027
+ # stay empty, i.e. gray) or, for a marker one or two behind, the data is
2028
+ # stale and dropped. Otherwise libjpeg's resync rules apply: one or two
2029
+ # ahead means lost intervals, one or two behind stale data, else resume.
2030
+ def restart_intervals(marks)
2031
+ order = [0]
2032
+ expected = 0
2033
+ n = marks.size
2034
+ j = 0
2035
+ while j < n
2036
+ m = marks[j] & 7
2037
+ ahead = (m - expected) & 7
2038
+ if ahead != 0
2039
+ nxt = j + 1 < n ? marks[j + 1] & 7 : -1
2040
+ if nxt == ((expected + 1) & 7)
2041
+ ahead = 0
2042
+ elsif nxt != ((m + 1) & 7) && ahead >= 3 && ahead <= 5
2043
+ ahead = 0
2044
+ end
2045
+ end
2046
+ if ahead < 6
2047
+ a = 0
2048
+ while a < ahead
2049
+ order << -1 # a lost (empty) interval
2050
+ a += 1
2051
+ end
2052
+ order << j + 1
2053
+ expected += ahead + 1
2054
+ end
2055
+ j += 1
2056
+ end
2057
+ order
2058
+ end
2059
+
2060
+ # ---------------------------------------------------------------
2061
+ # Output
2062
+
2063
+ def finish
2064
+ comps = @components
2065
+ i = 0
2066
+ while i < comps.size
2067
+ c = comps[i]
2068
+ if c.needed
2069
+ if @progressive
2070
+ render_raw(c)
2071
+ else
2072
+ c.finish_plane
2073
+ end
2074
+ end
2075
+ i += 1
2076
+ end
2077
+ output
2078
+ end
2079
+
2080
+ # Luminance from the component planes.
2081
+ def output
2082
+ comps = @components
2083
+ color = @color
2084
+ if color == JPEG_RGB
2085
+ convert_rgb(component_samples(comps[0]), component_samples(comps[1]), component_samples(comps[2]))
2086
+ elsif color == JPEG_CMYK || color == JPEG_YCCK
2087
+ convert_cmyk(component_samples(comps[0]), component_samples(comps[1]), component_samples(comps[2]),
2088
+ component_samples(comps[3]), color == JPEG_YCCK)
2089
+ else
2090
+ component_samples(comps[0])
2091
+ end
2092
+ end
2093
+
2094
+ # IDCTs the raw progressive coefficients of +c+ into its plane, row by
2095
+ # row (freeing them, or moving them to the store with +keep+).
2096
+ def render_raw(c)
2097
+ latch_quant(c)
2098
+ c.start_plane
2099
+ bs = c.bs
2100
+ stride = c.pw / JPEG_SAMPLES_PER_WORD[bs]
2101
+ buf = Array.new(stride * bs, 0)
2102
+ pack = JPEG_PACK[bs]
2103
+ dc_only = c.stride == 1
2104
+ row = dc_only ? JPEG_NONE : Array.new(c.abw * JPEG_BLOCK_STRIDE, 0)
2105
+ by = 0
2106
+ while by < c.abh
2107
+ raw = c.raw[by]
2108
+ if raw.empty?
2109
+ # No data: all coefficients 0.
2110
+ buf.fill(128 * JPEG_SPREAD[bs])
2111
+ elsif dc_only
2112
+ render_dc_row(c, raw, c.qz[0], buf)
2113
+ else
2114
+ raw_to_row(raw, 0, c.abw, c.qz, row)
2115
+ c.idct.render_row(row, c.abw, buf, 0, stride)
2116
+ row.fill(0)
2117
+ end
2118
+ c.store_raw(raw) if @keep
2119
+ c.release_raw(by)
2120
+ c.append_plane(buf.pack(pack))
2121
+ by += 1
2122
+ end
2123
+ nil
2124
+ end
2125
+
2126
+ # Dequantises the +n+ blocks of the raw coefficient row at raw[off, ...]
2127
+ # into the (all zero) coefficient row +row+.
2128
+ def raw_to_row(raw, off, n, qz, row)
2129
+ zz = JPEG_ZIGZAG
2130
+ q0 = qz[0]
2131
+ base = 0
2132
+ p = off
2133
+ x = 0
2134
+ while x < n
2135
+ v = raw.getbyte(p) | (raw.getbyte(p + 1) << 8)
2136
+ row[base] = (v < 32_768 ? v : v - 65_536) * q0
2137
+ km = raw.getbyte(p + JPEG_RAW_KM)
2138
+ km = 63 if km > 63
2139
+ k = 1
2140
+ while k <= km
2141
+ i = zz[k]
2142
+ v = raw.getbyte(p + 2 * i) | (raw.getbyte(p + 2 * i + 1) << 8)
2143
+ row[base + i] = (v < 32_768 ? v : v - 65_536) * qz[k] if v != 0
2144
+ k += 1
2145
+ end
2146
+ row[base + 64] = km
2147
+ base += JPEG_BLOCK_STRIDE
2148
+ p += JPEG_RAW_BLOCK
2149
+ x += 1
2150
+ end
2151
+ nil
2152
+ end
2153
+
2154
+ # DC-only samples (block size 1) of a raw row of DCs of +c+.
2155
+ def render_dc_row(c, raw, q0, buf)
2156
+ idct = c.idct
2157
+ n = c.abw
2158
+ x = 0
2159
+ while x < n
2160
+ v = raw.getbyte(2 * x) | (raw.getbyte(2 * x + 1) << 8)
2161
+ buf[x] = idct.dc_sample((v < 32_768 ? v : v - 65_536) * q0)
2162
+ x += 1
2163
+ end
2164
+ nil
2165
+ end
2166
+
2167
+ # Renders the plane of +c+ from the raw coefficient rows of a store
2168
+ # starting at @data[pos].
2169
+ def render_stored_raw(c, pos)
2170
+ c.start_plane
2171
+ bs = c.bs
2172
+ stride = c.pw / JPEG_SAMPLES_PER_WORD[bs]
2173
+ buf = Array.new(stride * bs, 0)
2174
+ pack = JPEG_PACK[bs]
2175
+ row = Array.new(c.abw * JPEG_BLOCK_STRIDE, 0)
2176
+ by = 0
2177
+ while by < c.abh
2178
+ raw_to_row(@data, pos, c.abw, c.qz, row)
2179
+ c.idct.render_row(row, c.abw, buf, 0, stride)
2180
+ row.fill(0)
2181
+ c.append_plane(buf.pack(pack))
2182
+ pos += c.abw * JPEG_RAW_BLOCK
2183
+ by += 1
2184
+ end
2185
+ nil
2186
+ end
2187
+
2188
+ # The marks (see JpegComponent#marks) marks[start, n] as store bytes.
2189
+ def mark_bytes(marks, start, n)
2190
+ out = String.new(capacity: n * 8, encoding: Encoding::BINARY)
2191
+ i = start
2192
+ stop = start + n
2193
+ while i < stop
2194
+ m = marks[i]
2195
+ if m < 0
2196
+ out << 255 << 255 << 255 << 255 << 0 << 0 << 0 << 0
2197
+ else
2198
+ v = m >> 16
2199
+ out << (v & 255) << ((v >> 8) & 255) << ((v >> 16) & 255) << ((v >> 24) & 255)
2200
+ out << (m & 255) << ((m >> 8) & 255) << 0 << 0
2201
+ end
2202
+ i += 1
2203
+ end
2204
+ out
2205
+ end
2206
+
2207
+ # Renders the plane of +c+ from a sequential store: block marks at
2208
+ # @data[marks], scan data at @data[scan, size], AC Huffman +table+.
2209
+ def render_marked(c, marks, scan, size, table)
2210
+ c.start_plane
2211
+ bs = c.bs
2212
+ stride = c.pw / JPEG_SAMPLES_PER_WORD[bs]
2213
+ buf = Array.new(stride * bs, 0)
2214
+ pack = JPEG_PACK[bs]
2215
+ row = Array.new(c.abw * JPEG_BLOCK_STRIDE, 0)
2216
+ # Blocks start at least one MCU's worth of padding before the end.
2217
+ limit = (size - JPEG_TAIL_PADDING.bytesize) << 3
2218
+ by = 0
2219
+ while by < c.abh
2220
+ if bs == 1
2221
+ marked_dc_row(row, marks + by * c.abw * 8, c.abw, limit, c.qz)
2222
+ else
2223
+ marked_row(row, marks + by * c.abw * 8, c.abw, scan, limit, table, c.qz)
2224
+ end
2225
+ c.idct.render_row(row, c.abw, buf, 0, stride)
2226
+ row.fill(0)
2227
+ c.append_plane(buf.pack(pack))
2228
+ by += 1
2229
+ end
2230
+ nil
2231
+ end
2232
+
2233
+ # The DCs of the +n+ blocks whose marks start at @data[mp] into +row+.
2234
+ def marked_dc_row(row, mp, n, limit, qz)
2235
+ data = @data
2236
+ q0 = qz[0]
2237
+ base = 0
2238
+ x = 0
2239
+ while x < n
2240
+ bitpos = data.getbyte(mp) | (data.getbyte(mp + 1) << 8) | (data.getbyte(mp + 2) << 16) | (data.getbyte(mp + 3) << 24)
2241
+ if bitpos < limit
2242
+ v = data.getbyte(mp + 4) | (data.getbyte(mp + 5) << 8)
2243
+ row[base] = (v < 32_768 ? v : v - 65_536) * q0
2244
+ end
2245
+ base += JPEG_BLOCK_STRIDE
2246
+ mp += 8
2247
+ x += 1
2248
+ end
2249
+ nil
2250
+ end
2251
+
2252
+ # Decodes the +n+ blocks whose marks start at @data[mp] into +row+: DC
2253
+ # from the mark, AC coefficients from the scan data at @data[scan] with
2254
+ # +table+ (like JpegSequential#decode_mcu).
2255
+ def marked_row(row, mp, n, scan, limit, table, qz)
2256
+ data = @data
2257
+ fast = table.fast
2258
+ look = table.look
2259
+ zz = JPEG_ZIGZAG_EXT
2260
+ q0 = qz[0]
2261
+ base = 0
2262
+ x = 0
2263
+ while x < n
2264
+ bitpos = data.getbyte(mp) | (data.getbyte(mp + 1) << 8) | (data.getbyte(mp + 2) << 16) | (data.getbyte(mp + 3) << 24)
2265
+ if bitpos < limit
2266
+ v = data.getbyte(mp + 4) | (data.getbyte(mp + 5) << 8)
2267
+ row[base] = (v < 32_768 ? v : v - 65_536) * q0
2268
+ pos = scan + (bitpos >> 3)
2269
+ acc = (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) | (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2270
+ pos += 4
2271
+ bits = 32 - (bitpos & 7)
2272
+ k = 1
2273
+ while k < 64
2274
+ if bits < 31
2275
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
2276
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2277
+ pos += 4
2278
+ bits += 32
2279
+ end
2280
+ e = fast[(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2281
+ if e != 0
2282
+ bits -= e & 255
2283
+ k += (e >> 8) & 255
2284
+ row[base + zz[k]] = (e >> 16) * qz[k]
2285
+ k += 1
2286
+ else
2287
+ e = look[(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2288
+ e = table.decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
2289
+ bits -= e >> 8
2290
+ s = e & 15
2291
+ if s != 0
2292
+ k += (e >> 4) & 15
2293
+ v = (acc >> (bits - s)) & ((1 << s) - 1)
2294
+ bits -= s
2295
+ v -= (1 << s) - 1 if v < (1 << (s - 1))
2296
+ row[base + zz[k]] = v * qz[k]
2297
+ k += 1
2298
+ elsif (e & 0xF0) == 0xF0
2299
+ k += 16
2300
+ else
2301
+ k += JPEG_EOB_RUN + 1
2302
+ end
2303
+ end
2304
+ end
2305
+ row[base + 64] = k > JPEG_EOB_RUN ? k - JPEG_EOB_RUN - 2 : 63
2306
+ end
2307
+ base += JPEG_BLOCK_STRIDE
2308
+ mp += 8
2309
+ x += 1
2310
+ end
2311
+ nil
2312
+ end
2313
+
2314
+ # Samples of component +c+ at output size (cropped, or upsampled when
2315
+ # the component is subsampled relative to the frame).
2316
+ def component_samples(c)
2317
+ ow = @out_w
2318
+ oh = @out_h
2319
+ # Samples per MCU after scaling (libjpeg's input group), which the
2320
+ # upsampler expands to hmax x vmax output pixels.
2321
+ h = c.h * c.bs / @bs
2322
+ v = c.v * c.bs / @bs
2323
+ return crop(c.plane, c.pw, ow, oh) if h == @hmax && v == @vmax
2324
+
2325
+ # Component size at this scale (libjpeg's downsampled size).
2326
+ cw = (@width * c.h * c.bs + @hmax * 8 - 1) / (@hmax * 8)
2327
+ ch = (@height * c.v * c.bs + @vmax * 8 - 1) / (@vmax * 8)
2328
+ # libjpeg's "fancy" upsampling needs DCT_scaled_size > 1.
2329
+ JpegUpsampler.new(c.plane, c.pw, cw, ch, @hmax, @vmax, h, v, @bs > 1).run(ow, oh)
2330
+ end
2331
+
2332
+ def crop(plane, pw, w, h)
2333
+ return plane.byteslice(0, w * h) if pw == w
2334
+
2335
+ out = String.new(capacity: w * h, encoding: Encoding::BINARY)
2336
+ y = 0
2337
+ while y < h
2338
+ out << plane.byteslice(y * pw, w)
2339
+ y += 1
2340
+ end
2341
+ out
2342
+ end
2343
+
2344
+ def convert_rgb(r, g, b)
2345
+ w = @out_w
2346
+ out = String.new(capacity: w * @out_h, encoding: Encoding::BINARY)
2347
+ y = 0
2348
+ while y < @out_h
2349
+ out << rgb_row(r, g, b, y * w, w)
2350
+ y += 1
2351
+ end
2352
+ out
2353
+ end
2354
+
2355
+ def rgb_row(r, g, b, i, n)
2356
+ row = String.new(capacity: n, encoding: Encoding::BINARY)
2357
+ stop = i + n
2358
+ while i < stop
2359
+ row << ((306 * r.getbyte(i) + 601 * g.getbyte(i) + 117 * b.getbyte(i) + 0x200) >> 10)
2360
+ i += 1
2361
+ end
2362
+ row
2363
+ end
2364
+
2365
+ def convert_cmyk(c, m, y, k, ycck)
2366
+ w = @out_w
2367
+ out = String.new(capacity: w * @out_h, encoding: Encoding::BINARY)
2368
+ row = 0
2369
+ while row < @out_h
2370
+ out << (ycck ? ycck_row(c, m, y, k, row * w, w) : cmyk_row(c, m, y, k, row * w, w))
2371
+ row += 1
2372
+ end
2373
+ out
2374
+ end
2375
+
2376
+ # Adobe CMYK JPEGs store inverted ink (255 = no ink), so the stored
2377
+ # values are 255 - ink: R = C' * K' / 255 (rounded) and so on.
2378
+ def cmyk_row(c, m, y, k, i, n)
2379
+ row = String.new(capacity: n, encoding: Encoding::BINARY)
2380
+ stop = i + n
2381
+ while i < stop
2382
+ kk = k.getbyte(i)
2383
+ r = (c.getbyte(i) * kk + 127) / 255
2384
+ g = (m.getbyte(i) * kk + 127) / 255
2385
+ b = (y.getbyte(i) * kk + 127) / 255
2386
+ row << ((306 * r + 601 * g + 117 * b + 0x200) >> 10)
2387
+ i += 1
2388
+ end
2389
+ row
2390
+ end
2391
+
2392
+ # YCCK stores YCbCr-encoded CMY plus K; libjpeg converts it to CMYK with
2393
+ # its fixed-point YCbCr->RGB tables (C = 255 - R, ...), which then goes
2394
+ # through #cmyk_row's formula.
2395
+ def ycck_row(y, cb, cr, k, i, n)
2396
+ row = String.new(capacity: n, encoding: Encoding::BINARY)
2397
+ cr_r = JPEG_CR_R
2398
+ cb_b = JPEG_CB_B
2399
+ cr_g = JPEG_CR_G
2400
+ cb_g = JPEG_CB_G
2401
+ stop = i + n
2402
+ while i < stop
2403
+ yy = 255 - y.getbyte(i)
2404
+ u = cb.getbyte(i)
2405
+ v = cr.getbyte(i)
2406
+ kk = k.getbyte(i)
2407
+ c = yy - cr_r[v]
2408
+ m = yy - ((cb_g[u] + cr_g[v]) >> 16)
2409
+ ye = yy - cb_b[u]
2410
+ c = c < 0 ? 0 : (c > 255 ? 255 : c)
2411
+ m = m < 0 ? 0 : (m > 255 ? 255 : m)
2412
+ ye = ye < 0 ? 0 : (ye > 255 ? 255 : ye)
2413
+ r = (c * kk + 127) / 255
2414
+ g = (m * kk + 127) / 255
2415
+ b = (ye * kk + 127) / 255
2416
+ row << ((306 * r + 601 * g + 117 * b + 0x200) >> 10)
2417
+ i += 1
2418
+ end
2419
+ row
2420
+ end
2421
+ end
2422
+
2423
+
2424
+ # Decodes one sequential (baseline or extended) scan into the component
2425
+ # planes. The needed blocks of an MCU row are decoded into coefficient
2426
+ # rows, which are IDCT'd into the planes (and kept in the coefficient
2427
+ # store) when the row is complete; blocks of components that do not
2428
+ # contribute to the luminance are entropy-decoded and dropped.
2429
+ class JpegSequential
2430
+ # Per block: skip it, decode only its DC, or its DC and AC coefficients.
2431
+ SKIP = 0
2432
+ DC_ONLY = 1
2433
+ FULL = 2
2434
+
2435
+ def initialize(decoder, comps, dcs, acs, data, starts, ends)
2436
+ @ri = decoder.restart_interval
2437
+ @keep = decoder.keep
2438
+ @data = data
2439
+ @starts = starts
2440
+ @ends = ends
2441
+ @acc = 0
2442
+ @bits = 0
2443
+ @pos = 0
2444
+ @endbit = 0
2445
+ interleaved = comps.size > 1
2446
+ if interleaved
2447
+ @mcux = decoder.mcux
2448
+ @mcuy = decoder.mcuy
2449
+ else
2450
+ @mcux = comps[0].bw
2451
+ @mcuy = comps[0].bh
2452
+ end
2453
+ @preds = Array.new(comps.size, 0)
2454
+ # Per block of the MCU.
2455
+ # (Object lists start from a literal and grow by index, which lets
2456
+ # Spinel compile them as typed object arrays.)
2457
+ @pred_idx = []
2458
+ @dc_fast = []
2459
+ @dc_look = []
2460
+ @dc_table = [JPEG_EMPTY_HUFFMAN]
2461
+ @ac_fast = []
2462
+ @ac_look = []
2463
+ @ac_table = [JPEG_EMPTY_HUFFMAN]
2464
+ @mode = []
2465
+ @q = []
2466
+ @coef = [] # its coefficient row
2467
+ @col = [] # its block column in the MCU
2468
+ @cols = [] # block columns per MCU of its component
2469
+ # With a store: its component's marks (JpegComponent#marks), its block
2470
+ # row in the MCU, block rows per MCU and blocks per block row.
2471
+ @marks = []
2472
+ @row = []
2473
+ @rowstep = []
2474
+ @width = []
2475
+ # Per needed component: its coefficient rows (one per block row of an
2476
+ # MCU row, in @rows from @first), sample buffer and words per row.
2477
+ @ncomp = 0
2478
+ @comp = [comps[0]]
2479
+ @rows = []
2480
+ @first = []
2481
+ @nrows = []
2482
+ @buf = []
2483
+ @stride = []
2484
+ setup_blocks(decoder, comps, dcs, acs, interleaved)
2485
+ @nb = @pred_idx.size
2486
+ # Per block of the last MCU: bit position of its AC data, and its DC.
2487
+ @ac_start = Array.new(@nb, 0)
2488
+ @dc = Array.new(@nb, 0)
2489
+ end
2490
+
2491
+ def run
2492
+ total = @mcux * @mcuy
2493
+ ri = @ri
2494
+ mcu = 0
2495
+ interval = 0
2496
+ mx = 0
2497
+ my = 0
2498
+ while mcu < total
2499
+ if interval >= @starts.size
2500
+ flush if mx > 0 # no data left: the rest stays gray
2501
+ return nil
2502
+ end
2503
+ n = total - mcu
2504
+ n = ri if ri > 0 && ri < n
2505
+ start_interval(interval)
2506
+ interval += 1
2507
+ dead = false
2508
+ while n > 0
2509
+ n -= 1
2510
+ mcu += 1
2511
+ if !dead && !decode_mcu(mx, my)
2512
+ # Ran past the end of the data: drop this MCU and the rest of
2513
+ # the interval (or of the image); they stay gray.
2514
+ dead = true
2515
+ if ri == 0 || interval >= @starts.size
2516
+ flush
2517
+ return nil
2518
+ end
2519
+ end
2520
+ mx += 1
2521
+ next unless mx == @mcux
2522
+
2523
+ flush
2524
+ mx = 0
2525
+ my += 1
2526
+ end
2527
+ end
2528
+ nil
2529
+ end
2530
+
2531
+ private
2532
+
2533
+ def setup_blocks(decoder, comps, dcs, acs, interleaved)
2534
+ si = 0
2535
+ while si < comps.size
2536
+ c = comps[si]
2537
+ dc = decoder.huffman_table(false, dcs[si])
2538
+ ac = decoder.huffman_table(true, acs[si])
2539
+ hn = interleaved ? c.h : 1
2540
+ vn = interleaved ? c.v : 1
2541
+ first = @rows.size
2542
+ if c.needed
2543
+ decoder.latch_quant(c)
2544
+ stride = c.pw / JPEG_SAMPLES_PER_WORD[c.bs]
2545
+ @comp[@ncomp] = c
2546
+ @ncomp += 1
2547
+ @first << first
2548
+ @nrows << vn
2549
+ @buf << Array.new(stride * vn * c.bs, 0)
2550
+ @stride << stride
2551
+ r = 0
2552
+ while r < vn
2553
+ @rows << Array.new(c.abw * JPEG_BLOCK_STRIDE, 0)
2554
+ r += 1
2555
+ end
2556
+ end
2557
+ by = 0
2558
+ while by < vn
2559
+ bx = 0
2560
+ while bx < hn
2561
+ @dc_table[@pred_idx.size] = dc
2562
+ @ac_table[@pred_idx.size] = ac
2563
+ @pred_idx << si
2564
+ @dc_fast << dc.fast
2565
+ @dc_look << dc.look
2566
+ @ac_fast << ac.fast
2567
+ @ac_look << ac.look
2568
+ if c.needed
2569
+ @mode << (c.bs > 1 ? FULL : DC_ONLY)
2570
+ @q << c.qz
2571
+ @coef << @rows[first + by]
2572
+ @col << bx
2573
+ @cols << hn
2574
+ @marks << c.marks
2575
+ else
2576
+ @mode << SKIP
2577
+ @q << JPEG_NONE
2578
+ @coef << JPEG_NONE
2579
+ @col << 0
2580
+ @cols << 0
2581
+ @marks << JPEG_NONE
2582
+ end
2583
+ @row << by
2584
+ @rowstep << vn
2585
+ @width << c.abw
2586
+ bx += 1
2587
+ end
2588
+ by += 1
2589
+ end
2590
+ si += 1
2591
+ end
2592
+ nil
2593
+ end
2594
+
2595
+ def start_interval(index)
2596
+ @pos = @starts[index]
2597
+ @endbit = @ends[index]
2598
+ @acc = 0
2599
+ @bits = 0
2600
+ @preds.fill(0)
2601
+ nil
2602
+ end
2603
+
2604
+ # Decodes the MCU at column +mx+ of MCU row +my+ into the coefficient
2605
+ # rows (and marks its blocks for the store). Returns false (leaving its
2606
+ # blocks zero) if the MCU ran past the end of the interval's data.
2607
+ def decode_mcu(mx, my)
2608
+ data = @data
2609
+ starts = @ac_start
2610
+ dcs = @dc
2611
+ acc = @acc
2612
+ bits = @bits
2613
+ pos = @pos
2614
+ preds = @preds
2615
+ zz = JPEG_ZIGZAG_EXT
2616
+ nb = @nb
2617
+ b = 0
2618
+ while b < nb
2619
+ # DC coefficient (bits >= 31 after a refill covers any code + extra bits)
2620
+ if bits < 31
2621
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
2622
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2623
+ pos += 4
2624
+ bits += 32
2625
+ end
2626
+ e = @dc_fast[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2627
+ diff = 0
2628
+ if e != 0
2629
+ bits -= e & 255
2630
+ diff = e >> 16
2631
+ else
2632
+ e = @dc_look[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2633
+ e = @dc_table[b].decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
2634
+ bits -= e >> 8
2635
+ s = e & 255
2636
+ if s != 0
2637
+ diff = (acc >> (bits - s)) & ((1 << s) - 1)
2638
+ bits -= s
2639
+ diff -= (1 << s) - 1 if diff < (1 << (s - 1))
2640
+ end
2641
+ end
2642
+ ci = @pred_idx[b]
2643
+ pred = ((preds[ci] + diff + 32_768) & 0xFFFF) - 32_768 # JCOEF wraps to 16 bits
2644
+ preds[ci] = pred
2645
+
2646
+ # AC coefficients
2647
+ fast = @ac_fast[b]
2648
+ mode = @mode[b]
2649
+ starts[b] = pos * 8 - bits
2650
+ dcs[b] = pred
2651
+ k = 1
2652
+ if mode == FULL
2653
+ q = @q[b]
2654
+ coef = @coef[b]
2655
+ base = (mx * @cols[b] + @col[b]) * JPEG_BLOCK_STRIDE
2656
+ coef[base] = pred * q[0]
2657
+ while k < 64
2658
+ if bits < 31
2659
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
2660
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2661
+ pos += 4
2662
+ bits += 32
2663
+ end
2664
+ e = fast[(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2665
+ if e != 0
2666
+ # (end of block writes 0 to slot 64, which is set below)
2667
+ bits -= e & 255
2668
+ k += (e >> 8) & 255
2669
+ coef[base + zz[k]] = (e >> 16) * q[k]
2670
+ k += 1
2671
+ else
2672
+ e = @ac_look[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2673
+ e = @ac_table[b].decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
2674
+ bits -= e >> 8
2675
+ s = e & 15
2676
+ if s != 0
2677
+ k += (e >> 4) & 15
2678
+ v = (acc >> (bits - s)) & ((1 << s) - 1)
2679
+ bits -= s
2680
+ v -= (1 << s) - 1 if v < (1 << (s - 1))
2681
+ coef[base + zz[k]] = v * q[k]
2682
+ k += 1
2683
+ elsif (e & 0xF0) == 0xF0
2684
+ k += 16
2685
+ else
2686
+ k += JPEG_EOB_RUN + 1
2687
+ end
2688
+ end
2689
+ end
2690
+ coef[base + 64] = k > JPEG_EOB_RUN ? k - JPEG_EOB_RUN - 2 : 63
2691
+ else
2692
+ if mode == DC_ONLY
2693
+ @coef[b][(mx * @cols[b] + @col[b]) * JPEG_BLOCK_STRIDE] = pred * @q[b][0]
2694
+ end
2695
+ # Skip the AC coefficients.
2696
+ while k < 64
2697
+ if bits < 31
2698
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
2699
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2700
+ pos += 4
2701
+ bits += 32
2702
+ end
2703
+ e = fast[(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2704
+ if e != 0
2705
+ bits -= e & 255
2706
+ k += ((e >> 8) & 255) + 1
2707
+ else
2708
+ e = @ac_look[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2709
+ e = @ac_table[b].decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
2710
+ bits -= (e >> 8) + (e & 15)
2711
+ if (e & 15) != 0
2712
+ k += ((e >> 4) & 15) + 1
2713
+ elsif (e & 0xF0) == 0xF0
2714
+ k += 16
2715
+ else
2716
+ k = 64
2717
+ end
2718
+ end
2719
+ end
2720
+ end
2721
+ b += 1
2722
+ end
2723
+
2724
+ if pos * 8 - bits > @endbit
2725
+ clear_mcu(mx)
2726
+ return false
2727
+ end
2728
+
2729
+ @acc = acc
2730
+ @bits = bits
2731
+ @pos = pos
2732
+ mark_mcu(mx, my) if @keep
2733
+ true
2734
+ end
2735
+
2736
+ # Marks the blocks of the MCU at column +mx+ of MCU row +my+ for the
2737
+ # store: where their AC coefficients start, and their DCs.
2738
+ def mark_mcu(mx, my)
2739
+ b = 0
2740
+ while b < @nb
2741
+ if @mode[b] != SKIP
2742
+ @marks[b][(my * @rowstep[b] + @row[b]) * @width[b] + mx * @cols[b] + @col[b]] =
2743
+ (@ac_start[b] << 16) | (@dc[b] & 0xFFFF)
2744
+ end
2745
+ b += 1
2746
+ end
2747
+ nil
2748
+ end
2749
+
2750
+ # Zeroes the blocks of the MCU at column +mx+ (mid-gray).
2751
+ def clear_mcu(mx)
2752
+ b = 0
2753
+ while b < @nb
2754
+ if @mode[b] != SKIP
2755
+ @coef[b].fill(0, (mx * @cols[b] + @col[b]) * JPEG_BLOCK_STRIDE, JPEG_BLOCK_STRIDE)
2756
+ end
2757
+ b += 1
2758
+ end
2759
+ nil
2760
+ end
2761
+
2762
+ # IDCTs the coefficient rows of the MCU row into the planes and clears
2763
+ # them.
2764
+ def flush
2765
+ i = 0
2766
+ while i < @ncomp
2767
+ c = @comp[i]
2768
+ buf = @buf[i]
2769
+ stride = @stride[i]
2770
+ idct = c.idct
2771
+ first = @first[i]
2772
+ r = 0
2773
+ while r < @nrows[i]
2774
+ row = @rows[first + r]
2775
+ idct.render_row(row, c.abw, buf, r * c.bs * stride, stride)
2776
+ row.fill(0)
2777
+ r += 1
2778
+ end
2779
+ c.append_plane(buf.pack(JPEG_PACK[c.bs]))
2780
+ i += 1
2781
+ end
2782
+ nil
2783
+ end
2784
+ end
2785
+
2786
+ # Decodes one progressive scan into the raw coefficient rows of its
2787
+ # components (packed signed 16-bit Strings, JpegComponent#raw_row): DC
2788
+ # first or refinement (possibly interleaved), or AC first or refinement
2789
+ # of one spectral band of one component. Coefficients wrap to 16 bits
2790
+ # like libjpeg's JCOEF.
2791
+ class JpegProgressive
2792
+ DC_FIRST = 0
2793
+ DC_REFINE = 1
2794
+ AC_FIRST = 2
2795
+ AC_REFINE = 3
2796
+ # Bytes per block of a raw coefficient row, and the offset of the last
2797
+ # nonzero zigzag index in a block.
2798
+ BLOCK_BYTES = JPEG_BLOCK_STRIDE * 2
2799
+ KM = 128
2800
+
2801
+ def initialize(decoder, comps, dcs, ss, se, ah, al, ac, data, starts, ends)
2802
+ @ri = decoder.restart_interval
2803
+ @data = data
2804
+ @starts = starts
2805
+ @ends = ends
2806
+ @ss = ss
2807
+ @se = se
2808
+ @al = al
2809
+ @acc = 0
2810
+ @bits = 0
2811
+ @pos = 0
2812
+ @endbit = 0
2813
+ @eobrun = 0
2814
+ @preds = Array.new(comps.size, 0)
2815
+ @newnz = Array.new(64, 0)
2816
+ @kind = ss == 0 ? (ah == 0 ? DC_FIRST : DC_REFINE) : (ah == 0 ? AC_FIRST : AC_REFINE)
2817
+ if comps.size == 1
2818
+ @units_x = comps[0].bw
2819
+ @units_y = comps[0].bh
2820
+ else
2821
+ @units_x = decoder.mcux
2822
+ @units_y = decoder.mcuy
2823
+ end
2824
+ # AC scans: the component and its Huffman table.
2825
+ @comp = comps[0]
2826
+ @table = JPEG_EMPTY_HUFFMAN
2827
+ @table = decoder.huffman_table(true, ac) if ss != 0
2828
+ # DC scans, per block of the MCU: component, whether needed, block
2829
+ # row in the MCU row, block column at MCU column 0 and per MCU
2830
+ # column (in coefficients), block rows per MCU row, predictor, table.
2831
+ @b_comp = [comps[0]]
2832
+ @b_need = []
2833
+ @b_row = []
2834
+ @b_col = []
2835
+ @b_colstep = []
2836
+ @b_rowstep = []
2837
+ @b_pred = []
2838
+ @b_fast = []
2839
+ @b_look = []
2840
+ @b_table = [JPEG_EMPTY_HUFFMAN]
2841
+ @nb = 0
2842
+ if ss == 0
2843
+ setup_dc(decoder, comps, dcs)
2844
+ else
2845
+ decoder.latch_quant(@comp)
2846
+ end
2847
+ end
2848
+
2849
+ def run
2850
+ ux = @units_x
2851
+ total = ux * @units_y
2852
+ ri = @ri
2853
+ u = 0
2854
+ interval = 0
2855
+ while u < total && interval < @starts.size
2856
+ n = total - u
2857
+ n = ri if ri > 0 && ri < n
2858
+ @pos = @starts[interval]
2859
+ @endbit = @ends[interval]
2860
+ @acc = 0
2861
+ @bits = 0
2862
+ @eobrun = 0
2863
+ @preds.fill(0)
2864
+ interval += 1
2865
+ stop = u + n
2866
+ while u < stop
2867
+ y = u / ux
2868
+ x0 = u - y * ux
2869
+ x1 = x0 + stop - u
2870
+ x1 = ux if x1 > ux
2871
+ kind = @kind
2872
+ ok = if kind <= DC_REFINE then dc_row(y, x0, x1)
2873
+ elsif kind == AC_FIRST then ac_first_row(y, x0, x1)
2874
+ else ac_refine_row(y, x0, x1)
2875
+ end
2876
+ # On running out of data, skip the rest of the interval.
2877
+ u = ok ? u + x1 - x0 : stop
2878
+ end
2879
+ end
2880
+ nil
2881
+ end
2882
+
2883
+ private
2884
+
2885
+ def setup_dc(decoder, comps, dcs)
2886
+ interleaved = comps.size > 1
2887
+ si = 0
2888
+ while si < comps.size
2889
+ c = comps[si]
2890
+ decoder.latch_quant(c) if c.needed
2891
+ t = decoder.huffman_table(false, dcs[si]) if @kind == DC_FIRST
2892
+ hn = interleaved ? c.h : 1
2893
+ vn = interleaved ? c.v : 1
2894
+ stride = c.stride
2895
+ by = 0
2896
+ while by < vn
2897
+ bx = 0
2898
+ while bx < hn
2899
+ @b_comp[@b_need.size] = c
2900
+ @b_table[@b_need.size] = t if t
2901
+ @b_need << (c.needed ? 1 : 0)
2902
+ @b_row << by
2903
+ @b_col << bx * stride
2904
+ @b_colstep << hn * stride
2905
+ @b_rowstep << vn
2906
+ @b_pred << si
2907
+ if t
2908
+ @b_fast << t.fast
2909
+ @b_look << t.look
2910
+ end
2911
+ bx += 1
2912
+ end
2913
+ by += 1
2914
+ end
2915
+ si += 1
2916
+ end
2917
+ @nb = @b_need.size
2918
+ nil
2919
+ end
2920
+
2921
+ # DC first / refinement scan, MCUs mx0...mx1 of MCU row my.
2922
+ def dc_row(my, mx0, mx1)
2923
+ data = @data
2924
+ acc = @acc
2925
+ bits = @bits
2926
+ pos = @pos
2927
+ preds = @preds
2928
+ refine = @kind == DC_REFINE
2929
+ al = @al
2930
+ bit = 1 << al
2931
+ nb = @nb
2932
+ mx = mx0
2933
+ while mx < mx1
2934
+ b = 0
2935
+ while b < nb
2936
+ if bits < 31
2937
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
2938
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
2939
+ pos += 4
2940
+ bits += 32
2941
+ end
2942
+ need = @b_need[b] == 1
2943
+ coefs = ""
2944
+ p = 0
2945
+ if need
2946
+ coefs = @b_comp[b].raw_row(@b_row[b] + my * @b_rowstep[b])
2947
+ p = (@b_col[b] + mx * @b_colstep[b]) * 2
2948
+ end
2949
+ if refine
2950
+ bits -= 1
2951
+ if need && ((acc >> bits) & 1) == 1
2952
+ u = coefs.getbyte(p) | (coefs.getbyte(p + 1) << 8) | bit
2953
+ coefs.setbyte(p, u & 255)
2954
+ coefs.setbyte(p + 1, (u >> 8) & 255)
2955
+ end
2956
+ else
2957
+ e = @b_fast[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2958
+ diff = 0
2959
+ if e != 0
2960
+ bits -= e & 255
2961
+ diff = e >> 16
2962
+ else
2963
+ e = @b_look[b][(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
2964
+ e = @b_table[b].decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
2965
+ bits -= e >> 8
2966
+ s = e & 255
2967
+ if s != 0
2968
+ diff = (acc >> (bits - s)) & ((1 << s) - 1)
2969
+ bits -= s
2970
+ diff -= (1 << s) - 1 if diff < (1 << (s - 1))
2971
+ end
2972
+ end
2973
+ ci = @b_pred[b]
2974
+ pred = ((preds[ci] + diff + 32_768) & 0xFFFF) - 32_768
2975
+ preds[ci] = pred
2976
+ if need
2977
+ u = (pred << al) & 0xFFFF
2978
+ coefs.setbyte(p, u & 255)
2979
+ coefs.setbyte(p + 1, u >> 8)
2980
+ end
2981
+ end
2982
+ b += 1
2983
+ end
2984
+ if pos * 8 - bits > @endbit
2985
+ # Out of data: undo this MCU of a first scan.
2986
+ undo_dc(my, mx) unless refine
2987
+ return false
2988
+ end
2989
+ mx += 1
2990
+ end
2991
+ @acc = acc
2992
+ @bits = bits
2993
+ @pos = pos
2994
+ true
2995
+ end
2996
+
2997
+ def undo_dc(my, mx)
2998
+ b = 0
2999
+ while b < @nb
3000
+ if @b_need[b] == 1
3001
+ coefs = @b_comp[b].raw_row(@b_row[b] + my * @b_rowstep[b])
3002
+ p = (@b_col[b] + mx * @b_colstep[b]) * 2
3003
+ coefs.setbyte(p, 0)
3004
+ coefs.setbyte(p + 1, 0)
3005
+ end
3006
+ b += 1
3007
+ end
3008
+ nil
3009
+ end
3010
+
3011
+ # First scan of AC band ss..se, blocks bx0...bx1 of block row by.
3012
+ def ac_first_row(by, bx0, bx1)
3013
+ data = @data
3014
+ acc = @acc
3015
+ bits = @bits
3016
+ pos = @pos
3017
+ eobrun = @eobrun
3018
+ table = @table
3019
+ fast = table.fast
3020
+ look = table.look
3021
+ coefs = @comp.raw_row(by)
3022
+ ss = @ss
3023
+ se = @se
3024
+ al = @al
3025
+ zz = JPEG_ZIGZAG_EXT
3026
+ bx = bx0
3027
+ while bx < bx1
3028
+ if eobrun > 0
3029
+ # Blocks inside an end-of-band run have nothing in this band.
3030
+ skip = bx1 - bx
3031
+ skip = eobrun if eobrun < skip
3032
+ eobrun -= skip
3033
+ bx += skip
3034
+ next
3035
+ end
3036
+ base = bx * BLOCK_BYTES
3037
+ k = ss
3038
+ last = 0
3039
+ while k <= se
3040
+ if bits < 31
3041
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
3042
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
3043
+ pos += 4
3044
+ bits += 32
3045
+ end
3046
+ peek = (acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK
3047
+ e = fast[peek]
3048
+ v = e >> 16
3049
+ if e != 0 && v != 0
3050
+ bits -= e & 255
3051
+ k += (e >> 8) & 255
3052
+ u = (v << al) & 0xFFFF
3053
+ p = base + 2 * zz[k]
3054
+ coefs.setbyte(p, u & 255)
3055
+ coefs.setbyte(p + 1, u >> 8)
3056
+ last = k
3057
+ k += 1
3058
+ else
3059
+ e = look[peek]
3060
+ e = table.decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
3061
+ bits -= e >> 8
3062
+ s = e & 15
3063
+ r = (e >> 4) & 15
3064
+ if s != 0
3065
+ k += r
3066
+ v = (acc >> (bits - s)) & ((1 << s) - 1)
3067
+ bits -= s
3068
+ v -= (1 << s) - 1 if v < (1 << (s - 1))
3069
+ u = (v << al) & 0xFFFF
3070
+ p = base + 2 * zz[k]
3071
+ coefs.setbyte(p, u & 255)
3072
+ coefs.setbyte(p + 1, u >> 8)
3073
+ last = k
3074
+ k += 1
3075
+ elsif r == 15
3076
+ k += 16
3077
+ else
3078
+ # End of band: this block and 2^r - 1 + (r extra bits) more.
3079
+ eobrun = (1 << r) - 1
3080
+ if r > 0
3081
+ eobrun += (acc >> (bits - r)) & ((1 << r) - 1)
3082
+ bits -= r
3083
+ end
3084
+ break
3085
+ end
3086
+ end
3087
+ end
3088
+ if pos * 8 - bits > @endbit
3089
+ # Out of data: undo this block (the band was empty before).
3090
+ k = ss
3091
+ while k <= se
3092
+ p = base + 2 * zz[k]
3093
+ coefs.setbyte(p, 0)
3094
+ coefs.setbyte(p + 1, 0)
3095
+ k += 1
3096
+ end
3097
+ return false
3098
+ end
3099
+ last = 63 if last > 63
3100
+ coefs.setbyte(base + KM, last) if last > coefs.getbyte(base + KM)
3101
+ bx += 1
3102
+ end
3103
+ @acc = acc
3104
+ @bits = bits
3105
+ @pos = pos
3106
+ @eobrun = eobrun
3107
+ true
3108
+ end
3109
+
3110
+ # Successive approximation refinement of AC band ss..se (libjpeg's
3111
+ # decode_mcu_AC_refine), blocks bx0...bx1 of block row by.
3112
+ def ac_refine_row(by, bx0, bx1)
3113
+ data = @data
3114
+ acc = @acc
3115
+ bits = @bits
3116
+ pos = @pos
3117
+ eobrun = @eobrun
3118
+ table = @table
3119
+ look = table.look
3120
+ coefs = @comp.raw_row(by)
3121
+ ss = @ss
3122
+ se = @se
3123
+ p1 = 1 << @al
3124
+ m1 = -1 << @al
3125
+ zz = JPEG_ZIGZAG_EXT
3126
+ newnz = @newnz
3127
+ bx = bx0
3128
+ while bx < bx1
3129
+ base = bx * BLOCK_BYTES
3130
+ last = coefs.getbyte(base + KM)
3131
+ nnz = 0
3132
+ if eobrun > 0 && last < ss
3133
+ # Inside an end-of-band run with nothing to refine in this band
3134
+ # (and likewise the following blocks).
3135
+ eobrun -= 1
3136
+ bx += 1
3137
+ while eobrun > 0 && bx < bx1 && coefs.getbyte(bx * BLOCK_BYTES + KM) < ss
3138
+ eobrun -= 1
3139
+ bx += 1
3140
+ end
3141
+ next
3142
+ end
3143
+ k = ss
3144
+ if eobrun == 0
3145
+ while k <= se
3146
+ if bits < 31
3147
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
3148
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
3149
+ pos += 4
3150
+ bits += 32
3151
+ end
3152
+ e = look[(acc >> (bits - JPEG_FAST_BITS)) & JPEG_FAST_MASK]
3153
+ e = table.decode_long((acc >> (bits - 16)) & 0xFFFF) if e == 0
3154
+ bits -= e >> 8
3155
+ s = e & 15
3156
+ r = (e >> 4) & 15
3157
+ if s != 0
3158
+ # A new coefficient of magnitude 1 (its size should be 1).
3159
+ bits -= 1
3160
+ s = ((acc >> bits) & 1) == 1 ? p1 : m1
3161
+ elsif r != 15
3162
+ eobrun = 1 << r
3163
+ if r > 0
3164
+ eobrun += (acc >> (bits - r)) & ((1 << r) - 1)
3165
+ bits -= r
3166
+ end
3167
+ break
3168
+ end
3169
+ # Skip r zero coefficients, refining the nonzero ones passed.
3170
+ while k <= se
3171
+ p = base + 2 * zz[k]
3172
+ u = coefs.getbyte(p) | (coefs.getbyte(p + 1) << 8)
3173
+ if u != 0
3174
+ if bits < 31
3175
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
3176
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
3177
+ pos += 4
3178
+ bits += 32
3179
+ end
3180
+ bits -= 1
3181
+ if ((acc >> bits) & 1) == 1 && (u & p1) == 0
3182
+ u = (u < 32_768 ? u + p1 : u + m1) & 0xFFFF
3183
+ coefs.setbyte(p, u & 255)
3184
+ coefs.setbyte(p + 1, u >> 8)
3185
+ end
3186
+ else
3187
+ r -= 1
3188
+ break if r < 0
3189
+ end
3190
+ k += 1
3191
+ end
3192
+ if s != 0
3193
+ p = base + 2 * zz[k]
3194
+ u = s & 0xFFFF
3195
+ coefs.setbyte(p, u & 255)
3196
+ coefs.setbyte(p + 1, u >> 8)
3197
+ newnz[nnz] = p
3198
+ nnz += 1 if nnz < 63
3199
+ last = k if k > last
3200
+ end
3201
+ k += 1
3202
+ end
3203
+ end
3204
+ if eobrun > 0
3205
+ # Refine the band's remaining nonzero coefficients; none lie beyond
3206
+ # the block's last nonzero position.
3207
+ limit = last < se ? last : se
3208
+ while k <= limit
3209
+ p = base + 2 * zz[k]
3210
+ u = coefs.getbyte(p) | (coefs.getbyte(p + 1) << 8)
3211
+ if u != 0
3212
+ if bits < 31
3213
+ acc = ((acc & ((1 << bits) - 1)) << 32) | (data.getbyte(pos) << 24) | (data.getbyte(pos + 1) << 16) |
3214
+ (data.getbyte(pos + 2) << 8) | data.getbyte(pos + 3)
3215
+ pos += 4
3216
+ bits += 32
3217
+ end
3218
+ bits -= 1
3219
+ if ((acc >> bits) & 1) == 1 && (u & p1) == 0
3220
+ u = (u < 32_768 ? u + p1 : u + m1) & 0xFFFF
3221
+ coefs.setbyte(p, u & 255)
3222
+ coefs.setbyte(p + 1, u >> 8)
3223
+ end
3224
+ end
3225
+ k += 1
3226
+ end
3227
+ eobrun -= 1
3228
+ end
3229
+ if pos * 8 - bits > @endbit
3230
+ # Out of data: re-zero the coefficients this block made nonzero
3231
+ # (like libjpeg), so that its last nonzero index stays valid.
3232
+ while nnz > 0
3233
+ nnz -= 1
3234
+ coefs.setbyte(newnz[nnz], 0)
3235
+ coefs.setbyte(newnz[nnz] + 1, 0)
3236
+ end
3237
+ return false
3238
+ end
3239
+
3240
+ coefs.setbyte(base + KM, last > 63 ? 63 : last)
3241
+ bx += 1
3242
+ end
3243
+ @acc = acc
3244
+ @bits = bits
3245
+ @pos = pos
3246
+ @eobrun = eobrun
3247
+ true
3248
+ end
3249
+ end
3250
+
3251
+ # Upsamples a subsampled component plane to the output size, choosing the
3252
+ # method like libjpeg (jdsample.c): with +fancy+ (DCT_scaled_size > 1) 2x
3253
+ # ratios use the "fancy" triangle filters (h2v1 and h2v2 only for
3254
+ # components wider than 2 samples, h1v2 always), other integer ratios
3255
+ # replicate samples. Fractional ratios, which libjpeg rejects, use the
3256
+ # nearest sample.
3257
+ class JpegUpsampler
3258
+ REPLICATE = 0
3259
+ H2V1 = 1
3260
+ H1V2 = 2
3261
+ H2V2 = 3
3262
+
3263
+ # +plane+ has row stride +stride+; the component's valid size is +cw+ x
3264
+ # +ch+ samples, and +h+ x +v+ of them cover +hmax+ x +vmax+ output pixels.
3265
+ def initialize(plane, stride, cw, ch, hmax, vmax, h, v, fancy)
3266
+ @plane = plane
3267
+ @stride = stride
3268
+ @cw = cw
3269
+ @ch = ch
3270
+ @hmax = hmax
3271
+ @vmax = vmax
3272
+ @h = h
3273
+ @v = v
3274
+ @rh = (hmax % h) == 0 ? hmax / h : 0
3275
+ rv = (vmax % v) == 0 ? vmax / v : 0
3276
+ @mode = if fancy && @rh == 2 && rv == 1 && cw > 2 then H2V1
3277
+ elsif fancy && @rh == 1 && rv == 2 then H1V2
3278
+ elsif fancy && @rh == 2 && rv == 2 && cw > 2 then H2V2
3279
+ else REPLICATE
3280
+ end
3281
+ end
3282
+
3283
+ def run(ow, oh)
3284
+ out = String.new(capacity: ow * oh, encoding: Encoding::BINARY)
3285
+ mode = @mode
3286
+ last_src = -1
3287
+ last = ""
3288
+ y = 0
3289
+ while y < oh
3290
+ row = ""
3291
+ if mode == H2V1
3292
+ row = h2v1(row_offset(y), ow)
3293
+ elsif mode == H1V2
3294
+ row = h1v2(y)
3295
+ elsif mode == H2V2
3296
+ row = h2v2(y, ow)
3297
+ else
3298
+ # Replicated rows: repeat the previous output row.
3299
+ src = y * @v / @vmax
3300
+ if src == last_src
3301
+ row = last
3302
+ else
3303
+ row = replicate_row(row_offset(src), ow)
3304
+ last = row
3305
+ last_src = src
3306
+ end
3307
+ end
3308
+ raise QrReader::ImageError, "corrupt JPEG: upsampling mismatch" unless row.bytesize == ow
3309
+
3310
+ out << row
3311
+ y += 1
3312
+ end
3313
+ out
3314
+ end
3315
+
3316
+ private
3317
+
3318
+ # Offset of component row +y+ in the plane (clamped to the valid rows,
3319
+ # as libjpeg repeats the first and last row for context).
3320
+ def row_offset(y)
3321
+ y = 0 if y < 0
3322
+ y = @ch - 1 if y >= @ch
3323
+ y * @stride
3324
+ end
3325
+
3326
+ # Samples x * h / hmax of the row at +off+ for x < ow: replication for
3327
+ # integer ratios, the nearest sample for fractional ones.
3328
+ def replicate_row(off, ow)
3329
+ plane = @plane
3330
+ out = String.new(capacity: ow, encoding: Encoding::BINARY)
3331
+ last = @cw - 1
3332
+ rh = @rh
3333
+ x = 0
3334
+ if rh > 0
3335
+ sx = off
3336
+ while x < ow
3337
+ v = plane.getbyte(sx)
3338
+ r = rh
3339
+ while r > 0 && x < ow
3340
+ out << v
3341
+ x += 1
3342
+ r -= 1
3343
+ end
3344
+ sx += 1
3345
+ end
3346
+ else
3347
+ h = @h
3348
+ hmax = @hmax
3349
+ while x < ow
3350
+ sx = x * h / hmax
3351
+ out << plane.getbyte(off + (sx > last ? last : sx))
3352
+ x += 1
3353
+ end
3354
+ end
3355
+ out
3356
+ end
3357
+
3358
+ # libjpeg h1v2_fancy_upsample: 3/4 nearer + 1/4 further row.
3359
+ def h1v2(y)
3360
+ plane = @plane
3361
+ lower = (y & 1) == 1
3362
+ near = row_offset(y >> 1)
3363
+ far = row_offset(lower ? (y >> 1) + 1 : (y >> 1) - 1)
3364
+ bias = lower ? 2 : 1
3365
+ n = @cw
3366
+ out = String.new(capacity: n, encoding: Encoding::BINARY)
3367
+ x = 0
3368
+ while x < n
3369
+ out << ((plane.getbyte(near + x) * 3 + plane.getbyte(far + x) + bias) >> 2)
3370
+ x += 1
3371
+ end
3372
+ out
3373
+ end
3374
+
3375
+ # libjpeg h2v1_fancy_upsample: 3/4 nearer + 1/4 further sample. The last
3376
+ # output exists only if the output is that wide.
3377
+ def h2v1(off, ow)
3378
+ s = @plane
3379
+ n = @cw
3380
+ out = String.new(capacity: ow, encoding: Encoding::BINARY)
3381
+ first = s.getbyte(off)
3382
+ out << first << ((first * 3 + s.getbyte(off + 1) + 2) >> 2)
3383
+ x = off + 1
3384
+ e = off + n - 1
3385
+ while x < e
3386
+ t = s.getbyte(x) * 3
3387
+ out << ((t + s.getbyte(x - 1) + 1) >> 2) << ((t + s.getbyte(x + 1) + 2) >> 2)
3388
+ x += 1
3389
+ end
3390
+ tail = s.getbyte(e)
3391
+ out << ((tail * 3 + s.getbyte(e - 1) + 1) >> 2)
3392
+ out << tail if 2 * n <= ow
3393
+ out
3394
+ end
3395
+
3396
+ # libjpeg h2v2_fancy_upsample on column sums 3 * nearer + further row.
3397
+ def h2v2(y, ow)
3398
+ s = @plane
3399
+ lower = (y & 1) == 1
3400
+ near = row_offset(y >> 1)
3401
+ far = row_offset(lower ? (y >> 1) + 1 : (y >> 1) - 1)
3402
+ n = @cw
3403
+ out = String.new(capacity: ow, encoding: Encoding::BINARY)
3404
+ this = s.getbyte(near) * 3 + s.getbyte(far)
3405
+ nxt = s.getbyte(near + 1) * 3 + s.getbyte(far + 1)
3406
+ out << ((this * 4 + 8) >> 4) << ((this * 3 + nxt + 7) >> 4)
3407
+ x = 1
3408
+ while x < n - 1
3409
+ last = this
3410
+ this = nxt
3411
+ nxt = s.getbyte(near + x + 1) * 3 + s.getbyte(far + x + 1)
3412
+ t = this * 3
3413
+ out << ((t + last + 8) >> 4) << ((t + nxt + 7) >> 4)
3414
+ x += 1
3415
+ end
3416
+ out << ((nxt * 3 + this + 8) >> 4)
3417
+ out << ((nxt * 4 + 7) >> 4) if 2 * n <= ow
3418
+ out
3419
+ end
3420
+ end
3421
+ end