blob: 2afa0dbfae8e35665002186b7508e76e9bc12205 [file] [log] [blame]
// 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
}