1use 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#[derive(Debug, Clone, Copy, PartialEq, Eq)]
44pub struct ColorComponent {
45 width: u8,
47 shift: u8,
49}
50
51impl ColorComponent {
52 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 pub fn width(self) -> u8 {
68 self.width
69 }
70
71 pub fn shift(self) -> u8 {
73 self.shift
74 }
75
76 pub fn mask(self) -> u32 {
87 let mask = (1u32 << self.width) - 1;
89 mask << self.shift
91 }
92
93 pub fn from_mask(mask: u32) -> Result<Self, ParseError> {
107 let width = mask.count_ones();
108 let shift = mask.trailing_zeros();
109 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 pub fn decode(self, pixel: u32) -> u16 {
129 let value = (pixel & self.mask()) >> self.shift;
131
132 let mut width = self.width;
134 let mut value = value << (16 - width);
135 while width < 16 {
137 value |= value >> width;
138 width <<= 1;
139 }
140 value.try_into().unwrap()
141 }
142
143 pub fn encode(self, intensity: u16) -> u32 {
152 (u32::from(intensity) >> (16 - self.width)) << self.shift
154 }
155}
156
157#[derive(Debug, Clone, Copy, PartialEq, Eq)]
163pub struct PixelLayout {
164 red: ColorComponent,
165 green: ColorComponent,
166 blue: ColorComponent,
167}
168
169impl PixelLayout {
170 pub fn new(red: ColorComponent, green: ColorComponent, blue: ColorComponent) -> Self {
172 Self { red, green, blue }
173 }
174
175 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 pub fn depth(self) -> u8 {
196 self.red.width + self.green.width + self.blue.width
199 }
200
201 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 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
241fn 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 (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 (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 (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 (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 (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
291fn 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 #[non_exhaustive]
351 pub enum ScanlinePad {
352 Pad8 = 8,
354 Pad16 = 16,
356 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 #[non_exhaustive]
436 pub enum BitsPerPixel {
437 B1 = 1,
439 B4 = 4,
441 B8 = 8,
443 B16 = 16,
445 B24 = 24,
451 B32 = 32,
453 }
454}
455
456#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
461pub enum ImageOrder {
462 LsbFirst,
464 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#[derive(Debug, PartialEq, Eq, Clone)]
482pub struct Image<'a> {
483 width: u16,
485
486 height: u16,
488
489 scanline_pad: ScanlinePad,
491
492 depth: u8,
494
495 bits_per_pixel: BitsPerPixel,
497
498 byte_order: ImageOrder,
502
503 data: Cow<'a, [u8]>,
505}
506
507impl<'a> Image<'a> {
508 pub fn width(&self) -> u16 {
510 self.width
511 }
512
513 pub fn height(&self) -> u16 {
515 self.height
516 }
517
518 pub fn scanline_pad(&self) -> ScanlinePad {
522 self.scanline_pad
523 }
524
525 pub fn depth(&self) -> u8 {
527 self.depth
528 }
529
530 pub fn bits_per_pixel(&self) -> BitsPerPixel {
534 self.bits_per_pixel
535 }
536
537 pub fn byte_order(&self) -> ImageOrder {
542 self.byte_order
543 }
544
545 pub fn data(&self) -> &[u8] {
547 &self.data
548 }
549
550 pub fn data_mut(&mut self) -> &mut [u8] {
555 self.data.to_mut()
556 }
557
558 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 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 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 fn stride(&self) -> usize {
653 compute_stride(self.width, self.bits_per_pixel, self.scanline_pad)
654 }
655
656 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 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 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 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, self.depth,
771 data,
772 )?);
773
774 y_offset += next_lines;
775 byte_offset = next_byte_offset;
776 }
777 Ok(result)
778 }
779
780 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 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 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 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 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 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 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 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 pub fn into_owned(self) -> Image<'static> {
979 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 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 let data = vec![0];
1059 let orig_ptr = data.as_ptr();
1060 assert_ne!(with_data(Cow::Borrowed(&data)), orig_ptr);
1061
1062 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 0x18, 0xF8, 0, 0, 0, 0, 0, 0, 0x56, 0x78,
1163 0, 0,
1165 0, 0, 0, 0, 0, 0, 0, 0, 0xBA, 0x98,
1167 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 0xAB, 0x36, 0x18, 0xF8, 0x12, 0x34, 0x56, 0x78,
1190 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}