works with imlib!

This commit is contained in:
Michael Zhang 2018-09-11 13:21:59 -05:00
parent 6cb1dd1b6e
commit 24d019fdcb
No known key found for this signature in database
GPG key ID: A1B65B603268116B
7 changed files with 51 additions and 93 deletions

View file

@ -12,11 +12,6 @@ pub struct 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.
pub fn create_from_drawable(
drawable: impl AsRef<im::Drawable>,
@ -29,7 +24,14 @@ impl Image {
) -> Result<Self, Error> {
unsafe { im::imlib_context_set_drawable(*drawable.as_ref()) };
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 })
}

View file

@ -9,7 +9,20 @@ extern crate x11;
mod errors;
mod image;
mod visual;
pub use errors::Error;
pub use image::Image;
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
View 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 }
}
}

View file

@ -23,12 +23,7 @@ pub fn capture(opt: &Options) -> Result<(), ScreenshotError> {
let height = attr.get_height();
let root = gui.display.get_default_root_window()?;
let (x, y, _) = gui.display.translate_coordinates(win, 0, 0, root)?;
Some(Rectangle {
x: x as u32,
y: y as u32,
width,
height,
})
Some(Rectangle::new(x as u32, y as u32, width, height))
}
_ => None,
};

View file

@ -1,5 +1,5 @@
use imlib2::{self, Image as Image2, Visual};
use xlib::{Display, Image, Window};
use imlib2::{Image as Image2,};
use errors::ScreenshotError;
use Rectangle;
@ -21,7 +21,8 @@ impl GUI {
let height = attr.get_height() as i32;
let root = self.display.get_default_root_window()?;
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())
}

View file

@ -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(())
}
}

View file

@ -10,13 +10,11 @@ extern crate xlib;
mod capture;
mod errors;
mod gui;
mod image;
mod options;
use structopt::StructOpt;
pub use capture::capture;
pub use image::ImageExt;
pub use options::Options;
#[derive(Debug)]
@ -26,3 +24,14 @@ pub struct Rectangle {
pub width: u32,
pub height: u32,
}
impl Rectangle {
pub fn new(x: u32, y: u32, width: u32, height: u32) -> Self {
Rectangle {
x,
y,
width,
height,
}
}
}