vlib/image/decoders/common/common.v
Rama master · réplica de lectura del repositorio original.
/**********************************************************************
*
* Shared decoder types: decoded image, animation frame, bit reader
*
* Copyright (c) 2026 Dario Deledda. All rights reserved.
* Use of this source code is governed by an MIT license
* that can be found in the LICENSE file.
*
**********************************************************************/
module common
// Image is a decoded, top-down RGBA image (straight, non-premultiplied alpha).
pub struct Image {
pub:
width int
height int
rgba []u8 // len == width * height * 4
}
// Frame is one coalesced animation frame.
pub struct Frame {
pub:
image Image
delay_ms int
disposal int
}
// Animation is a sequence of frames with a loop count.
pub struct Animation {
pub:
frames []Frame
loop_count int // 0 = forever, >= 1 finite
}
// BitReader reads bits from a byte buffer in either LSB-first (GIF/WebP)
// or MSB-first (JPEG) order. Format-specific byte stuffing (e.g. JPEG
// FF00) is handled by the caller.
pub struct BitReader {
mut:
data []u8
byte_pos int
bit_pos int // bits already consumed in the current byte (0..8)
msb bool
}
// new_bitreader_lsb creates an LSB-first reader.
pub fn new_bitreader_lsb(data []u8) BitReader {
return BitReader{
data: data
msb: false
}
}
// new_bitreader_msb creates an MSB-first reader.
pub fn new_bitreader_msb(data []u8) BitReader {
return BitReader{
data: data
msb: true
}
}
// read_bits reads up to 32 bits and returns them as a u32.
// Bits are assembled in the order they are read.
pub fn (mut r BitReader) read_bits(n int) !u32 {
mut val := u32(0)
if r.msb {
for _ in 0 .. n {
if r.bit_pos == 8 {
r.bit_pos = 0
r.byte_pos++
}
if r.byte_pos >= r.data.len {
return error('BitReader: unexpected EOF (msb)')
}
bit := (r.data[r.byte_pos] >> (7 - r.bit_pos)) & 1
val = (val << 1) | u32(bit)
r.bit_pos++
}
} else {
for i in 0 .. n {
if r.bit_pos == 8 {
r.bit_pos = 0
r.byte_pos++
}
if r.byte_pos >= r.data.len {
return error('BitReader: unexpected EOF (lsb)')
}
bit := (r.data[r.byte_pos] >> r.bit_pos) & 1
val |= u32(bit) << i
r.bit_pos++
}
}
return val
}
// align_bytes skips to the next byte boundary (no-op if already aligned).
pub fn (mut r BitReader) align_bytes() {
if r.bit_pos != 0 {
r.bit_pos = 0
r.byte_pos++
}
}
// remaining returns the number of whole bytes left (approximate).
pub fn (r BitReader) remaining() int {
return r.data.len - r.byte_pos
}