Skip to content

Commit

Permalink
Fix alpha handling for non-extended lossless (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
fintelia authored Dec 24, 2023
1 parent a737d91 commit 681c84d
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 6 deletions.
16 changes: 10 additions & 6 deletions src/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,7 @@ pub struct WebPDecoder<R> {

kind: ImageKind,
is_lossy: bool,
has_alpha: bool,

chunks: HashMap<WebPRiffChunk, Range<u64>>,
}
Expand All @@ -239,6 +240,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
animation: Default::default(),
memory_limit: usize::MAX,
is_lossy: false,
has_alpha: false,
};
decoder.read_data()?;
Ok(decoder)
Expand Down Expand Up @@ -301,6 +303,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
self.chunks
.insert(WebPRiffChunk::VP8L, start..start + chunk_size as u64);
self.kind = ImageKind::Lossless;
self.has_alpha = (header >> 28) & 1 != 0;
}
WebPRiffChunk::VP8X => {
let mut info = extended::read_extended_header(&mut self.r)?;
Expand Down Expand Up @@ -417,6 +420,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
}
}

self.has_alpha = info.alpha;
self.kind = ImageKind::Extended(info);
}
_ => return Err(DecodingError::ChunkHeaderInvalid(chunk.to_fourcc())),
Expand All @@ -443,11 +447,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
/// Returns whether the image has an alpha channel. If so, the pixel format is Rgba8 and
/// otherwise Rgb8.
pub fn has_alpha(&self) -> bool {
match &self.kind {
ImageKind::Lossy => false,
ImageKind::Lossless => true,
ImageKind::Extended(extended) => extended.alpha,
}
self.has_alpha
}

/// Returns whether the image is lossy. For animated images, this is true if any frame is lossy.
Expand Down Expand Up @@ -534,7 +534,11 @@ impl<R: Read + Seek> WebPDecoder<R> {
return Err(DecodingError::InconsistentImageSizes);
}

frame.fill_rgba(buf);
if self.has_alpha {
frame.fill_rgba(buf);
} else {
frame.fill_rgb(buf);
}
} else {
let range = self
.chunks
Expand Down
8 changes: 8 additions & 0 deletions src/lossless.rs
Original file line number Diff line number Diff line change
Expand Up @@ -698,6 +698,14 @@ impl LosslessFrame {
}
}

pub(crate) fn fill_rgb(&self, buf: &mut [u8]) {
for (&argb_val, chunk) in self.buf.iter().zip(buf.chunks_exact_mut(3)) {
chunk[0] = ((argb_val >> 16) & 0xff).try_into().unwrap();
chunk[1] = ((argb_val >> 8) & 0xff).try_into().unwrap();
chunk[2] = (argb_val & 0xff).try_into().unwrap();
}
}

/// Fills a buffer with just the green values from the lossless decoding
/// Used in extended alpha decoding
pub(crate) fn fill_green(&self, buf: &mut [u8]) {
Expand Down

0 comments on commit 681c84d

Please sign in to comment.