fast image operations
use vec2's
bendn 2023-10-15
parent cd17b48 · commit c264f73
-rw-r--r--Cargo.toml1
-rw-r--r--src/drawing/line.rs25
-rw-r--r--src/drawing/poly.rs46
-rw-r--r--src/drawing/tri.rs15
-rw-r--r--src/lib.rs1
5 files changed, 51 insertions, 37 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 7d1ddc4..1b1bde0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -11,6 +11,7 @@ exclude = ["tdata", "benches/", ".gitignore"]
[dependencies]
mattr = "0.0.2"
png = { version = "0.17", features = ["unstable"], optional = true }
+vecto = "0.1.0"
[dev-dependencies]
iai = { version = "0.1.1", features = [
diff --git a/src/drawing/line.rs b/src/drawing/line.rs
index 3498d95..e1dde96 100644
--- a/src/drawing/line.rs
+++ b/src/drawing/line.rs
@@ -2,6 +2,7 @@
#![allow(clippy::missing_docs_in_private_items)]
use crate::Image;
use std::iter::Iterator;
+use vecto::Vec2;
/// taken from [bresenham-rs](https://github.com/mbr/bresenham-rs)
pub struct Bresenham {
@@ -156,20 +157,18 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// ```
pub fn thick_line(
&mut self,
- (x1, y1): (f32, f32),
- (x2, y2): (f32, f32),
+ a: impl Into<Vec2>,
+ b: impl Into<Vec2>,
stroke: f32,
color: [u8; CHANNELS],
) {
- let (wx, wy) = {
- let (x, y) = (y1 - y2, -(x1 - x2));
- let l = (x * x + y * y).sqrt();
- ((x / l) * (stroke / 2.0), (y / l) * (stroke / 2.0))
- };
+ let a = a.into();
+ let b = b.into();
+ let w = (a - b).orthogonal().normalized() * (stroke / 2.0);
macro_rules! p {
- ($x:expr,$y:expr) => {
+ ($x:expr) => {
#[allow(clippy::cast_possible_truncation)]
- ($x.round() as i32, $y.round() as i32)
+ ($x.x.round() as i32, $x.y.round() as i32)
};
}
// order:
@@ -177,10 +176,10 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
// [ ]
// ^ x3 ^ x4
self.quad(
- p!(x1 - wx, y1 - wy), // x1
- p!(x2 - wx, y2 - wy), // x2
- p!(x2 + wx, y2 + wy), // x3
- p!(x1 + wx, y1 + wy), // x4
+ p!(a - w), // x1
+ p!(b - w), // x2
+ p!(b + w), // x3
+ p!(a + w), // x4
color,
);
}
diff --git a/src/drawing/poly.rs b/src/drawing/poly.rs
index ecad1ab..0b8f3ac 100644
--- a/src/drawing/poly.rs
+++ b/src/drawing/poly.rs
@@ -2,6 +2,7 @@
use crate::math::{madd, FExt};
use std::cmp::{max, min};
use std::f32::consts::TAU;
+use vecto::Vec2;
use crate::Image;
@@ -97,22 +98,22 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// ```
pub fn poly(
&mut self,
- (x, y): (f32, f32),
+ pos: impl Into<Vec2>,
sides: usize,
radius: f32,
rotation: f32,
c: [u8; CHANNELS],
) {
- let trans = |a: f32| (a.cos() * radius, a.sin() * radius);
- let r = |(a, b): (f32, f32)| (a.round() as i32, b.round() as i32);
- let add = |(a, b)| (a + x, b + y);
+ let pos = pos.into();
+ let trans = |a: f32| Vec2::from_angle(a) * radius;
+ let r = |v: Vec2| (v.x.round() as i32, v.y.round() as i32);
match sides {
3 => {
let space = TAU / 3.0;
self.tri(
- add(trans(space + rotation)),
- add(trans(rotation)),
- add(trans(madd(space, 2.0, rotation))),
+ trans(space + rotation) + pos,
+ trans(rotation) + pos,
+ trans(madd(space, 2.0, rotation)) + pos,
c,
);
}
@@ -120,10 +121,10 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
let space = TAU / sides as f32;
for i in (0..sides - 1).step_by(2).map(|i| i as f32) {
self.quad(
- r((x, y)),
- r(add(trans(madd(space, i, rotation)))),
- r(add(trans(madd(space, i + 1., rotation)))),
- r(add(trans(madd(space, i + 2., rotation)))),
+ r(pos),
+ r(trans(madd(space, i, rotation)) + pos),
+ r(trans(madd(space, i + 1., rotation)) + pos),
+ r(trans(madd(space, i + 2., rotation)) + pos),
c,
);
}
@@ -132,9 +133,9 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
let i = (sides - 1) as f32;
// the missing piece
self.tri(
- (x, y),
- add(trans(madd(space, i, rotation))),
- add(trans(madd(space, i + 1., rotation))),
+ pos,
+ trans(madd(space, i, rotation)) + pos,
+ trans(madd(space, i + 1., rotation)) + pos,
c,
);
}
@@ -152,13 +153,14 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// ```
pub fn border_poly(
&mut self,
- (x, y): (f32, f32),
+ pos: impl Into<Vec2>,
sides: usize,
radius: f32,
rotation: f32,
stroke: f32,
c: [u8; CHANNELS],
) {
+ let pos = pos.into();
let space = TAU / sides as f32;
let step = stroke / 2.0 / (space / 2.0).cos();
let r1 = radius - step;
@@ -167,10 +169,16 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
for i in 0..sides {
let a = space.madd(i as f32, rotation);
self.quad(
- r(r1.madd(a.cos(), x), r1.madd(a.sin(), y)),
- r(r1.madd((a + space).cos(), x), r1.madd((a + space).sin(), y)),
- r(r2.madd((a + space).cos(), x), r2.madd((a + space).sin(), y)),
- r(r2.madd(a.cos(), x), r2.madd(a.sin(), y)),
+ r(r1.madd(a.cos(), pos.x), r1.madd(a.sin(), pos.y)),
+ r(
+ r1.madd((a + space).cos(), pos.x),
+ r1.madd((a + space).sin(), pos.y),
+ ),
+ r(
+ r2.madd((a + space).cos(), pos.x),
+ r2.madd((a + space).sin(), pos.y),
+ ),
+ r(r2.madd(a.cos(), pos.x), r2.madd(a.sin(), pos.y)),
c,
);
}
diff --git a/src/drawing/tri.rs b/src/drawing/tri.rs
index 1333abe..5fb90bb 100644
--- a/src/drawing/tri.rs
+++ b/src/drawing/tri.rs
@@ -1,4 +1,6 @@
//! trongle drawing
+use vecto::Vec2;
+
use crate::math::madd;
use crate::Image;
use std::cmp::{max, min};
@@ -19,11 +21,14 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
/// ```
pub fn tri(
&mut self,
- (x2, y2): (f32, f32),
- (x1, y1): (f32, f32),
- (x3, y3): (f32, f32),
- c: [u8; CHANNELS],
+ b: impl Into<Vec2>,
+ a: impl Into<Vec2>,
+ c: impl Into<Vec2>,
+ col: [u8; CHANNELS],
) {
+ let Vec2 { x: x1, y: y1 } = a.into();
+ let Vec2 { x: x2, y: y2 } = b.into();
+ let Vec2 { x: x3, y: y3 } = c.into();
let ymin = max(y1.min(y2).min(y3) as u32, 0);
let ymax = min(y1.max(y2).max(y3) as u32, self.height());
let xmin = max(x1.min(x2).min(x3) as u32, 0);
@@ -36,7 +41,7 @@ impl<T: AsMut<[u8]> + AsRef<[u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
&& madd(x3 - x1, y as f32 - y3, -(y3 - y1) * (x as f32 - x3)) > 0.
{
// SAFETY: x, y are bounded
- unsafe { self.set_pixel(x, y, c) };
+ unsafe { self.set_pixel(x, y, col) };
}
}
}
diff --git a/src/lib.rs b/src/lib.rs
index 1427562..cd82ba8 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -254,6 +254,7 @@ impl<const CHANNELS: usize, const N: usize> Image<[u8; N], CHANNELS> {
impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
/// Box this image.
pub fn boxed(self) -> Image<Box<[u8]>, CHANNELS> {
+ // SAFETY: ctor
unsafe { Image::new(self.width, self.height, self.buffer.into()) }
}
}