| // Copyright 2023 The Wuffs Authors. |
| // |
| // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or |
| // https://www.apache.org/licenses/LICENSE-2.0> or the MIT license |
| // <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your |
| // option. This file may not be copied, modified, or distributed |
| // except according to those terms. |
| // |
| // SPDX-License-Identifier: Apache-2.0 OR MIT |
| |
| pri func decoder.decode_mcu_progressive_dc_low_bit!(workbuf: slice base.u8, mx: base.u32[..= 0x1FFF], my: base.u32[..= 0x1FFF]) base.u32 { |
| var ret : base.u32 |
| |
| var bits : base.u64 |
| var n_bits : base.u32 |
| |
| var one_lshift_scan_al : base.u16[..= 0x2000] |
| |
| var r : base.io_reader |
| var pos : base.u32 |
| |
| bits = this.bitstream_bits |
| n_bits = this.bitstream_n_bits |
| |
| one_lshift_scan_al = (1 as base.u16) << this.scan_al |
| |
| if this.bitstream_ri > this.bitstream_wi { |
| return 2 // Internal error. |
| } |
| io_bind (io: r, data: this.bitstream_buffer[this.bitstream_ri .. this.bitstream_wi], history_position: this.bitstream_ri as base.u64) { |
| while.goto_done true {{ |
| |
| while.block this.mcu_current_block < this.mcu_num_blocks { |
| assert this.mcu_current_block < 10 via "a < b: a < c; c <= b"(c: this.mcu_num_blocks) |
| |
| // Ensure that we have enough bits for this iteration of the |
| // while.block loop body. Worst case, there are 64 components and |
| // each one needs (16 + 15) bits (round that up to 4 bytes), so we |
| // need (64 * 4) = 256 bytes available. 8 more bytes of slack means |
| // that we can always call peek_u64be. |
| if r.length() < 264 { |
| ret = 1 // Request another fill_bitstream call. |
| break.goto_done |
| } |
| |
| while.dc_component true, |
| inv this.mcu_current_block < 10, |
| { |
| // Load at least 56 bits. |
| if r.length() < 8 { |
| ret = 2 // Internal error. |
| break.goto_done |
| } |
| bits |= r.peek_u64be() >> (n_bits & 63) |
| r.skip_u32_fast!(actual: (63 - (n_bits & 63)) >> 3, worst_case: 8) |
| n_bits |= 56 |
| |
| // Refine a bit. |
| if (bits >> 63) <> 0 { |
| this.mcu_blocks[this.mcu_current_block][0] |= one_lshift_scan_al |
| } |
| bits ~mod<<= 1 |
| n_bits ~mod-= 1 |
| |
| break.dc_component |
| } endwhile.dc_component |
| |
| assert this.mcu_current_block < 10 |
| this.mcu_current_block += 1 |
| } endwhile.block |
| this.mcu_current_block = 0 |
| |
| break.goto_done |
| }} endwhile.goto_done |
| |
| pos = (r.position() & 0xFFFF_FFFF) as base.u32 |
| if pos > this.bitstream_wi { |
| ret = 2 // Internal error. |
| } else { |
| assert pos <= 0x800 via "a <= b: a <= c; c <= b"(c: this.bitstream_wi) |
| this.bitstream_ri = pos |
| } |
| } |
| |
| this.bitstream_bits = bits |
| this.bitstream_n_bits = n_bits |
| return ret |
| } |