benchmarks comparing the rust image processing ecosystem
bendn 2023-11-01
commit 083382c
-rw-r--r--.gitignore5
-rw-r--r--Cargo.toml29
-rw-r--r--README.md10
-rw-r--r--affine.svg1
-rw-r--r--benches/affine.rs71
-rw-r--r--benches/drawing.rs87
-rw-r--r--benches/resizing.rs50
-rw-r--r--data.pngbin0 -> 44175176 bytes
-rw-r--r--drawing.svg1
-rw-r--r--resizing.svg1
-rw-r--r--src/main.rs1
11 files changed, 256 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..0cf4a1b
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+/target
+data.imgbuf
+*.dat
+*.plot
+Cargo.lock
diff --git a/Cargo.toml b/Cargo.toml
new file mode 100644
index 0000000..2207c03
--- /dev/null
+++ b/Cargo.toml
@@ -0,0 +1,29 @@
+[package]
+name = "imenchmark"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+fimg = { version = "0.4.23", features = [
+ "text",
+ "blur",
+ "scale",
+], git = "https://github.com/bend-n/fimg" }
+iai = { git = "https://github.com/bend-n/iai", version = "0.1.1" }
+image = { version = "0.24.7", default-features = false, features = ["png"] }
+imageproc = { version = "0.23.0", default-features = false }
+umath = "0.0.7"
+
+[[bench]]
+harness = false
+name = "affine"
+
+[[bench]]
+harness = false
+name = "resizing"
+
+[[bench]]
+harness = false
+name = "drawing"
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..f734349
--- /dev/null
+++ b/README.md
@@ -0,0 +1,10 @@
+## a series of benchmarks, comparing [imageproc](https://crates.io/crates/imageproc) and [fimg](https://crates.io/crates/fimg)
+
+![](./affine.svg)
+![](./resizing.svg)
+![](./drawing.svg)
+
+### how to run benchmarks
+
+step 1: unhew. `cargo install --git https://github.com/bend-n/hew && hew data.png data.imgbuf`
+step 2: run. `cargo bench` \ No newline at end of file
diff --git a/affine.svg b/affine.svg
new file mode 100644
index 0000000..0baa667
--- /dev/null
+++ b/affine.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="600" height="480"><path fill="#fff" d="M0 0h600v480H0z"/><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 444h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 447.9)"><tspan> 0</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 389.57h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 393.47)"><tspan> 2x10</tspan><tspan dy="-6" font-size="9.6">8</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 335.15h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 339.05)"><tspan> 4x10</tspan><tspan dy="-6" font-size="9.6">8</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 280.72h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 284.62)"><tspan> 6x10</tspan><tspan dy="-6" font-size="9.6">8</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 226.29h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 230.19)"><tspan> 8x10</tspan><tspan dy="-6" font-size="9.6">8</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 171.86h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 175.76)"><tspan> 1x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 117.44h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 121.34)"><tspan> 1.2x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M106.09 63.01h9m459.73 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(97.7 66.91)"><tspan> 1.4x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M184.21 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(184.21 465.9)"><tspan>270 degrees</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M262.33 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(262.33 465.9)"><tspan>180 degrees</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M340.46 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(340.46 465.9)"><tspan>90 degrees</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M418.58 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(418.58 465.9)"><tspan>flip h</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M496.7 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(496.7 465.9)"><tspan>flip v</tspan></text></g><path fill="none" stroke="#000" d="M106.09 63.01V444h468.73V63.01H106.09Z" color="#000"/><text color="#000" font-family="Arial" font-size="12" text-anchor="middle" transform="rotate(-90 136.345 117.165)"><tspan>cycles</tspan></text><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 84.91)"><tspan>fimg</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M515.48 85.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 85.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M158.17 444h26.05V217.77h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M158.17 444V217.78h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M236.29 444h26.05V296.63h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M236.29 444V296.64h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M314.41 444h26.06V165.65h-26.06z" shape-rendering="crispEdges"/><path stroke="#000" d="M314.41 444V165.66h26.05V444h-26.05Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M392.54 444h26.05V310.26h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M392.54 444V310.27h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M470.66 444h26.05V310.26h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M470.66 444V310.27h26.04V444h-26.04Z"/></g><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 102.91)"><tspan>imgproc</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M515.48 103.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 103.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M184.21 444h26.05V83.03h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M184.21 444V83.04h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M262.33 444h26.05V122.08h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M262.33 444V122.09h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M340.46 444h26.05V123.05h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M340.46 444V123.06h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M418.58 444h26.05V122.09h-26.05z" shape-rendering="crispEdges"/><path stroke="#000" d="M418.58 444V122.1h26.04V444h-26.04Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M496.7 444h26.05V146.09H496.7z" shape-rendering="crispEdges"/><path stroke="#000" d="M496.7 444V146.1h26.04V444H496.7Z"/></g><path fill="none" stroke="#000" d="M106.09 63.01V444h468.73V63.01H106.09Z" color="#000"/><text color="#000" font-family="Verdana" font-size="18" text-anchor="middle" transform="translate(340.45 32.86)"><tspan>affine</tspan></text></svg> \ No newline at end of file
diff --git a/benches/affine.rs b/benches/affine.rs
new file mode 100644
index 0000000..9daa7d3
--- /dev/null
+++ b/benches/affine.rs
@@ -0,0 +1,71 @@
+//! note that imageproc doesnt support in-place transformations.
+use fimg::Image;
+use image::{imageops, RgbImage};
+const SIZE: u32 = 5424;
+
+// dont have to alloc, but it would be less fair.
+pub fn fimg() -> Image<Vec<u8>, 3> {
+ Image::build(SIZE, SIZE).buf(iai::black_box(include_bytes!("../data.imgbuf").to_vec()))
+}
+
+pub fn ipimg() -> RgbImage {
+ RgbImage::from_raw(
+ SIZE,
+ SIZE,
+ iai::black_box(include_bytes!("../data.imgbuf").to_vec()),
+ )
+ .unwrap()
+}
+
+pub fn rot_90_fimg() {
+ iai::black_box(unsafe { fimg().cloner().rot_90() });
+}
+
+pub fn rot_90_imgproc() {
+ iai::black_box(imageops::rotate90(&ipimg()));
+}
+
+pub fn rot_180_fimg() {
+ iai::black_box(fimg().cloner().rot_180());
+}
+
+pub fn rot_180_imgproc() {
+ iai::black_box(imageops::rotate180(&ipimg()));
+}
+
+pub fn rot_270_fimg() {
+ iai::black_box(unsafe { fimg().cloner().rot_270() });
+}
+
+pub fn rot_270_imgproc() {
+ iai::black_box(imageops::rotate270(&ipimg()));
+}
+
+pub fn flip_h_fimg() {
+ iai::black_box(fimg().cloner().flip_h());
+}
+
+pub fn flip_h_imgproc() {
+ iai::black_box(imageops::flip_horizontal(&ipimg()));
+}
+
+pub fn flip_v_fimg() {
+ iai::black_box(fimg().cloner().flip_h());
+}
+
+pub fn flip_v_imgproc() {
+ iai::black_box(imageops::flip_vertical(&ipimg()));
+}
+
+iai::main!(
+ rot_90_fimg,
+ rot_90_imgproc,
+ rot_180_fimg,
+ rot_180_imgproc,
+ rot_270_fimg,
+ rot_270_imgproc,
+ flip_h_fimg,
+ flip_h_imgproc,
+ flip_v_fimg,
+ flip_v_imgproc,
+);
diff --git a/benches/drawing.rs b/benches/drawing.rs
new file mode 100644
index 0000000..96dcc80
--- /dev/null
+++ b/benches/drawing.rs
@@ -0,0 +1,87 @@
+use fimg::Image;
+use image::Rgba;
+use imageproc::point::Point;
+use umath::generic_float::Constructors;
+use umath::FF32;
+
+macro_rules! run_fimg {
+ (fn $fn:ident($img:ident) { $($tt:tt)+ }) => {
+ fn $fn() {
+ let mut $img = iai::black_box(Image::<_, 4>::alloc(1000, 1000).boxed());
+ $($tt)+
+ iai::black_box($img);
+ }
+ };
+}
+
+macro_rules! run_imgp {
+ (fn $fn:ident($img:ident) { $($tt:tt)+ }) => {
+ fn $fn() {
+ let mut $img = iai::black_box(image::RgbaImage::new(1000, 1000));
+ $($tt)+
+ iai::black_box($img);
+ }
+ };
+}
+
+run_fimg! {
+ fn tri_fimg(img) { unsafe {
+ // btw it would be faster if it used points() but futureā„¢
+ img.tri::<FF32>(
+ (FF32::zero(), FF32::zero()),
+ (FF32::new(1000.), FF32::new(500.)),
+ (FF32::zero(), FF32::new(999.)),
+ [255, 255, 255, 255],
+ );
+ } }
+}
+
+run_imgp! {
+ fn tri_imgp(img) {
+ // fimg L tbh
+ imageproc::drawing::draw_polygon_mut(&mut img, &[Point::new(0, 0), Point::new(1000, 500), Point::new(0, 999)], Rgba([255,255,255,255]));
+ }
+}
+
+run_fimg! { fn circle_filled_fimg(i) {
+ i.circle((500,500), 500, [128, 128, 128, 255]);
+} }
+
+run_imgp! { fn circle_filled_imgp(i) {
+ imageproc::drawing::draw_filled_circle_mut(&mut i, (500,500), 500, Rgba([128, 128, 128, 255]));
+} }
+
+run_fimg! { fn border_circle_fimg(i) {
+ for radius in (5..500).step_by(5) {
+ i.border_circle((500, 500), radius, [128, 128, 128, 255]);
+ }
+} }
+
+run_imgp! { fn border_circle_imgp(i) {
+ for radius in (5..500).step_by(5) {
+ imageproc::drawing::draw_hollow_circle_mut(&mut i, (500,500), radius, Rgba([128, 128, 128, 255]));
+ }
+} }
+
+run_fimg! { fn line_fimg(i) {
+ for y in (250..750).step_by(10) {
+ i.line((0, y), (2000,2000), [128, 0, 0, 255]);
+ }
+} }
+
+run_imgp! { fn line_imgp(i) {
+ for y in (250..750).step_by(10) {
+ imageproc::drawing::draw_line_segment_mut(&mut i, (0.0, y as f32), (2000.0,2000.0), Rgba([128, 0, 0, 255]));
+ }
+} }
+
+iai::main!(
+ tri_fimg,
+ tri_imgp,
+ circle_filled_fimg,
+ circle_filled_imgp,
+ border_circle_fimg,
+ border_circle_imgp,
+ line_fimg,
+ line_imgp,
+);
diff --git a/benches/resizing.rs b/benches/resizing.rs
new file mode 100644
index 0000000..fc26eae
--- /dev/null
+++ b/benches/resizing.rs
@@ -0,0 +1,50 @@
+use fimg::Image;
+const SIZE: u32 = 5424;
+const TO: u32 = 2712;
+
+macro_rules! scale_fimg {
+ ($name:ident => { scale($alg: ident) }) => {
+ fn $name() {
+ #[allow(unused_mut)]
+ let mut img = Image::<_, 3>::build(SIZE, SIZE)
+ .buf(iai::black_box(include_bytes!("../data.imgbuf").to_vec()));
+ img.scale::<fimg::scale::$alg>(TO, TO);
+ iai::black_box(img);
+ }
+ };
+}
+
+macro_rules! scale_img {
+ ($name:ident => { scale($alg: ident) }) => {
+ fn $name() {
+ let img = image::RgbImage::from_raw(
+ SIZE,
+ SIZE,
+ iai::black_box(include_bytes!("../data.imgbuf").to_vec()),
+ )
+ .unwrap();
+ iai::black_box(image::imageops::resize(
+ &img,
+ TO,
+ TO,
+ image::imageops::FilterType::$alg,
+ ));
+ }
+ };
+}
+
+scale_fimg!(nearest_fimg => { scale(Nearest) });
+scale_img!(nearest_img => { scale(Nearest) });
+scale_fimg!(lanczos_fimg => { scale(Lanczos3) });
+scale_img!(lanczos_img => { scale(Lanczos3) });
+scale_fimg!(catmull_fimg => { scale(CatmullRom) });
+scale_img!(catmull_img => { scale(CatmullRom) });
+
+iai::main!(
+ nearest_fimg,
+ nearest_img,
+ lanczos_fimg,
+ lanczos_img,
+ catmull_fimg,
+ catmull_img
+);
diff --git a/data.png b/data.png
new file mode 100644
index 0000000..a0c73f2
--- /dev/null
+++ b/data.png
Binary files differ
diff --git a/drawing.svg b/drawing.svg
new file mode 100644
index 0000000..d51ca60
--- /dev/null
+++ b/drawing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="600" height="480"><path fill="#fff" d="M0 0h600v480H0z"/><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 444h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 447.9)"><tspan> 0</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 389.57h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 393.47)"><tspan> 1x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 335.15h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 339.05)"><tspan> 2x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 280.72h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 284.62)"><tspan> 3x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 226.29h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 230.19)"><tspan> 4x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 171.86h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 175.76)"><tspan> 5x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 117.44h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 121.34)"><tspan> 6x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M89.31 63.01h9m476.51 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(80.92 66.91)"><tspan> 7x10</tspan><tspan dy="-6" font-size="9.6">7</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M186.41 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(186.41 465.9)"><tspan>tri</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M283.51 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(283.51 465.9)"><tspan>circle filled</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M380.62 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(380.62 465.9)"><tspan>hollow circle</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M477.72 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(477.72 465.9)"><tspan>line</tspan></text></g><path fill="none" stroke="#000" d="M89.31 63.01V444h485.51V63.01H89.31Z" color="#000"/><text color="#000" font-family="Arial" font-size="12" text-anchor="middle" transform="rotate(-90 136.345 117.165)"><tspan>cycles</tspan></text><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 84.91)"><tspan>fimg</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M515.48 85.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 85.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M154.04 444h32.38v-81.68h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M154.04 444v-81.67h32.37V444h-32.37Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M251.15 444h32.37v-73.84h-32.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M251.15 444v-73.83h32.36V444h-32.36Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M348.25 444h32.38v-26.31h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M348.25 444v-26.3h32.37V444h-32.37Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M445.35 444h32.38v-6.64h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M445.35 444v-6.63h32.37V444h-32.37Z"/></g><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 102.91)"><tspan>imgproc</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M515.48 103.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 103.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M186.41 444h32.38v-42.16h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M186.41 444v-42.15h32.37V444h-32.37Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M283.51 444h32.38V78.07h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M283.51 444V78.08h32.37V444h-32.37Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M380.62 444h32.37v-49.55h-32.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M380.62 444v-49.54h32.36V444h-32.36Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M477.72 444h32.38v-23.77h-32.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M477.72 444v-23.76h32.37V444h-32.37Z"/></g><path fill="none" stroke="#000" d="M89.31 63.01V444h485.51V63.01H89.31Z" color="#000"/><text color="#000" font-family="Verdana" font-size="18" text-anchor="middle" transform="translate(332.06 32.86)"><tspan>drawing</tspan></text></svg> \ No newline at end of file
diff --git a/resizing.svg b/resizing.svg
new file mode 100644
index 0000000..7f5598c
--- /dev/null
+++ b/resizing.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="600" height="480"><path fill="#fff" d="M0 0h600v480H0z"/><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 444h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 447.9)"><tspan> 0</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 380.5h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 384.4)"><tspan> 2x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 317h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 320.9)"><tspan> 4x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 253.5h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 257.4)"><tspan> 6x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 190.01h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 193.91)"><tspan> 8x10</tspan><tspan dy="-6" font-size="9.6">9</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 126.51h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 130.41)"><tspan> 1x10</tspan><tspan dy="-6" font-size="9.6">10</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M114.48 63.01h9m451.34 0h-9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="end" transform="translate(106.09 66.91)"><tspan> 1.2x10</tspan><tspan dy="-6" font-size="9.6">10</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M229.57 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(229.57 465.9)"><tspan>lanczos3</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M344.65 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(344.65 465.9)"><tspan>catmull</tspan></text></g><g fill="none" stroke="currentColor" color="#000"><path stroke="#000" d="M459.74 444v-9m0-371.99v9"/><text fill="#000" stroke="none" font-family="Arial" font-size="12" text-anchor="middle" transform="translate(459.74 465.9)"><tspan>nearest</tspan></text></g><path fill="none" stroke="#000" d="M114.48 63.01V444h460.34V63.01H114.48Z" color="#000"/><text color="#000" font-family="Arial" font-size="12" text-anchor="middle" transform="rotate(-90 136.345 117.165)"><tspan>cycles</tspan></text><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 84.91)"><tspan>fimg</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M515.48 85.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 85.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M191.2 444h38.38v-53.53H191.2z" shape-rendering="crispEdges"/><path stroke="#000" d="M191.2 444v-53.52h38.37V444H191.2Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M306.29 444h38.37v-43.95h-38.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M306.29 444v-43.94h38.36V444h-38.36Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#9400D3" stroke="none" d="M421.37 444h38.38v-7.81h-38.38z" shape-rendering="crispEdges"/><path stroke="#000" d="M421.37 444v-7.8h38.37v7.8h-38.37Z"/></g><text color="#000" font-family="Arial" font-size="12" text-anchor="end" transform="translate(507.09 102.91)"><tspan>imgproc</tspan></text><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M515.48 103.51h42.56v-9h-42.56z" shape-rendering="crispEdges"/><path stroke="#000" d="M515.48 103.51h42.56v-9h-42.56v9Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M229.57 444h38.37V71.82h-38.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M229.57 444V71.83h38.36V444h-38.36Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M344.65 444h38.37V166.29h-38.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M344.65 444V166.3h38.36V444h-38.36Z"/></g><g fill="none" stroke="currentColor" color="#000"><path fill="#009E73" stroke="none" d="M459.74 444h38.37V332.24h-38.37z" shape-rendering="crispEdges"/><path stroke="#000" d="M459.74 444V332.25h38.36V444h-38.36Z"/></g><path fill="none" stroke="#000" d="M114.48 63.01V444h460.34V63.01H114.48Z" color="#000"/><text color="#000" font-family="Verdana" font-size="18" text-anchor="middle" transform="translate(344.65 32.86)"><tspan>resizing</tspan></text></svg> \ No newline at end of file
diff --git a/src/main.rs b/src/main.rs
new file mode 100644
index 0000000..9027818
--- /dev/null
+++ b/src/main.rs
@@ -0,0 +1 @@
+fn main(){}