alpha image, transforms
This commit is contained in:
parent
b647d95713
commit
2f7b20fde7
69
src/main.rs
69
src/main.rs
|
@ -617,22 +617,29 @@ fn main() {
|
||||||
|
|
||||||
image_rect = rect_union(image_rect, rect);
|
image_rect = rect_union(image_rect, rect);
|
||||||
|
|
||||||
(info, offset, rect, output.frame.inverted_y)
|
(
|
||||||
|
info,
|
||||||
|
offset,
|
||||||
|
rect,
|
||||||
|
output.frame.inverted_y,
|
||||||
|
output.transform.unwrap_or(wl_output::Transform::Normal),
|
||||||
|
)
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let mut image = image::RgbImage::new(image_rect.width, image_rect.height);
|
let mut image = image::RgbaImage::new(image_rect.width, image_rect.height);
|
||||||
|
|
||||||
let now = std::time::Instant::now();
|
let now = std::time::Instant::now();
|
||||||
for (info, offset, rect, inverted_y) in buffers {
|
for (info, offset, rect, inverted_y, transform) in buffers {
|
||||||
let size = info.stride * info.height;
|
let size = info.stride * info.height;
|
||||||
let view = BufferView {
|
let view = BufferView {
|
||||||
info,
|
info,
|
||||||
inverted_y,
|
inverted_y,
|
||||||
|
transform,
|
||||||
bytes: &buffer[offset..][..size as usize],
|
bytes: &buffer[offset..][..size as usize],
|
||||||
};
|
};
|
||||||
|
|
||||||
if rect.width != info.width || rect.height != info.height {
|
if rect.width != view.width() || rect.height != view.height() {
|
||||||
let sampled = SampledView {
|
let sampled = SampledView {
|
||||||
view: &view,
|
view: &view,
|
||||||
dimensions: (rect.width, rect.height),
|
dimensions: (rect.width, rect.height),
|
||||||
|
@ -680,17 +687,52 @@ impl<'a, V: GenericImageView> GenericImageView for SampledView<'a, V> {
|
||||||
struct BufferView<'a> {
|
struct BufferView<'a> {
|
||||||
info: BufferInfo,
|
info: BufferInfo,
|
||||||
inverted_y: bool,
|
inverted_y: bool,
|
||||||
|
transform: wl_output::Transform,
|
||||||
bytes: &'a [u8],
|
bytes: &'a [u8],
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BufferView<'_> {
|
impl BufferView<'_> {
|
||||||
fn pixel_offset(&self, x: u32, y: u32) -> usize {
|
fn transformed_pixel_position(&self, x: u32, y: u32) -> (u32, u32) {
|
||||||
|
let (width, height) = self.transformed_dimensions();
|
||||||
|
let width = width - 1;
|
||||||
|
let height = height - 1;
|
||||||
|
|
||||||
|
let (x, y) = match self.transform {
|
||||||
|
Transform::Normal => (x, y),
|
||||||
|
Transform::_90 => (y, x),
|
||||||
|
Transform::_180 => (width - x, height - y),
|
||||||
|
Transform::_270 => (height - y, x),
|
||||||
|
Transform::Flipped => (width - x, y),
|
||||||
|
Transform::Flipped90 => (y, width - x),
|
||||||
|
Transform::Flipped180 => (x, height - y),
|
||||||
|
Transform::Flipped270 => (height - y, width - x),
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
|
||||||
|
// apply buffer-local y flip
|
||||||
let y = if self.inverted_y {
|
let y = if self.inverted_y {
|
||||||
self.info.height - y
|
self.info.height - y
|
||||||
} else {
|
} else {
|
||||||
y
|
y
|
||||||
};
|
};
|
||||||
|
|
||||||
|
(x, y)
|
||||||
|
}
|
||||||
|
fn transformed_dimensions(&self) -> (u32, u32) {
|
||||||
|
match self.transform {
|
||||||
|
Transform::Flipped180 | Transform::_180 | Transform::Flipped | Transform::Normal => {
|
||||||
|
(self.info.width, self.info.height)
|
||||||
|
}
|
||||||
|
Transform::_90 | Transform::_270 | Transform::Flipped90 | Transform::Flipped270 => {
|
||||||
|
(self.info.height, self.info.width)
|
||||||
|
}
|
||||||
|
_ => unreachable!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn pixel_offset(&self, x: u32, y: u32) -> usize {
|
||||||
|
// apply transform
|
||||||
|
let (x, y) = self.transformed_pixel_position(x, y);
|
||||||
|
|
||||||
self.info.stride as usize * y as usize + (x as usize * self.pixel_stride() as usize)
|
self.info.stride as usize * y as usize + (x as usize * self.pixel_stride() as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -918,22 +960,27 @@ impl BufferView<'_> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GenericImageView for BufferView<'_> {
|
impl GenericImageView for BufferView<'_> {
|
||||||
type Pixel = image::Rgb<u8>;
|
type Pixel = image::Rgba<u8>;
|
||||||
|
|
||||||
fn dimensions(&self) -> (u32, u32) {
|
fn dimensions(&self) -> (u32, u32) {
|
||||||
(self.info.width, self.info.height)
|
self.transformed_dimensions()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
|
fn get_pixel(&self, x: u32, y: u32) -> Self::Pixel {
|
||||||
match self.info.format {
|
match self.info.format {
|
||||||
wl_shm::Format::Xbgr8888 => Self::Pixel::from(
|
wl_shm::Format::Xbgr8888 => {
|
||||||
<[u8; 3] as TryFrom<&[u8]>>::try_from(&self.bytes[self.pixel_offset(x, y)..][..3])
|
let [r, g, b] = <[u8; 3] as TryFrom<&[u8]>>::try_from(
|
||||||
.unwrap(),
|
&self.bytes[self.pixel_offset(x, y)..][..3],
|
||||||
),
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self::Pixel::from([r, g, b, 255])
|
||||||
|
}
|
||||||
_ => Self::Pixel::from([
|
_ => Self::Pixel::from([
|
||||||
self.sample_r(x, y),
|
self.sample_r(x, y),
|
||||||
self.sample_g(x, y),
|
self.sample_g(x, y),
|
||||||
self.sample_b(x, y),
|
self.sample_b(x, y),
|
||||||
|
255,
|
||||||
]),
|
]),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue