Initial commit with simplify function that RLE scales images.
This commit is contained in:
commit
bb496e61a5
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
||||||
334
Cargo.lock
generated
Normal file
334
Cargo.lock
generated
Normal file
@ -0,0 +1,334 @@
|
|||||||
|
# This file is automatically @generated by Cargo.
|
||||||
|
# It is not intended for manual editing.
|
||||||
|
[[package]]
|
||||||
|
name = "adler32"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "567b077b825e468cc974f0020d4082ee6e03132512f207ef1a02fd5d00d1f32d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "autocfg"
|
||||||
|
version = "1.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bytemuck"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "37fa13df2292ecb479ec23aa06f4507928bef07839be9ef15281411076629431"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "byteorder"
|
||||||
|
version = "1.3.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cfg-if"
|
||||||
|
version = "0.1.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "color_quant"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0dbbb57365263e881e805dc77d94697c9118fd94d8da011240555aa7b23445bd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crc32fast"
|
||||||
|
version = "1.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-deque"
|
||||||
|
version = "0.7.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-epoch",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-epoch"
|
||||||
|
version = "0.8.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"maybe-uninit",
|
||||||
|
"memoffset",
|
||||||
|
"scopeguard",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-queue"
|
||||||
|
version = "0.2.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"maybe-uninit",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "crossbeam-utils"
|
||||||
|
version = "0.7.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"cfg-if",
|
||||||
|
"lazy_static",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deflate"
|
||||||
|
version = "0.8.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e7e5d2a2273fed52a7f947ee55b092c4057025d7a3e04e5ecdbd25d6c3fb1bd7"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
"byteorder",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "either"
|
||||||
|
version = "1.5.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "gif"
|
||||||
|
version = "0.10.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "471d90201b3b223f3451cd4ad53e34295f16a1df17b1edf3736d47761c3981af"
|
||||||
|
dependencies = [
|
||||||
|
"color_quant",
|
||||||
|
"lzw",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hermit-abi"
|
||||||
|
version = "0.1.14"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "image"
|
||||||
|
version = "0.23.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b5b0553fec6407d63fe2975b794dfb099f3f790bdc958823851af37b26404ab4"
|
||||||
|
dependencies = [
|
||||||
|
"bytemuck",
|
||||||
|
"byteorder",
|
||||||
|
"gif",
|
||||||
|
"jpeg-decoder",
|
||||||
|
"num-iter",
|
||||||
|
"num-rational",
|
||||||
|
"num-traits",
|
||||||
|
"png",
|
||||||
|
"scoped_threadpool",
|
||||||
|
"tiff",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "jpeg-decoder"
|
||||||
|
version = "0.1.19"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5b47b4c4e017b01abdc5bcc126d2d1002e5a75bbe3ce73f9f4f311a916363704"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"rayon",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lazy_static"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libc"
|
||||||
|
version = "0.2.71"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9457b06509d27052635f90d6466700c65095fdf75409b3fbdd903e988b886f49"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "log"
|
||||||
|
version = "0.4.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "lzw"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7d947cbb889ed21c2a84be6ffbaebf5b4e0f4340638cba0444907e38b56be084"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "maybe-uninit"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "memoffset"
|
||||||
|
version = "0.5.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "miniz_oxide"
|
||||||
|
version = "0.3.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "791daaae1ed6889560f8c4359194f56648355540573244a5448a83ba1ecc7435"
|
||||||
|
dependencies = [
|
||||||
|
"adler32",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-integer"
|
||||||
|
version = "0.1.43"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-iter"
|
||||||
|
version = "0.1.41"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7a6e6b7c748f995c4c29c5f5ae0248536e04a5739927c74ec0fa564805094b9f"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-rational"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a5b4d7360f362cfb50dde8143501e6940b22f644be75a4cc90b2d81968908138"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"num-integer",
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num-traits"
|
||||||
|
version = "0.2.12"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "num_cpus"
|
||||||
|
version = "1.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
|
||||||
|
dependencies = [
|
||||||
|
"hermit-abi",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "perler"
|
||||||
|
version = "0.1.0"
|
||||||
|
dependencies = [
|
||||||
|
"image",
|
||||||
|
"lazy_static",
|
||||||
|
"log",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "png"
|
||||||
|
version = "0.16.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "34ccdd66f6fe4b2433b07e4728e9a013e43233120427046e93ceb709c3a439bf"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags",
|
||||||
|
"crc32fast",
|
||||||
|
"deflate",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon"
|
||||||
|
version = "1.3.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "62f02856753d04e03e26929f820d0a0a337ebe71f849801eea335d464b349080"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
"crossbeam-deque",
|
||||||
|
"either",
|
||||||
|
"rayon-core",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rayon-core"
|
||||||
|
version = "1.7.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e92e15d89083484e11353891f1af602cc661426deb9564c298b270c726973280"
|
||||||
|
dependencies = [
|
||||||
|
"crossbeam-deque",
|
||||||
|
"crossbeam-queue",
|
||||||
|
"crossbeam-utils",
|
||||||
|
"lazy_static",
|
||||||
|
"num_cpus",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scoped_threadpool"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "scopeguard"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tiff"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3f3b8a87c4da944c3f27e5943289171ac71a6150a79ff6bacfff06d159dfff2f"
|
||||||
|
dependencies = [
|
||||||
|
"byteorder",
|
||||||
|
"lzw",
|
||||||
|
"miniz_oxide",
|
||||||
|
]
|
||||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "perler"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Bill Thiede <git@xinu.tv>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
image = "0.23.6"
|
||||||
|
log = "0.4.8"
|
||||||
|
|
||||||
|
[dev-dependencies]
|
||||||
|
lazy_static = "1.4.0"
|
||||||
202
src/lib.rs
Normal file
202
src/lib.rs
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
use image::{DynamicImage, GenericImage, GenericImageView};
|
||||||
|
use log::debug;
|
||||||
|
|
||||||
|
pub fn simplify(input: &DynamicImage) -> DynamicImage {
|
||||||
|
let (w, h) = input.dimensions();
|
||||||
|
// The dimensions method returns the images width and height.
|
||||||
|
debug!("dimensions {}x{}", w, h);
|
||||||
|
|
||||||
|
let mut smallest_run = usize::MAX;
|
||||||
|
// Search for longest vertical runs
|
||||||
|
for y in 0..h {
|
||||||
|
let mut last_pix = input.get_pixel(0, y);
|
||||||
|
let mut run = 1;
|
||||||
|
for x in 1..w {
|
||||||
|
let pix = input.get_pixel(x, y);
|
||||||
|
debug!("xy {}x{} pix {:?} last pix {:?}", x, y, &pix.0, &last_pix.0);
|
||||||
|
if last_pix == pix {
|
||||||
|
run += 1;
|
||||||
|
} else {
|
||||||
|
smallest_run = smallest_run.min(run);
|
||||||
|
debug!(
|
||||||
|
"xy {}x{} pix {:?} last pix {:?} run {}",
|
||||||
|
x, y, &pix.0, &last_pix.0, &run
|
||||||
|
);
|
||||||
|
run = 1;
|
||||||
|
}
|
||||||
|
last_pix = pix;
|
||||||
|
}
|
||||||
|
smallest_run = smallest_run.min(run);
|
||||||
|
}
|
||||||
|
debug!("Smallest vertical run {}", smallest_run);
|
||||||
|
|
||||||
|
// Search for longest vertical runs
|
||||||
|
for x in 0..w {
|
||||||
|
let mut last_pix = input.get_pixel(x, 0);
|
||||||
|
let mut run = 1;
|
||||||
|
for y in 1..h {
|
||||||
|
let pix = input.get_pixel(x, y);
|
||||||
|
debug!("xy {}x{} pix {:?} last pix {:?}", x, y, &pix.0, &last_pix.0);
|
||||||
|
if last_pix == pix {
|
||||||
|
run += 1;
|
||||||
|
} else {
|
||||||
|
smallest_run = smallest_run.min(run);
|
||||||
|
debug!(
|
||||||
|
"xy {}x{} pix {:?} last pix {:?} run {}",
|
||||||
|
x, y, &pix.0, &last_pix.0, &run
|
||||||
|
);
|
||||||
|
run = 1;
|
||||||
|
}
|
||||||
|
last_pix = pix;
|
||||||
|
}
|
||||||
|
smallest_run = smallest_run.min(run);
|
||||||
|
}
|
||||||
|
|
||||||
|
debug!("Smallest run {}", smallest_run);
|
||||||
|
let scale = smallest_run as u32;
|
||||||
|
let s_w = w / scale;
|
||||||
|
let s_h = h / scale;
|
||||||
|
let mut out = DynamicImage::new_rgba8(s_w, s_h);
|
||||||
|
debug!("Creating image {}x{}", s_w, s_h);
|
||||||
|
for y in 0..s_h {
|
||||||
|
for x in 0..s_w {
|
||||||
|
let x_orig = x * scale;
|
||||||
|
let y_orig = y * scale;
|
||||||
|
let p = input.get_pixel(x_orig, y_orig);
|
||||||
|
debug!(
|
||||||
|
"getting {}x{} {:?} and storing in {}x{}",
|
||||||
|
x_orig, y_orig, p.0, x, y
|
||||||
|
);
|
||||||
|
out.put_pixel(x, y, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
use image::{GenericImage, Rgba};
|
||||||
|
use lazy_static::lazy_static;
|
||||||
|
|
||||||
|
lazy_static! {
|
||||||
|
static ref WHITE: Rgba<u8> = [255, 255, 255, 255].into();
|
||||||
|
static ref BLACK: Rgba<u8> = [0, 0, 0, 255].into();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DebugImage<'r>(&'r DynamicImage);
|
||||||
|
use std::fmt;
|
||||||
|
impl<'r> fmt::Display for DebugImage<'r> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
let img = &self.0;
|
||||||
|
let (w, h) = img.dimensions();
|
||||||
|
for y in 0..h {
|
||||||
|
let p = img.get_pixel(0, y);
|
||||||
|
write!(f, "[{:^3}", p.0[0])?;
|
||||||
|
for x in 1..w {
|
||||||
|
let p = img.get_pixel(x, y);
|
||||||
|
write!(f, " {:^3}", p.0[0])?;
|
||||||
|
}
|
||||||
|
write!(f, "]\n")?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_horiz(w: u32, h: u32, scale: u32) -> DynamicImage {
|
||||||
|
let mut img = DynamicImage::new_rgba8(w * scale, h * scale);
|
||||||
|
for y in 0..h * scale {
|
||||||
|
for x in 0..w * scale {
|
||||||
|
if (y / scale) % 2 == 0 {
|
||||||
|
img.put_pixel(x, y, *WHITE);
|
||||||
|
} else {
|
||||||
|
img.put_pixel(x, y, *BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_vert(w: u32, h: u32, scale: u32) -> DynamicImage {
|
||||||
|
let mut img = DynamicImage::new_rgba8(w * scale, h * scale);
|
||||||
|
for y in 0..h * scale {
|
||||||
|
for x in 0..w * scale {
|
||||||
|
if (x / scale) % 2 == 0 {
|
||||||
|
img.put_pixel(x, y, *WHITE);
|
||||||
|
} else {
|
||||||
|
img.put_pixel(x, y, *BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_check(w: u32, h: u32, scale: u32) -> DynamicImage {
|
||||||
|
let mut img = DynamicImage::new_rgba8(w * scale, h * scale);
|
||||||
|
for y in 0..h * scale {
|
||||||
|
for x in 0..w * scale {
|
||||||
|
if (x / scale) % 2 == 0 || (y / scale) % 2 == 0 {
|
||||||
|
img.put_pixel(x, y, *WHITE);
|
||||||
|
} else {
|
||||||
|
img.put_pixel(x, y, *BLACK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
img
|
||||||
|
}
|
||||||
|
|
||||||
|
fn compare_images(lhs: DynamicImage, rhs: DynamicImage) {
|
||||||
|
let lhs = &lhs.to_rgba();
|
||||||
|
let rhs = &rhs.to_rgba();
|
||||||
|
let l_dim = lhs.dimensions();
|
||||||
|
let r_dim = rhs.dimensions();
|
||||||
|
assert_eq!(
|
||||||
|
l_dim, r_dim,
|
||||||
|
"image sizes don't match {:?} != {:?}",
|
||||||
|
l_dim, r_dim
|
||||||
|
);
|
||||||
|
|
||||||
|
// Based on https://en.wikipedia.org/wiki/Peak_signal-to-noise_ratio#Definition
|
||||||
|
let mut mse: [i64; 3] = [0, 0, 0];
|
||||||
|
let (w, _) = l_dim;
|
||||||
|
let w = w as usize;
|
||||||
|
for (c, (l, r)) in lhs.pixels().zip(rhs.pixels()).enumerate() {
|
||||||
|
let image::Rgba(l_pix) = l;
|
||||||
|
let image::Rgba(r_pix) = r;
|
||||||
|
|
||||||
|
{
|
||||||
|
for i in 0..3 {
|
||||||
|
let d = l_pix[i] as i64 - r_pix[i] as i64;
|
||||||
|
let d2 = d * d;
|
||||||
|
mse[i] += d2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let x = c / w;
|
||||||
|
let y = c % w;
|
||||||
|
if l_pix != r_pix {
|
||||||
|
lhs.save("/tmp/lhs.png").expect("Failed to save lhs image");
|
||||||
|
rhs.save("/tmp/rhs.png").expect("Failed to save rhs image");
|
||||||
|
assert_eq!(l_pix, r_pix, "{:?} != {:?} @ {} x {} ", l_pix, r_pix, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_simplify() {
|
||||||
|
for (input, want) in vec![
|
||||||
|
(mk_horiz(3, 3, 5), mk_horiz(3, 3, 1)),
|
||||||
|
(mk_vert(3, 3, 5), mk_vert(3, 3, 1)),
|
||||||
|
(mk_check(3, 3, 5), mk_check(3, 3, 1)),
|
||||||
|
(mk_horiz(3, 9, 5), mk_horiz(3, 9, 1)),
|
||||||
|
(mk_vert(9, 3, 5), mk_vert(9, 3, 1)),
|
||||||
|
] {
|
||||||
|
let got = simplify(&input);
|
||||||
|
println!("input:\n{}", DebugImage(&input));
|
||||||
|
println!("want:\n{}", DebugImage(&want));
|
||||||
|
println!("got:\n{}", DebugImage(&got));
|
||||||
|
compare_images(want, got);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/main.rs
Normal file
1
src/main.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
fn main() {}
|
||||||
Loading…
x
Reference in New Issue
Block a user