render: Random cleanups

Avoid some `Vec::with_capacity` and de-duplicate code.
This commit is contained in:
relrelb 2022-09-10 11:17:30 +03:00 committed by relrelb
parent 9d4ab37ef6
commit c31e9e2b11
1 changed files with 35 additions and 74 deletions

View File

@ -113,15 +113,7 @@ fn decode_jpeg(jpeg_data: &[u8], alpha_data: Option<&[u8]>) -> Result<Bitmap, Er
[r as u8, g as u8, b as u8] [r as u8, g as u8, b as u8]
}) })
.collect(), .collect(),
jpeg_decoder::PixelFormat::L8 => { jpeg_decoder::PixelFormat::L8 => decoded_data.iter().flat_map(|&c| [c, c, c]).collect(),
let mut rgb = Vec::with_capacity(decoded_data.len() * 3);
for elem in decoded_data {
rgb.push(elem);
rgb.push(elem);
rgb.push(elem);
}
rgb
}
jpeg_decoder::PixelFormat::L16 => { jpeg_decoder::PixelFormat::L16 => {
log::warn!("Unimplemented L16 JPEG pixel format"); log::warn!("Unimplemented L16 JPEG pixel format");
decoded_data decoded_data
@ -133,22 +125,21 @@ fn decode_jpeg(jpeg_data: &[u8], alpha_data: Option<&[u8]>) -> Result<Bitmap, Er
let alpha_data = decompress_zlib(alpha_data)?; let alpha_data = decompress_zlib(alpha_data)?;
if alpha_data.len() == decoded_data.len() / 3 { if alpha_data.len() == decoded_data.len() / 3 {
let mut rgba = Vec::with_capacity((decoded_data.len() / 3) * 4); let rgba = decoded_data
let mut i = 0; .chunks_exact(3)
let mut a = 0; .zip(alpha_data)
while i < decoded_data.len() { .flat_map(|(rgb, a)| {
// The JPEG data should be premultiplied alpha, but it isn't in some incorrect SWFs (see #6893). // The JPEG data should be premultiplied alpha, but it isn't in some incorrect
// This means 0% alpha pixels may have color and incorrectly show as visible. // SWFs (see #6893).
// Flash Player clamps color to the alpha value to fix this case. // This means 0% alpha pixels may have color and incorrectly show as visible.
// Only applies to DefineBitsJPEG3; DefineBitsLossless does not seem to clamp. // Flash Player clamps color to the alpha value to fix this case.
let alpha = alpha_data[a]; // Only applies to DefineBitsJPEG3; DefineBitsLossless does not seem to clamp.
rgba.push(decoded_data[i].min(alpha)); let r = rgb[0].min(a);
rgba.push(decoded_data[i + 1].min(alpha)); let g = rgb[1].min(a);
rgba.push(decoded_data[i + 2].min(alpha)); let b = rgb[2].min(a);
rgba.push(alpha); [r, g, b, a]
i += 3; })
a += 1; .collect();
}
return Ok(Bitmap::new( return Ok(Bitmap::new(
metadata.width.into(), metadata.width.into(),
metadata.height.into(), metadata.height.into(),
@ -188,39 +179,28 @@ pub fn decode_define_bits_lossless(swf_tag: &swf::DefineBitsLossless) -> Result<
for _ in 0..swf_tag.width { for _ in 0..swf_tag.width {
let compressed = u16::from_be_bytes([decoded_data[i], decoded_data[i + 1]]); let compressed = u16::from_be_bytes([decoded_data[i], decoded_data[i + 1]]);
let rgb5_component = |shift: u16| { let rgb5_component = |shift: u16| {
let component = compressed >> shift & 0x1F; let component = (compressed >> shift) & 0x1F;
((component * 255 + 15) / 31) as u8 ((component * 255 + 15) / 31) as u8
}; };
out_data.push(rgb5_component(10)); out_data.extend([
out_data.push(rgb5_component(5)); rgb5_component(10),
out_data.push(rgb5_component(0)); rgb5_component(5),
out_data.push(0xff); rgb5_component(0),
0xff,
]);
i += 2; i += 2;
} }
i += (padded_width - swf_tag.width) as usize * 2; i += (padded_width - swf_tag.width) as usize * 2;
} }
out_data out_data
} }
(1, swf::BitmapFormat::Rgb32) => { (1 | 2, swf::BitmapFormat::Rgb32) => {
let mut i = 0; let has_alpha = swf_tag.version == 2;
while i < decoded_data.len() { for rgba in decoded_data.chunks_exact_mut(4) {
decoded_data[i] = decoded_data[i + 1]; rgba.rotate_left(1);
decoded_data[i + 1] = decoded_data[i + 2]; if !has_alpha {
decoded_data[i + 2] = decoded_data[i + 3]; rgba[3] = 0xff;
decoded_data[i + 3] = 0xff; }
i += 4;
}
decoded_data
}
(2, swf::BitmapFormat::Rgb32) => {
let mut i = 0;
while i < decoded_data.len() {
let alpha = decoded_data[i];
decoded_data[i] = decoded_data[i + 1];
decoded_data[i + 1] = decoded_data[i + 2];
decoded_data[i + 2] = decoded_data[i + 3];
decoded_data[i + 3] = alpha;
i += 4;
} }
decoded_data decoded_data
} }
@ -243,18 +223,8 @@ pub fn decode_define_bits_lossless(swf_tag: &swf::DefineBitsLossless) -> Result<
for _ in 0..swf_tag.height { for _ in 0..swf_tag.height {
for _ in 0..swf_tag.width { for _ in 0..swf_tag.width {
let entry = decoded_data[i] as usize; let entry = decoded_data[i] as usize;
if entry < palette.len() { let color = palette.get(entry).unwrap_or(&Color::BLACK);
let color = &palette[entry]; out_data.extend([color.r, color.g, color.b, color.a]);
out_data.push(color.r);
out_data.push(color.g);
out_data.push(color.b);
out_data.push(color.a);
} else {
out_data.push(0);
out_data.push(0);
out_data.push(0);
out_data.push(255);
}
i += 1; i += 1;
} }
i += (padded_width - swf_tag.width) as usize; i += (padded_width - swf_tag.width) as usize;
@ -280,18 +250,9 @@ pub fn decode_define_bits_lossless(swf_tag: &swf::DefineBitsLossless) -> Result<
for _ in 0..swf_tag.height { for _ in 0..swf_tag.height {
for _ in 0..swf_tag.width { for _ in 0..swf_tag.width {
let entry = decoded_data[i] as usize; let entry = decoded_data[i] as usize;
if entry < palette.len() { const TRANSPARENT: Color = Color::from_rgb(0, 0);
let color = &palette[entry]; let color = palette.get(entry).unwrap_or(&TRANSPARENT);
out_data.push(color.r); out_data.extend([color.r, color.g, color.b, color.a]);
out_data.push(color.g);
out_data.push(color.b);
out_data.push(color.a);
} else {
out_data.push(0);
out_data.push(0);
out_data.push(0);
out_data.push(0);
}
i += 1; i += 1;
} }
i += (padded_width - swf_tag.width) as usize; i += (padded_width - swf_tag.width) as usize;