Skip to content

Commit 681c84d

Browse files
authored
Fix alpha handling for non-extended lossless (#26)
1 parent a737d91 commit 681c84d

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

src/decoder.rs

+10-6
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ pub struct WebPDecoder<R> {
221221

222222
kind: ImageKind,
223223
is_lossy: bool,
224+
has_alpha: bool,
224225

225226
chunks: HashMap<WebPRiffChunk, Range<u64>>,
226227
}
@@ -239,6 +240,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
239240
animation: Default::default(),
240241
memory_limit: usize::MAX,
241242
is_lossy: false,
243+
has_alpha: false,
242244
};
243245
decoder.read_data()?;
244246
Ok(decoder)
@@ -301,6 +303,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
301303
self.chunks
302304
.insert(WebPRiffChunk::VP8L, start..start + chunk_size as u64);
303305
self.kind = ImageKind::Lossless;
306+
self.has_alpha = (header >> 28) & 1 != 0;
304307
}
305308
WebPRiffChunk::VP8X => {
306309
let mut info = extended::read_extended_header(&mut self.r)?;
@@ -417,6 +420,7 @@ impl<R: Read + Seek> WebPDecoder<R> {
417420
}
418421
}
419422

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

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

537-
frame.fill_rgba(buf);
537+
if self.has_alpha {
538+
frame.fill_rgba(buf);
539+
} else {
540+
frame.fill_rgb(buf);
541+
}
538542
} else {
539543
let range = self
540544
.chunks

src/lossless.rs

+8
Original file line numberDiff line numberDiff line change
@@ -698,6 +698,14 @@ impl LosslessFrame {
698698
}
699699
}
700700

701+
pub(crate) fn fill_rgb(&self, buf: &mut [u8]) {
702+
for (&argb_val, chunk) in self.buf.iter().zip(buf.chunks_exact_mut(3)) {
703+
chunk[0] = ((argb_val >> 16) & 0xff).try_into().unwrap();
704+
chunk[1] = ((argb_val >> 8) & 0xff).try_into().unwrap();
705+
chunk[2] = (argb_val & 0xff).try_into().unwrap();
706+
}
707+
}
708+
701709
/// Fills a buffer with just the green values from the lossless decoding
702710
/// Used in extended alpha decoding
703711
pub(crate) fn fill_green(&self, buf: &mut [u8]) {

0 commit comments

Comments
 (0)