x11rb/
image.rs

1//! Utility code for working with images.
2//!
3//! This module contains the [`Image`] struct which represents an arbitrary image in
4//! `ImageFormat::ZPixmap`. If you do not know what `ZPixmap` means, then rest assured that you do
5//! not want to know the details. It suffices to know that the values of the individual pixels are
6//! saved one after another in memory.
7//!
8//! An [`Image`] can be converted to a different internal representation. [`Image::native`]
9//! converts it to the native format of the X11 server. These conversions do not change the actual
10//! content of the image, but only the way that it is laid out in memory (e.g. byte order and
11//! padding). Specifically, there is no support for converting an image to another `depth`.
12//!
13//! The code in this module is only available when the `image` feature of the library is
14//! enabled.
15
16// For future readers:
17//
18// - Z-Pixmap means that the pixels are right next to each other. I.e. first you have the value of
19//   the pixel at (0, 0), then (1, 0), .... At the end of the row, there might be some padding
20//   before the next row begins.
21// - XY-Bitmap consists of individual bits. The bits are assigned colors via a GC's foreground and
22//   background color when uploading to the X11 server.
23// - XY-Pixmap consists of bit planes. This means you first get the first bit of each pixel,
24//   stuffed together into bytes. After all of the first pixels are represented, the second plane
25//   begins with the second bit of each pixel etc.
26
27use std::borrow::Cow;
28
29use crate::connection::Connection;
30use crate::cookie::VoidCookie;
31use crate::errors::{ConnectionError, ParseError, ReplyError};
32use crate::protocol::xproto::{
33    get_image, put_image, Drawable, Format, Gcontext, GetImageReply, ImageFormat,
34    ImageOrder as XprotoImageOrder, Setup, VisualClass, Visualid, Visualtype,
35};
36
37/// The description of a single color component.
38///
39/// For example, in an RGB image, pixels are often saved as `0xRRGGBB`, where each letter
40/// represents the respective color component. In the example, green has a `width` of 8 (it takes
41/// up 8 bits) and a `shift` of `16` (there are 16 less significant bits beyond it). This info is
42/// represented as a `ColorComponent`.
43#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct ColorComponent {
45    /// Number of bits for the component
46    width: u8,
47    /// Offset in an u32 of the component
48    shift: u8,
49}
50
51impl ColorComponent {
52    /// Create a new color component with the given information.
53    ///
54    /// The following conditions must be satisfied:
55    /// - `width <= 16`: color components have at most 16 bits.
56    /// - `shift < 32`: pixel values have at most 32 bits.
57    /// - `shift + width <= 32`: pixel values have at most 32 bits.
58    pub fn new(width: u8, shift: u8) -> Result<Self, ParseError> {
59        if width > 16 || shift >= 32 || shift + width > 32 {
60            Err(ParseError::InvalidValue)
61        } else {
62            Ok(Self { width, shift })
63        }
64    }
65
66    /// Get the bit width of the color component.
67    pub fn width(self) -> u8 {
68        self.width
69    }
70
71    /// Get the bit shift of the color component.
72    pub fn shift(self) -> u8 {
73        self.shift
74    }
75
76    /// Get the pixel mask representing this color component.
77    ///
78    /// The mask can be used to mask off other colors in a pixel value. Only the bits that
79    /// correspond to this color component are set.
80    /// ```
81    /// # use x11rb::image::ColorComponent;
82    /// let red = ColorComponent::new(8, 16)?;
83    /// assert_eq!(red.mask(), 0xff0000);
84    /// # Ok::<(), x11rb::errors::ParseError>(())
85    /// ```
86    pub fn mask(self) -> u32 {
87        // Get a mask with 'width' set bits.
88        let mask = (1u32 << self.width) - 1;
89        // Shift the mask into the right position
90        mask << self.shift
91    }
92
93    /// Create a new color component from a color mask.
94    ///
95    /// This turns a color mask into its individual components.
96    /// ```
97    /// # use x11rb::image::ColorComponent;
98    /// let red1 = ColorComponent::new(8, 16);
99    /// let red2 = ColorComponent::from_mask(0xff0000);
100    /// ```
101    ///
102    /// # Errors
103    ///
104    /// This function fails if the given value is not a well-formed mask. This means that at least
105    /// one bit must be set and the set bits must be consecutive.
106    pub fn from_mask(mask: u32) -> Result<Self, ParseError> {
107        let width = mask.count_ones();
108        let shift = mask.trailing_zeros();
109        // Both width and shift can be at most 32, which should fit into u8.
110        let result = Self::new(width.try_into().unwrap(), shift.try_into().unwrap())?;
111        if mask != result.mask() {
112            Err(ParseError::InvalidValue)
113        } else {
114            Ok(result)
115        }
116    }
117
118    /// Get this color component out of a pixel value.
119    ///
120    /// This function gets a single pixel value and returns this color component's value in that
121    /// pixel value, expanded to width 16.
122    /// ```
123    /// # use x11rb::image::ColorComponent;
124    /// let red = ColorComponent::new(8, 16)?;
125    /// assert_eq!(0xABAB, red.decode(0x78AB_4321));
126    /// # Ok::<(), x11rb::errors::ParseError>(())
127    /// ```
128    pub fn decode(self, pixel: u32) -> u16 {
129        // Get the color component out
130        let value = (pixel & self.mask()) >> self.shift;
131
132        // Now expand from with `self.width` to width 16.
133        let mut width = self.width;
134        let mut value = value << (16 - width);
135        // Add some low bits by using the high bits
136        while width < 16 {
137            value |= value >> width;
138            width <<= 1;
139        }
140        value.try_into().unwrap()
141    }
142
143    /// Encode a color value according to this pixel format.
144    ///
145    /// ```
146    /// # use x11rb::image::ColorComponent;
147    /// let red = ColorComponent::new(8, 16)?;
148    /// assert_eq!(0xAB0000, red.encode(0xABCD));
149    /// # Ok::<(), x11rb::errors::ParseError>(())
150    /// ```
151    pub fn encode(self, intensity: u16) -> u32 {
152        // First truncate to width `self.width`, then place at the correct offset.
153        (u32::from(intensity) >> (16 - self.width)) << self.shift
154    }
155}
156
157/// A collection of color components describing the red, green, and blue components of a pixel.
158///
159/// A [`ColorComponent`] describes a single color component in an image. This structure describes
160/// the `red`, `green`, and `blue` color components by containing a [`ColorComponent`] for each of
161/// them.
162#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub struct PixelLayout {
164    red: ColorComponent,
165    green: ColorComponent,
166    blue: ColorComponent,
167}
168
169impl PixelLayout {
170    /// Create a new pixel layout from the description of each component
171    pub fn new(red: ColorComponent, green: ColorComponent, blue: ColorComponent) -> Self {
172        Self { red, green, blue }
173    }
174
175    /// Create a new pixel layout
176    ///
177    /// This function errors if the visual has a different class than `TrueColor` or `DirectColor`,
178    /// because color pallets and grayscales are not supported. This function also errors if the
179    /// mask components of the visual are malformed.
180    pub fn from_visual_type(visual: Visualtype) -> Result<Self, ParseError> {
181        if visual.class != VisualClass::TRUE_COLOR && visual.class != VisualClass::DIRECT_COLOR {
182            Err(ParseError::InvalidValue)
183        } else {
184            Ok(Self::new(
185                ColorComponent::from_mask(visual.red_mask)?,
186                ColorComponent::from_mask(visual.green_mask)?,
187                ColorComponent::from_mask(visual.blue_mask)?,
188            ))
189        }
190    }
191
192    /// Get the depth of this pixel layout.
193    ///
194    /// The depth is the number of significant bits of each pixel value.
195    pub fn depth(self) -> u8 {
196        // TODO: I am not quite sure this implementation is correct. The protocol seems to allow
197        // unused bits in the middle..?
198        self.red.width + self.green.width + self.blue.width
199    }
200
201    /// Decode a pixel value into its red, green, and blue components.
202    ///
203    /// This function returns each component expanded to width 16.
204    /// ```
205    /// # use x11rb::image::{ColorComponent, PixelLayout};
206    /// let layout = PixelLayout::new(
207    ///     ColorComponent::new(8, 16)?,
208    ///     ColorComponent::new(8, 8)?,
209    ///     ColorComponent::new(8, 0)?,
210    /// );
211    /// assert_eq!((0xABAB, 0x4343, 0x2121), layout.decode(0x78AB_4321));
212    /// # Ok::<(), x11rb::errors::ParseError>(())
213    /// ```
214    pub fn decode(self, pixel: u32) -> (u16, u16, u16) {
215        let red = self.red.decode(pixel);
216        let green = self.green.decode(pixel);
217        let blue = self.blue.decode(pixel);
218        (red, green, blue)
219    }
220
221    /// Encode a color value according to this layout.
222    ///
223    /// ```
224    /// # use x11rb::image::{ColorComponent, PixelLayout};
225    /// let layout = PixelLayout::new(
226    ///     ColorComponent::new(8, 16)?,
227    ///     ColorComponent::new(8, 8)?,
228    ///     ColorComponent::new(8, 0)?,
229    /// );
230    /// assert_eq!(0x00AB_4321, layout.encode((0xABAB, 0x4343, 0x2121)));
231    /// # Ok::<(), x11rb::errors::ParseError>(())
232    /// ```
233    pub fn encode(self, (red, green, blue): (u16, u16, u16)) -> u32 {
234        let red = self.red.encode(red);
235        let green = self.green.encode(green);
236        let blue = self.blue.encode(blue);
237        red | green | blue
238    }
239}
240
241// Compute the stride based on some information of the image
242fn compute_stride(width: u16, bits_per_pixel: BitsPerPixel, scanline_pad: ScanlinePad) -> usize {
243    let value = usize::from(width) * usize::from(bits_per_pixel);
244    scanline_pad.round_to_multiple(value) / 8
245}
246
247#[cfg(test)]
248mod test_stride {
249    use super::compute_stride;
250
251    #[test]
252    fn test_stride() {
253        for &(width, bpp, pad, stride) in &[
254            // bpp=pad=8
255            (0, 8, 8, 0),
256            (1, 8, 8, 1),
257            (2, 8, 8, 2),
258            (3, 8, 8, 3),
259            (41, 8, 8, 41),
260            // bpp=8, pad=16
261            (0, 8, 16, 0),
262            (1, 8, 16, 2),
263            (2, 8, 16, 2),
264            (3, 8, 16, 4),
265            (41, 8, 16, 42),
266            // bpp=16, pad=16
267            (0, 16, 16, 0),
268            (1, 16, 16, 2),
269            (2, 16, 16, 4),
270            (3, 16, 16, 6),
271            (41, 16, 16, 82),
272            // bpp=16, pad=32
273            (0, 16, 32, 0),
274            (1, 16, 32, 4),
275            (2, 16, 32, 4),
276            (3, 16, 32, 8),
277            (41, 16, 32, 84),
278            // bpp=32, pad=32
279            (0, 32, 32, 0),
280            (1, 32, 32, 4),
281            (2, 32, 32, 8),
282            (3, 32, 32, 12),
283            (41, 32, 32, 164),
284        ] {
285            let actual = compute_stride(width, bpp.try_into().unwrap(), pad.try_into().unwrap());
286            assert_eq!(stride, actual, "width={width}, bpp={bpp}, pad={pad}");
287        }
288    }
289}
290
291// Find the format with the given depth in `setup.pixmap_formats`.
292fn find_format(setup: &Setup, depth: u8) -> Result<&Format, ParseError> {
293    setup
294        .pixmap_formats
295        .iter()
296        .find(|f| f.depth == depth)
297        .ok_or(ParseError::InvalidValue)
298}
299
300macro_rules! number_enum {
301    {
302        $(#[$meta:meta])*
303        $vis:vis enum $enum_name:ident {
304            $(
305                $(#[$variant_meta:meta])*
306                $variant_name:ident = $value:literal,
307            )*
308        }
309    } => {
310        $(#[$meta])*
311        #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
312        $vis enum $enum_name {
313            $(
314                $(#[$variant_meta])*
315                $variant_name = $value,
316            )*
317        }
318
319        impl TryFrom<u8> for $enum_name {
320            type Error = ParseError;
321            fn try_from(value: u8) -> Result<Self, Self::Error> {
322                match value {
323                    $($value => Ok(Self::$variant_name),)*
324                    _ => Err(ParseError::InvalidValue),
325                }
326            }
327        }
328
329        impl From<$enum_name> for u8 {
330            fn from(value: $enum_name) -> u8 {
331                match value {
332                    $($enum_name::$variant_name => $value,)*
333                }
334            }
335        }
336
337        impl From<$enum_name> for usize {
338            fn from(value: $enum_name) -> usize {
339                u8::from(value).into()
340            }
341        }
342    }
343}
344
345number_enum! {
346    /// The padding of scanlines.
347    ///
348    /// Each line of an image is padded to a multiple of some value. This value is the scanline
349    /// padding, which this enum represents.
350    #[non_exhaustive]
351    pub enum ScanlinePad {
352        /// Padding to multiples of 8 bits, i.e. no padding.
353        Pad8 = 8,
354        /// Padding to multiples of 16 bits, i.e. the next even number of bytes.
355        Pad16 = 16,
356        /// Padding to multiples of 32 bits, i.e. the next multiple of 4.
357        Pad32 = 32,
358    }
359}
360
361impl ScanlinePad {
362    fn round_to_multiple(self, value: usize) -> usize {
363        let value = value + usize::from(self) - 1;
364        value - value % usize::from(self)
365    }
366}
367
368#[cfg(test)]
369mod test_scanline_pad {
370    use super::ScanlinePad;
371
372    #[test]
373    fn number_conversions() {
374        assert_eq!(8_u8, ScanlinePad::Pad8.into());
375        assert_eq!(16_u8, ScanlinePad::Pad16.into());
376        assert_eq!(32_u8, ScanlinePad::Pad32.into());
377        assert_eq!(8.try_into(), Ok(ScanlinePad::Pad8));
378        assert_eq!(16.try_into(), Ok(ScanlinePad::Pad16));
379        assert_eq!(32.try_into(), Ok(ScanlinePad::Pad32));
380    }
381
382    #[test]
383    fn test_round_to_multiple() {
384        for &(value, pad8, pad16, pad32) in [
385            (0, 0, 0, 0),
386            (1, 8, 16, 32),
387            (2, 8, 16, 32),
388            (3, 8, 16, 32),
389            (4, 8, 16, 32),
390            (5, 8, 16, 32),
391            (6, 8, 16, 32),
392            (7, 8, 16, 32),
393            (8, 8, 16, 32),
394            (9, 16, 16, 32),
395            (10, 16, 16, 32),
396            (11, 16, 16, 32),
397            (12, 16, 16, 32),
398            (13, 16, 16, 32),
399            (14, 16, 16, 32),
400            (15, 16, 16, 32),
401            (16, 16, 16, 32),
402            (17, 24, 32, 32),
403            (33, 40, 48, 64),
404            (47, 48, 48, 64),
405            (48, 48, 48, 64),
406            (49, 56, 64, 64),
407        ]
408        .iter()
409        {
410            assert_eq!(
411                pad8,
412                ScanlinePad::Pad8.round_to_multiple(value),
413                "value={value} for pad8"
414            );
415            assert_eq!(
416                pad16,
417                ScanlinePad::Pad16.round_to_multiple(value),
418                "value={value} for pad16"
419            );
420            assert_eq!(
421                pad32,
422                ScanlinePad::Pad32.round_to_multiple(value),
423                "value={value} for pad32"
424            );
425        }
426    }
427}
428
429number_enum! {
430    /// The number of bits required to store one pixel.
431    ///
432    /// This value is only about the size of one pixel in memory. Other names for it include
433    /// `bits_per_pixel` or `bpp`. It may be larger than the number of meaningful bits for a pixel
434    /// value, which is its `depth`.
435    #[non_exhaustive]
436    pub enum BitsPerPixel {
437        /// Each pixel takes one bit of memory.
438        B1 = 1,
439        /// Each pixel takes four bits of memory.
440        B4 = 4,
441        /// Each pixel takes one byte of memory.
442        B8 = 8,
443        /// Each pixel takes two bytes of memory.
444        B16 = 16,
445        /// Each pixel takes three bytes of memory.
446        ///
447        /// This is most likely not what you want to use, even if you have RGB data with 8 bits per
448        /// channel. This corresponds to `depth=24`, but is almost always stored as four bytes
449        /// per pixel, which is `BitsPerPixel::B32`.
450        B24 = 24,
451        /// Each pixel takes four bytes of memory.
452        B32 = 32,
453    }
454}
455
456/// Order in which bytes are stored in memory.
457///
458/// If the numberof bits per pixel is less than 8, then this is the
459/// order in which bits are packed into bytes.
460#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
461pub enum ImageOrder {
462    /// Least significant byte first
463    LsbFirst,
464    /// Most significant byte first
465    MsbFirst,
466}
467
468impl TryFrom<XprotoImageOrder> for ImageOrder {
469    type Error = ParseError;
470
471    fn try_from(value: XprotoImageOrder) -> Result<Self, ParseError> {
472        match value {
473            XprotoImageOrder::LSB_FIRST => Ok(Self::LsbFirst),
474            XprotoImageOrder::MSB_FIRST => Ok(Self::MsbFirst),
475            _ => Err(ParseError::InvalidValue),
476        }
477    }
478}
479
480/// The description of an image.
481#[derive(Debug, PartialEq, Eq, Clone)]
482pub struct Image<'a> {
483    /// Width in pixels.
484    width: u16,
485
486    /// Height in pixels.
487    height: u16,
488
489    /// Right padding on each scanline.
490    scanline_pad: ScanlinePad,
491
492    /// Color depth in bits.
493    depth: u8,
494
495    /// Storage per pixel in bits. Must be >= depth.
496    bits_per_pixel: BitsPerPixel,
497
498    /// Byte order of components.
499    ///
500    /// This is the nibble order when bits_per_pixel is 4.
501    byte_order: ImageOrder,
502
503    /// The image data.
504    data: Cow<'a, [u8]>,
505}
506
507impl<'a> Image<'a> {
508    /// The width in pixels.
509    pub fn width(&self) -> u16 {
510        self.width
511    }
512
513    /// The height in pixels.
514    pub fn height(&self) -> u16 {
515        self.height
516    }
517
518    /// The padding on the right side of each scanline.
519    ///
520    /// Each scanline is rounded up to some multiple of the `scanline_pad`.
521    pub fn scanline_pad(&self) -> ScanlinePad {
522        self.scanline_pad
523    }
524
525    /// Color depth in bits.
526    pub fn depth(&self) -> u8 {
527        self.depth
528    }
529
530    /// Number of bits required to store one pixel.
531    ///
532    /// This is always `>= depth`.
533    pub fn bits_per_pixel(&self) -> BitsPerPixel {
534        self.bits_per_pixel
535    }
536
537    /// Order in which bytes are stored in memory.
538    ///
539    /// If `bits_per_pixel()` is smaller than 8, then this is the order in which bits are packed
540    /// into bytes.
541    pub fn byte_order(&self) -> ImageOrder {
542        self.byte_order
543    }
544
545    /// Raw pixel data.
546    pub fn data(&self) -> &[u8] {
547        &self.data
548    }
549
550    /// Mutable access to the raw pixel data.
551    ///
552    /// If the `Image` was constructed with `Cow::Borrowed`-access to its pixel data, then a copy
553    /// is made when this method is called.
554    pub fn data_mut(&mut self) -> &mut [u8] {
555        self.data.to_mut()
556    }
557
558    /// Construct a new image from existing data.
559    ///
560    /// This constructs a new `Image` from given `data` without copying this data around. The other
561    /// parameters describe the format that the image data is in.
562    ///
563    /// See [`Image::allocate`] for a variant that allocates memory for you and
564    /// [`Image::allocate_native`] for allocating an image that is in an X11 server's native
565    /// format.
566    ///
567    /// # Errors
568    ///
569    /// The only possible error is that `data.len()` is too short for an image as described by the
570    /// other parameters.
571    pub fn new(
572        width: u16,
573        height: u16,
574        scanline_pad: ScanlinePad,
575        depth: u8,
576        bits_per_pixel: BitsPerPixel,
577        byte_order: ImageOrder,
578        data: Cow<'a, [u8]>,
579    ) -> Result<Self, ParseError> {
580        let stride = compute_stride(width, bits_per_pixel, scanline_pad);
581        let expected_size = usize::from(height) * stride;
582        if data.len() < expected_size {
583            Err(ParseError::InsufficientData)
584        } else {
585            Ok(Self {
586                width,
587                height,
588                scanline_pad,
589                depth,
590                bits_per_pixel,
591                byte_order,
592                data,
593            })
594        }
595    }
596
597    /// Construct a new, empty image.
598    ///
599    /// This function allocates memory for a new image in the format that is described by the
600    /// parameters.
601    ///
602    /// See [`Image::new`] for a variant that wraps an existing in-memory image in an `Image` and
603    /// [`Image::allocate_native`] for allocating an image that is in an X11 server's native
604    /// format.
605    pub fn allocate(
606        width: u16,
607        height: u16,
608        scanline_pad: ScanlinePad,
609        depth: u8,
610        bits_per_pixel: BitsPerPixel,
611        byte_order: ImageOrder,
612    ) -> Self {
613        let stride = compute_stride(width, bits_per_pixel, scanline_pad);
614        let data = Cow::Owned(vec![0; usize::from(height) * stride]);
615        Self {
616            width,
617            height,
618            scanline_pad,
619            depth,
620            bits_per_pixel,
621            byte_order,
622            data,
623        }
624    }
625
626    /// Construct a new, empty image.
627    ///
628    /// This function allocates memory for a new image in the format that the X11 server expects.
629    /// The image will have size `width`x`height` and a depth of `depth`.
630    ///
631    /// See [`Image::new`] for a variant that wraps an existing in-memory image in an `Image` and
632    /// [`Image::allocate`] for allocating an image that is in a more general format, not
633    /// necessarily what the X11 server wants.
634    pub fn allocate_native(
635        width: u16,
636        height: u16,
637        depth: u8,
638        setup: &Setup,
639    ) -> Result<Self, ParseError> {
640        let format = find_format(setup, depth)?;
641        Ok(Self::allocate(
642            width,
643            height,
644            format.scanline_pad.try_into()?,
645            depth,
646            format.bits_per_pixel.try_into()?,
647            setup.image_byte_order.try_into()?,
648        ))
649    }
650
651    /// The stride is the number of bytes that each row of pixel data occupies in memory.
652    fn stride(&self) -> usize {
653        compute_stride(self.width, self.bits_per_pixel, self.scanline_pad)
654    }
655
656    /// Get an image from the X11 server.
657    ///
658    /// This function sends a [`GetImage`](crate::protocol::xproto::GetImageRequest) request, waits
659    /// for its response and wraps it in a new `Image`. The image and the corresponding visual id
660    /// are returned.
661    ///
662    /// The returned image contains the rectangle with top left corner `(x, y)` and size `(width,
663    /// height)` of the given `drawable`.
664    pub fn get(
665        conn: &impl Connection,
666        drawable: Drawable,
667        x: i16,
668        y: i16,
669        width: u16,
670        height: u16,
671    ) -> Result<(Self, Visualid), ReplyError> {
672        let reply = get_image(
673            conn,
674            ImageFormat::Z_PIXMAP,
675            drawable,
676            x,
677            y,
678            width,
679            height,
680            !0,
681        )?
682        .reply()?;
683        let visual = reply.visual;
684        let image = Self::get_from_reply(conn.setup(), width, height, reply)?;
685        Ok((image, visual))
686    }
687
688    /// Construct an `Image` from a `GetImageReply`.
689    ///
690    /// This function takes a `GetImageReply` and wraps it in an `Image`. The given `width` and
691    /// `height` describe the corresponding values of the `GetImage` request that was used to get
692    /// the `GetImageReply`.
693    pub fn get_from_reply(
694        setup: &Setup,
695        width: u16,
696        height: u16,
697        reply: GetImageReply,
698    ) -> Result<Self, ParseError> {
699        let format = find_format(setup, reply.depth)?;
700        Self::new(
701            width,
702            height,
703            format.scanline_pad.try_into()?,
704            reply.depth,
705            format.bits_per_pixel.try_into()?,
706            setup.image_byte_order.try_into()?,
707            Cow::Owned(reply.data),
708        )
709    }
710
711    /// Put an image to the X11 server.
712    ///
713    /// This function sends a [`PutImage`](crate::protocol::xproto::PutImageRequest) request. This
714    /// will upload this image to the given `drawable` to position `(dst_x, dst_y)`.
715    ///
716    /// The server's maximum request size is honored. This means that a too large `PutImage`
717    /// request is automatically split up into smaller pieces. Thus, if this function returns an
718    /// error, the image could already be partially sent.
719    ///
720    /// Before uploading, the image is translated into the server's native format via
721    /// [`Image::native`]. This may convert the image to another format, which can be slow. If you
722    /// intend to upload the same image multiple times, it is likely more efficient to call
723    /// [`Image::native`] once initially so that the conversion is not repeated on each upload.
724    pub fn put<'c, Conn: Connection>(
725        &self,
726        conn: &'c Conn,
727        drawable: Drawable,
728        gc: Gcontext,
729        dst_x: i16,
730        dst_y: i16,
731    ) -> Result<Vec<VoidCookie<'c, Conn>>, ConnectionError> {
732        self.native(conn.setup())?
733            .put_impl(conn, drawable, gc, dst_x, dst_y)
734    }
735
736    fn put_impl<'c, Conn: Connection>(
737        &self,
738        conn: &'c Conn,
739        drawable: Drawable,
740        gc: Gcontext,
741        dst_x: i16,
742        dst_y: i16,
743    ) -> Result<Vec<VoidCookie<'c, Conn>>, ConnectionError> {
744        // Upload the image without exceeding the server's maximum request size
745        let max_bytes = conn.maximum_request_bytes();
746        let put_image_header = 24;
747        let stride = self.stride();
748        let lines_per_request = (max_bytes - put_image_header) / stride;
749        let mut result = Vec::with_capacity(
750            (usize::from(self.height()) + lines_per_request - 1) / lines_per_request,
751        );
752        let lines_per_request = lines_per_request.try_into().unwrap_or(u16::MAX);
753        assert!(lines_per_request > 0);
754
755        let (mut y_offset, mut byte_offset) = (0, 0);
756        while y_offset < self.height {
757            let next_lines = lines_per_request.min(self.height - y_offset);
758            let next_byte_offset = byte_offset + usize::from(next_lines) * stride;
759            let data = &self.data[byte_offset..next_byte_offset];
760            result.push(put_image(
761                conn,
762                ImageFormat::Z_PIXMAP,
763                drawable,
764                gc,
765                self.width,
766                next_lines,
767                dst_x,
768                dst_y + i16::try_from(y_offset).unwrap(),
769                0, // left_pad must always be 0 for ZPixmap
770                self.depth,
771                data,
772            )?);
773
774            y_offset += next_lines;
775            byte_offset = next_byte_offset;
776        }
777        Ok(result)
778    }
779
780    /// Convert this image into the format specified by the other parameters.
781    ///
782    /// This function may need to copy the image, hence returns a `Cow`.
783    pub fn convert(
784        &self,
785        scanline_pad: ScanlinePad,
786        bits_per_pixel: BitsPerPixel,
787        byte_order: ImageOrder,
788    ) -> Cow<'_, Self> {
789        let already_converted = scanline_pad == self.scanline_pad
790            && bits_per_pixel == self.bits_per_pixel
791            && byte_order == self.byte_order;
792        if already_converted {
793            Cow::Borrowed(self)
794        } else {
795            let mut copy = Image::allocate(
796                self.width,
797                self.height,
798                scanline_pad,
799                self.depth,
800                bits_per_pixel,
801                byte_order,
802            );
803            // This is the slowest possible way to do this. But also the easiest one to implement.
804            for y in 0..self.height {
805                for x in 0..self.width {
806                    copy.put_pixel(x, y, self.get_pixel(x, y))
807                }
808            }
809            Cow::Owned(copy)
810        }
811    }
812
813    /// Convert this image into the native format of the X11 server.
814    ///
815    /// This function may need to copy the image, hence returns a `Cow`.
816    pub fn native(&self, setup: &Setup) -> Result<Cow<'_, Self>, ParseError> {
817        let format = find_format(setup, self.depth)?;
818        Ok(self.convert(
819            format.scanline_pad.try_into()?,
820            format.bits_per_pixel.try_into()?,
821            setup.image_byte_order.try_into()?,
822        ))
823    }
824
825    /// Reencode this image to a different pixel layout / depth.
826    ///
827    /// Each pixel of this image is interpreted according to `own` and written to the resulting
828    /// image in the format described by `output`.
829    ///
830    /// The resulting image is always in the native format as described by `setup`.
831    pub fn reencode<'b>(
832        &'b self,
833        own: PixelLayout,
834        output: PixelLayout,
835        setup: &Setup,
836    ) -> Result<Cow<'b, Self>, ParseError> {
837        if own == output {
838            self.native(setup)
839        } else {
840            // Yay, we get to convert the image :-(
841            let (width, height) = (self.width(), self.height());
842            let mut result = Image::allocate_native(width, height, output.depth(), setup)?;
843            for y in 0..height {
844                for x in 0..width {
845                    let pixel = self.get_pixel(x, y);
846                    let pixel = output.encode(own.decode(pixel));
847                    result.put_pixel(x, y, pixel);
848                }
849            }
850            Ok(Cow::Owned(result))
851        }
852    }
853
854    /// Set a single pixel in this image.
855    ///
856    /// The pixel at position `(x, y)` will be set to the value `pixel`. `pixel` is truncated to
857    /// this image's [`Self::bits_per_pixel`].
858    ///
859    /// If the image was constructed from a `Cow::Borrowed` access to its pixel data, this causes
860    /// the whole pixel data to be copied. See [`Image::new`] and [`Image::data_mut`].
861    pub fn put_pixel(&mut self, x: u16, y: u16, pixel: u32) {
862        assert!(x < self.width);
863        assert!(y < self.height);
864
865        let row_start = usize::from(y) * self.stride();
866        let x = usize::from(x);
867        let data = self.data.to_mut();
868        match self.bits_per_pixel {
869            BitsPerPixel::B1 => {
870                let (byte, bit) = compute_depth_1_address(x, self.byte_order);
871                let pixel = ((pixel & 0x01) << bit) as u8;
872                let old = data[row_start + byte];
873                let bit_cleared = old & !(1 << bit);
874                data[row_start + byte] = bit_cleared | pixel;
875            }
876            BitsPerPixel::B4 => {
877                let mut pixel = pixel & 0x0f;
878                let odd_x = x % 2 == 1;
879                let mask = if odd_x == (self.byte_order == ImageOrder::MsbFirst) {
880                    pixel <<= 4;
881                    0xf0
882                } else {
883                    0x0f
884                };
885                data[row_start + x / 2] = (data[row_start + x / 2] & !mask) | (pixel as u8);
886            }
887            BitsPerPixel::B8 => data[row_start + x] = pixel as u8,
888            BitsPerPixel::B16 => {
889                let (p0, p1) = match self.byte_order {
890                    ImageOrder::LsbFirst => (pixel, pixel >> 8),
891                    ImageOrder::MsbFirst => (pixel >> 8, pixel),
892                };
893                data[row_start + 2 * x + 1] = p1 as u8;
894                data[row_start + 2 * x] = p0 as u8;
895            }
896            BitsPerPixel::B24 => {
897                let (p0, p1, p2) = match self.byte_order {
898                    ImageOrder::LsbFirst => (pixel, pixel >> 8, pixel >> 16),
899                    ImageOrder::MsbFirst => (pixel >> 16, pixel >> 8, pixel),
900                };
901                data[row_start + 3 * x + 2] = p2 as u8;
902                data[row_start + 3 * x + 1] = p1 as u8;
903                data[row_start + 3 * x] = p0 as u8;
904            }
905            BitsPerPixel::B32 => {
906                let (p0, p1, p2, p3) = match self.byte_order {
907                    ImageOrder::LsbFirst => (pixel, pixel >> 8, pixel >> 16, pixel >> 24),
908                    ImageOrder::MsbFirst => (pixel >> 24, pixel >> 16, pixel >> 8, pixel),
909                };
910                data[row_start + 4 * x + 3] = p3 as u8;
911                data[row_start + 4 * x + 2] = p2 as u8;
912                data[row_start + 4 * x + 1] = p1 as u8;
913                data[row_start + 4 * x] = p0 as u8;
914            }
915        }
916    }
917
918    /// Get the value of a single pixel.
919    ///
920    /// This function gets the value of the pixel at `(x, y)`.
921    pub fn get_pixel(&self, x: u16, y: u16) -> u32 {
922        assert!(x < self.width);
923        assert!(y < self.height);
924
925        let row_start = usize::from(y) * self.stride();
926        let x = usize::from(x);
927        // TODO Can this code (and the one in put_pixel) be simplified? E.g. handle B4 as a special
928        // case and copy bits_per_pixel.into() / 8 bytes in other cases?
929        match self.bits_per_pixel {
930            BitsPerPixel::B1 => {
931                let (byte, bit) = compute_depth_1_address(x, self.byte_order);
932                ((self.data[row_start + byte] >> bit) & 1).into()
933            }
934            BitsPerPixel::B4 => {
935                let byte = u32::from(self.data[row_start + x / 2]);
936                let odd_x = x % 2 == 1;
937                if odd_x == (self.byte_order == ImageOrder::MsbFirst) {
938                    byte >> 4
939                } else {
940                    byte & 0x0f
941                }
942            }
943            BitsPerPixel::B8 => self.data[row_start + x].into(),
944            BitsPerPixel::B16 => {
945                let p1 = u32::from(self.data[row_start + 2 * x + 1]);
946                let p0 = u32::from(self.data[row_start + 2 * x]);
947                match self.byte_order {
948                    ImageOrder::LsbFirst => p0 | (p1 << 8),
949                    ImageOrder::MsbFirst => p1 | (p0 << 8),
950                }
951            }
952            BitsPerPixel::B24 => {
953                let p2 = u32::from(self.data[row_start + 3 * x + 2]);
954                let p1 = u32::from(self.data[row_start + 3 * x + 1]);
955                let p0 = u32::from(self.data[row_start + 3 * x]);
956                match self.byte_order {
957                    ImageOrder::LsbFirst => p0 | (p1 << 8) | (p2 << 16),
958                    ImageOrder::MsbFirst => p2 | (p1 << 8) | (p0 << 16),
959                }
960            }
961            BitsPerPixel::B32 => {
962                let p3 = u32::from(self.data[row_start + 4 * x + 3]);
963                let p2 = u32::from(self.data[row_start + 4 * x + 2]);
964                let p1 = u32::from(self.data[row_start + 4 * x + 1]);
965                let p0 = u32::from(self.data[row_start + 4 * x]);
966                match self.byte_order {
967                    ImageOrder::LsbFirst => p0 | (p1 << 8) | (p2 << 16) | (p3 << 24),
968                    ImageOrder::MsbFirst => p3 | (p2 << 8) | (p1 << 16) | (p0 << 24),
969                }
970            }
971        }
972    }
973
974    /// Get a version of this image with `'static` lifetime.
975    ///
976    /// If the image was constructed from a `Cow::Borrowed`, this clones the contained data.
977    /// Otherwise, this simply returns `self`.
978    pub fn into_owned(self) -> Image<'static> {
979        // It would be great if we could just implement ToOwned, but that requires implementing
980        // Borrow, which we cannot do. Thus, this function exists as a work-around.
981        Image {
982            data: self.data.into_owned().into(),
983            ..self
984        }
985    }
986}
987
988fn compute_depth_1_address(x: usize, order: ImageOrder) -> (usize, usize) {
989    let bit = match order {
990        ImageOrder::MsbFirst => 7 - x % 8,
991        ImageOrder::LsbFirst => x % 8,
992    };
993    (x / 8, bit)
994}
995
996#[cfg(test)]
997mod test_image {
998    use super::{BitsPerPixel, Image, ImageOrder, ParseError, ScanlinePad};
999    use std::borrow::Cow;
1000
1001    #[test]
1002    fn test_new_too_short() {
1003        let depth = 16;
1004        // Due to Pad16, this image needs two bytes
1005        let result = Image::new(
1006            1,
1007            1,
1008            ScanlinePad::Pad16,
1009            depth,
1010            BitsPerPixel::B8,
1011            ImageOrder::MsbFirst,
1012            Cow::Owned(vec![0]),
1013        );
1014        assert_eq!(result.unwrap_err(), ParseError::InsufficientData);
1015    }
1016
1017    #[test]
1018    fn test_new() {
1019        let depth = 16;
1020        let image = Image::new(
1021            2,
1022            1,
1023            ScanlinePad::Pad16,
1024            depth,
1025            BitsPerPixel::B8,
1026            ImageOrder::MsbFirst,
1027            Cow::Owned(vec![42, 125]),
1028        )
1029        .unwrap();
1030        assert_eq!(image.width(), 2);
1031        assert_eq!(image.height(), 1);
1032        assert_eq!(image.scanline_pad(), ScanlinePad::Pad16);
1033        assert_eq!(image.depth(), depth);
1034        assert_eq!(image.bits_per_pixel(), BitsPerPixel::B8);
1035        assert_eq!(image.byte_order(), ImageOrder::MsbFirst);
1036        assert_eq!(image.data(), [42, 125]);
1037    }
1038
1039    #[test]
1040    fn test_into_owned_keeps_owned_data() {
1041        fn with_data(data: Cow<'_, [u8]>) -> *const u8 {
1042            let orig_ptr = data.as_ptr();
1043            let image = Image::new(
1044                1,
1045                1,
1046                ScanlinePad::Pad8,
1047                1,
1048                BitsPerPixel::B1,
1049                ImageOrder::MsbFirst,
1050                data,
1051            )
1052            .unwrap();
1053            assert_eq!(image.data().as_ptr(), orig_ptr);
1054            image.into_owned().data().as_ptr()
1055        }
1056
1057        // Cow::Borrowed is copied
1058        let data = vec![0];
1059        let orig_ptr = data.as_ptr();
1060        assert_ne!(with_data(Cow::Borrowed(&data)), orig_ptr);
1061
1062        // Cow::Owned is kept
1063        assert_eq!(with_data(Cow::Owned(data)), orig_ptr);
1064    }
1065
1066    #[test]
1067    fn put_pixel_depth1() {
1068        let mut image = Image::allocate(
1069            16,
1070            2,
1071            ScanlinePad::Pad32,
1072            1,
1073            BitsPerPixel::B1,
1074            ImageOrder::MsbFirst,
1075        );
1076        for x in 0..8 {
1077            image.put_pixel(x, 0, 1);
1078        }
1079        assert_eq!(0b_1111_1111, image.data()[0]);
1080
1081        image.put_pixel(0, 0, 0);
1082        assert_eq!(0b_0111_1111, image.data()[0]);
1083
1084        image.put_pixel(2, 0, 0);
1085        assert_eq!(0b_0101_1111, image.data()[0]);
1086
1087        image.put_pixel(4, 0, 0);
1088        assert_eq!(0b_0101_0111, image.data()[0]);
1089
1090        image.put_pixel(6, 0, 0);
1091        assert_eq!(0b_0101_0101, image.data()[0]);
1092
1093        image.data_mut()[1] = 0;
1094
1095        image.put_pixel(8, 0, 1);
1096        assert_eq!(0b_1000_0000, image.data()[1]);
1097
1098        image.put_pixel(15, 0, 1);
1099        assert_eq!(0b_1000_0001, image.data()[1]);
1100
1101        assert_eq!(0b_0000_0000, image.data()[5]);
1102        image.put_pixel(15, 1, 1);
1103        assert_eq!(0b_0000_0001, image.data()[5]);
1104    }
1105
1106    #[test]
1107    fn put_pixel_depth4() {
1108        let mut image = Image::allocate(
1109            8,
1110            2,
1111            ScanlinePad::Pad16,
1112            1,
1113            BitsPerPixel::B4,
1114            ImageOrder::MsbFirst,
1115        );
1116        for pos in 0..=0xf {
1117            image.put_pixel(pos % 8, pos / 8, pos.into());
1118        }
1119        assert_eq!(
1120            image.data(),
1121            [0x10, 0x32, 0x54, 0x76, 0x98, 0xBA, 0xDC, 0xFE]
1122        );
1123    }
1124
1125    #[test]
1126    fn put_pixel_depth8() {
1127        let mut image = Image::allocate(
1128            256,
1129            2,
1130            ScanlinePad::Pad8,
1131            1,
1132            BitsPerPixel::B8,
1133            ImageOrder::MsbFirst,
1134        );
1135        for x in 0..=0xff {
1136            image.put_pixel(x, 0, x.into());
1137        }
1138        image.put_pixel(255, 1, 0x1245_89AB);
1139        let expected = (0..=0xff)
1140            .chain((0..0xff).map(|_| 0))
1141            .chain(std::iter::once(0xAB))
1142            .collect::<Vec<_>>();
1143        assert_eq!(image.data(), &expected[..]);
1144    }
1145
1146    #[test]
1147    fn put_pixel_depth16() {
1148        let mut image = Image::allocate(
1149            5,
1150            2,
1151            ScanlinePad::Pad32,
1152            1,
1153            BitsPerPixel::B16,
1154            ImageOrder::MsbFirst,
1155        );
1156        image.put_pixel(0, 0, 0xAB_36_18_F8);
1157        image.put_pixel(4, 0, 0x12_34_56_78);
1158        image.put_pixel(4, 1, 0xFE_DC_BA_98);
1159        #[rustfmt::skip]
1160        let expected = [
1161            // First row
1162            0x18, 0xF8, 0, 0, 0, 0, 0, 0, 0x56, 0x78,
1163            // Padding Pad32
1164            0, 0,
1165            // Second row
1166            0, 0, 0, 0, 0, 0, 0, 0, 0xBA, 0x98,
1167            // Padding Pad32
1168            0, 0,
1169        ];
1170        assert_eq!(image.data(), expected);
1171    }
1172
1173    #[test]
1174    fn put_pixel_depth32() {
1175        let mut image = Image::allocate(
1176            2,
1177            2,
1178            ScanlinePad::Pad32,
1179            1,
1180            BitsPerPixel::B32,
1181            ImageOrder::MsbFirst,
1182        );
1183        image.put_pixel(0, 0, 0xAB_36_18_F8);
1184        image.put_pixel(1, 0, 0x12_34_56_78);
1185        image.put_pixel(1, 1, 0xFE_DC_BA_98);
1186        #[rustfmt::skip]
1187        let expected = [
1188            // First row
1189            0xAB, 0x36, 0x18, 0xF8, 0x12, 0x34, 0x56, 0x78,
1190            // Second row
1191            0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0xBA, 0x98,
1192        ];
1193        assert_eq!(image.data(), expected);
1194    }
1195
1196    #[test]
1197    fn get_pixel_depth1() {
1198        let image = Image::new(
1199            16,
1200            2,
1201            ScanlinePad::Pad32,
1202            1,
1203            BitsPerPixel::B1,
1204            ImageOrder::MsbFirst,
1205            Cow::Borrowed(&DATA),
1206        )
1207        .unwrap();
1208        assert_eq!(1, image.get_pixel(0, 0));
1209        assert_eq!(1, image.get_pixel(10, 0));
1210        assert_eq!(0, image.get_pixel(15, 0));
1211        assert_eq!(0, image.get_pixel(0, 1));
1212        assert_eq!(1, image.get_pixel(10, 1));
1213        assert_eq!(0, image.get_pixel(15, 1));
1214    }
1215
1216    #[test]
1217    fn get_pixel_depth4() {
1218        let image = Image::new(
1219            16,
1220            2,
1221            ScanlinePad::Pad32,
1222            1,
1223            BitsPerPixel::B4,
1224            ImageOrder::MsbFirst,
1225            Cow::Borrowed(&DATA),
1226        )
1227        .unwrap();
1228        assert_eq!(0xB, image.get_pixel(0, 0));
1229        assert_eq!(0x4, image.get_pixel(10, 0));
1230        assert_eq!(0x7, image.get_pixel(15, 0));
1231        assert_eq!(0x0, image.get_pixel(0, 1));
1232        assert_eq!(0xC, image.get_pixel(10, 1));
1233        assert_eq!(0x9, image.get_pixel(15, 1));
1234    }
1235
1236    #[test]
1237    fn get_pixel_depth8() {
1238        let image = Image::new(
1239            3,
1240            2,
1241            ScanlinePad::Pad32,
1242            1,
1243            BitsPerPixel::B8,
1244            ImageOrder::MsbFirst,
1245            Cow::Borrowed(&DATA),
1246        )
1247        .unwrap();
1248        assert_eq!(0xAB, image.get_pixel(0, 0));
1249        assert_eq!(0x36, image.get_pixel(1, 0));
1250        assert_eq!(0x18, image.get_pixel(2, 0));
1251        assert_eq!(0x12, image.get_pixel(0, 1));
1252        assert_eq!(0x34, image.get_pixel(1, 1));
1253        assert_eq!(0x56, image.get_pixel(2, 1));
1254    }
1255
1256    #[test]
1257    fn get_pixel_depth16() {
1258        let image = Image::new(
1259            3,
1260            2,
1261            ScanlinePad::Pad32,
1262            1,
1263            BitsPerPixel::B16,
1264            ImageOrder::MsbFirst,
1265            Cow::Borrowed(&DATA),
1266        )
1267        .unwrap();
1268        assert_eq!(0xAB36, image.get_pixel(0, 0));
1269        assert_eq!(0x18F8, image.get_pixel(1, 0));
1270        assert_eq!(0x1234, image.get_pixel(2, 0));
1271        assert_eq!(0x0000, image.get_pixel(0, 1));
1272        assert_eq!(0x0000, image.get_pixel(1, 1));
1273        assert_eq!(0xFEDC, image.get_pixel(2, 1));
1274    }
1275
1276    #[test]
1277    fn get_pixel_depth32() {
1278        let image = Image::new(
1279            2,
1280            2,
1281            ScanlinePad::Pad32,
1282            1,
1283            BitsPerPixel::B32,
1284            ImageOrder::MsbFirst,
1285            Cow::Borrowed(&DATA),
1286        )
1287        .unwrap();
1288        assert_eq!(0xAB36_18F8, image.get_pixel(0, 0));
1289        assert_eq!(0x1234_5678, image.get_pixel(1, 0));
1290        assert_eq!(0x0000_0000, image.get_pixel(0, 1));
1291        assert_eq!(0xFEDC_BA98, image.get_pixel(1, 1));
1292    }
1293
1294    static DATA: [u8; 16] = [
1295        0xAB, 0x36, 0x18, 0xF8, 0x12, 0x34, 0x56, 0x78, 0x00, 0x00, 0x00, 0x00, 0xFE, 0xDC, 0xBA,
1296        0x98,
1297    ];
1298}