mindustry logic execution, map- and schematic- parsing and rendering
move image out
bendn 2023-09-05
parent 8d474e3 · commit f5a8619
-rw-r--r--Cargo.toml6
-rw-r--r--src/data/renderer.rs2
-rw-r--r--src/utils/image/affine.rs186
-rw-r--r--src/utils/image/holder.rs10
-rw-r--r--src/utils/image/mod.rs259
-rw-r--r--src/utils/image/overlay.rs231
-rw-r--r--src/utils/mod.rs2
7 files changed, 10 insertions, 686 deletions
diff --git a/Cargo.toml b/Cargo.toml
index cc089fe..46ced3b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "mindus"
-version = "4.0.15"
+version = "4.0.17"
edition = "2021"
description = "A library for working with mindustry data formats (eg schematics and maps) (fork of plandustry)"
authors = [
@@ -19,7 +19,6 @@ base64 = "0.21"
paste = "1.0"
strconv = "0.1"
amap = "0.1"
-png = { version = "0.17", features = ["unstable"], optional = true }
color-hex = "0.2"
thiserror = "1.0"
bobbin-bits = "0.1"
@@ -27,9 +26,10 @@ blurslice = { version = "0.1" }
enum_dispatch = "0.3"
fast_image_resize = "2.7"
phf = { version = "0.11", features = ["macros"] }
+fimg = { version = "0.2", default-features = false }
[features]
-bin = ["png"]
+bin = ["fimg/save"]
default = ["bin"]
[build-dependencies]
diff --git a/src/data/renderer.rs b/src/data/renderer.rs
index 62c5fcd..e070022 100644
--- a/src/data/renderer.rs
+++ b/src/data/renderer.rs
@@ -3,7 +3,7 @@ pub(crate) use super::autotile::*;
use super::schematic::Schematic;
use super::GridPos;
use crate::block::Rotation;
-pub(crate) use crate::utils::{Image, ImageHolder, ImageUtils, Overlay, OverlayAt, Repeat};
+pub(crate) use crate::utils::*;
use crate::Map;
include!(concat!(env!("OUT_DIR"), "/full.rs"));
include!(concat!(env!("OUT_DIR"), "/quar.rs"));
diff --git a/src/utils/image/affine.rs b/src/utils/image/affine.rs
deleted file mode 100644
index f2b23bf..0000000
--- a/src/utils/image/affine.rs
+++ /dev/null
@@ -1,186 +0,0 @@
-use super::Image;
-
-/// Rotate a image 180 degrees clockwise.
-pub fn rot_180<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- for y in 0..img.height() / 2 {
- for x in 0..img.width() {
- let p = unsafe { img.pixel(x, y) };
- let x2 = img.width() - x - 1;
- let y2 = img.height() - y - 1;
- let p2 = unsafe { img.pixel(x2, y2) };
- unsafe { img.set_pixel(x, y, p2) };
- unsafe { img.set_pixel(x2, y2, p) };
- }
- }
-
- if img.height() % 2 != 0 {
- let middle = img.height() / 2;
-
- for x in 0..img.width() / 2 {
- let p = unsafe { img.pixel(x, middle) };
- let x2 = img.width() - x - 1;
- let p2 = unsafe { img.pixel(x2, middle) };
- unsafe { img.set_pixel(x, middle, p2) };
- unsafe { img.set_pixel(x2, middle, p) };
- }
- }
-}
-
-/// # Safety
-///
-/// UB if supplied image rectangular
-unsafe fn transpose<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- debug_assert_eq!(img.width(), img.height());
- let size = img.width();
- for i in 0..size {
- for j in i..size {
- for c in 0..CHANNELS {
- // SAFETY: caller gurantees rectangularity
- unsafe {
- img.buffer.swap_unchecked(
- (i * size + j) as usize * CHANNELS + c,
- (j * size + i) as usize * CHANNELS + c,
- )
- };
- }
- }
- }
-}
-
-/// Rotate a image 90 degrees clockwise.
-/// This is done by first [flipping vertically](flip_v), then [transposing](transpose) the image, to save allocations.
-///
-/// # Safety
-///
-/// UB if the image is not square
-#[inline]
-pub unsafe fn rot_90<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- flip_v(img);
- // SAFETY: caller ensures rectangularity
- unsafe { transpose(img) };
-}
-
-/// Rotate a image 270 degrees clockwise, or 90 degrees anti clockwise.
-/// [horizontal flip](flip_h), then [transpose].
-///
-/// # Safety
-///
-/// UB if the image is not square
-#[inline]
-pub unsafe fn rot_270<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- flip_h(img);
- // SAFETY: caller ensures rectangularity
- unsafe { transpose(img) };
-}
-
-/// Flip a image vertically.
-pub fn flip_v<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- for y in 0..img.height() / 2 {
- for x in 0..img.width() {
- let y2 = img.height() - y - 1;
- // SAFETY: within bounds
- let p2 = unsafe { img.pixel(x, y2) };
- let p = unsafe { img.pixel(x, y) };
- unsafe { img.set_pixel(x, y2, p) };
- unsafe { img.set_pixel(x, y, p2) };
- }
- }
-}
-
-/// Flip a image horizontally.
-pub fn flip_h<const CHANNELS: usize>(img: &mut Image<&mut [u8], CHANNELS>) {
- for y in 0..img.height() {
- for x in 0..img.width() / 2 {
- let x2 = img.width() - x - 1;
- let p2 = unsafe { img.pixel(x2, y) };
- let p = unsafe { img.pixel(x, y) };
- unsafe { img.set_pixel(x2, y, p) };
- unsafe { img.set_pixel(x, y, p2) };
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::utils::image::img;
-
- #[test]
- fn rotate_90() {
- let mut from = img![
- [00, 01]
- [02, 10]
- ];
- unsafe { rot_90(&mut from.as_mut()) };
- assert_eq!(
- from,
- img![
- [02, 00]
- [10, 01]
- ]
- );
- }
-
- #[test]
- fn rotate_180() {
- let mut from = img![
- [00, 01]
- [02, 10]
- ];
- rot_180(&mut from.as_mut());
- assert_eq!(
- from,
- img![
- [10, 02]
- [01, 00]
- ]
- );
- }
-
- #[test]
- fn rotate_270() {
- let mut from = img![
- [00, 01]
- [20, 10]
- ];
- unsafe { rot_270(&mut from.as_mut()) };
- assert_eq!(
- from,
- img![
- [01, 10]
- [00, 20]
- ]
- );
- }
-
- #[test]
- fn flip_vertical() {
- let mut from = img![
- [90, 01]
- [21, 42]
- ];
- flip_v(&mut from.as_mut());
- assert_eq!(
- from,
- img![
- [21, 42]
- [90, 01]
- ]
- )
- }
- #[test]
- fn flip_horizontal() {
- let mut from = img![
- [90, 01]
- [21, 42]
- ];
- flip_h(&mut from.as_mut());
- assert_eq!(
- from,
- img![
- [01, 90]
- [42, 21]
- ]
- )
- }
-}
diff --git a/src/utils/image/holder.rs b/src/utils/image/holder.rs
index 4c1b6a5..e905f48 100644
--- a/src/utils/image/holder.rs
+++ b/src/utils/image/holder.rs
@@ -68,16 +68,6 @@ impl ImageUtils for ImageHolder<4> {
self
}
- fn flip_h(&mut self) -> &mut Self {
- self.borrow_mut().flip_h();
- self
- }
-
- fn flip_v(&mut self) -> &mut Self {
- self.borrow_mut().flip_v();
- self
- }
-
fn shadow(&mut self) -> &mut Self {
self.borrow_mut().shadow();
self
diff --git a/src/utils/image/mod.rs b/src/utils/image/mod.rs
index 02c1a43..9d853b6 100644
--- a/src/utils/image/mod.rs
+++ b/src/utils/image/mod.rs
@@ -1,21 +1,8 @@
use fast_image_resize as fr;
-use std::{num::NonZeroU32, slice::SliceIndex};
+pub use fimg::*;
-mod affine;
-use affine::*;
mod holder;
-mod overlay;
-pub use holder::*;
-pub use overlay::*;
-
-pub trait RepeatNew {
- type Output;
- /// Repeat self till it fills a new image of size x, y
- /// # Safety
- ///
- /// UB if self's width is not a multiple of x, or self's height is not a multiple of y
- unsafe fn repeated(&self, x: u32, y: u32) -> Self::Output;
-}
+pub use holder::ImageHolder;
pub trait ImageUtils {
/// Tint this image with the color
@@ -25,51 +12,18 @@ pub trait ImageUtils {
///
/// UB if image is not square
unsafe fn rotate(&mut self, times: u8) -> &mut Self;
- /// flip along the horizontal axis
- fn flip_h(&mut self) -> &mut Self;
- /// flip along the vertical axis
- fn flip_v(&mut self) -> &mut Self;
/// shadow
fn shadow(&mut self) -> &mut Self;
/// scale a image
fn scale(self, to: u32) -> Image<Vec<u8>, 4>;
}
-macro_rules! assert_unchecked {
- ($cond:expr) => {{
- if !$cond {
- #[cfg(debug_assertions)]
- let _ = ::core::ptr::NonNull::<()>::dangling().as_ref(); // force unsafe wrapping block
- #[cfg(debug_assertions)]
- panic!("assertion failed: {} returned false", stringify!($cond));
- #[cfg(not(debug_assertions))]
- std::hint::unreachable_unchecked()
- }
- }};
-}
-use assert_unchecked;
-
-impl RepeatNew for Image<&[u8], 3> {
- type Output = Image<Vec<u8>, 3>;
- unsafe fn repeated(&self, x: u32, y: u32) -> Self::Output {
- let mut img = Image::alloc(x, y); // could probably optimize this a ton but eh
- for x in 0..(x / self.width()) {
- for y in 0..(y / self.height()) {
- let a: &mut Image<&mut [u8], 3> = &mut img.as_mut();
- // SAFETY: caller upholds
- unsafe { a.overlay_at(self, x * self.width(), y * self.height()) };
- }
- }
- img
- }
-}
-
impl ImageUtils for Image<&mut [u8], 4> {
unsafe fn rotate(&mut self, times: u8) -> &mut Self {
match times {
- 2 => rot_180(self),
- 1 => unsafe { rot_90(self) },
- 3 => unsafe { rot_270(self) },
+ 2 => self.rot_180(),
+ 1 => unsafe { self.rot_90() },
+ 3 => unsafe { self.rot_270() },
_ => {}
}
self
@@ -126,209 +80,6 @@ impl ImageUtils for Image<&mut [u8], 4> {
}
self
}
-
- #[inline]
- fn flip_h(&mut self) -> &mut Self {
- flip_h(self);
- self
- }
-
- #[inline(always)]
- fn flip_v(&mut self) -> &mut Self {
- flip_v(self);
- self
- }
-}
-
-#[inline]
-unsafe fn really_unsafe_index(x: u32, y: u32, w: u32) -> usize {
- // y * w + x
- let tmp = unsafe { (y as usize).unchecked_mul(w as usize) };
- unsafe { tmp.unchecked_add(x as usize) }
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Image<T, const CHANNELS: usize> {
- pub buffer: T,
- pub width: NonZeroU32,
- pub height: NonZeroU32,
-}
-
-impl<const CHANNELS: usize> Default for Image<&'static [u8], CHANNELS> {
- fn default() -> Self {
- Self {
- buffer: &[0; CHANNELS],
- width: NonZeroU32::new(1).unwrap(),
- height: NonZeroU32::new(1).unwrap(),
- }
- }
-}
-
-impl<T, const CHANNELS: usize> Image<T, CHANNELS> {
- #[inline]
- pub fn height(&self) -> u32 {
- self.height.into()
- }
-
- #[inline]
- pub fn width(&self) -> u32 {
- self.width.into()
- }
-
- #[inline]
- pub const fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self {
- Image {
- width,
- height,
- buffer,
- }
- }
-}
-
-impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
- #[inline]
- pub const fn copy(&self) -> Self {
- Self {
- width: self.width,
- height: self.height,
- buffer: self.buffer,
- }
- }
-}
-
-impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
- /// # Safety
- ///
- /// - UB if x, y is out of bounds
- /// - UB if buffer is too small
- #[inline]
- pub unsafe fn slice(&self, x: u32, y: u32) -> impl SliceIndex<[u8], Output = [u8]> {
- debug_assert!(x < self.width(), "x out of bounds");
- debug_assert!(y < self.height(), "y out of bounds");
- let index = unsafe { really_unsafe_index(x, y, self.width()) };
- let index = unsafe { index.unchecked_mul(CHANNELS) };
- debug_assert!(self.buffer.len() > index);
- index..unsafe { index.unchecked_add(CHANNELS) }
- }
-
- #[inline]
- pub fn chunked(&self) -> impl Iterator<Item = &[u8; CHANNELS]> {
- // SAFETY: 0 sized images illegal
- unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) };
- // SAFETY: no half pixels!
- unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) };
- self.buffer.array_chunks::<CHANNELS>()
- }
-
- /// Return a pixel at (x, y).
- /// # Safety
- ///
- /// Refer to [`slice`]
- #[inline]
- pub unsafe fn pixel(&self, x: u32, y: u32) -> [u8; CHANNELS] {
- let idx = unsafe { self.slice(x, y) };
- let ptr = unsafe { self.buffer.get_unchecked(idx).as_ptr().cast() };
- unsafe { *ptr }
- }
-}
-
-impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
- /// Return a mutable reference to a pixel at (x, y).
- /// # Safety
- ///
- /// Refer to [`slice`]
- #[inline]
- pub unsafe fn pixel_mut(&mut self, x: u32, y: u32) -> &mut [u8] {
- let idx = unsafe { self.slice(x, y) };
- unsafe { self.buffer.get_unchecked_mut(idx) }
- }
-
- #[inline]
- pub fn chunked_mut(&mut self) -> impl Iterator<Item = &mut [u8; CHANNELS]> {
- // SAFETY: 0 sized images are not allowed
- unsafe { assert_unchecked!(self.buffer.len() > CHANNELS) };
- // SAFETY: buffer cannot have half pixels
- unsafe { assert_unchecked!(self.buffer.len() % CHANNELS == 0) };
- self.buffer.array_chunks_mut::<CHANNELS>()
- }
-
- /// Set the pixel at x, y
- ///
- /// # Safety
- ///
- /// UB if x, y is out of bounds.
- #[inline]
- pub unsafe fn set_pixel(&mut self, x: u32, y: u32, px: [u8; CHANNELS]) {
- // SAFETY: Caller says that x, y is in bounds
- let out = unsafe { self.pixel_mut(x, y) };
- // SAFETY: px must be CHANNELS long
- unsafe { std::ptr::copy_nonoverlapping(px.as_ptr(), out.as_mut_ptr(), CHANNELS) };
- }
-}
-
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- pub fn alloc(width: u32, height: u32) -> Self {
- Image {
- width: width.try_into().unwrap(),
- height: height.try_into().unwrap(),
- buffer: vec![0; CHANNELS * width as usize * height as usize],
- }
- }
-
- pub fn as_ref(&self) -> Image<&[u8], CHANNELS> {
- Image::new(self.width, self.height, &self.buffer)
- }
-
- pub fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
- Image::new(self.width, self.height, &mut self.buffer)
- }
-}
-
-impl Image<Vec<u8>, 3> {
- #[cfg(feature = "bin")]
- pub fn save(&self, f: impl AsRef<std::path::Path>) {
- let p = std::fs::File::create(f).unwrap();
- let w = &mut std::io::BufWriter::new(p);
- let mut enc = png::Encoder::new(w, self.width(), self.height());
- enc.set_color(png::ColorType::Rgb);
- enc.set_depth(png::BitDepth::Eight);
- enc.set_source_gamma(png::ScaledFloat::new(1.0 / 2.2));
- enc.set_source_chromaticities(png::SourceChromaticities::new(
- (0.31270, 0.32900),
- (0.64000, 0.33000),
- (0.30000, 0.60000),
- (0.15000, 0.06000),
- ));
- let mut writer = enc.write_header().unwrap();
- writer.write_image_data(&self.buffer).unwrap();
- }
-}
-
-#[cfg(test)]
-macro_rules! img {
- [[$($v:literal),+] [$($v2:literal),+]] => {{
- let from: Image<Vec<u8>, 1> = Image::new(
- 2.try_into().unwrap(),
- 2.try_into().unwrap(),
- vec![$($v,)+ $($v2,)+]
- );
- from
- }}
-}
-#[cfg(test)]
-pub(self) use img;
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn scale() {
- let mut from = Image::alloc(6, 6);
- unsafe { from.set_pixel(3, 3, [255, 255, 255, 255]) };
- let from = from.as_mut().scale(12);
- assert_eq!(unsafe { from.pixel(6, 6) }, [255, 255, 255, 255]);
- }
}
pub fn blend(bg: &mut [u8; 4], fg: [u8; 4]) {
diff --git a/src/utils/image/overlay.rs b/src/utils/image/overlay.rs
deleted file mode 100644
index 3b6745b..0000000
--- a/src/utils/image/overlay.rs
+++ /dev/null
@@ -1,231 +0,0 @@
-use super::{assert_unchecked, really_unsafe_index, Image};
-use std::simd::SimdInt;
-use std::simd::SimdPartialOrd;
-use std::simd::{simd_swizzle, Simd};
-
-pub trait OverlayAt<W> {
- /// Overlay with => self at coordinates x, y, without blending
- /// # Safety
- ///
- /// UB if x, y is out of bounds
- unsafe fn overlay_at(&mut self, with: &W, x: u32, y: u32) -> &mut Self;
-}
-
-pub trait Overlay<W> {
- /// Overlay with => self (does not blend)
- /// # Safety
- ///
- /// UB if a.width != b.width || a.height != b.height
- unsafe fn overlay(&mut self, with: &W) -> &mut Self;
-}
-
-#[inline]
-pub unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
- const LAST4: Simd<u8, 16> = Simd::from_array([
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0, 0, 0, 0,
- ]);
-
- let mut srci = 0;
- let mut dsti = 0;
- while dsti + 16 <= rgb.len() {
- let old: Simd<u8, 16> = Simd::from_slice(unsafe { rgb.get_unchecked(dsti..dsti + 16) });
- let new: Simd<u8, 16> = Simd::from_slice(unsafe { rgba.get_unchecked(srci..srci + 16) });
-
- let threshold = new.simd_ge(Simd::splat(128)).to_int().cast::<u8>();
- let mut mask = simd_swizzle!(
- threshold,
- [3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0]
- );
- mask &= LAST4;
-
- let new_rgb = simd_swizzle!(new, [0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 0, 0, 0, 0]);
- let blended = (new_rgb & mask) | (old & !mask);
- blended.copy_to_slice(unsafe { rgb.get_unchecked_mut(dsti..dsti + 16) });
-
- srci += 16;
- dsti += 12;
- }
-
- while dsti + 3 <= rgb.len() {
- if unsafe { *rgba.get_unchecked(srci + 3) } >= 128 {
- let src = unsafe { rgba.get_unchecked(srci..srci + 3) };
- let end = unsafe { rgb.get_unchecked_mut(dsti..dsti + 3) };
- unsafe { std::ptr::copy_nonoverlapping(src.as_ptr(), end.as_mut_ptr(), 3) };
- }
-
- srci += 4;
- dsti += 3;
- }
-}
-
-impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 4> {
- #[inline]
- unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self {
- debug_assert!(self.width() == with.width());
- debug_assert!(self.height() == with.height());
- for (i, other_pixels) in with.chunked().enumerate() {
- if other_pixels[3] >= 128 {
- let idx_begin = unsafe { i.unchecked_mul(4) };
- let idx_end = unsafe { idx_begin.unchecked_add(4) };
- let own_pixels = unsafe { self.buffer.get_unchecked_mut(idx_begin..idx_end) };
- unsafe {
- std::ptr::copy_nonoverlapping(other_pixels.as_ptr(), own_pixels.as_mut_ptr(), 4)
- };
- }
- }
- self
- }
-}
-
-impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> {
- #[inline]
- unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self {
- // SAFETY: caller upholds these
- unsafe { assert_unchecked!(x + with.width() <= self.width()) };
- unsafe { assert_unchecked!(y + with.height() <= self.height()) };
- for j in 0..with.height() {
- let i_x = j as usize * with.width() as usize * 4
- ..(j as usize + 1) * with.width() as usize * 4;
- let o_x = ((j as usize + y as usize) * self.width() as usize + x as usize) * 3
- ..((j as usize + y as usize) * self.width() as usize
- + x as usize
- + with.width() as usize)
- * 3;
- let rgb = unsafe { self.buffer.get_unchecked_mut(o_x) };
- let rgba = unsafe { with.buffer.get_unchecked(i_x) };
- unsafe { blit(rgb, rgba) }
- }
- self
- }
-}
-
-impl OverlayAt<Image<&[u8], 3>> for Image<&mut [u8], 3> {
- #[inline]
- unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self {
- macro_rules! o3x3 {
- ($n:expr) => {{
- for j in 0..($n as usize) {
- let i_x = j * ($n as usize) * 3..(j + 1) * ($n as usize) * 3;
- let o_x = ((j + y as usize) * self.width() as usize + x as usize) * 3
- ..((j + y as usize) * self.width() as usize + x as usize + ($n as usize))
- * 3;
- let a = unsafe { self.buffer.get_unchecked_mut(o_x) };
- let b = unsafe { with.buffer.get_unchecked(i_x) };
- a.copy_from_slice(b);
- }
- }};
- }
- // let it unroll
- match with.width() {
- 8 => o3x3!(8),
- 16 => o3x3!(16), // this branch makes 8x8 0.16 times slower; but 16x16 0.2 times faster.
- _ => o3x3!(with.width()),
- }
- self
- }
-}
-
-impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 3> {
- #[inline]
- unsafe fn overlay(&mut self, with: &Image<&[u8], 4>) -> &mut Self {
- debug_assert!(self.width() == with.width());
- debug_assert!(self.height() == with.height());
- for (i, chunk) in with
- .buffer
- .chunks_exact(with.width() as usize * 4)
- .enumerate()
- {
- let rgb = unsafe {
- self.buffer.get_unchecked_mut(
- i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3,
- )
- };
- unsafe { blit(rgb, chunk) };
- }
- self
- }
-}
-
-impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 4> {
- #[inline]
- unsafe fn overlay_at(&mut self, with: &Image<&[u8], 4>, x: u32, y: u32) -> &mut Self {
- for j in 0..with.height() {
- for i in 0..with.width() {
- let index = unsafe { really_unsafe_index(i, j, with.width()) };
- let their_px = unsafe { with.buffer.get_unchecked(index * 4..index * 4 + 4) };
- if unsafe { *their_px.get_unchecked(3) } >= 128 {
- let x = unsafe { i.unchecked_add(x) };
- let y = unsafe { j.unchecked_add(y) };
- let index = unsafe { really_unsafe_index(x, y, self.width()) };
- let our_px = unsafe { self.buffer.get_unchecked_mut(index * 4..index * 4 + 4) };
- our_px.copy_from_slice(their_px);
- }
- }
- }
-
- self
- }
-}
-
-#[cfg(test)]
-mod bench {
- extern crate test;
- use test::{black_box, Bencher};
-
- use super::*;
- use crate::{data::renderer::Scale, load};
-
- #[bench]
- fn overlay_3on3at(bench: &mut Bencher) {
- let mut v = vec![0u8; 3 * 64 * 64];
- let mut a: Image<_, 3> = Image::new(
- 64.try_into().unwrap(),
- 64.try_into().unwrap(),
- v.as_mut_slice(),
- );
- let b = load!("darksand", Scale::Eigth);
- bench.iter(|| unsafe {
- for x in 0..16 {
- for y in 0..16 {
- black_box(a.overlay_at(&b.borrow(), x, y));
- }
- }
- });
- }
-
- #[bench]
- fn overlay_4on3at(bench: &mut Bencher) {
- let mut v = vec![0u8; 3 * 64 * 64];
- let mut a: Image<_, 3> = Image::new(
- 64.try_into().unwrap(),
- 64.try_into().unwrap(),
- v.as_mut_slice(),
- );
- let b = load!("salt-wall", Scale::Eigth);
- bench.iter(|| unsafe {
- for x in 0..16 {
- for y in 0..16 {
- black_box(a.overlay_at(&b.borrow(), x, y));
- }
- }
- });
- }
-
- #[bench]
- fn overlay_4on4at(bench: &mut Bencher) {
- let mut v = vec![0u8; 4 * 64 * 64];
- let mut a: Image<_, 4> = Image::new(
- 64.try_into().unwrap(),
- 64.try_into().unwrap(),
- v.as_mut_slice(),
- );
- let b = load!("salt-wall", Scale::Eigth);
- bench.iter(|| unsafe {
- for x in 0..16 {
- for y in 0..16 {
- black_box(a.overlay_at(&b.borrow(), x, y));
- }
- }
- });
- }
-}
diff --git a/src/utils/mod.rs b/src/utils/mod.rs
index 4518839..3e12541 100644
--- a/src/utils/mod.rs
+++ b/src/utils/mod.rs
@@ -1,3 +1,3 @@
pub mod array;
pub mod image;
-pub use self::image::{Image, ImageHolder, ImageUtils, Overlay, OverlayAt, RepeatNew as Repeat};
+pub use self::image::{Image, ImageHolder, ImageUtils, Overlay, OverlayAt};