This commit is contained in:
Michael Zhang 2020-06-29 14:22:39 -05:00
parent 5cf99dda34
commit 1b17246d8d
Signed by: michael
GPG key ID: BDA47A31A3C8EE6B
2 changed files with 42 additions and 50 deletions

View file

@ -1,22 +1,19 @@
//! XImage
//! ======
//!
//! Xlib provides some structures to perform operations on images. However, because there are
//! different in-memory representations, working with images is actually totally fucked. If you
//! want to maintain your sanity, do NOT pry into the raw data buffer of an Image. Instead, index
//! into the image using `PixBuffer::get_pixel` which already performs the conversion and returns a
//! tuple of RGB values.
//!
//! Peeking into the raw data buffer of an Image
//! --------------------------------------------
//!
//! Images consist of lines of longs in row-major form.
use x11::xlib;
use crate::errors::{Error, Result};
/// A handle to an XImage.
/// A handle to an XImage
///
/// Xlib provides some structures to perform operations on images. However, because there are
/// different in-memory representations, working with images is actually totally fucked. If you
/// want to maintain your sanity, do NOT pry into the raw data buffer of an Image. Instead, index
/// into the image using `PixBuffer::get_pixel` which already performs the conversion and returns a
/// tuple of RGB values.
///
/// Peeking into the raw data buffer of an Image
/// --------------------------------------------
///
/// Images consist of lines of longs in row-major form.
pub struct Image {
pub(super) inner: *mut xlib::XImage,
}
@ -29,20 +26,6 @@ pub enum ImageByteOrder {
MSBFirst,
}
/// The buffer pointed to by an XImage.
pub struct PixBuffer<'a> {
/// The raw pointer to the buffer
pub buf: *mut u8,
/// The size of the buffer
pub size: usize,
/// Rgb masks
pub masks: (u64, u64, u64),
pub image: &'a Image,
}
impl Image {
/// Get the size (in bytes) of the data buffer.
pub fn get_size(&self) -> usize {
@ -64,7 +47,7 @@ impl Image {
unsafe { (*self.inner).depth as u32 }
}
/// Get byte order
/// Get byte order (LSB or MSB)
pub fn get_byte_order(&self) -> Result<ImageByteOrder> {
let byte_order = unsafe { (*self.inner).byte_order };
match byte_order {
@ -81,7 +64,7 @@ impl Image {
(red_mask, blue_mask, green_mask)
}
/// Produces a PixBuffer
/// Produces a PixBuffer.
pub fn buffer(&self) -> PixBuffer {
let size = self.get_size();
let buf = unsafe { (*self.inner).data as *mut u8 };
@ -101,34 +84,43 @@ impl Drop for Image {
}
}
/// The buffer pointed to by an XImage.
pub struct PixBuffer<'a> {
/// The raw pointer to the buffer
pub buf: *mut u8,
/// The size of the buffer
pub size: usize,
/// Rgb masks
pub masks: (u64, u64, u64),
pub image: &'a Image,
}
impl<'a> PixBuffer<'a> {
/// Gets the byte at the index of the data buffer.
pub fn get_byte(&self, index: usize) -> Option<u8> {
if index > self.size {
return None;
}
Some(unsafe { *self.buf.offset(index as isize) as u8 })
/// Retrieve a direct reference to the internal buffer.
pub fn get_buffer(&self) -> &[u8] {
unsafe { std::slice::from_raw_parts(self.buf, self.size) }
}
/// Gets the rgb value of a particular pixel
/// Gets the rgb value of a particular pixel, after performing conversion
///
/// This uses XImage's get_pixel function to retrieve the pixel value, and then the various
/// red/green/blue masks to actually perform the conversions, and fails (returns `None`) if the
/// (x, y) coordinates given aren't actually in the image.
pub fn get_pixel(&self, x: u32, y: u32) -> Option<(u8, u8, u8)> {
// let bytes_per_line = unsafe{(*self.image.inner).bytes_per_line} as u32;
// let bits_per_pixel=unsafe{(*self.image.inner).bits_per_pixel} as u32;
// let pixel_ptr = (y * bytes_per_line + x * bits_per_pixel) / 8;
// let pixel = unsafe{*((*self.image.inner).data.offset(pixel_ptr as isize) as *mut c_ulong)};
let get_pixel = unsafe { (*self.image.inner).funcs.get_pixel }.unwrap();
let pixel = unsafe { get_pixel(self.image.inner, x as i32, y as i32) };
// warn!("pixel: {:?} {:#b}", pixel, pixel);
let red_mask = unsafe { (*self.image.inner).red_mask };
let green_mask = unsafe { (*self.image.inner).green_mask };
let blue_mask = unsafe { (*self.image.inner).blue_mask };
// warn!("masks: {:b} {:b} {:b}", red_mask, green_mask, blue_mask);
let red = ((pixel & unsafe { (*self.image.inner).red_mask }) >> 16) as u8;
let green = ((pixel & unsafe { (*self.image.inner).green_mask }) >> 8) as u8;
let blue = ((pixel & unsafe { (*self.image.inner).blue_mask }) >> 0) as u8;
// warn!("rgb: {:?}", (red, green, blue));
let red = ((pixel & red_mask) >> 16) as u8;
let green = ((pixel & green_mask) >> 8) as u8;
let blue = ((pixel & blue_mask) >> 0) as u8;
Some((red, green, blue))
}
}

View file

@ -12,6 +12,6 @@ pub use self::cursor::Cursor;
pub use self::display::{Display, GetDisplay};
pub use self::drawable::Drawable;
pub use self::event::{Event, EventKind};
pub use self::image::{Image, ImageByteOrder};
pub use self::image::{Image, ImageByteOrder, PixBuffer};
pub use self::visual::Visual;
pub use self::window::{EventMask, Window};