| ... | ... | @@ -53,12 +53,10 @@ pub(crate) fn pixels(encoded: &[u8]) -> Result<([u32; 2], Vec<u8>), Box<dyn Erro |
| 53 | 53 | .map_err(|error| format!("{error:?}"))?; |
| 54 | 54 | let mut rgba = image.pixels().to_vec(); |
| 55 | 55 | for pixel in rgba.chunks_exact_mut(4) { |
| 56 | | let alpha = u32::from(pixel[3]); |
| 57 | | for channel in &mut pixel[..3] { |
| 58 | | *channel = (u32::from(*channel) * 255 + alpha / 2) |
| 59 | | .checked_div(alpha) |
| 60 | | .unwrap_or(0) |
| 61 | | .min(255) as u8; |
| 56 | if pixel[3] != 255 { |
| 57 | let scale = 255.0 / f32::from(pixel[3].max(1)); |
| 58 | let linear = draw::srgb(pixel[0], pixel[1], pixel[2]).map(|v| v * scale); |
| 59 | pixel[..3].copy_from_slice(&draw::srgb_bytes(linear)); |
| 62 | 60 | } |
| 63 | 61 | } |
| 64 | 62 | return Ok((image.size(), rgba)); |
| ... | ... | @@ -487,6 +485,22 @@ mod tests { |
| 487 | 485 | assert_eq!(pixels(&encoded).unwrap(), ([2, 1], rgba.to_vec())); |
| 488 | 486 | } |
| 489 | 487 | |
| 488 | #[test] |
| 489 | fn clipboard_pixels_keep_translucent_tiff_colors() { |
| 490 | use image::ImageEncoder; |
| 491 | let rgba = [220, 120, 80, 128]; |
| 492 | let mut encoded = Vec::new(); |
| 493 | image::codecs::tiff::TiffEncoder::new(std::io::Cursor::new(&mut encoded)) |
| 494 | .write_image(&rgba, 1, 1, image::ExtendedColorType::Rgba8) |
| 495 | .unwrap(); |
| 496 | let (size, decoded) = pixels(&encoded).unwrap(); |
| 497 | assert_eq!(size, [1, 1]); |
| 498 | assert_eq!(decoded[3], rgba[3]); |
| 499 | for (actual, expected) in decoded[..3].iter().zip(&rgba[..3]) { |
| 500 | assert!(actual.abs_diff(*expected) <= 2, "{decoded:?}"); |
| 501 | } |
| 502 | } |
| 503 | |
| 490 | 504 | fn png_at(pixels_per_metre: Option<u32>) -> Vec<u8> { |
| 491 | 505 | let mut bytes = Vec::new(); |
| 492 | 506 | let mut encoder = png::Encoder::new(&mut bytes, 200, 100); |