Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
bokuweb committed Aug 15, 2024
1 parent 74c547a commit 7486b0c
Show file tree
Hide file tree
Showing 8 changed files with 444 additions and 1 deletion.
155 changes: 155 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,158 @@ report.html
/screenshot/*
sample/index.html
from-json.html
### Generated by gibo (https://github.com/simonwhitaker/gibo)
### https://raw.github.com/github/gitignore/e5323759e387ba347a9d50f8b0ddd16502eb71d4/Node.gitignore

# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*


### https://raw.github.com/github/gitignore/e5323759e387ba347a9d50f8b0ddd16502eb71d4/Rust.gitignore

# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk

# MSVC Windows builds of rustc generate these, which store debugging information
*.pdb

wasi-sdk-21.0
m.md

5 changes: 5 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[workspace]
resolver = "2"
members = [
"crates/*",
]
18 changes: 18 additions & 0 deletions crates/core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
[package]
name = "core"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
image-diff-rs = { git = "https://github.com/bokuweb/image-diff-rs.git" }
globmatch = "0.3"
rayon = "1.8"
mustache = "0.9.0"
serde = { version = "1.0.207", features = ["derive"] }
serde_json = "1.0.125"
percent-encoding = "2.3.1"

[dev-dependencies]
rstest = "0.18.2"
5 changes: 5 additions & 0 deletions crates/core/examples/simple.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use core::run;

pub fn main() {
run("./sample/actual/", "./sample/expected")
}
144 changes: 144 additions & 0 deletions crates/core/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// type RegParams = {
// actualDir: string,
// expectedDir: string,
// diffDir: string,
// report?: string,
// junitReport?: string,
// json?: string,
// update?: boolean,
// extendedErrors?: boolean,
// urlPrefix?: string,
// matchingThreshold?: number,
// threshold?: number, // alias to thresholdRate.
// thresholdRate?: number,
// thresholdPixel?: number,
// concurrency?: number,
// enableAntialias?: boolean,
// enableClientAdditionalDetection?: boolean,
// };
// fn main() {
// // let a = include_bytes!("../../sample/actual/sample.png");
// // let b = include_bytes!("../../sample/expected/sample.png");
// // image_diff_rs::diff(
// // a,
// // b,
// // &image_diff_rs::DiffOption {
// // threshold: Some(0.1),
// // include_anti_alias: Some(true),
// // },
// // )
// // .unwrap();
// // crate::run();
// }
//
//const aggregate = result => {
// const passed = result.filter(r => r.passed).map(r => r.image);
// const failed = result.filter(r => !r.passed).map(r => r.image);
// const diffItems = failed.map(image => image.replace(/\.[^\.]+$/, '.png'));
// return { passed, failed, diffItems };
// };
mod report;

use image_diff_rs::DiffOption;
use rayon::prelude::*;
use std::{
collections::BTreeSet,
path::{Path, PathBuf},
};

static IMAGE_FILES: &str = "/**/*.{tiff,jpeg,jpg,gif,png,bmp,webp}";

#[derive(Debug)]
pub(crate) struct DetectedImages {
pub(crate) expected: BTreeSet<PathBuf>,
pub(crate) actual: BTreeSet<PathBuf>,
pub(crate) deleted: BTreeSet<PathBuf>,
pub(crate) new: BTreeSet<PathBuf>,
}

pub fn run(expected_dir: impl AsRef<Path>, actual_dir: impl AsRef<Path>) {
let actual_dir = actual_dir.as_ref().to_owned();
let expected_dir = expected_dir.as_ref().to_owned();
let detected = find_images(&expected_dir, &actual_dir);

let targets: Vec<PathBuf> = detected
.actual
.intersection(&detected.expected)
.cloned()
.collect();

let result: Result<Vec<()>, std::io::Error> = targets
.par_iter()
.map(|path| {
let img1 = std::fs::read(actual_dir.clone().join(path))?;
let img2 = std::fs::read(expected_dir.clone().join(path))?;
let res = image_diff_rs::diff(
img1,
img2,
&DiffOption {
threshold: Some(0.05),
include_anti_alias: Some(true),
},
);
std::fs::write("./test.png", res.unwrap().diff_image)?;
Ok(())
})
.inspect(|r| if let Err(e) = r { /*TODO: logging */ })
.collect();
report::Report::create();
}

pub(crate) fn find_images(
expected_dir: impl AsRef<Path>,
actual_dir: impl AsRef<Path>,
) -> DetectedImages {
let expected_dir = expected_dir.as_ref();
let actual_dir = actual_dir.as_ref();

let expected: BTreeSet<PathBuf> =
globmatch::Builder::new(&(expected_dir.display().to_string() + IMAGE_FILES))
.build(".")
.expect("the pattern should be correct.")
.into_iter()
.flatten()
.map(|p| p.strip_prefix(expected_dir).unwrap().to_path_buf())
.collect();

let actual: BTreeSet<PathBuf> =
globmatch::Builder::new(&(actual_dir.display().to_string() + IMAGE_FILES))
.build(".")
.expect("the pattern should be correct.")
.into_iter()
.flatten()
.map(|p| p.strip_prefix(actual_dir).unwrap().to_path_buf())
.collect();

let deleted = expected.difference(&actual).cloned().collect();

let new = actual.difference(&expected).cloned().collect();

DetectedImages {
expected,
actual,
deleted,
new,
}
}

fn is_passed(
width: u32,
height: u32,
diff_count: u32,
threshold_pixel: Option<u32>,
threshold_rate: Option<f32>,
) -> bool {
if let Some(t) = threshold_pixel {
diff_count <= t
} else if let Some(t) = threshold_rate {
let pixel = width * height;
let ratio = diff_count as f32 / pixel as f32;
ratio <= t
} else {
diff_count == 0
}
}
5 changes: 5 additions & 0 deletions crates/core/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
use core::run;

pub fn main() {
run("./sample/actual/", "./sample/expected")
}
Loading

0 comments on commit 7486b0c

Please sign in to comment.