fast image operations
-rw-r--r--Cargo.toml11
-rw-r--r--README.md9
-rw-r--r--benches/3_4x4.imgbuf (renamed from benches/3_8x8.imgbuf)0
-rw-r--r--benches/3x3_at_out.imgbuf1
-rw-r--r--benches/4_4x4.imgbuf (renamed from benches/4_8x8.imgbuf)0
-rw-r--r--benches/4x3_at_out.imgbuf1
-rw-r--r--benches/4x4_at_out.imgbuf1
-rw-r--r--benches/affine_transformations.rs23
-rw-r--r--benches/overlays.rs83
-rw-r--r--src/affine.rs149
-rw-r--r--src/builder.rs98
-rw-r--r--src/cat.pngbin2533832 -> 0 bytes
-rw-r--r--src/drawing/box.rs65
-rw-r--r--src/drawing/line.rs174
-rw-r--r--src/drawing/mod.rs4
-rw-r--r--src/drawing/tri.rs45
-rw-r--r--src/lib.rs246
-rw-r--r--src/overlay.rs82
-rw-r--r--src/scale.rs41
-rw-r--r--src/small_cat.pngbin77497 -> 0 bytes
-rw-r--r--test_data/4_180x180.imgbuf (renamed from benches/4_160x160.imgbuf)bin102400 -> 102400 bytes
21 files changed, 231 insertions, 802 deletions
diff --git a/Cargo.toml b/Cargo.toml
index d1554b0..ab92c06 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,27 +1,24 @@
[package]
name = "fimg"
-version = "0.4.1"
+version = "0.1.0"
authors = ["bend-n <[email protected]>"]
license = "MIT"
edition = "2021"
description = "fast image operations"
repository = "https://github.com/bend-n/fimg"
-exclude = ["src/cat.png", "src/small_cat.png", "benches/"]
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
png = { version = "0.17", features = ["unstable"], optional = true }
[dev-dependencies]
-iai = { version = "0.1.1", features = [], git = "https://github.com/bend-n/iai/" }
+criterion = "0.5"
[[bench]]
name = "overlays"
harness = false
-[[bench]]
-name = "affine_transformations"
-harness = false
-
[features]
save = ["png"]
default = ["save"]
diff --git a/README.md b/README.md
index 8e36c96..f77c5cc 100644
--- a/README.md
+++ b/README.md
@@ -6,11 +6,4 @@ quick simple image operations
- [x] overlay
- [x] rotation
-- [x] flipping
-- [x] nearest neighbor scaling
-- [x] triangle drawing
-- [x] simple line drawing
-- [x] box drawing
-- [ ] thick box drawing
-- [ ] thick line drawing
-- [ ] polygon drawing
+- [x] flipping \ No newline at end of file
diff --git a/benches/3_8x8.imgbuf b/benches/3_4x4.imgbuf
index f3a8624..f3a8624 100644
--- a/benches/3_8x8.imgbuf
+++ b/benches/3_4x4.imgbuf
diff --git a/benches/3x3_at_out.imgbuf b/benches/3x3_at_out.imgbuf
new file mode 100644
index 0000000..21d0141
--- /dev/null
+++ b/benches/3x3_at_out.imgbuf
@@ -0,0 +1 @@
+Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ��ˤ�ˤӮ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ�Ӯ� \ No newline at end of file
diff --git a/benches/4_8x8.imgbuf b/benches/4_4x4.imgbuf
index bc6cdf8..bc6cdf8 100644
--- a/benches/4_8x8.imgbuf
+++ b/benches/4_4x4.imgbuf
diff --git a/benches/4x3_at_out.imgbuf b/benches/4x3_at_out.imgbuf
new file mode 100644
index 0000000..d5d8851
--- /dev/null
+++ b/benches/4x3_at_out.imgbuf
@@ -0,0 +1 @@
+������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������ \ No newline at end of file
diff --git a/benches/4x4_at_out.imgbuf b/benches/4x4_at_out.imgbuf
new file mode 100644
index 0000000..4dedb62
--- /dev/null
+++ b/benches/4x4_at_out.imgbuf
@@ -0,0 +1 @@
+���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������� \ No newline at end of file
diff --git a/benches/affine_transformations.rs b/benches/affine_transformations.rs
deleted file mode 100644
index b74d9ba..0000000
--- a/benches/affine_transformations.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use fimg::*;
-
-macro_rules! bench {
- (fn $name: ident() { run $fn: ident() }) => {
- fn $name() {
- let mut img: Image<_, 4> =
- Image::build(160, 160).buf(include_bytes!("4_160x160.imgbuf").to_vec());
- for _ in 0..256 {
- #[allow(unused_unsafe)]
- unsafe {
- img.$fn()
- };
- }
- }
- };
-}
-
-bench!(fn flip_h() { run flip_h() });
-bench!(fn flip_v() { run flip_v() });
-bench!(fn rotate_90() { run rot_90() });
-bench!(fn rotate_180() { run rot_180() });
-bench!(fn rotate_270() { run rot_270() });
-iai::main!(flip_h, flip_v, rotate_90, rotate_180, rotate_270);
diff --git a/benches/overlays.rs b/benches/overlays.rs
index 46e10f6..2236905 100644
--- a/benches/overlays.rs
+++ b/benches/overlays.rs
@@ -1,32 +1,65 @@
+use criterion::{criterion_group, criterion_main, Criterion};
use fimg::*;
-fn overlay_3on3at() {
- let mut a: Image<_, 3> = Image::alloc(128, 128);
- let b: Image<&[u8], 3> = Image::build(8, 8).buf(include_bytes!("3_8x8.imgbuf"));
- for x in 0..16 {
- for y in 0..16 {
- unsafe { a.as_mut().overlay_at(&b, x * 8, y * 8) };
- }
+pub fn criterion_benchmark(bench: &mut Criterion) {
+ let mut group = bench.benchmark_group("overlays");
+ {
+ let mut a: Image<_, 3> = Image::alloc(64, 64);
+ let b = Image::<&[u8], 3>::new(
+ 4.try_into().unwrap(),
+ 4.try_into().unwrap(),
+ *&include_bytes!("3_4x4.imgbuf"),
+ );
+ group.bench_function("overlay 3x3 offset", |bench| {
+ bench.iter(|| unsafe {
+ for x in 0..16 {
+ for y in 0..16 {
+ a.as_mut().overlay_at(&b, x * 4, y * 4);
+ }
+ }
+ });
+ });
+ assert_eq!(a.as_ref().buffer, include_bytes!("3x3_at_out.imgbuf"));
}
-}
+ {
+ let mut a: Image<_, 3> = Image::alloc(64, 64);
+ let b = Image::<&[u8], 4>::new(
+ 4.try_into().unwrap(),
+ 4.try_into().unwrap(),
+ *&include_bytes!("4_4x4.imgbuf"),
+ );
+ group.bench_function("overlay 4x3 offset", |bench| {
+ bench.iter(|| unsafe {
+ for x in 0..16 {
+ for y in 0..16 {
+ a.as_mut().overlay_at(&b, x * 4, y * 4);
+ }
+ }
+ });
+ });
-fn overlay_4on3at() {
- let mut a: Image<_, 3> = Image::alloc(128, 128);
- let b: Image<&[u8], 4> = Image::build(8, 8).buf(include_bytes!("4_8x8.imgbuf"));
- for x in 0..16 {
- for y in 0..16 {
- unsafe { a.as_mut().overlay_at(&b, x * 8, y * 8) };
- }
+ assert_eq!(a.as_ref().buffer, include_bytes!("4x3_at_out.imgbuf"));
}
-}
-
-fn overlay_4on4at() {
- let mut a: Image<_, 4> = Image::alloc(128, 128);
- let b: Image<&[u8], 4> = Image::build(8, 8).buf(include_bytes!("4_8x8.imgbuf"));
- for x in 0..16 {
- for y in 0..16 {
- unsafe { a.as_mut().overlay_at(&b, x * 8, y * 8) };
- }
+ {
+ let mut a: Image<_, 4> = Image::alloc(64, 64);
+ let b = Image::<&[u8], 4>::new(
+ 4.try_into().unwrap(),
+ 4.try_into().unwrap(),
+ *&include_bytes!("4_4x4.imgbuf"),
+ );
+ group.bench_function("overlay 4x4 offset", |bench| {
+ bench.iter(|| unsafe {
+ for x in 0..16 {
+ for y in 0..16 {
+ a.as_mut().overlay_at(&b, x * 4, y * 4);
+ }
+ }
+ });
+ });
+ assert_eq!(a.as_ref().buffer, include_bytes!("4x4_at_out.imgbuf"));
}
+ group.finish();
}
-iai::main!(overlay_3on3at, overlay_4on3at, overlay_4on4at);
+
+criterion_group!(benches, criterion_benchmark);
+criterion_main!(benches);
diff --git a/src/affine.rs b/src/affine.rs
index 362a746..393b571 100644
--- a/src/affine.rs
+++ b/src/affine.rs
@@ -1,92 +1,87 @@
-//! Manages the affine image transformations.
-use crate::Image;
+use crate::{FromRefMut, Image};
+
+pub trait Rotations {
+ /// Rotate a image 180 degrees clockwise.
+ fn rot_180(&mut self);
+ /// Rotate a image 90 degrees clockwise.
+ /// # Safety
+ ///
+ /// UB if the image is not square
+ unsafe fn rot_90(&mut self);
+ /// Rotate a image 270 degrees clockwise, or 90 degrees anti clockwise.
+ /// # Safety
+ ///
+ /// UB if the image is not square
+ unsafe fn rot_270(&mut self);
+}
+
+pub trait Flips {
+ /// Flip a image vertically.
+ fn flip_v(&mut self);
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
/// Flip a image horizontally.
- pub fn flip_h(&mut self) {
+ fn flip_h(&mut self);
+}
+
+impl<const CHANNELS: usize> Flips for Image<Vec<u8>, CHANNELS> {
+ fn flip_h(&mut self) {
self.as_mut().flip_h();
}
- /// Flip a image vertically.
- pub fn flip_v(&mut self) {
+ fn flip_v(&mut self) {
self.as_mut().flip_v();
}
}
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Flip a image vertically.
- pub fn flip_v(&mut self) {
+impl<const CHANNELS: usize> Flips for Image<&mut [u8], CHANNELS> {
+ fn flip_v(&mut self) {
for y in 0..self.height() / 2 {
for x in 0..self.width() {
let y2 = self.height() - y - 1;
- #[allow(clippy::multiple_unsafe_ops_per_block)]
// SAFETY: within bounds
- unsafe {
- let p2 = self.pixel(x, y2);
- let p = self.pixel(x, y);
- self.set_pixel(x, y2, p);
- self.set_pixel(x, y, p2);
- }
+ let p2 = unsafe { self.pixel(x, y2) };
+ let p = unsafe { self.pixel(x, y) };
+ unsafe { self.set_pixel(x, y2, p) };
+ unsafe { self.set_pixel(x, y, p2) };
}
}
}
- /// Flip a image horizontally.
- pub fn flip_h(&mut self) {
+ fn flip_h(&mut self) {
for y in 0..self.height() {
for x in 0..self.width() / 2 {
let x2 = self.width() - x - 1;
- #[allow(clippy::multiple_unsafe_ops_per_block)]
- // SAFETY: bounded
- unsafe {
- let p2 = self.pixel(x2, y);
- let p = self.pixel(x, y);
- self.set_pixel(x2, y, p);
- self.set_pixel(x, y, p2);
- }
+ let p2 = unsafe { self.pixel(x2, y) };
+ let p = unsafe { self.pixel(x, y) };
+ unsafe { self.set_pixel(x2, y, p) };
+ unsafe { self.set_pixel(x, y, p2) };
}
}
}
}
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- /// Rotate a image 180 degrees clockwise.
- pub fn rot_180(&mut self) {
+impl<const CHANNELS: usize> Rotations for Image<Vec<u8>, CHANNELS> {
+ fn rot_180(&mut self) {
self.as_mut().rot_180();
}
- /// Rotate a image 90 degrees clockwise.
- /// # Safety
- ///
- /// UB if the image is not square
- pub unsafe fn rot_90(&mut self) {
- // SAFETY: make sure to keep the safety docs linked
+ unsafe fn rot_90(&mut self) {
unsafe { self.as_mut().rot_90() }
}
- /// Rotate a image 270 degrees clockwise, or 90 degrees anti clockwise.
- /// # Safety
- ///
- /// UB if the image is not square
- pub unsafe fn rot_270(&mut self) {
- // SAFETY: idk this is just a convenience impl
+ unsafe fn rot_270(&mut self) {
unsafe { self.as_mut().rot_270() }
}
}
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Rotate a image 180 degrees clockwise.
- pub fn rot_180(&mut self) {
+impl<const CHANNELS: usize> Rotations for Image<&mut [u8], CHANNELS> {
+ fn rot_180(&mut self) {
for y in 0..self.height() / 2 {
for x in 0..self.width() {
- // SAFETY: x, y come from the loop, must be ok
let p = unsafe { self.pixel(x, y) };
let x2 = self.width() - x - 1;
let y2 = self.height() - y - 1;
- // SAFETY: values are good
let p2 = unsafe { self.pixel(x2, y2) };
- // SAFETY: swapping would be cool, alas.
unsafe { self.set_pixel(x, y, p2) };
- // SAFETY: although maybe i can cast it to a `[[u8; CHANNELS]]` and swap that 🤔
unsafe { self.set_pixel(x2, y2, p) };
}
}
@@ -95,38 +90,26 @@ impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
let middle = self.height() / 2;
for x in 0..self.width() / 2 {
+ let p = unsafe { self.pixel(x, middle) };
let x2 = self.width() - x - 1;
- #[allow(clippy::multiple_unsafe_ops_per_block)]
- // SAFETY: its just doing the swappy
- unsafe {
- let p = self.pixel(x, middle);
- let p2 = self.pixel(x2, middle);
- self.set_pixel(x, middle, p2);
- self.set_pixel(x2, middle, p);
- }
+ let p2 = unsafe { self.pixel(x2, middle) };
+ unsafe { self.set_pixel(x, middle, p2) };
+ unsafe { self.set_pixel(x2, middle, p) };
}
}
}
- /// Rotate a image 90 degrees clockwise.
- /// # Safety
- ///
- /// UB if the image is not square
#[inline]
- pub unsafe fn rot_90(&mut self) {
+ unsafe fn rot_90(&mut self) {
// This is done by first flipping
self.flip_v();
- // Then transposing the image, as to not allocate.
+ // Then transposing the image, to save allocations.
// SAFETY: caller ensures square
unsafe { transpose(self) };
}
- /// Rotate a image 270 degrees clockwise, or 90 degrees anti clockwise.
- /// # Safety
- ///
- /// UB if the image is not square
#[inline]
- pub unsafe fn rot_270(&mut self) {
+ unsafe fn rot_270(&mut self) {
self.flip_h();
// SAFETY: caller ensures squareness
unsafe { transpose(self) };
@@ -236,3 +219,35 @@ mod tests {
);
}
}
+
+#[cfg(test)]
+mod bench {
+ use super::*;
+ extern crate test;
+ use crate::Image;
+ use test::Bencher;
+
+ macro_rules! bench {
+ (fn $name: ident() { run $fn: ident() }) => {
+ #[bench]
+ fn $name(b: &mut Bencher) {
+ let mut img: Image<_, 4> = Image::new(
+ 64.try_into().unwrap(),
+ 64.try_into().unwrap(),
+ include_bytes!("../test_data/4_180x180.imgbuf").to_vec(),
+ );
+ b.iter(|| {
+ for _ in 0..256 {
+ img.flip_h();
+ }
+ });
+ }
+ };
+ }
+
+ bench!(fn flip_h() { run flip_h() });
+ bench!(fn flip_v() { run flip_v() });
+ bench!(fn rotate_90() { run rot_90() });
+ bench!(fn rotate_180() { run rot_180() });
+ bench!(fn rotate_270() { run rot_270() });
+}
diff --git a/src/builder.rs b/src/builder.rs
deleted file mode 100644
index be5a837..0000000
--- a/src/builder.rs
+++ /dev/null
@@ -1,98 +0,0 @@
-//! safe builder for the image
-//!
-//! does not let you do funny things
-use std::marker::PhantomData;
-
-use crate::Image;
-
-impl<B: buf::Buffer, const C: usize> Image<B, C> {
- /// creates a builder
- pub const fn build(w: u32, h: u32) -> Builder<B, C> {
- Builder::new(w, h)
- }
-}
-
-/// Safe [Image] builder.
-pub struct Builder<B, const C: usize> {
- /// the width in a zeroable type. zeroable so as to make the check in [`buf`] easier.
- width: u32,
- /// the height in a zeroable type.
- height: u32,
- #[allow(clippy::missing_docs_in_private_items)]
- _buffer: PhantomData<B>,
-}
-impl<B: buf::Buffer, const C: usize> Builder<B, C> {
- /// create new builder
- pub const fn new(w: u32, h: u32) -> Self {
- Self {
- width: w,
- height: h,
- _buffer: PhantomData,
- }
- }
-
- /// apply a buffer, and build
- #[track_caller]
- pub fn buf(self, buffer: B) -> Image<B, C> {
- let len = C as u32 * self.width * self.height;
- assert!(
- buffer.len() as u32 == len,
- "invalid buffer size (expected {len}, got {})",
- buffer.len()
- );
- Image {
- buffer,
- width: self.width.try_into().expect("passed zero width to builder"),
- height: self
- .height
- .try_into()
- .expect("passed zero height to builder"),
- }
- }
-}
-
-impl<const C: usize> Builder<Vec<u8>, C> {
- /// allocate this image
- pub fn alloc(self) -> Image<Vec<u8>, C> {
- Image::alloc(self.width, self.height)
- }
-}
-
-/// seals the [`Buffer`] trait
-mod buf {
- /// A valid buffer for use in the builder
- pub trait Buffer {
- #[doc(hidden)]
- fn len(&self) -> usize;
- }
- impl<T> Buffer for Vec<T> {
- fn len(&self) -> usize {
- self.len()
- }
- }
- impl<T> Buffer for &[T] {
- fn len(&self) -> usize {
- <[T]>::len(self)
- }
- }
- impl<T> Buffer for &mut [T] {
- fn len(&self) -> usize {
- <[T]>::len(self)
- }
- }
- impl<T, const N: usize> Buffer for [T; N] {
- fn len(&self) -> usize {
- N
- }
- }
- impl<T, const N: usize> Buffer for &[T; N] {
- fn len(&self) -> usize {
- N
- }
- }
- impl<T, const N: usize> Buffer for &mut [T; N] {
- fn len(&self) -> usize {
- N
- }
- }
-}
diff --git a/src/cat.png b/src/cat.png
deleted file mode 100644
index 361804d..0000000
--- a/src/cat.png
+++ /dev/null
Binary files differ
diff --git a/src/drawing/box.rs b/src/drawing/box.rs
deleted file mode 100644
index 15f183f..0000000
--- a/src/drawing/box.rs
+++ /dev/null
@@ -1,65 +0,0 @@
-//! `Box<cat>`
-use crate::Image;
-
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Draw a bordered box
- ///
- /// # Safety
- ///
- /// UB if the box is out of bounds
- /// ```
- /// # use fimg::Image;
- /// let mut b = Image::alloc(10, 9);
- /// unsafe { b.as_mut().r#box((1, 1), 7, 6, [255]) };
- /// # assert_eq!(b.buffer(), b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\x00\x00\x00\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\x00\x00\x00\xff\x00\x00\xff\x00\x00\x00\x00\x00\x00\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
- /// ```
- pub unsafe fn r#box(
- &mut self,
- (x1, y1): (u32, u32),
- width: u32,
- height: u32,
- c: [u8; CHANNELS],
- ) {
- // skip sides, leave that to second loop
- for x in x1 + 1..width + x1 {
- // top line
- // SAFETY: responsibility is on caller
- unsafe { self.set_pixel(x, x1, c) };
- // bottom line
- // SAFETY: shift responsibility
- unsafe { self.set_pixel(x, x1 + height, c) };
- }
- for y in y1..=height + y1 {
- // SAFETY: >> responsibility
- unsafe { self.set_pixel(y1, y, c) };
- // SAFETY: << responsibility
- unsafe { self.set_pixel(y1 + width, y, c) };
- }
- }
-
- /// Draw a *filled* box.
- ///
- /// # Safety
- ///
- /// UB if box is out of bounds
- /// ```
- /// # use fimg::Image;
- /// let mut b = Image::alloc(10, 9);
- /// unsafe { b.as_mut().filled_box((1, 1), 7, 6, [255]) };
- /// # assert_eq!(b.buffer(), b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\xff\xff\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00")
- /// ```
- pub unsafe fn filled_box(
- &mut self,
- (x1, y1): (u32, u32),
- width: u32,
- height: u32,
- c: [u8; CHANNELS],
- ) {
- for x in x1..=width + x1 {
- for y in y1..=height + y1 {
- // SAFETY: fill it
- unsafe { self.set_pixel(x, y, c) };
- }
- }
- }
-}
diff --git a/src/drawing/line.rs b/src/drawing/line.rs
deleted file mode 100644
index c48f923..0000000
--- a/src/drawing/line.rs
+++ /dev/null
@@ -1,174 +0,0 @@
-//! adds a `line` function to Image
-#![allow(clippy::missing_docs_in_private_items)]
-use crate::Image;
-use std::iter::Iterator;
-
-/// taken from https://github.com/mbr/bresenham-rs/
-pub struct Bresenham {
- x: i32,
- y: i32,
- dx: i32,
- dy: i32,
- x1: i32,
- diff: i32,
- octant: Octant,
-}
-
-#[derive(Copy, Clone)]
-struct Octant(u8);
-
-impl Octant {
- #[inline]
- const fn from_points(start: (i32, i32), end: (i32, i32)) -> Octant {
- let mut dx = end.0 - start.0;
- let mut dy = end.1 - start.1;
-
- let mut octant = 0;
-
- if dy < 0 {
- dx = -dx;
- dy = -dy;
- octant += 4;
- }
-
- if dx < 0 {
- let tmp = dx;
- dx = dy;
- dy = -tmp;
- octant += 2
- }
-
- if dx < dy {
- octant += 1
- }
-
- Octant(octant)
- }
-
- #[inline]
- const fn to_octant0(self, p: (i32, i32)) -> (i32, i32) {
- match self.0 {
- 0 => (p.0, p.1),
- 1 => (p.1, p.0),
- 2 => (p.1, -p.0),
- 3 => (-p.0, p.1),
- 4 => (-p.0, -p.1),
- 5 => (-p.1, -p.0),
- 6 => (-p.1, p.0),
- 7 => (p.0, -p.1),
- _ => unreachable!(),
- }
- }
-
- #[inline]
- #[allow(clippy::wrong_self_convention)]
- fn from_octant0(self, p: (i32, i32)) -> (i32, i32) {
- match self.0 {
- 0 => (p.0, p.1),
- 1 => (p.1, p.0),
- 2 => (-p.1, p.0),
- 3 => (-p.0, p.1),
- 4 => (-p.0, -p.1),
- 5 => (-p.1, -p.0),
- 6 => (p.1, -p.0),
- 7 => (p.0, -p.1),
- _ => unreachable!(),
- }
- }
-}
-
-impl Bresenham {
- /// Creates a new iterator. Yields intermediate points between `start`
- /// and `end`. Includes `start` and `end`.
- #[inline]
- pub const fn new(start: (i32, i32), end: (i32, i32)) -> Bresenham {
- let octant = Octant::from_points(start, end);
-
- let start = octant.to_octant0(start);
- let end = octant.to_octant0(end);
-
- let dx = end.0 - start.0;
- let dy = end.1 - start.1;
-
- Bresenham {
- x: start.0,
- y: start.1,
- dy,
- dx,
- x1: end.0,
- diff: dy - dx,
- octant,
- }
- }
-}
-
-impl Iterator for Bresenham {
- type Item = (i32, i32);
-
- #[inline]
- fn next(&mut self) -> Option<Self::Item> {
- if self.x > self.x1 {
- return None;
- }
-
- let p = (self.x, self.y);
-
- if self.diff >= 0 {
- self.y += 1;
- self.diff -= self.dx;
- }
-
- self.diff += self.dy;
-
- // loop inc
- self.x += 1;
-
- Some(self.octant.from_octant0(p))
- }
-}
-
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Draw a line from point a to point b
- ///
- /// Points not in bounds will not be included.
- ///
- /// Uses [bresenshams](https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) line algorithm.
- pub fn line(&mut self, a: (i32, i32), b: (i32, i32), color: [u8; CHANNELS]) {
- for (x, y) in Bresenham::new(a, b).map(|(x, y)| (x as u32, y as u32)) {
- if x < self.width() && y < self.height() {
- // SAFETY: bound are checked ^
- unsafe { self.set_pixel(x, y, color) };
- }
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn bresenham() {
- macro_rules! test_bresenham {
- ($a:expr, $b:expr => [$(($x:expr, $y:expr)),+]) => {{
- let mut bi = Bresenham::new($a, $b);
- $(assert_eq!(bi.next(), Some(($x, $y)));)+
- assert_eq!(bi.next(), None);
- }}
- }
- test_bresenham!((6, 4), (0, 1) => [(6, 4), (5, 4), (4, 3), (3, 3), (2, 2), (1, 2), (0, 1)]);
- test_bresenham!((2, 3), (2, 6) => [(2, 3), (2, 4), (2, 5), (2, 6)]);
- test_bresenham!((2, 3), (5, 3) => [(2, 3), (3, 3), (4, 3), (5, 3)]);
- test_bresenham!((0, 1), (6, 4) => [(0, 1), (1, 1), (2, 2), (3, 2), (4, 3), (5, 3), (6, 4)]);
- }
-
- #[test]
- fn line() {
- let mut a = Image::build(5, 5).alloc();
- a.as_mut().line((0, 1), (6, 4), [255]);
- assert_eq!(
- a.buffer,
- b"\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\xff\x00\x00\x00\x00\x00"
- )
- }
-}
diff --git a/src/drawing/mod.rs b/src/drawing/mod.rs
deleted file mode 100644
index 6ffdf23..0000000
--- a/src/drawing/mod.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-//! contains drawing operations, like {line, box, triangle} drawing
-mod r#box;
-mod line;
-mod tri;
diff --git a/src/drawing/tri.rs b/src/drawing/tri.rs
deleted file mode 100644
index 3cc390b..0000000
--- a/src/drawing/tri.rs
+++ /dev/null
@@ -1,45 +0,0 @@
-//! trongle drawing
-use crate::Image;
-
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Draw a (filled) triangle
- ///
- /// # Safety
- ///
- /// UB if any point is out of bounds
- /// ```
- /// # use fimg::*;
- /// let mut a = Image::alloc(10, 10);
- /// // draw a triangle from point a v point b v point c v
- /// // with color white
- /// unsafe { a.as_mut().tri((3.0, 2.0), (8.0, 7.0), (1.0, 8.0), [255]) };
- /// # assert_eq!(a.buffer(), b"\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\xff\xff\xff\xff\x00\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");
- /// ```
- pub unsafe fn tri(
- &mut self,
- (x1, y1): (f32, f32),
- (x2, y2): (f32, f32),
- (x3, y3): (f32, f32),
- c: [u8; CHANNELS],
- ) {
- // TODO optimize
- for y in y1.min(y2).min(y3) as u32..y1.max(y2).max(y3) as u32 {
- for x in x1.min(x2).min(x3) as u32..x1.max(x2).max(x3) as u32 {
- let s = (x1 - x3) * (y as f32 - y3) - (y1 - y2) * (x as f32 - x3);
- let t = (x2 - x1) * (y as f32 - y1) - (y2 - y1) * (x as f32 - x1);
-
- if (s < 0.0) != (t < 0.0) && s != 0.0 && t != 0.0 {
- continue;
- }
-
- let d = (x3 - x2) * (y as f32 - y2) - (y3 - y2) * (x as f32 - x2);
- if d == 0.0 || (d < 0.0) == (s + t <= 0.0) {
- // SAFETY:
- // caller gurantees triangle is in bounds, this loops over the
- // bounding box of the triangle, therefore this is fine.
- unsafe { self.set_pixel(x, y, c) };
- }
- }
- }
- }
-}
diff --git a/src/lib.rs b/src/lib.rs
index 9de0643..fda1cb2 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,42 +1,37 @@
-//! # fimg
-//!
-//! Provides fast image operations, such as rotation, flipping, and overlaying.
#![feature(
slice_swap_unchecked,
- generic_const_exprs,
slice_as_chunks,
unchecked_math,
portable_simd,
- const_option,
array_chunks,
test
)]
#![warn(
- clippy::missing_docs_in_private_items,
clippy::multiple_unsafe_ops_per_block,
- clippy::undocumented_unsafe_blocks,
clippy::missing_const_for_fn,
clippy::missing_safety_doc,
unsafe_op_in_unsafe_fn,
clippy::dbg_macro,
- missing_docs
+ clippy::perf
)]
-#![allow(clippy::zero_prefixed_literal, incomplete_features)]
+#![allow(clippy::zero_prefixed_literal)]
use std::{num::NonZeroU32, slice::SliceIndex};
mod affine;
-pub mod builder;
-mod drawing;
mod overlay;
-pub mod scale;
+pub use affine::{Flips, Rotations};
pub use overlay::{Overlay, OverlayAt};
-/// like assert!(), but causes undefined behaviour at runtime when the condition is not met.
-///
-/// # Safety
-///
-/// UB if condition is false.
+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;
+}
+
macro_rules! assert_unchecked {
($cond:expr) => {{
if !$cond {
@@ -51,12 +46,9 @@ macro_rules! assert_unchecked {
}
use assert_unchecked;
-impl Image<&[u8], 3> {
- /// 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
- pub unsafe fn repeated(&self, x: u32, y: u32) -> Image<Vec<u8>, 3> {
+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()) {
@@ -69,96 +61,54 @@ impl Image<&[u8], 3> {
}
}
-/// calculates a column major index, with unchecked math
#[inline]
unsafe fn really_unsafe_index(x: u32, y: u32, w: u32) -> usize {
// y * w + x
- // SAFETY: FIXME make safe math
let tmp = unsafe { (y as usize).unchecked_mul(w as usize) };
- // SAFETY: FIXME make safe math
unsafe { tmp.unchecked_add(x as usize) }
}
-/// A image with a variable number of channels, and a nonzero size.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Image<T, const CHANNELS: usize> {
- /// column order 2d slice/vec
- buffer: T,
- /// image horizontal size
- width: NonZeroU32,
- /// image vertical size
- height: NonZeroU32,
+ 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]
- /// get the height as a [`u32`]
pub fn height(&self) -> u32 {
self.height.into()
}
#[inline]
- /// get the width as a [`u32`]
pub fn width(&self) -> u32 {
self.width.into()
}
#[inline]
- /// create a new image
- ///
- /// # Safety
- ///
- /// does not check that buffer.len() == w * h * C
- ///
- /// using this with invalid values may result in future UB
- pub const unsafe fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self {
- Self {
+ pub const fn new(width: NonZeroU32, height: NonZeroU32, buffer: T) -> Self {
+ Image {
buffer,
width,
height,
}
}
-
- /// consumes the image, returning the image buffer
- pub fn take_buffer(self) -> T {
- self.buffer
- }
-
- /// returns a immutable reference to the backing buffer
- pub const fn buffer(&self) -> &T {
- &self.buffer
- }
-
- /// returns a mutable(!) reference to the backing buffer
- ///
- /// # Safety
- ///
- /// please do not change buffer size.
- pub unsafe fn buffer_mut(&mut self) -> &mut T {
- &mut self.buffer
- }
-}
-
-impl<const CHANNELS: usize, T: Clone> Image<&[T], CHANNELS> {
- /// Allocate a new `Image<Vec<T>>` from this imageref.
- pub fn to_owned(&self) -> Image<Vec<T>, CHANNELS> {
- // SAFETY: we have been constructed already, so must be valid
- unsafe { Image::new(self.width, self.height, self.buffer.to_vec()) }
- }
-}
-
-impl<const CHANNELS: usize, T: Clone> Image<&mut [T], CHANNELS> {
- /// Allocate a new `Image<Vec<T>>` from this mutable imageref.
- pub fn to_owned(&self) -> Image<Vec<T>, CHANNELS> {
- // SAFETY: we have been constructed already, so must be valid
- unsafe { Image::new(self.width, self.height, self.buffer.to_vec()) }
- }
}
impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
#[inline]
#[must_use]
- /// Copy this ref image
pub const fn copy(&self) -> Self {
Self {
width: self.width,
@@ -166,28 +116,6 @@ impl<const CHANNELS: usize> Image<&[u8], CHANNELS> {
buffer: self.buffer,
}
}
-
- /// Create a new immutable image of width x, y.
- ///
- /// # Panics
- ///
- /// if width || height == 0
- ///
- /// ```
- /// # use fimg::Image;
- /// let img = Image::make::<5, 5>();
- /// # let img: Image<_, 4> = img;
- /// ```
- pub const fn make<'a, const WIDTH: u32, const HEIGHT: u32>() -> Image<&'a [u8], CHANNELS>
- where
- [(); CHANNELS * WIDTH as usize * HEIGHT as usize]: Sized,
- {
- Image {
- width: NonZeroU32::new(WIDTH).expect("passed zero width to builder"),
- height: NonZeroU32::new(HEIGHT).expect("passed zero height to builder"),
- buffer: &[0; CHANNELS * WIDTH as usize * HEIGHT as usize],
- }
- }
}
impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS> {
@@ -199,12 +127,9 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
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");
- // SAFETY: me when uncheck math: 😧
let index = unsafe { really_unsafe_index(x, y, self.width()) };
- // SAFETY: 🧐 is unsound? 😖
let index = unsafe { index.unchecked_mul(CHANNELS) };
debug_assert!(self.buffer.len() > index);
- // SAFETY: as long as the buffer isnt wrong, this is 😄
index..unsafe { index.unchecked_add(CHANNELS) }
}
@@ -225,11 +150,8 @@ impl<T: std::ops::Deref<Target = [u8]>, const CHANNELS: usize> Image<T, CHANNELS
/// - UB if buffer is too small
#[inline]
pub unsafe fn pixel(&self, x: u32, y: u32) -> [u8; CHANNELS] {
- // SAFETY: we have been told x, y is in bounds
let idx = unsafe { self.slice(x, y) };
- // SAFETY: slice always returns a valid index
let ptr = unsafe { self.buffer.get_unchecked(idx).as_ptr().cast() };
- // SAFETY: slice always returns a length of `CHANNELS`, so we `cast()` it for convenience.
unsafe { *ptr }
}
}
@@ -242,9 +164,7 @@ impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANN
/// - UB if buffer is too small
#[inline]
pub unsafe fn pixel_mut(&mut self, x: u32, y: u32) -> &mut [u8] {
- // SAFETY: we have been told x, y is in bounds.
let idx = unsafe { self.slice(x, y) };
- // SAFETY: slice should always return a valid index
unsafe { self.buffer.get_unchecked_mut(idx) }
}
@@ -272,39 +192,37 @@ impl<T: std::ops::DerefMut<Target = [u8]>, const CHANNELS: usize> Image<T, CHANN
}
}
-impl<const CHANNELS: usize> Image<&mut [u8], CHANNELS> {
- /// Downcast the mutable reference
- pub fn as_ref(&self) -> Image<&[u8], CHANNELS> {
- // SAFETY: we got constructed okay, parameters must be valid
- unsafe { Image::new(self.width, self.height, self.buffer) }
+pub trait FromRef<const CHANNELS: usize> {
+ /// Reference the buffer
+ fn as_ref(&self) -> Image<&[u8], CHANNELS>;
+}
+
+pub trait FromRefMut<const CHANNELS: usize> {
+ /// Reference the buffer, mutably
+ fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS>;
+}
+
+impl<const CHANNELS: usize> FromRef<CHANNELS> for Image<&mut [u8], CHANNELS> {
+ fn as_ref(&self) -> Image<&[u8], CHANNELS> {
+ Image::new(self.width, self.height, self.buffer)
}
+}
- /// Copy this ref image
- pub fn copy(&mut self) -> Image<&mut [u8], CHANNELS> {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- Image::new(self.width, self.height, self.buffer)
- }
+impl<const CHANNELS: usize> FromRefMut<CHANNELS> for Image<&mut [u8], CHANNELS> {
+ fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
+ Image::new(self.width, self.height, self.buffer)
}
}
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- /// Create a reference to this owned image
- pub fn as_ref(&self) -> Image<&[u8], CHANNELS> {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- Image::new(self.width, self.height, &self.buffer)
- }
+impl<const CHANNELS: usize> FromRef<CHANNELS> for Image<Vec<u8>, CHANNELS> {
+ fn as_ref(&self) -> Image<&[u8], CHANNELS> {
+ Image::new(self.width, self.height, &self.buffer)
}
}
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- /// Create a mutable reference to this owned image
- pub fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
- #[allow(clippy::undocumented_unsafe_blocks)]
- unsafe {
- Image::new(self.width, self.height, &mut self.buffer)
- }
+impl<const CHANNELS: usize> FromRefMut<CHANNELS> for Image<Vec<u8>, CHANNELS> {
+ fn as_mut(&mut self) -> Image<&mut [u8], CHANNELS> {
+ Image::new(self.width, self.height, &mut self.buffer)
}
}
@@ -316,27 +234,15 @@ impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
/// if width || height == 0
#[must_use]
pub fn alloc(width: u32, height: u32) -> Self {
- Self {
+ Image {
width: width.try_into().unwrap(),
height: height.try_into().unwrap(),
buffer: vec![0; CHANNELS * width as usize * height as usize],
}
}
}
-
-/// helper macro for defining the save() method.
macro_rules! save {
($channels:literal == $clr:ident ($clrhuman:literal)) => {
- impl Image<Vec<u8>, $channels> {
- #[cfg(feature = "save")]
- #[doc = "Save this "]
- #[doc = $clrhuman]
- #[doc = " image."]
- pub fn save(&self, f: impl AsRef<std::path::Path>) {
- self.as_ref().save(f)
- }
- }
-
impl Image<&[u8], $channels> {
#[cfg(feature = "save")]
#[doc = "Save this "]
@@ -362,29 +268,6 @@ macro_rules! save {
};
}
-impl<const CHANNELS: usize> Image<Vec<u8>, CHANNELS> {
- #[cfg(feature = "save")]
- /// Open a PNG image
- pub fn open(f: impl AsRef<std::path::Path>) -> Self {
- let p = std::fs::File::open(f).unwrap();
- let r = std::io::BufReader::new(p);
- let dec = png::Decoder::new(r);
- let mut reader = dec.read_info().unwrap();
- let mut buf = vec![0; reader.output_buffer_size()];
- let info = reader.next_frame(&mut buf).unwrap();
- use png::ColorType::*;
- match info.color_type {
- Indexed | Grayscale => {
- assert_eq!(CHANNELS, 1, "indexed | grayscale requires one channel")
- }
- Rgb => assert_eq!(CHANNELS, 3, "rgb requires three channels"),
- Rgba => assert_eq!(CHANNELS, 4, "rgba requires four channels"),
- GrayscaleAlpha => assert_eq!(CHANNELS, 2, "ya requires two channels"),
- }
- Self::build(info.width, info.height).buf(buf)
- }
-}
-
save!(3 == Rgb("RGB"));
save!(4 == Rgba("RGBA"));
save!(2 == GrayscaleAlpha("YA"));
@@ -392,19 +275,14 @@ save!(1 == Grayscale("Y"));
#[cfg(test)]
macro_rules! img {
- [[$($v:literal),+] [$($v2:literal),+]] => {
- Image::<Vec<u8>, 1>::build(2,2).buf(vec![$($v,)+ $($v2,)+])
- }
+ [[$($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)]
use img;
-
-#[cfg(test)]
-mod tests {
- use super::*;
- #[test]
- fn repeat() {
- let x: Image<&[u8], 3> = Image::build(8, 8).buf(include_bytes!("../benches/3_8x8.imgbuf"));
- unsafe { x.repeated(128, 128) }; // repeat 16 times
- }
-}
diff --git a/src/overlay.rs b/src/overlay.rs
index 3dbc45e..d1211a9 100644
--- a/src/overlay.rs
+++ b/src/overlay.rs
@@ -1,10 +1,8 @@
-//! Handles image overlay
use super::{assert_unchecked, really_unsafe_index, Image};
use std::simd::SimdInt;
use std::simd::SimdPartialOrd;
use std::simd::{simd_swizzle, Simd};
-/// Trait for layering a image ontop of another, with a offset to the second image.
pub trait OverlayAt<W> {
/// Overlay with => self at coordinates x, y, without blending
/// # Safety
@@ -12,8 +10,7 @@ pub trait OverlayAt<W> {
/// UB if x, y is out of bounds
unsafe fn overlay_at(&mut self, with: &W, x: u32, y: u32) -> &mut Self;
}
-/// Trait for layering images ontop of each other.
-/// Think `magick a b -layers flatten a`
+
pub trait Overlay<W> {
/// Overlay with => self (does not blend)
/// # Safety
@@ -23,20 +20,15 @@ pub trait Overlay<W> {
}
#[inline]
-/// SIMD accelerated rgba => rgb overlay.
-///
-/// See [blit](https://en.wikipedia.org/wiki/Bit_blit)
-///
-/// # Safety
-/// - UB if rgb.len() % 3 != 0
-/// - UB if rgba.len() % 4 != 0
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() {
- // SAFETY: i think it ok
let old: Simd<u8, 16> = Simd::from_slice(unsafe { rgb.get_unchecked(dsti..dsti + 16) });
- // SAFETY: definetly ok
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>();
@@ -44,13 +36,10 @@ unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
threshold,
[3, 3, 3, 7, 7, 7, 11, 11, 11, 15, 15, 15, 0, 0, 0, 0]
);
- mask &= Simd::from_array([
- 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 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);
- // SAFETY: 4 * 4 == 16, so in bounds
blended.copy_to_slice(unsafe { rgb.get_unchecked_mut(dsti..dsti + 16) });
srci += 16;
@@ -58,13 +47,10 @@ unsafe fn blit(rgb: &mut [u8], rgba: &[u8]) {
}
while dsti + 3 <= rgb.len() {
- // SAFETY: caller gurantees slice is big enough
if unsafe { *rgba.get_unchecked(srci + 3) } >= 128 {
- // SAFETY: slice is big enough!
- let src = unsafe { rgba.get_unchecked(srci..=srci + 2) };
- // SAFETY: i hear it bound
- let end = unsafe { rgb.get_unchecked_mut(dsti..=dsti + 2) };
- end.copy_from_slice(src);
+ 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;
@@ -79,9 +65,16 @@ impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 4> {
debug_assert!(self.height() == with.height());
for (i, other_pixels) in with.chunked().enumerate() {
if other_pixels[3] >= 128 {
- // SAFETY: outside are bounds of index from slice
- let own_pixels = unsafe { self.buffer.get_unchecked_mut(i * 4..i * 4 + 4) };
- own_pixels.copy_from_slice(other_pixels);
+ 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
@@ -91,9 +84,9 @@ impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 4> {
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 this
+ // SAFETY: caller upholds these
unsafe { assert_unchecked!(x + with.width() <= self.width()) };
- debug_assert!(y + with.height() <= self.height());
+ 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;
@@ -102,11 +95,8 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> {
+ x as usize
+ with.width() as usize)
* 3;
- // SAFETY: index is in bounds
let rgb = unsafe { self.buffer.get_unchecked_mut(o_x) };
- // SAFETY: bounds are outside index
let rgba = unsafe { with.buffer.get_unchecked(i_x) };
- // SAFETY: arguments are 🟢
unsafe { blit(rgb, rgba) }
}
self
@@ -114,16 +104,8 @@ impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 3> {
}
impl OverlayAt<Image<&[u8], 3>> for Image<&mut [u8], 3> {
- /// Overlay a RGB image(with) => self at coordinates x, y.
- /// As this is a `RGBxRGB` operation, blending is unnecessary,
- /// and this is simply a copy.
- ///
- /// # Safety
- ///
- /// UB if x, y is out of bounds
#[inline]
unsafe fn overlay_at(&mut self, with: &Image<&[u8], 3>, x: u32, y: u32) -> &mut Self {
- /// helper macro for defining rgb=>rgb overlays. allows unrolling
macro_rules! o3x3 {
($n:expr) => {{
for j in 0..($n as usize) {
@@ -131,12 +113,7 @@ impl OverlayAt<Image<&[u8], 3>> for Image<&mut [u8], 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;
- // <= because ".." range
- debug_assert!(o_x.end <= self.buffer().len());
- debug_assert!(i_x.end <= with.buffer().len());
- // SAFETY: bounds are ✅
let a = unsafe { self.buffer.get_unchecked_mut(o_x) };
- // SAFETY: we are in ⬜!
let b = unsafe { with.buffer.get_unchecked(i_x) };
a.copy_from_slice(b);
}
@@ -162,13 +139,11 @@ impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 3> {
.chunks_exact(with.width() as usize * 4)
.enumerate()
{
- // SAFETY: all the bounds are good
let rgb = unsafe {
self.buffer.get_unchecked_mut(
i * with.width() as usize * 3..(i + 1) * with.width() as usize * 3,
)
};
- // SAFETY: we have the rgb and rgba arguments right
unsafe { blit(rgb, chunk) };
}
self
@@ -177,30 +152,15 @@ impl Overlay<Image<&[u8], 4>> for Image<&mut [u8], 3> {
impl OverlayAt<Image<&[u8], 4>> for Image<&mut [u8], 4> {
#[inline]
- /// Overlay with => self at coordinates x, y, without blending
- ///
- /// # Safety
- /// - UB if x, y is out of bounds
- /// - UB if x + with.width() > [`u32::MAX`]
- /// - UB if y + with.height() > [`u32::MAX`]
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() {
- // SAFETY: i, j is in bounds.
let index = unsafe { really_unsafe_index(i, j, with.width()) };
- // SAFETY: using .pixel() results in horrible asm (+5k ns/iter)
let their_px = unsafe { with.buffer.get_unchecked(index * 4..index * 4 + 4) };
- // SAFETY: must be sized right
if unsafe { *their_px.get_unchecked(3) } >= 128 {
- // SAFETY:
- // they said it cant go over.
- // i dont know why, but this has performance importance™
let x = unsafe { i.unchecked_add(x) };
- // SAFETY: caller gurantees this cannot overflow.
let y = unsafe { j.unchecked_add(y) };
- // SAFETY: compute the offset index.
let index = unsafe { really_unsafe_index(x, y, self.width()) };
- // SAFETY: if everything else goes well, this is fine
let our_px = unsafe { self.buffer.get_unchecked_mut(index * 4..index * 4 + 4) };
our_px.copy_from_slice(their_px);
}
diff --git a/src/scale.rs b/src/scale.rs
deleted file mode 100644
index 0ba614b..0000000
--- a/src/scale.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-//! holds scaling operations, at current only the Nearest Neighbor
-use crate::Image;
-
-/// [Nearest Neighbor](https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation) image scaling algorithm implementation.
-/// Use [`Nearest::scale`].
-pub struct Nearest;
-impl Nearest {
- /// Resize a image.
- /// # Safety
- ///
- /// `image` must be as big or bigger than `width`, `height.
- pub unsafe fn scale<const N: usize>(
- image: Image<&[u8], N>,
- width: u32,
- height: u32,
- ) -> Image<Vec<u8>, N> {
- let x_scale = image.width() as f32 / width as f32;
- let y_scale = image.height() as f32 / height as f32;
- let mut out = Image::alloc(width, height);
- for y in 0..height {
- for x in 0..width {
- let x1 = ((x as f32 + 0.5) * x_scale).floor() as u32;
- let y1 = ((y as f32 + 0.5) * y_scale).floor() as u32;
- // SAFETY: i asked the caller to make sure its ok
- let px = unsafe { image.pixel(x1, y1) };
- // SAFETY: were looping over the width and height of out. its ok.
- unsafe { out.set_pixel(x, y, px) };
- }
- }
- out
- }
-}
-
-#[test]
-fn test_nearest() {
- let i = Image::<_, 3>::open("src/cat.png");
- assert_eq!(
- unsafe { Nearest::scale(i.as_ref(), 268, 178) }.buffer,
- Image::<_, 3>::open("src/small_cat.png").buffer
- );
-}
diff --git a/src/small_cat.png b/src/small_cat.png
deleted file mode 100644
index ec6e5bf..0000000
--- a/src/small_cat.png
+++ /dev/null
Binary files differ
diff --git a/benches/4_160x160.imgbuf b/test_data/4_180x180.imgbuf
index 58aabd0..58aabd0 100644
--- a/benches/4_160x160.imgbuf
+++ b/test_data/4_180x180.imgbuf
Binary files differ