|
| 1 | +use crate::{Image, Margin, Result}; |
| 2 | +use image::flat::View; |
| 3 | +use image::{Bgra, GenericImageView}; |
| 4 | + |
| 5 | +/// |
| 6 | +/// this helps to identify outer transparent regions |
| 7 | +/// since some backends provides transparency either from a compositor effect like drop shadow on ubuntu / GNOME |
| 8 | +/// or some strange right side strip on MacOS |
| 9 | +pub fn identify_transparency(image: Image) -> Result<Option<Margin>> { |
| 10 | + let image: View<_, Bgra<u8>> = image.as_view()?; |
| 11 | + let (width, height) = image.dimensions(); |
| 12 | + let half_width = width / 2; |
| 13 | + let half_height = height / 2; |
| 14 | + // > 3/4 transparency is good enough to declare the end of transparent regions |
| 15 | + let transparency_end: u8 = 0xff - (0xff / 4); |
| 16 | + |
| 17 | + let mut margin = Margin::zero(); |
| 18 | + // identify top margin |
| 19 | + for y in 0..half_height { |
| 20 | + let Bgra([_, _, _, a]) = image.get_pixel(half_width, y); |
| 21 | + if a > transparency_end { |
| 22 | + // the end of the transparent area |
| 23 | + margin.top = y as u16; |
| 24 | + dbg!(margin.top); |
| 25 | + break; |
| 26 | + } |
| 27 | + } |
| 28 | + // identify bottom margin |
| 29 | + for y in (half_height..height).rev() { |
| 30 | + let Bgra([_, _, _, a]) = image.get_pixel(half_width, y); |
| 31 | + if a > transparency_end { |
| 32 | + // the end of the transparent area |
| 33 | + margin.bottom = (height - y - 1) as u16; |
| 34 | + dbg!(margin.bottom); |
| 35 | + break; |
| 36 | + } |
| 37 | + } |
| 38 | + // identify left margin |
| 39 | + for x in 0..half_width { |
| 40 | + let Bgra([_, _, _, a]) = image.get_pixel(x, half_height); |
| 41 | + if a > transparency_end { |
| 42 | + // the end of the transparent area |
| 43 | + margin.left = x as u16; |
| 44 | + dbg!(margin.left); |
| 45 | + break; |
| 46 | + } |
| 47 | + } |
| 48 | + // identify right margin |
| 49 | + for x in (half_width..width).rev() { |
| 50 | + let Bgra([_, _, _, a]) = image.get_pixel(x, half_height); |
| 51 | + if a > transparency_end { |
| 52 | + // the end of the transparent area |
| 53 | + margin.right = (width - x - 1) as u16; |
| 54 | + dbg!(margin.right); |
| 55 | + break; |
| 56 | + } |
| 57 | + } |
| 58 | + |
| 59 | + Ok(Some(margin)) |
| 60 | +} |
| 61 | + |
| 62 | +#[cfg(test)] |
| 63 | +mod test { |
| 64 | + use super::*; |
| 65 | + |
| 66 | + #[test] |
| 67 | + fn should_identify_macos_right_side_issue() -> Result<()> { |
| 68 | + // given an screen capture with transparency on the right side |
| 69 | + let image_org = image::open("tests/frames/frame-macos-right-side-issue.tga")?; |
| 70 | + let image = image_org.into_bgra8(); |
| 71 | + let (width, height) = image.dimensions(); |
| 72 | + let Bgra([blue, green, red, alpha]) = image.get_pixel(width - 1, height / 2); |
| 73 | + assert_eq!(alpha, &0, "the test image was not transparent"); |
| 74 | + assert_eq!(red, &0, "the test image is not as expected"); |
| 75 | + assert_eq!(green, &0, "the test image is not as expected"); |
| 76 | + assert_eq!(blue, &0, "the test image is not as expected"); |
| 77 | + |
| 78 | + // when |
| 79 | + let image_raw = image.into_flat_samples(); |
| 80 | + let margin = identify_transparency(image_raw)?; |
| 81 | + |
| 82 | + // then |
| 83 | + assert_eq!(margin, Some(Margin::new(0, 14, 0, 0))); |
| 84 | + |
| 85 | + Ok(()) |
| 86 | + } |
| 87 | +} |
0 commit comments