works with imlib!
This commit is contained in:
parent
6cb1dd1b6e
commit
24d019fdcb
7 changed files with 51 additions and 93 deletions
|
@ -12,11 +12,6 @@ pub struct Image {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Image {
|
impl Image {
|
||||||
/// Set the display for the imlib context.
|
|
||||||
pub fn context_set_display(display: *mut x11::xlib::Display) {
|
|
||||||
unsafe { im::imlib_context_set_display(display as *mut im::_XDisplay) };
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Creates an Image from a pixmap.
|
/// Creates an Image from a pixmap.
|
||||||
pub fn create_from_drawable(
|
pub fn create_from_drawable(
|
||||||
drawable: impl AsRef<im::Drawable>,
|
drawable: impl AsRef<im::Drawable>,
|
||||||
|
@ -29,7 +24,14 @@ impl Image {
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
unsafe { im::imlib_context_set_drawable(*drawable.as_ref()) };
|
unsafe { im::imlib_context_set_drawable(*drawable.as_ref()) };
|
||||||
let image = unsafe {
|
let image = unsafe {
|
||||||
im::imlib_create_image_from_drawable(pixmap, x, y, width, height, if grab_x{ 1 } else { 0 }) as im::Imlib_Image
|
im::imlib_create_image_from_drawable(
|
||||||
|
pixmap,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
if grab_x { 1 } else { 0 },
|
||||||
|
) as im::Imlib_Image
|
||||||
};
|
};
|
||||||
Ok(Image { inner: image })
|
Ok(Image { inner: image })
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,20 @@ extern crate x11;
|
||||||
|
|
||||||
mod errors;
|
mod errors;
|
||||||
mod image;
|
mod image;
|
||||||
|
mod visual;
|
||||||
|
|
||||||
pub use errors::Error;
|
pub use errors::Error;
|
||||||
pub use image::Image;
|
pub use image::Image;
|
||||||
pub use imlib2_sys::{Drawable, Pixmap};
|
pub use imlib2_sys::{Drawable, Pixmap};
|
||||||
|
pub use visual::Visual;
|
||||||
|
|
||||||
|
/// Set the display for the imlib context.
|
||||||
|
pub fn context_set_display(display: *mut x11::xlib::Display) {
|
||||||
|
unsafe { imlib2_sys::imlib_context_set_display(display as *mut imlib2_sys::_XDisplay) };
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set the visual for the imlib context.
|
||||||
|
pub fn context_set_visual(visual: Visual) {
|
||||||
|
unsafe { imlib2_sys::imlib_context_set_visual(visual.inner) };
|
||||||
|
}
|
||||||
|
|
||||||
|
|
15
imlib2/visual.rs
Normal file
15
imlib2/visual.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use imlib2_sys as im;
|
||||||
|
use x11;
|
||||||
|
|
||||||
|
/// Visual
|
||||||
|
pub struct Visual {
|
||||||
|
pub(crate) inner: *mut im::Visual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Visual {
|
||||||
|
/// get the default visual for a display
|
||||||
|
pub fn default(display: *mut x11::xlib::_XDisplay, screen: i32) -> Self {
|
||||||
|
let inner = unsafe { im::XDefaultVisual(display as *mut im::_XDisplay, screen) };
|
||||||
|
Visual { inner }
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,12 +23,7 @@ pub fn capture(opt: &Options) -> Result<(), ScreenshotError> {
|
||||||
let height = attr.get_height();
|
let height = attr.get_height();
|
||||||
let root = gui.display.get_default_root_window()?;
|
let root = gui.display.get_default_root_window()?;
|
||||||
let (x, y, _) = gui.display.translate_coordinates(win, 0, 0, root)?;
|
let (x, y, _) = gui.display.translate_coordinates(win, 0, 0, root)?;
|
||||||
Some(Rectangle {
|
Some(Rectangle::new(x as u32, y as u32, width, height))
|
||||||
x: x as u32,
|
|
||||||
y: y as u32,
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
use imlib2::{self, Image as Image2, Visual};
|
||||||
use xlib::{Display, Image, Window};
|
use xlib::{Display, Image, Window};
|
||||||
use imlib2::{Image as Image2,};
|
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
use errors::ScreenshotError;
|
||||||
use Rectangle;
|
use Rectangle;
|
||||||
|
@ -21,7 +21,8 @@ impl GUI {
|
||||||
let height = attr.get_height() as i32;
|
let height = attr.get_height() as i32;
|
||||||
let root = self.display.get_default_root_window()?;
|
let root = self.display.get_default_root_window()?;
|
||||||
let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
let (x, y, _) = self.display.translate_coordinates(window, 0, 0, root)?;
|
||||||
Image2::context_set_display(self.display.as_raw());
|
imlib2::context_set_display(self.display.as_raw());
|
||||||
|
imlib2::context_set_visual(Visual::default(self.display.as_raw(), 0));
|
||||||
Image2::create_from_drawable(window, 0, x, y, width, height, true).map_err(|err| err.into())
|
Image2::create_from_drawable(window, 0, x, y, width, height, true).map_err(|err| err.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
77
src/image.rs
77
src/image.rs
|
@ -1,77 +0,0 @@
|
||||||
use std::fs::File;
|
|
||||||
use std::io::BufWriter;
|
|
||||||
use std::path::Path;
|
|
||||||
|
|
||||||
use png::{self, Encoder, HasParameters};
|
|
||||||
use xlib::{Image, ImageByteOrder};
|
|
||||||
|
|
||||||
use errors::ScreenshotError;
|
|
||||||
use Rectangle;
|
|
||||||
|
|
||||||
pub trait ImageExt {
|
|
||||||
fn to_data_buf(&self, rect: Rectangle) -> Result<Vec<u8>, ScreenshotError>;
|
|
||||||
fn write_png(
|
|
||||||
&self,
|
|
||||||
out: impl AsRef<Path>,
|
|
||||||
rect: Option<Rectangle>,
|
|
||||||
) -> Result<(), ScreenshotError>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ImageExt for Image {
|
|
||||||
/// Converts the image buffer into RGB(A).
|
|
||||||
fn to_data_buf(&self, rect: Rectangle) -> Result<Vec<u8>, ScreenshotError> {
|
|
||||||
let (full_width, _) = (self.get_width() as usize, self.get_height() as usize);
|
|
||||||
let bytes_per_row = 4 * rect.width as usize;
|
|
||||||
let size = bytes_per_row * rect.height as usize;
|
|
||||||
let mut buf = vec![1; size];
|
|
||||||
let sbuf = self.buffer(); // source buffer
|
|
||||||
let mut rx = rect.y as usize;
|
|
||||||
if let ImageByteOrder::LSBFirst = self.get_byte_order()? {
|
|
||||||
// LSBFirst
|
|
||||||
while rx < rect.height as usize {
|
|
||||||
let mut sx = (rx * full_width + rect.x as usize) * 4; // source idx
|
|
||||||
let mut dx = rx * bytes_per_row; // dest idx
|
|
||||||
let edx = (rx + 1) * bytes_per_row;
|
|
||||||
// println!("sx={} dx={} edx={}", sx,dx,edx);
|
|
||||||
while dx < edx {
|
|
||||||
buf[dx] = sbuf.get_byte(sx + 2).unwrap() as u8;
|
|
||||||
buf[dx + 1] = sbuf.get_byte(sx + 1).unwrap() as u8;
|
|
||||||
buf[dx + 2] = sbuf.get_byte(sx).unwrap() as u8;
|
|
||||||
buf[dx + 3] = if self.get_depth() == 32 {
|
|
||||||
sbuf.get_byte(sx + 3).unwrap() as u8
|
|
||||||
} else {
|
|
||||||
255u8
|
|
||||||
};
|
|
||||||
sx += 4;
|
|
||||||
dx += 4;
|
|
||||||
}
|
|
||||||
rx += 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_png(
|
|
||||||
&self,
|
|
||||||
out: impl AsRef<Path>,
|
|
||||||
rect: Option<Rectangle>,
|
|
||||||
) -> Result<(), ScreenshotError> {
|
|
||||||
let rect = rect.unwrap_or_else(|| Rectangle {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: self.get_width(),
|
|
||||||
height: self.get_height(),
|
|
||||||
});
|
|
||||||
|
|
||||||
let file = File::create(out.as_ref())?;
|
|
||||||
let ref mut out = BufWriter::new(file);
|
|
||||||
|
|
||||||
let mut encoder = Encoder::new(out, rect.width, rect.height);
|
|
||||||
encoder.set(png::ColorType::RGBA).set(png::BitDepth::Eight);
|
|
||||||
let mut writer = encoder.write_header()?;
|
|
||||||
|
|
||||||
let data = self.to_data_buf(rect)?;
|
|
||||||
writer.write_image_data(data.as_slice())?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -10,13 +10,11 @@ extern crate xlib;
|
||||||
mod capture;
|
mod capture;
|
||||||
mod errors;
|
mod errors;
|
||||||
mod gui;
|
mod gui;
|
||||||
mod image;
|
|
||||||
mod options;
|
mod options;
|
||||||
|
|
||||||
use structopt::StructOpt;
|
use structopt::StructOpt;
|
||||||
|
|
||||||
pub use capture::capture;
|
pub use capture::capture;
|
||||||
pub use image::ImageExt;
|
|
||||||
pub use options::Options;
|
pub use options::Options;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -26,3 +24,14 @@ pub struct Rectangle {
|
||||||
pub width: u32,
|
pub width: u32,
|
||||||
pub height: u32,
|
pub height: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rectangle {
|
||||||
|
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
|
||||||
|
Rectangle {
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
width,
|
||||||
|
height,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue