Skip to content

Commit 47d619d

Browse files
committed
- Implement first draft of async streamed frame capturing for linux
1 parent f1ba095 commit 47d619d

File tree

4 files changed

+50
-37
lines changed

4 files changed

+50
-37
lines changed

src/common/frame.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,12 @@ impl AsRef<Instant> for Frame {
4747
&self.timecode
4848
}
4949
}
50+
51+
impl From<FlatSamples<Vec<u8>>> for Frame {
52+
fn from(image: FlatSamples<Vec<u8>>) -> Self {
53+
Self {
54+
image,
55+
timecode: Instant::now(),
56+
}
57+
}
58+
}

src/common/identify_transparency.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ pub fn identify_transparency(image: impl AsRef<Image>) -> Result<Option<Margin>>
5858
#[cfg(test)]
5959
mod test {
6060
use super::*;
61+
use crate::common::Frame;
6162

6263
#[test]
6364
fn should_identify_macos_right_side_issue() -> Result<()> {
@@ -72,8 +73,8 @@ mod test {
7273
assert_eq!(blue, &0, "the test image is not as expected");
7374

7475
// when
75-
let image_raw = image.into_flat_samples();
76-
let margin = identify_transparency(image_raw)?;
76+
let image_raw: Frame = image.into_flat_samples().into();
77+
let margin = identify_transparency(&image_raw)?;
7778

7879
// then
7980
assert_eq!(margin, Some(Margin::new(0, 14, 0, 0)));

src/common/image.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub fn convert_bgra_to_rgba(buffer: &mut [u8]) {
4545

4646
#[cfg(test)]
4747
mod tests {
48+
use crate::common::Frame;
4849
use image::open;
4950

5051
use super::*;
@@ -56,9 +57,10 @@ mod tests {
5657
let image = image_org.into_rgba8();
5758
let image_raw = image.into_flat_samples();
5859
let (width, height) = (image_raw.layout.width, image_raw.layout.height);
60+
let frame: Frame = image_raw.into();
5961

6062
// when
61-
let cropped = crop(image_raw, &Margin::new(1, 1, 1, 1))?;
63+
let cropped = crop(&frame, &Margin::new(1, 1, 1, 1))?;
6264

6365
// then
6466
assert_eq!(cropped.layout.width, width - 2);

src/linux/x11_api.rs

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
use crate::common::identify_transparency::identify_transparency;
22
use crate::common::image::convert_bgra_to_rgba;
3-
use crate::{ImageOnHeap, Margin, PlatformApi, Result, WindowId, WindowList};
3+
use crate::{Margin, PlatformApi, Result, WindowId, WindowList};
44

5+
use crate::common::Frame;
56
use anyhow::Context;
6-
use image::flat::SampleLayout;
7-
use image::{ColorType, FlatSamples};
87
use log::debug;
98
use x11rb::connection::Connection;
109
use x11rb::protocol::xproto::*;
@@ -117,11 +116,11 @@ impl X11Api {
117116
self.get_all_sub_windows(&(screen.root as WindowId))
118117
}
119118

120-
pub fn get_window_geometry(&self, window: &WindowId) -> Result<(i16, i16, u16, u16)> {
119+
pub fn get_window_geometry(&self, window: &WindowId) -> Result<(i32, i32, u32, u32)> {
121120
let conn = &self.conn;
122121
let window = *window as Window;
123122
let geom = conn.get_geometry(window)?.reply()?;
124-
Ok((geom.x, geom.y, geom.width, geom.height))
123+
Ok((geom.x as _, geom.y as _, geom.width as _, geom.height as _))
125124
}
126125
}
127126

@@ -131,7 +130,7 @@ impl PlatformApi for X11Api {
131130
/// to cut them away in further screenshots
132131
fn calibrate(&mut self, window_id: WindowId) -> Result<()> {
133132
let image = self.capture_window_screenshot(window_id)?;
134-
self.margin = identify_transparency(*image)?;
133+
self.margin = identify_transparency(&image)?;
135134

136135
Ok(())
137136
}
@@ -153,15 +152,15 @@ impl PlatformApi for X11Api {
153152
Ok(wins)
154153
}
155154

156-
fn capture_window_screenshot(&self, window_id: WindowId) -> Result<ImageOnHeap> {
155+
fn capture_window_screenshot(&self, window_id: WindowId) -> Result<Frame> {
157156
let (_, _, mut width, mut height) = self.get_window_geometry(&window_id)?;
158-
let (mut x, mut y) = (0_i16, 0_i16);
157+
let (mut x, mut y) = (0_i32, 0_i32);
159158
if let Some(margin) = self.margin.as_ref() {
160159
if !margin.is_zero() {
161-
width -= margin.left + margin.right;
162-
height -= margin.top + margin.bottom;
163-
x = margin.left as i16;
164-
y = margin.top as i16;
160+
width -= (margin.left + margin.right) as u32;
161+
height -= (margin.top + margin.bottom) as u32;
162+
x = margin.left as _;
163+
y = margin.top as _;
165164
}
166165
}
167166
let image = self
@@ -170,10 +169,10 @@ impl PlatformApi for X11Api {
170169
.get_image(
171170
ImageFormat::Z_PIXMAP,
172171
window_id as Drawable,
173-
x,
174-
y,
175-
width,
176-
height,
172+
x as _,
173+
y as _,
174+
width as _,
175+
height as _,
177176
!0,
178177
)?
179178
.reply()
@@ -182,24 +181,17 @@ impl PlatformApi for X11Api {
182181
window_id
183182
))?;
184183

185-
let mut raw_data = image.data;
186-
convert_bgra_to_rgba(&mut raw_data);
187-
188-
let color = ColorType::Rgba8;
189-
let channels = 4;
190-
let mut buffer = FlatSamples {
191-
samples: raw_data,
192-
layout: SampleLayout::row_major_packed(channels, width as u32, height as u32),
193-
color_hint: Some(color),
194-
};
184+
let mut samples = image.data;
185+
convert_bgra_to_rgba(&mut samples);
195186

196187
if image.depth == 24 {
188+
let stride = 3;
197189
// NOTE: in this case the alpha channel is 0, but should be set to 0xff
198190
// the index into the alpha channel
199-
let mut i = 3;
200-
let len = buffer.samples.len();
191+
let mut i = stride;
192+
let len = samples.len();
201193
while i < len {
202-
let alpha = buffer.samples.get_mut(i).unwrap();
194+
let alpha = samples.get_mut(i).unwrap();
203195
if alpha == &0 {
204196
*alpha = 0xff;
205197
} else {
@@ -208,27 +200,36 @@ impl PlatformApi for X11Api {
208200
}
209201

210202
// going one pixel further, still pointing to the alpha channel
211-
i += buffer.layout.width_stride;
203+
i += stride;
212204
}
213205
}
214206
if self.margin.is_some() {
207+
let stride = 3;
215208
// once first image is captured, we make sure that transparency is removed
216209
// even in cases where `margin.is_zero()`
217210
let mut i = 3;
218-
let len = buffer.samples.len();
211+
let len = samples.len();
219212
while i < len {
220-
let alpha = buffer.samples.get_mut(i).unwrap();
213+
let alpha = samples.get_mut(i).unwrap();
221214
if alpha != &0xff {
222215
*alpha = 0xff;
223216
}
224217

225218
// going one pixel further, still pointing to the alpha channel
226-
i += buffer.layout.width_stride;
219+
i += stride;
227220
}
228221
}
229222
debug!("Image dimensions: {}x{}", width, height);
230223

231-
Ok(ImageOnHeap::new(buffer))
224+
let channels = 4;
225+
Ok(Frame::from_bgra(samples, channels, width, height))
226+
// let color = ColorType::Rgba8;
227+
// let mut buffer = FlatSamples {
228+
// samples,
229+
// layout: SampleLayout::row_major_packed(channels, width as u32, height as u32),
230+
// color_hint: Some(color),
231+
// };
232+
// Ok(ImageOnHeap::new(buffer))
232233
}
233234

234235
fn get_active_window(&self) -> Result<WindowId> {

0 commit comments

Comments
 (0)