diff --git a/src/xlib/image.rs b/src/xlib/image.rs index 15636aa..71c0c6a 100644 --- a/src/xlib/image.rs +++ b/src/xlib/image.rs @@ -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 { 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 { - 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)) } } diff --git a/src/xlib/mod.rs b/src/xlib/mod.rs index 984653a..7366e92 100644 --- a/src/xlib/mod.rs +++ b/src/xlib/mod.rs @@ -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};