Skip to content
Snippets Groups Projects
Verified Commit 15828c2d authored by João Magalhães's avatar João Magalhães :rocket:
Browse files

chore: remove unsafe tag from copy fast

parent ad6f3971
No related branches found
No related tags found
No related merge requests found
Pipeline #4401 passed
//! Color manipulation functions and constants. //! Color manipulation functions and constants.
use crate::util::copy_fast; use crate::util::copy_fast;
pub const RGB_SIZE: usize = 3; pub const RGB_SIZE: usize = 3;
pub const RGBA_SIZE: usize = 4; pub const RGBA_SIZE: usize = 4;
pub const RGB888_SIZE: usize = 3; pub const RGB888_SIZE: usize = 3;
pub const XRGB8888_SIZE: usize = 4; pub const XRGB8888_SIZE: usize = 4;
pub const RGB1555_SIZE: usize = 2; pub const RGB1555_SIZE: usize = 2;
pub const RGB565_SIZE: usize = 2; pub const RGB565_SIZE: usize = 2;
/// Defines the Game Boy pixel type as a buffer /// Defines the Game Boy pixel type as a buffer
/// with the size of RGB (3 bytes). /// with the size of RGB (3 bytes).
pub type Pixel = [u8; RGB_SIZE]; pub type Pixel = [u8; RGB_SIZE];
/// Defines a transparent Game Boy pixel type as a buffer /// Defines a transparent Game Boy pixel type as a buffer
/// with the size of RGBA (4 bytes). /// with the size of RGBA (4 bytes).
pub type PixelAlpha = [u8; RGBA_SIZE]; pub type PixelAlpha = [u8; RGBA_SIZE];
/// Defines a pixel with 5 bits per channel plus a padding /// Defines a pixel with 5 bits per channel plus a padding
/// bit at the beginning. /// bit at the beginning.
pub type PixelRgb1555 = [u8; RGB1555_SIZE]; pub type PixelRgb1555 = [u8; RGB1555_SIZE];
/// Defines a pixel with 5 bits per channel except for the /// Defines a pixel with 5 bits per channel except for the
/// green channel which uses 6 bits. /// green channel which uses 6 bits.
pub type PixelRgb565 = [u8; RGB565_SIZE]; pub type PixelRgb565 = [u8; RGB565_SIZE];
pub fn rgb555_to_rgb888(first: u8, second: u8) -> Pixel { pub fn rgb555_to_rgb888(first: u8, second: u8) -> Pixel {
let r = (first & 0x1f) << 3; let r = (first & 0x1f) << 3;
let g = (((first & 0xe0) >> 5) | ((second & 0x03) << 3)) << 3; let g = (((first & 0xe0) >> 5) | ((second & 0x03) << 3)) << 3;
let b = ((second & 0x7c) >> 2) << 3; let b = ((second & 0x7c) >> 2) << 3;
[r, g, b] [r, g, b]
} }
pub fn rgb888_to_rgb1555(first: u8, second: u8, third: u8) -> PixelRgb1555 { pub fn rgb888_to_rgb1555(first: u8, second: u8, third: u8) -> PixelRgb1555 {
let pixel = rgb888_to_rgb1555_u16(first, second, third); let pixel = rgb888_to_rgb1555_u16(first, second, third);
[pixel as u8, (pixel >> 8) as u8] [pixel as u8, (pixel >> 8) as u8]
} }
pub fn rgb888_to_rgb1555_u16(first: u8, second: u8, third: u8) -> u16 { pub fn rgb888_to_rgb1555_u16(first: u8, second: u8, third: u8) -> u16 {
let r = (first as u16 >> 3) & 0x1f; let r = (first as u16 >> 3) & 0x1f;
let g = (second as u16 >> 3) & 0x1f; let g = (second as u16 >> 3) & 0x1f;
let b = (third as u16 >> 3) & 0x1f; let b = (third as u16 >> 3) & 0x1f;
let a = 1; let a = 1;
(a << 15) | (r << 10) | (g << 5) | b (a << 15) | (r << 10) | (g << 5) | b
} }
pub fn rgb888_to_rgb565(first: u8, second: u8, third: u8) -> PixelRgb565 { pub fn rgb888_to_rgb565(first: u8, second: u8, third: u8) -> PixelRgb565 {
let pixel = rgb888_to_rgb565_u16(first, second, third); let pixel = rgb888_to_rgb565_u16(first, second, third);
[pixel as u8, (pixel >> 8) as u8] [pixel as u8, (pixel >> 8) as u8]
} }
pub fn rgb888_to_rgb565_u16(first: u8, second: u8, third: u8) -> u16 { pub fn rgb888_to_rgb565_u16(first: u8, second: u8, third: u8) -> u16 {
let r = (first as u16 >> 3) & 0x1f; let r = (first as u16 >> 3) & 0x1f;
let g = (second as u16 >> 2) & 0x3f; let g = (second as u16 >> 2) & 0x3f;
let b = (third as u16 >> 3) & 0x1f; let b = (third as u16 >> 3) & 0x1f;
(r << 11) | (g << 5) | b (r << 11) | (g << 5) | b
} }
pub fn rgb888_to_rgb1555_array(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) { pub fn rgb888_to_rgb1555_array(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) {
#[cfg(feature = "simd")] #[cfg(feature = "simd")]
{ {
rgb888_to_rgb1555_simd(rgb888_pixels, rgb1555_pixels); rgb888_to_rgb1555_simd(rgb888_pixels, rgb1555_pixels);
} }
#[cfg(not(feature = "simd"))] #[cfg(not(feature = "simd"))]
{ {
rgb888_to_rgb1555_scalar(rgb888_pixels, rgb1555_pixels); rgb888_to_rgb1555_scalar(rgb888_pixels, rgb1555_pixels);
} }
} }
/// Converts an array of RGB888 pixels to RGB565 format using a scalar implementation. /// Converts an array of RGB888 pixels to RGB565 format using a scalar implementation.
/// ///
/// This method should provide the same results as the SIMD implementation. /// This method should provide the same results as the SIMD implementation.
pub fn rgb888_to_rgb1555_scalar(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) { pub fn rgb888_to_rgb1555_scalar(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) {
assert!( assert!(
rgb888_pixels.len() % 3 == 0, rgb888_pixels.len() % 3 == 0,
"Length of rgb888_pixels must be a multiple of 3" "Length of rgb888_pixels must be a multiple of 3"
); );
assert!( assert!(
rgb1555_pixels.len() % 2 == 0, rgb1555_pixels.len() % 2 == 0,
"Length of rgb1555_pixels must be a multiple of 2" "Length of rgb1555_pixels must be a multiple of 2"
); );
assert!( assert!(
rgb888_pixels.len() / 3 == rgb1555_pixels.len() / 2, rgb888_pixels.len() / 3 == rgb1555_pixels.len() / 2,
"Length of rgb1555_pixels must be two thirds the length of rgb888_pixels" "Length of rgb1555_pixels must be two thirds the length of rgb888_pixels"
); );
for index in 0..rgb888_pixels.len() / RGB_SIZE { for index in 0..rgb888_pixels.len() / RGB_SIZE {
let (r, g, b) = ( let (r, g, b) = (
rgb888_pixels[index * RGB_SIZE], rgb888_pixels[index * RGB_SIZE],
rgb888_pixels[index * RGB_SIZE + 1], rgb888_pixels[index * RGB_SIZE + 1],
rgb888_pixels[index * RGB_SIZE + 2], rgb888_pixels[index * RGB_SIZE + 2],
); );
let rgb1555 = rgb888_to_rgb1555(r, g, b); let rgb1555 = rgb888_to_rgb1555(r, g, b);
unsafe { let output_offset = index * RGB1555_SIZE;
copy_fast( copy_fast(
&rgb1555, &rgb1555,
&mut rgb1555_pixels[index * RGB1555_SIZE..index * RGB1555_SIZE + RGB1555_SIZE], &mut rgb1555_pixels[output_offset..output_offset + RGB1555_SIZE],
RGB1555_SIZE, RGB1555_SIZE,
) )
} }
} }
}
/// Converts an array of RGB888 pixels to RGB1555 format using SIMD.
/// Converts an array of RGB888 pixels to RGB1555 format using SIMD. ///
/// /// This method is only available when the `simd` feature is enabled.
/// This method is only available when the `simd` feature is enabled. ///
/// /// Note: The length of `rgb888_pixels` must be a multiple of 3, and
/// Note: The length of `rgb888_pixels` must be a multiple of 3, and /// `rgb1555_pixels` must be a multiple of 2.
/// `rgb1555_pixels` must be a multiple of 2. #[cfg(feature = "simd")]
#[cfg(feature = "simd")] pub fn rgb888_to_rgb1555_simd(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) {
pub fn rgb888_to_rgb1555_simd(rgb888_pixels: &[u8], rgb1555_pixels: &mut [u8]) { use std::simd::u8x16;
use std::simd::u8x16;
use crate::util::interleave_arrays;
use crate::util::interleave_arrays;
const SIMD_WIDTH: usize = 16;
const SIMD_WIDTH: usize = 16;
assert!(
assert!( rgb888_pixels.len() % 3 == 0,
rgb888_pixels.len() % 3 == 0, "Length of rgb888_pixels must be a multiple of 3"
"Length of rgb888_pixels must be a multiple of 3" );
); assert!(
assert!( rgb1555_pixels.len() % 2 == 0,
rgb1555_pixels.len() % 2 == 0, "Length of rgb1555_pixels must be a multiple of 2"
"Length of rgb1555_pixels must be a multiple of 2" );
); assert!(
assert!( rgb888_pixels.len() / 3 == rgb1555_pixels.len() / 2,
rgb888_pixels.len() / 3 == rgb1555_pixels.len() / 2, "Length of rgb1555_pixels must be two thirds the length of rgb888_pixels"
"Length of rgb1555_pixels must be two thirds the length of rgb888_pixels" );
);
let num_pixels = rgb888_pixels.len() / 3;
let num_pixels = rgb888_pixels.len() / 3; let simd_chunks = num_pixels / SIMD_WIDTH;
let simd_chunks = num_pixels / SIMD_WIDTH;
for index in 0..simd_chunks {
for index in 0..simd_chunks { let offset = index * SIMD_WIDTH * 3;
let offset = index * SIMD_WIDTH * 3; let r = u8x16::from_slice(&[
let r = u8x16::from_slice(&[ rgb888_pixels[offset],
rgb888_pixels[offset], rgb888_pixels[offset + 3],
rgb888_pixels[offset + 3], rgb888_pixels[offset + 6],
rgb888_pixels[offset + 6], rgb888_pixels[offset + 9],
rgb888_pixels[offset + 9], rgb888_pixels[offset + 12],
rgb888_pixels[offset + 12], rgb888_pixels[offset + 15],
rgb888_pixels[offset + 15], rgb888_pixels[offset + 18],
rgb888_pixels[offset + 18], rgb888_pixels[offset + 21],
rgb888_pixels[offset + 21], rgb888_pixels[offset + 24],
rgb888_pixels[offset + 24], rgb888_pixels[offset + 27],
rgb888_pixels[offset + 27], rgb888_pixels[offset + 30],
rgb888_pixels[offset + 30], rgb888_pixels[offset + 33],
rgb888_pixels[offset + 33], rgb888_pixels[offset + 36],
rgb888_pixels[offset + 36], rgb888_pixels[offset + 39],
rgb888_pixels[offset + 39], rgb888_pixels[offset + 42],
rgb888_pixels[offset + 42], rgb888_pixels[offset + 45],
rgb888_pixels[offset + 45], ]);
]); let g = u8x16::from_slice(&[
let g = u8x16::from_slice(&[ rgb888_pixels[offset + 1],
rgb888_pixels[offset + 1], rgb888_pixels[offset + 4],
rgb888_pixels[offset + 4], rgb888_pixels[offset + 7],
rgb888_pixels[offset + 7], rgb888_pixels[offset + 10],
rgb888_pixels[offset + 10], rgb888_pixels[offset + 13],
rgb888_pixels[offset + 13], rgb888_pixels[offset + 16],
rgb888_pixels[offset + 16], rgb888_pixels[offset + 19],
rgb888_pixels[offset + 19], rgb888_pixels[offset + 22],
rgb888_pixels[offset + 22], rgb888_pixels[offset + 25],
rgb888_pixels[offset + 25], rgb888_pixels[offset + 28],
rgb888_pixels[offset + 28], rgb888_pixels[offset + 31],
rgb888_pixels[offset + 31], rgb888_pixels[offset + 34],
rgb888_pixels[offset + 34], rgb888_pixels[offset + 37],
rgb888_pixels[offset + 37], rgb888_pixels[offset + 40],
rgb888_pixels[offset + 40], rgb888_pixels[offset + 43],
rgb888_pixels[offset + 43], rgb888_pixels[offset + 46],
rgb888_pixels[offset + 46], ]);
]); let b = u8x16::from_slice(&[
let b = u8x16::from_slice(&[ rgb888_pixels[offset + 2],
rgb888_pixels[offset + 2], rgb888_pixels[offset + 5],
rgb888_pixels[offset + 5], rgb888_pixels[offset + 8],
rgb888_pixels[offset + 8], rgb888_pixels[offset + 11],
rgb888_pixels[offset + 11], rgb888_pixels[offset + 14],
rgb888_pixels[offset + 14], rgb888_pixels[offset + 17],
rgb888_pixels[offset + 17], rgb888_pixels[offset + 20],
rgb888_pixels[offset + 20], rgb888_pixels[offset + 23],
rgb888_pixels[offset + 23], rgb888_pixels[offset + 26],
rgb888_pixels[offset + 26], rgb888_pixels[offset + 29],
rgb888_pixels[offset + 29], rgb888_pixels[offset + 32],
rgb888_pixels[offset + 32], rgb888_pixels[offset + 35],
rgb888_pixels[offset + 35], rgb888_pixels[offset + 38],
rgb888_pixels[offset + 38], rgb888_pixels[offset + 41],
rgb888_pixels[offset + 41], rgb888_pixels[offset + 44],
rgb888_pixels[offset + 44], rgb888_pixels[offset + 47],
rgb888_pixels[offset + 47], ]);
]);
let r_shifted_high = (r >> 1) & u8x16::splat(0x7c);
let r_shifted_high = (r >> 1) & u8x16::splat(0x7c); let g_shifted_high = (g >> 6) & u8x16::splat(0x03);
let g_shifted_high = (g >> 6) & u8x16::splat(0x03); let g_shifted_low = (g << 2) & u8x16::splat(0xe0);
let g_shifted_low = (g << 2) & u8x16::splat(0xe0); let b_shifted = (b >> 3) & u8x16::splat(0x3f);
let b_shifted = (b >> 3) & u8x16::splat(0x3f);
let high_byte = u8x16::splat(0x80) | r_shifted_high | g_shifted_high;
let high_byte = u8x16::splat(0x80) | r_shifted_high | g_shifted_high; let low_byte = g_shifted_low | b_shifted;
let low_byte = g_shifted_low | b_shifted;
let output_offset = index * SIMD_WIDTH * RGB1555_SIZE;
let output_offset = index * SIMD_WIDTH * RGB1555_SIZE; interleave_arrays(
interleave_arrays( low_byte.as_array(),
low_byte.as_array(), high_byte.as_array(),
high_byte.as_array(), &mut rgb1555_pixels[output_offset..output_offset + SIMD_WIDTH * RGB1555_SIZE],
&mut rgb1555_pixels[output_offset..output_offset + SIMD_WIDTH * RGB1555_SIZE], );
); }
}
let remainder = num_pixels % SIMD_WIDTH;
let remainder = num_pixels % SIMD_WIDTH; let offset = simd_chunks * SIMD_WIDTH * RGB_SIZE;
let offset = simd_chunks * SIMD_WIDTH * RGB_SIZE; let offset_rgb1555 = simd_chunks * SIMD_WIDTH * RGB1555_SIZE;
let offset_rgb1555 = simd_chunks * SIMD_WIDTH * RGB1555_SIZE;
for index in 0..remainder {
for index in 0..remainder { let current_offset = offset + index * RGB_SIZE;
let current_offset = offset + index * RGB_SIZE; let (r, g, b) = (
let (r, g, b) = ( rgb888_pixels[current_offset],
rgb888_pixels[current_offset], rgb888_pixels[current_offset + 1],
rgb888_pixels[current_offset + 1], rgb888_pixels[current_offset + 2],
rgb888_pixels[current_offset + 2], );
); let rgb1555 = rgb888_to_rgb1555(r, g, b);
let rgb1555 = rgb888_to_rgb1555(r, g, b); let output_offset = offset_rgb1555 + index * RGB1555_SIZE;
let output_offset = offset_rgb1555 + index * RGB1555_SIZE; copy_fast(
unsafe { &rgb1555,
copy_fast( &mut rgb1555_pixels[output_offset..output_offset + RGB1555_SIZE],
&rgb1555, RGB1555_SIZE,
&mut rgb1555_pixels[output_offset..output_offset + RGB1555_SIZE], );
RGB1555_SIZE, }
); }
}
} #[cfg(test)]
} mod tests {
use super::{rgb888_to_rgb1555, rgb888_to_rgb1555_scalar};
#[cfg(test)]
mod tests { #[test]
use super::{rgb888_to_rgb1555, rgb888_to_rgb1555_scalar}; fn test_rgb888_to_rgb1555() {
let result = rgb888_to_rgb1555(255, 0, 0);
#[test] assert_eq!(result, [0b00000000, 0b11111100]);
fn test_rgb888_to_rgb1555() {
let result = rgb888_to_rgb1555(255, 0, 0); let result = rgb888_to_rgb1555(0, 255, 0);
assert_eq!(result, [0b00000000, 0b11111100]); assert_eq!(result, [0b11100000, 0b10000011]);
let result = rgb888_to_rgb1555(0, 255, 0); let result = rgb888_to_rgb1555(0, 0, 255);
assert_eq!(result, [0b11100000, 0b10000011]); assert_eq!(result, [0b00011111, 0b10000000]);
let result = rgb888_to_rgb1555(0, 0, 255); let result = rgb888_to_rgb1555(255, 255, 0);
assert_eq!(result, [0b00011111, 0b10000000]); assert_eq!(result, [0b11100000, 0b11111111]);
}
let result = rgb888_to_rgb1555(255, 255, 0);
assert_eq!(result, [0b11100000, 0b11111111]); #[test]
} fn test_rgb888_to_rgb1555_scalar() {
let rgb888_pixels: Vec<u8> = vec![
#[test] 255, 000, 000, // Red
fn test_rgb888_to_rgb1555_scalar() { 000, 255, 000, // Green
let rgb888_pixels: Vec<u8> = vec![ 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 020, 020, 200, // Blueish
255, 255, 000, // Yellow ];
255, 000, 000, // Red let mut rgb1555_pixels: Vec<u8> = vec![0; 36];
020, 020, 200, // Blueish
]; rgb888_to_rgb1555_scalar(&rgb888_pixels, &mut rgb1555_pixels);
let mut rgb1555_pixels: Vec<u8> = vec![0; 36];
let expected_rgb1555: Vec<u8> = vec![
rgb888_to_rgb1555_scalar(&rgb888_pixels, &mut rgb1555_pixels); 0b00000000, 0b11111100, // Red
0b11100000, 0b10000011, // Green
let expected_rgb1555: Vec<u8> = vec![ 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b01011001, 0b10001000, // Blueish
0b11100000, 0b11111111, // Yellow ];
0b00000000, 0b11111100, // Red
0b01011001, 0b10001000, // Blueish assert_eq!(rgb1555_pixels, expected_rgb1555);
]; }
assert_eq!(rgb1555_pixels, expected_rgb1555); #[test]
} #[cfg(feature = "simd")]
fn test_rgb888_to_rgb1555_simd() {
#[test] use super::rgb888_to_rgb1555_simd;
#[cfg(feature = "simd")]
fn test_rgb888_to_rgb1555_simd() { let rgb888_pixels: Vec<u8> = vec![
use super::rgb888_to_rgb1555_simd; 255, 000, 000, // Red
000, 255, 000, // Green
let rgb888_pixels: Vec<u8> = vec![ 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 000, 255, 000, // Green
255, 255, 000, // Yellow 000, 000, 255, // Blue
255, 000, 000, // Red 255, 255, 000, // Yellow
000, 255, 000, // Green 255, 000, 000, // Red
000, 000, 255, // Blue 020, 020, 200, // Blueish
255, 255, 000, // Yellow ];
255, 000, 000, // Red let mut rgb1555_pixels: Vec<u8> = vec![0; 36];
020, 020, 200, // Blueish
]; rgb888_to_rgb1555_simd(&rgb888_pixels, &mut rgb1555_pixels);
let mut rgb1555_pixels: Vec<u8> = vec![0; 36];
let expected_rgb1555: Vec<u8> = vec![
rgb888_to_rgb1555_simd(&rgb888_pixels, &mut rgb1555_pixels); 0b00000000, 0b11111100, // Red
0b11100000, 0b10000011, // Green
let expected_rgb1555: Vec<u8> = vec![ 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b11100000, 0b10000011, // Green
0b11100000, 0b11111111, // Yellow 0b00011111, 0b10000000, // Blue
0b00000000, 0b11111100, // Red 0b11100000, 0b11111111, // Yellow
0b11100000, 0b10000011, // Green 0b00000000, 0b11111100, // Red
0b00011111, 0b10000000, // Blue 0b01011001, 0b10001000, // Blueish
0b11100000, 0b11111111, // Yellow ];
0b00000000, 0b11111100, // Red
0b01011001, 0b10001000, // Blueish assert_eq!(rgb1555_pixels, expected_rgb1555);
]; }
}
assert_eq!(rgb1555_pixels, expected_rgb1555);
}
}
...@@ -118,13 +118,15 @@ pub fn save_bmp(path: &str, pixels: &[u8], width: u32, height: u32) -> Result<() ...@@ -118,13 +118,15 @@ pub fn save_bmp(path: &str, pixels: &[u8], width: u32, height: u32) -> Result<()
/// ///
/// This function is optimized for performance and uses pointer-based /// This function is optimized for performance and uses pointer-based
/// operations to copy the data as fast as possible. /// operations to copy the data as fast as possible.
pub unsafe fn copy_fast(src: &[u8], dst: &mut [u8], count: usize) { pub fn copy_fast(src: &[u8], dst: &mut [u8], count: usize) {
debug_assert!(src.len() >= count); debug_assert!(src.len() >= count);
debug_assert!(dst.len() >= count); debug_assert!(dst.len() >= count);
let src_ptr = src.as_ptr(); unsafe {
let dst_ptr = dst.as_mut_ptr(); let src_ptr = src.as_ptr();
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, count); let dst_ptr = dst.as_mut_ptr();
std::ptr::copy_nonoverlapping(src_ptr, dst_ptr, count);
}
} }
// Interleaves two arrays of bytes into a single array using // Interleaves two arrays of bytes into a single array using
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment