Skip to content

Commit

Permalink
Clippy
Browse files Browse the repository at this point in the history
  • Loading branch information
kornelski committed Jan 4, 2025
1 parent 34223fa commit f798911
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 170 deletions.
1 change: 1 addition & 0 deletions .rustfmt.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# reset to default
30 changes: 16 additions & 14 deletions src/alpha_blending.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
//! Optimized alpha blending routines based on libwebp
//!
//! https://github.com/webmproject/libwebp/blob/e4f7a9f0c7c9fbfae1568bc7fa5c94b989b50872/src/demux/anim_decode.c#L215-L267
//! <https://github.com/webmproject/libwebp/blob/e4f7a9f0c7c9fbfae1568bc7fa5c94b989b50872/src/demux/anim_decode.c#L215-L267>
fn channel_shift(i: u32) -> u32 {
const fn channel_shift(i: u32) -> u32 {
i * 8
}

Expand All @@ -18,8 +18,9 @@ fn blend_channel_nonpremult(
) -> u8 {
let src_channel = ((src >> shift) & 0xff) as u8;
let dst_channel = ((dst >> shift) & 0xff) as u8;
let blend_unscaled = (src_channel as u32 * src_a as u32) + (dst_channel as u32 * dst_a as u32);
debug_assert!(u64::from(blend_unscaled) < (1u64 << 32) / scale as u64);
let blend_unscaled =
(u32::from(src_channel) * u32::from(src_a)) + (u32::from(dst_channel) * u32::from(dst_a));
debug_assert!(u64::from(blend_unscaled) < (1u64 << 32) / u64::from(scale));
((blend_unscaled * scale) >> channel_shift(3)) as u8
}

Expand All @@ -35,8 +36,8 @@ fn blend_pixel_nonpremult(src: u32, dst: u32) -> u32 {
// libwebp used the following formula here:
//let dst_factor_a = (dst_a as u32 * (256 - src_a as u32)) >> 8;
// however, we've found that we can use a more precise approximation without losing performance:
let dst_factor_a = div_by_255(dst_a as u32 * (255 - src_a as u32));
let blend_a = src_a as u32 + dst_factor_a;
let dst_factor_a = div_by_255(u32::from(dst_a) * (255 - u32::from(src_a)));
let blend_a = u32::from(src_a) + dst_factor_a;
let scale = (1u32 << 24) / blend_a;

let blend_r =
Expand All @@ -45,11 +46,11 @@ fn blend_pixel_nonpremult(src: u32, dst: u32) -> u32 {
blend_channel_nonpremult(src, src_a, dst, dst_factor_a as u8, scale, channel_shift(1));
let blend_b =
blend_channel_nonpremult(src, src_a, dst, dst_factor_a as u8, scale, channel_shift(2));
debug_assert!(src_a as u32 + dst_factor_a < 256);
debug_assert!(u32::from(src_a) + dst_factor_a < 256);

((blend_r as u32) << channel_shift(0))
| ((blend_g as u32) << channel_shift(1))
| ((blend_b as u32) << channel_shift(2))
(u32::from(blend_r) << channel_shift(0))
| (u32::from(blend_g) << channel_shift(1))
| (u32::from(blend_b) << channel_shift(2))
| (blend_a << channel_shift(3))
}
}
Expand All @@ -69,7 +70,7 @@ pub(crate) fn do_alpha_blending(buffer: [u8; 4], canvas: [u8; 4]) -> [u8; 4] {
// https://arxiv.org/pdf/2202.02864
// https://github.com/image-rs/image-webp/issues/119#issuecomment-2544007820
#[inline]
fn div_by_255(v: u32) -> u32 {
const fn div_by_255(v: u32) -> u32 {
(((v + 0x80) >> 8) + v + 0x80) >> 8
}

Expand Down Expand Up @@ -116,9 +117,10 @@ mod tests {
let slow = do_alpha_blending_reference([r1, 0, 0, a1], [r2, 0, 0, a2]);
// libwebp doesn't do exact blending and so we don't either
for (o, s) in opt.iter().zip(slow.iter()) {
if o.abs_diff(*s) > 3 {
panic!("Mismatch in results! opt: {opt:?}, slow: {slow:?}, blended values: [{r1}, 0, 0, {a1}], [{r2}, 0, 0, {a2}]");
}
assert!(
o.abs_diff(*s) <= 3,
"Mismatch in results! opt: {opt:?}, slow: {slow:?}, blended values: [{r1}, 0, 0, {a1}], [{r2}, 0, 0, {a2}]"
);
}
}
}
Expand Down
25 changes: 13 additions & 12 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ pub(crate) enum WebPRiffChunk {
}

impl WebPRiffChunk {
pub(crate) fn from_fourcc(chunk_fourcc: [u8; 4]) -> Self {
pub(crate) const fn from_fourcc(chunk_fourcc: [u8; 4]) -> Self {
match &chunk_fourcc {
b"RIFF" => Self::RIFF,
b"WEBP" => Self::WEBP,
Expand All @@ -203,7 +203,7 @@ impl WebPRiffChunk {
}
}

pub(crate) fn to_fourcc(self) -> [u8; 4] {
pub(crate) const fn to_fourcc(self) -> [u8; 4] {
match self {
Self::RIFF => *b"RIFF",
Self::WEBP => *b"WEBP",
Expand All @@ -220,7 +220,7 @@ impl WebPRiffChunk {
}
}

pub(crate) fn is_unknown(&self) -> bool {
pub(crate) const fn is_unknown(self) -> bool {
matches!(self, Self::Unknown(_))
}
}
Expand Down Expand Up @@ -292,10 +292,10 @@ pub struct WebPDecoder<R> {
}

impl<R: BufRead + Seek> WebPDecoder<R> {
/// Create a new WebPDecoder from the reader `r`. The decoder performs many small reads, so the
/// Create a new `WebPDecoder` from the reader `r`. The decoder performs many small reads, so the
/// reader should be buffered.
pub fn new(r: R) -> Result<WebPDecoder<R>, DecodingError> {
let mut decoder = WebPDecoder {
pub fn new(r: R) -> Result<Self, DecodingError> {
let mut decoder = Self {
r,
width: 0,
height: 0,
Expand Down Expand Up @@ -346,8 +346,8 @@ impl<R: BufRead + Seek> WebPDecoder<R> {
let w = self.r.read_u16::<LittleEndian>()?;
let h = self.r.read_u16::<LittleEndian>()?;

self.width = (w & 0x3FFF) as u32;
self.height = (h & 0x3FFF) as u32;
self.width = u32::from(w & 0x3FFF);
self.height = u32::from(h & 0x3FFF);
if self.width == 0 || self.height == 0 {
return Err(DecodingError::InconsistentImageSizes);
}
Expand Down Expand Up @@ -402,7 +402,7 @@ impl<R: BufRead + Seek> WebPDecoder<R> {
self.chunks.entry(chunk).or_insert(range);
}

if let WebPRiffChunk::ANMF = chunk {
if chunk == WebPRiffChunk::ANMF {
self.num_frames += 1;
if chunk_size < 24 {
return Err(DecodingError::InvalidChunkSize);
Expand Down Expand Up @@ -603,7 +603,7 @@ impl<R: BufRead + Seek> WebPDecoder<R> {
}

/// Returns the number of bytes required to store the image or a single frame, or None if that
/// would take more than usize::MAX bytes.
/// would take more than `usize::MAX` bytes.
pub fn output_buffer_size(&self) -> Option<usize> {
let bytes_per_pixel = if self.has_alpha() { 4 } else { 3 };
(self.width as usize)
Expand Down Expand Up @@ -656,7 +656,7 @@ impl<R: BufRead + Seek> WebPDecoder<R> {
.ok_or(DecodingError::ChunkMissing)?
.clone();
let alpha_chunk = read_alpha_chunk(
&mut range_reader(&mut self.r, range.start..range.end)?,
&mut range_reader(&mut self.r, range)?,
self.width as u16,
self.height as u16,
)?;
Expand Down Expand Up @@ -748,7 +748,8 @@ impl<R: BufRead + Seek> WebPDecoder<R> {
let reader = (&mut self.r).take(chunk_size);
let mut vp8_decoder = Vp8Decoder::new(reader);
let raw_frame = vp8_decoder.decode_frame()?;
if raw_frame.width as u32 != frame_width || raw_frame.height as u32 != frame_height
if u32::from(raw_frame.width) != frame_width
|| u32::from(raw_frame.height) != frame_height
{
return Err(DecodingError::InconsistentImageSizes);
}
Expand Down
62 changes: 31 additions & 31 deletions src/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl<W: Write> BitWriter<W> {
if self.nbits >= 64 {
self.writer.write_all(&self.buffer.to_le_bytes())?;
self.nbits -= 64;
self.buffer = bits.checked_shr((nbits - self.nbits) as u32).unwrap_or(0);
self.buffer = bits.checked_shr(u32::from(nbits - self.nbits)).unwrap_or(0);
}
debug_assert!(self.nbits < 64);
Ok(())
Expand All @@ -82,10 +82,10 @@ fn write_single_entry_huffman_tree<W: Write>(w: &mut BitWriter<W>, symbol: u8) -
w.write_bits(1, 2)?;
if symbol <= 1 {
w.write_bits(0, 1)?;
w.write_bits(symbol as u64, 1)?;
w.write_bits(u64::from(symbol), 1)?;
} else {
w.write_bits(1, 1)?;
w.write_bits(symbol as u64, 8)?;
w.write_bits(u64::from(symbol), 8)?;
}
Ok(())
}
Expand Down Expand Up @@ -188,7 +188,7 @@ fn build_huffman_tree(
let mut len = length_limit;
let mut indexes = frequencies.iter().copied().enumerate().collect::<Vec<_>>();
indexes.sort_unstable_by_key(|&(_, frequency)| frequency);
for &(i, frequency) in indexes.iter() {
for &(i, frequency) in &indexes {
if frequency > 0 {
while counts[len as usize] == 0 {
len -= 1;
Expand Down Expand Up @@ -251,13 +251,13 @@ fn write_huffman_tree<W: Write>(
w.write_bits(0, 1)?; // normal huffman tree
w.write_bits(19 - 4, 4)?; // num_code_lengths - 4

for &i in CODE_LENGTH_ORDER.iter() {
for i in CODE_LENGTH_ORDER {
if i > 15 || code_length_frequencies[i] == 0 {
w.write_bits(0, 3)?;
} else if single_code_length_length {
w.write_bits(1, 3)?;
} else {
w.write_bits(code_length_lengths[i] as u64, 3)?;
w.write_bits(u64::from(code_length_lengths[i]), 3)?;
}
}

Expand All @@ -275,7 +275,7 @@ fn write_huffman_tree<W: Write>(
if !single_code_length_length {
for &len in lengths.iter() {
w.write_bits(
code_length_codes[len as usize] as u64,
u64::from(code_length_codes[len as usize]),
code_length_lengths[len as usize],
)?;
}
Expand All @@ -284,7 +284,7 @@ fn write_huffman_tree<W: Write>(
Ok(())
}

fn length_to_symbol(len: u16) -> (u16, u8) {
const fn length_to_symbol(len: u16) -> (u16, u8) {
let len = len - 1;
let highest_bit = 15 - len.leading_zeros() as u16; // TODO: use ilog2 once MSRV >= 1.67
let second_highest_bit = (len >> (highest_bit - 1)) & 1;
Expand Down Expand Up @@ -331,11 +331,11 @@ fn write_run<W: Write>(
if run_length > 0 {
if run_length <= 4 {
let symbol = 256 + run_length - 1;
w.write_bits(codes1[symbol] as u64, lengths1[symbol])?;
w.write_bits(u64::from(codes1[symbol]), lengths1[symbol])?;
} else {
let (symbol, extra_bits) = length_to_symbol(run_length as u16);
w.write_bits(
codes1[256 + symbol as usize] as u64,
u64::from(codes1[256 + symbol as usize]),
lengths1[256 + symbol as usize],
)?;
w.write_bits(
Expand Down Expand Up @@ -392,7 +392,7 @@ fn encode_frame<W: Write>(
};

assert_eq!(
(width as u64 * height as u64).saturating_mul(bytes_per_pixel),
(u64::from(width) * u64::from(height)).saturating_mul(bytes_per_pixel),
data.len() as u64
);

Expand All @@ -401,10 +401,10 @@ fn encode_frame<W: Write>(
}

w.write_bits(0x2f, 8)?; // signature
w.write_bits(width as u64 - 1, 14)?;
w.write_bits(height as u64 - 1, 14)?;
w.write_bits(u64::from(width) - 1, 14)?;
w.write_bits(u64::from(height) - 1, 14)?;

w.write_bits(is_alpha as u64, 1)?; // alpha used
w.write_bits(u64::from(is_alpha), 1)?; // alpha used
w.write_bits(0x0, 3)?; // version

// subtract green transform
Expand Down Expand Up @@ -542,7 +542,7 @@ fn encode_frame<W: Write>(
ColorType::L8 => {
while let Some(pixel) = it.next() {
w.write_bits(
codes1[pixel[1] as usize] as u64,
u64::from(codes1[pixel[1] as usize]),
lengths1[pixel[1] as usize],
)?;
write_run(w, pixel, &mut it, &codes1, &lengths1)?;
Expand All @@ -553,8 +553,8 @@ fn encode_frame<W: Write>(
let len1 = lengths1[pixel[1] as usize];
let len3 = lengths3[pixel[3] as usize];

let code =
codes1[pixel[1] as usize] as u64 | (codes3[pixel[3] as usize] as u64) << len1;
let code = u64::from(codes1[pixel[1] as usize])
| u64::from(codes3[pixel[3] as usize]) << len1;

w.write_bits(code, len1 + len3)?;
write_run(w, pixel, &mut it, &codes1, &lengths1)?;
Expand All @@ -566,9 +566,9 @@ fn encode_frame<W: Write>(
let len0 = lengths0[pixel[0] as usize];
let len2 = lengths2[pixel[2] as usize];

let code = codes1[pixel[1] as usize] as u64
| (codes0[pixel[0] as usize] as u64) << len1
| (codes2[pixel[2] as usize] as u64) << (len1 + len0);
let code = u64::from(codes1[pixel[1] as usize])
| u64::from(codes0[pixel[0] as usize]) << len1
| u64::from(codes2[pixel[2] as usize]) << (len1 + len0);

w.write_bits(code, len1 + len0 + len2)?;
write_run(w, pixel, &mut it, &codes1, &lengths1)?;
Expand All @@ -581,10 +581,10 @@ fn encode_frame<W: Write>(
let len2 = lengths2[pixel[2] as usize];
let len3 = lengths3[pixel[3] as usize];

let code = codes1[pixel[1] as usize] as u64
| (codes0[pixel[0] as usize] as u64) << len1
| (codes2[pixel[2] as usize] as u64) << (len1 + len0)
| (codes3[pixel[3] as usize] as u64) << (len1 + len0 + len2);
let code = u64::from(codes1[pixel[1] as usize])
| u64::from(codes0[pixel[0] as usize]) << len1
| u64::from(codes2[pixel[2] as usize]) << (len1 + len0)
| u64::from(codes3[pixel[3] as usize]) << (len1 + len0 + len2);

w.write_bits(code, len1 + len0 + len2 + len3)?;
write_run(w, pixel, &mut it, &codes1, &lengths1)?;
Expand All @@ -596,7 +596,7 @@ fn encode_frame<W: Write>(
Ok(())
}

fn chunk_size(inner_bytes: usize) -> u32 {
const fn chunk_size(inner_bytes: usize) -> u32 {
if inner_bytes % 2 == 1 {
(inner_bytes + 1) as u32 + 8
} else {
Expand Down Expand Up @@ -809,7 +809,7 @@ mod tests {
.encode(&img[..256 * 256 * 3], 256, 256, crate::ColorType::Rgb8)
.unwrap();
let decoded = webp::Decoder::new(&output).decode().unwrap();
assert!(&img[..256 * 256 * 3] == &*decoded);
assert_eq!(img[..256 * 256 * 3], *decoded);

let mut output = Vec::new();
let mut encoder = WebPEncoder::new(&mut output);
Expand All @@ -818,7 +818,7 @@ mod tests {
.encode(&img, 256, 256, crate::ColorType::Rgba8)
.unwrap();
let decoded = webp::Decoder::new(&output).decode().unwrap();
assert!(&img == &*decoded);
assert_eq!(img, *decoded);

let mut output = Vec::new();
let mut encoder = WebPEncoder::new(&mut output);
Expand All @@ -828,7 +828,7 @@ mod tests {
.encode(&img, 256, 256, crate::ColorType::Rgba8)
.unwrap();
let decoded = webp::Decoder::new(&output).decode().unwrap();
assert!(&img == &*decoded);
assert_eq!(img, *decoded);

let mut output = Vec::new();
let mut encoder = WebPEncoder::new(&mut output);
Expand All @@ -838,18 +838,18 @@ mod tests {
.encode(&img, 256, 256, crate::ColorType::Rgba8)
.unwrap();
let decoded = webp::Decoder::new(&output).decode().unwrap();
assert!(&img == &*decoded);
assert_eq!(img, *decoded);

let mut output = Vec::new();
let mut encoder = WebPEncoder::new(&mut output);
encoder.set_params(params.clone());
encoder.set_params(params);
encoder.set_xmp_metadata(vec![0; 7]);
encoder.set_icc_profile(vec![0; 8]);
encoder.set_icc_profile(vec![0; 9]);
encoder
.encode(&img, 256, 256, crate::ColorType::Rgba8)
.unwrap();
let decoded = webp::Decoder::new(&output).decode().unwrap();
assert!(&img == &*decoded);
assert_eq!(img, *decoded);
}
}
2 changes: 1 addition & 1 deletion src/extended.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ pub(crate) fn read_alpha_chunk<R: BufRead>(
let mut decoder = LosslessDecoder::new(reader);

let mut data = vec![0; usize::from(width) * usize::from(height) * 4];
decoder.decode_frame(width as u32, height as u32, true, &mut data)?;
decoder.decode_frame(u32::from(width), u32::from(height), true, &mut data)?;

let mut green = vec![0; usize::from(width) * usize::from(height)];
for (rgba_val, green_val) in data.chunks_exact(4).zip(green.iter_mut()) {
Expand Down
Loading

0 comments on commit f798911

Please sign in to comment.