forked from external-repos/squoosh
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b831aa0075 | ||
|
|
bf4d4b78cb | ||
|
|
496896e36e | ||
|
|
6b88ec1f8a | ||
|
|
3af5f3a96d | ||
|
|
ddc5564515 |
1
codecs/resize/.gitignore
vendored
1
codecs/resize/.gitignore
vendored
@@ -3,3 +3,4 @@ target
|
|||||||
Cargo.lock
|
Cargo.lock
|
||||||
bin/
|
bin/
|
||||||
pkg/README.md
|
pkg/README.md
|
||||||
|
lut.inc
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "resize"
|
name = "squooshresize"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
authors = ["Surma <surma@surma.link>"]
|
authors = ["Surma <surma@surma.link>"]
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// [1]: https://github.com/GoogleChromeLabs/jsvu
|
// [1]: https://github.com/GoogleChromeLabs/jsvu
|
||||||
|
|
||||||
self = global = this;
|
self = global = this;
|
||||||
load('./pkg/resize.js');
|
load("./pkg/resize.js");
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
// Adjustable constants.
|
// Adjustable constants.
|
||||||
@@ -19,23 +19,35 @@ async function init() {
|
|||||||
|
|
||||||
const module = await WebAssembly.compile(readbuffer("./pkg/resize_bg.wasm"));
|
const module = await WebAssembly.compile(readbuffer("./pkg/resize_bg.wasm"));
|
||||||
await wasm_bindgen(module);
|
await wasm_bindgen(module);
|
||||||
[false, true].forEach(premulti => {
|
[[false, false], [true, false], [false, true], [true, true]].forEach(
|
||||||
print(`\npremultiplication: ${premulti}`);
|
opts => {
|
||||||
print(`==============================`);
|
print(`\npremultiplication: ${opts[0]}`);
|
||||||
for (let i = 0; i < 100; i++) {
|
print(`color space conversion: ${opts[1]}`);
|
||||||
const start = Date.now();
|
print(`==============================`);
|
||||||
wasm_bindgen.resize(imageBuffer, inputDimensions, inputDimensions, outputDimensions, outputDimensions, algorithm, premulti);
|
for (let i = 0; i < 100; i++) {
|
||||||
iterations[i] = Date.now() - start;
|
const start = Date.now();
|
||||||
|
wasm_bindgen.resize(
|
||||||
|
imageBuffer,
|
||||||
|
inputDimensions,
|
||||||
|
inputDimensions,
|
||||||
|
outputDimensions,
|
||||||
|
outputDimensions,
|
||||||
|
algorithm,
|
||||||
|
...opts
|
||||||
|
);
|
||||||
|
iterations[i] = Date.now() - start;
|
||||||
|
}
|
||||||
|
const average =
|
||||||
|
iterations.reduce((sum, c) => sum + c) / iterations.length;
|
||||||
|
const stddev = Math.sqrt(
|
||||||
|
iterations
|
||||||
|
.map(i => Math.pow(i - average, 2))
|
||||||
|
.reduce((sum, c) => sum + c) / iterations.length
|
||||||
|
);
|
||||||
|
print(`n = ${iterations.length}`);
|
||||||
|
print(`Average: ${average}`);
|
||||||
|
print(`StdDev: ${stddev}`);
|
||||||
}
|
}
|
||||||
const average = iterations.reduce((sum, c) => sum + c) / iterations.length;
|
);
|
||||||
const stddev = Math.sqrt(
|
|
||||||
iterations
|
|
||||||
.map(i => Math.pow(i - average, 2))
|
|
||||||
.reduce((sum, c) => sum + c) / iterations.length
|
|
||||||
);
|
|
||||||
print(`n = ${iterations.length}`);
|
|
||||||
print(`Average: ${average}`);
|
|
||||||
print(`StdDev: ${stddev}`);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
init().catch(e => console.error(e, e.stack));
|
init().catch(e => console.error(e, e.stack));
|
||||||
|
|||||||
23
codecs/resize/build.rs
Normal file
23
codecs/resize/build.rs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
include!("./src/srgb.rs");
|
||||||
|
|
||||||
|
use std::io::Write;
|
||||||
|
|
||||||
|
fn main() -> std::io::Result<()> {
|
||||||
|
let mut srgb_to_linear_lut = String::from("static SRGB_TO_LINEAR_LUT: [f32; 256] = [");
|
||||||
|
let mut linear_to_srgb_lut = String::from("static LINEAR_TO_SRGB_LUT: [f32; 256] = [");
|
||||||
|
for i in 0..256 {
|
||||||
|
srgb_to_linear_lut.push_str(&format!("{0:.7}", srgb_to_linear((i as f32) / 255.0)));
|
||||||
|
srgb_to_linear_lut.push_str(",");
|
||||||
|
linear_to_srgb_lut.push_str(&format!("{0:.7}", linear_to_srgb((i as f32) / 255.0)));
|
||||||
|
linear_to_srgb_lut.push_str(",");
|
||||||
|
}
|
||||||
|
srgb_to_linear_lut.pop().unwrap();
|
||||||
|
linear_to_srgb_lut.pop().unwrap();
|
||||||
|
srgb_to_linear_lut.push_str("];");
|
||||||
|
linear_to_srgb_lut.push_str("];");
|
||||||
|
|
||||||
|
let mut file = std::fs::File::create("src/lut.inc")?;
|
||||||
|
file.write_all(srgb_to_linear_lut.as_bytes())?;
|
||||||
|
file.write_all(linear_to_srgb_lut.as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
3
codecs/resize/pkg/resize.d.ts
vendored
3
codecs/resize/pkg/resize.d.ts
vendored
@@ -7,6 +7,7 @@
|
|||||||
* @param {number} arg4
|
* @param {number} arg4
|
||||||
* @param {number} arg5
|
* @param {number} arg5
|
||||||
* @param {boolean} arg6
|
* @param {boolean} arg6
|
||||||
|
* @param {boolean} arg7
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
export function resize(arg0: Uint8Array, arg1: number, arg2: number, arg3: number, arg4: number, arg5: number, arg6: boolean): Uint8Array;
|
export function resize(arg0: Uint8Array, arg1: number, arg2: number, arg3: number, arg4: number, arg5: number, arg6: boolean, arg7: boolean): Uint8Array;
|
||||||
|
|||||||
@@ -47,13 +47,14 @@
|
|||||||
* @param {number} arg4
|
* @param {number} arg4
|
||||||
* @param {number} arg5
|
* @param {number} arg5
|
||||||
* @param {boolean} arg6
|
* @param {boolean} arg6
|
||||||
|
* @param {boolean} arg7
|
||||||
* @returns {Uint8Array}
|
* @returns {Uint8Array}
|
||||||
*/
|
*/
|
||||||
__exports.resize = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6) {
|
__exports.resize = function(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) {
|
||||||
const ptr0 = passArray8ToWasm(arg0);
|
const ptr0 = passArray8ToWasm(arg0);
|
||||||
const len0 = WASM_VECTOR_LEN;
|
const len0 = WASM_VECTOR_LEN;
|
||||||
const retptr = globalArgumentPtr();
|
const retptr = globalArgumentPtr();
|
||||||
wasm.resize(retptr, ptr0, len0, arg1, arg2, arg3, arg4, arg5, arg6);
|
wasm.resize(retptr, ptr0, len0, arg1, arg2, arg3, arg4, arg5, arg6, arg7);
|
||||||
const mem = getUint32Memory();
|
const mem = getUint32Memory();
|
||||||
const rustptr = mem[retptr / 4];
|
const rustptr = mem[retptr / 4];
|
||||||
const rustlen = mem[retptr / 4 + 1];
|
const rustlen = mem[retptr / 4 + 1];
|
||||||
|
|||||||
2
codecs/resize/pkg/resize_bg.d.ts
vendored
2
codecs/resize/pkg/resize_bg.d.ts
vendored
@@ -3,4 +3,4 @@ export const memory: WebAssembly.Memory;
|
|||||||
export function __wbindgen_global_argument_ptr(): number;
|
export function __wbindgen_global_argument_ptr(): number;
|
||||||
export function __wbindgen_malloc(a: number): number;
|
export function __wbindgen_malloc(a: number): number;
|
||||||
export function __wbindgen_free(a: number, b: number): void;
|
export function __wbindgen_free(a: number, b: number): void;
|
||||||
export function resize(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number): void;
|
export function resize(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number): void;
|
||||||
|
|||||||
Binary file not shown.
@@ -9,6 +9,9 @@ use resize::Pixel::RGBA;
|
|||||||
use resize::Type;
|
use resize::Type;
|
||||||
use wasm_bindgen::prelude::*;
|
use wasm_bindgen::prelude::*;
|
||||||
|
|
||||||
|
mod srgb;
|
||||||
|
use srgb::Clamp;
|
||||||
|
|
||||||
cfg_if! {
|
cfg_if! {
|
||||||
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
|
||||||
// allocator.
|
// allocator.
|
||||||
@@ -19,6 +22,39 @@ cfg_if! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
include!("./lut.inc");
|
||||||
|
|
||||||
|
// If `with_space_conversion` is true, this function returns 2 functions that
|
||||||
|
// convert from sRGB to linear RGB and vice versa. If `with_space_conversion` is
|
||||||
|
// false, the 2 functions returned do nothing.
|
||||||
|
fn converter_funcs(with_space_conversion: bool) -> ((fn(u8) -> f32), (fn(f32) -> u8)) {
|
||||||
|
if with_space_conversion {
|
||||||
|
(
|
||||||
|
|v| SRGB_TO_LINEAR_LUT[v as usize] * 255.0,
|
||||||
|
|v| (LINEAR_TO_SRGB_LUT[v as usize] * 255.0) as u8,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(|v| v as f32, |v| v as u8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If `with_alpha_premultiplication` is true, this function returns a function
|
||||||
|
// that premultiply the alpha channel with the given channel value and another
|
||||||
|
// function that reverses that process. If `with_alpha_premultiplication` is
|
||||||
|
// false, the functions just return the channel value.
|
||||||
|
fn alpha_multiplier_funcs(
|
||||||
|
with_alpha_premultiplication: bool,
|
||||||
|
) -> ((fn(f32, u8) -> u8), (fn(u8, u8) -> f32)) {
|
||||||
|
if with_alpha_premultiplication {
|
||||||
|
(
|
||||||
|
|v, a| (v * (a as f32) / 255.0) as u8,
|
||||||
|
|v, a| (v as f32) * 255.0 / (a as f32).clamp(0.0, 255.0),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(|v, _a| v as u8, |v, _a| v as f32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[wasm_bindgen]
|
#[wasm_bindgen]
|
||||||
#[no_mangle]
|
#[no_mangle]
|
||||||
pub fn resize(
|
pub fn resize(
|
||||||
@@ -29,6 +65,7 @@ pub fn resize(
|
|||||||
output_height: usize,
|
output_height: usize,
|
||||||
typ_idx: usize,
|
typ_idx: usize,
|
||||||
premultiply: bool,
|
premultiply: bool,
|
||||||
|
color_space_conversion: bool,
|
||||||
) -> Vec<u8> {
|
) -> Vec<u8> {
|
||||||
let typ = match typ_idx {
|
let typ = match typ_idx {
|
||||||
0 => Type::Triangle,
|
0 => Type::Triangle,
|
||||||
@@ -40,12 +77,16 @@ pub fn resize(
|
|||||||
let num_input_pixels = input_width * input_height;
|
let num_input_pixels = input_width * input_height;
|
||||||
let num_output_pixels = output_width * output_height;
|
let num_output_pixels = output_width * output_height;
|
||||||
|
|
||||||
if premultiply {
|
let (to_linear, to_color_space) = converter_funcs(color_space_conversion);
|
||||||
|
let (premultiplier, demultiplier) = alpha_multiplier_funcs(premultiply);
|
||||||
|
|
||||||
|
// If both options are false, there is no preprocessing on the pixel valus
|
||||||
|
// and we can skip the loop.
|
||||||
|
if premultiply || color_space_conversion {
|
||||||
for i in 0..num_input_pixels {
|
for i in 0..num_input_pixels {
|
||||||
for j in 0..3 {
|
for j in 0..3 {
|
||||||
input_image[4 * i + j] = ((input_image[4 * i + j] as f32)
|
input_image[4 * i + j] =
|
||||||
* (input_image[4 * i + 3] as f32)
|
premultiplier(to_linear(input_image[4 * i + j]), input_image[4 * i + 3]);
|
||||||
/ 255.0) as u8;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -62,15 +103,16 @@ pub fn resize(
|
|||||||
output_image.resize(num_output_pixels * 4, 0);
|
output_image.resize(num_output_pixels * 4, 0);
|
||||||
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
|
resizer.resize(input_image.as_slice(), output_image.as_mut_slice());
|
||||||
|
|
||||||
if premultiply {
|
if premultiply || color_space_conversion {
|
||||||
for i in 0..num_output_pixels {
|
for i in 0..num_output_pixels {
|
||||||
for j in 0..3 {
|
for j in 0..3 {
|
||||||
// We don’t need to worry about division by zero, as division by zero
|
// We don’t need to worry about division by zero, as division by zero
|
||||||
// is well-defined on floats to return `±Inf`. ±Inf is converted to 0
|
// is well-defined on floats to return ±Inf. ±Inf is converted to 0
|
||||||
// when casting to integers.
|
// when casting to integers.
|
||||||
output_image[4 * i + j] = ((output_image[4 * i + j] as f32) * 255.0
|
output_image[4 * i + j] = to_color_space(demultiplier(
|
||||||
/ (output_image[4 * i + 3] as f32))
|
output_image[4 * i + j],
|
||||||
as u8;
|
output_image[4 * i + 3],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
29
codecs/resize/src/srgb.rs
Normal file
29
codecs/resize/src/srgb.rs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
pub trait Clamp: std::cmp::PartialOrd + Sized {
|
||||||
|
fn clamp(self, min: Self, max: Self) -> Self {
|
||||||
|
if self.lt(&min) {
|
||||||
|
min
|
||||||
|
} else if self.gt(&max) {
|
||||||
|
max
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clamp for f32 {}
|
||||||
|
|
||||||
|
pub fn srgb_to_linear(v: f32) -> f32 {
|
||||||
|
if v < 0.04045 {
|
||||||
|
v / 12.92
|
||||||
|
} else {
|
||||||
|
((v + 0.055) / 1.055).powf(2.4).clamp(0.0, 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn linear_to_srgb(v: f32) -> f32 {
|
||||||
|
if v < 0.0031308 {
|
||||||
|
v * 12.92
|
||||||
|
} else {
|
||||||
|
(1.055 * v.powf(1.0 / 2.4) - 0.055).clamp(0.0, 1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
27
package-lock.json
generated
27
package-lock.json
generated
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "squoosh",
|
"name": "squoosh",
|
||||||
"version": "1.5.0",
|
"version": "1.6.0",
|
||||||
"lockfileVersion": 1,
|
"lockfileVersion": 1,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -3232,13 +3232,14 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"copy-webpack-plugin": {
|
"copy-webpack-plugin": {
|
||||||
"version": "5.0.0",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.0.1.tgz",
|
||||||
"integrity": "sha512-iiDj+8nnZeW/i8vYJ3+ABSZkOefJnDYIGLojiZKKFDvf1wcEInABXH1+hN7axQMn04qvJxKjgVOee0e14XPtCg==",
|
"integrity": "sha512-yMTURAkYZO/6h6pGMbHQl2jpKtRNC+0Cy/4kRRP6qUHmpbGGAzNnyMecE6aHgGFCb4ksrL3YcDqYGb8ds3J9cw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"cacache": "^11.3.1",
|
"cacache": "^11.3.1",
|
||||||
"find-cache-dir": "^2.0.0",
|
"find-cache-dir": "^2.0.0",
|
||||||
|
"glob-parent": "^3.1.0",
|
||||||
"globby": "^7.1.1",
|
"globby": "^7.1.1",
|
||||||
"is-glob": "^4.0.0",
|
"is-glob": "^4.0.0",
|
||||||
"loader-utils": "^1.1.0",
|
"loader-utils": "^1.1.0",
|
||||||
@@ -3256,9 +3257,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"p-limit": {
|
"p-limit": {
|
||||||
"version": "2.1.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.2.0.tgz",
|
||||||
"integrity": "sha512-NhURkNcrVB+8hNfLuysU8enY5xn2KXphsHBaC2YmRNTZRc7RWusw6apSpdEj3jo4CMb6W9nrF6tTnsJsJeyu6g==",
|
"integrity": "sha512-pZbTJpoUsCzV48Mc9Nh51VbwO0X9cuPFE8gYwx9BTCt9SF8/b7Zljd2fVgOxhIF/HDTKgpVzs+GPhyKfjLLFRQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"p-try": "^2.0.0"
|
"p-try": "^2.0.0"
|
||||||
@@ -15178,9 +15179,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typed-css-modules": {
|
"typed-css-modules": {
|
||||||
"version": "0.4.1",
|
"version": "0.4.2",
|
||||||
"resolved": "https://registry.npmjs.org/typed-css-modules/-/typed-css-modules-0.4.1.tgz",
|
"resolved": "https://registry.npmjs.org/typed-css-modules/-/typed-css-modules-0.4.2.tgz",
|
||||||
"integrity": "sha512-aOMv55N5s2oRYnlitEDQXdBjSqULg/X68UeYs2AwSZyUk7TgrOZlnZ38/ZEpA1GF5wcHAovk4YR7Db+mYtoL2A==",
|
"integrity": "sha512-8L6efZplgnraEw1RWz1Nc6swfLm6PAawivvdwFhzkFa3CJu+cPbK9712i4CAAf+JA0/Ufe19iDTPIk1WSpoz/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"camelcase": "^4.1.0",
|
"camelcase": "^4.1.0",
|
||||||
@@ -15233,7 +15234,7 @@
|
|||||||
},
|
},
|
||||||
"get-stream": {
|
"get-stream": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
|
||||||
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
@@ -15245,7 +15246,7 @@
|
|||||||
},
|
},
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
||||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
@@ -15295,7 +15296,7 @@
|
|||||||
},
|
},
|
||||||
"pify": {
|
"pify": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
"resolved": "http://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
||||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"name": "squoosh",
|
"name": "squoosh",
|
||||||
"version": "1.5.0",
|
"version": "1.6.0",
|
||||||
"license": "apache-2.0",
|
"license": "apache-2.0",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "webpack-dev-server --host 0.0.0.0 --hot",
|
"start": "webpack-dev-server --host 0.0.0.0 --hot",
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
"classnames": "2.2.6",
|
"classnames": "2.2.6",
|
||||||
"clean-webpack-plugin": "1.0.1",
|
"clean-webpack-plugin": "1.0.1",
|
||||||
"comlink": "3.1.1",
|
"comlink": "3.1.1",
|
||||||
"copy-webpack-plugin": "5.0.0",
|
"copy-webpack-plugin": "5.0.1",
|
||||||
"critters-webpack-plugin": "2.3.0",
|
"critters-webpack-plugin": "2.3.0",
|
||||||
"css-loader": "1.0.1",
|
"css-loader": "1.0.1",
|
||||||
"ejs": "2.6.1",
|
"ejs": "2.6.1",
|
||||||
@@ -63,7 +63,7 @@
|
|||||||
"tslint-config-airbnb": "5.11.1",
|
"tslint-config-airbnb": "5.11.1",
|
||||||
"tslint-config-semistandard": "7.0.0",
|
"tslint-config-semistandard": "7.0.0",
|
||||||
"tslint-react": "3.6.0",
|
"tslint-react": "3.6.0",
|
||||||
"typed-css-modules": "0.4.1",
|
"typed-css-modules": "0.4.2",
|
||||||
"typescript": "3.3.3333",
|
"typescript": "3.3.3333",
|
||||||
"url-loader": "1.1.2",
|
"url-loader": "1.1.2",
|
||||||
"webpack": "4.28.0",
|
"webpack": "4.28.0",
|
||||||
|
|||||||
@@ -19,13 +19,11 @@ interface Props {
|
|||||||
|
|
||||||
interface State {
|
interface State {
|
||||||
maintainAspect: boolean;
|
maintainAspect: boolean;
|
||||||
premultiply: boolean;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export default class ResizerOptions extends Component<Props, State> {
|
export default class ResizerOptions extends Component<Props, State> {
|
||||||
state: State = {
|
state: State = {
|
||||||
maintainAspect: true,
|
maintainAspect: true,
|
||||||
premultiply: true,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
form?: HTMLFormElement;
|
form?: HTMLFormElement;
|
||||||
@@ -43,6 +41,7 @@ export default class ResizerOptions extends Component<Props, State> {
|
|||||||
height: inputFieldValueAsNumber(height),
|
height: inputFieldValueAsNumber(height),
|
||||||
method: form.resizeMethod.value,
|
method: form.resizeMethod.value,
|
||||||
premultiply: inputFieldChecked(form.premultiply, true),
|
premultiply: inputFieldChecked(form.premultiply, true),
|
||||||
|
linearRGB: inputFieldChecked(form.linearRGB, true),
|
||||||
// Casting, as the formfield only returns the correct values.
|
// Casting, as the formfield only returns the correct values.
|
||||||
fitMethod: inputFieldValue(form.fitMethod, options.fitMethod) as ResizeOptions['fitMethod'],
|
fitMethod: inputFieldValue(form.fitMethod, options.fitMethod) as ResizeOptions['fitMethod'],
|
||||||
};
|
};
|
||||||
@@ -95,7 +94,7 @@ export default class ResizerOptions extends Component<Props, State> {
|
|||||||
<option value="lanczos3">Lanczos3</option>
|
<option value="lanczos3">Lanczos3</option>
|
||||||
<option value="mitchell">Mitchell</option>
|
<option value="mitchell">Mitchell</option>
|
||||||
<option value="catrom">Catmull-Rom</option>
|
<option value="catrom">Catmull-Rom</option>
|
||||||
<option value="triangle">Triangle</option>
|
<option value="triangle">Triangle (bilinear)</option>
|
||||||
<option value="browser-pixelated">Browser pixelated</option>
|
<option value="browser-pixelated">Browser pixelated</option>
|
||||||
<option value="browser-low">Browser low quality</option>
|
<option value="browser-low">Browser low quality</option>
|
||||||
<option value="browser-medium">Browser medium quality</option>
|
<option value="browser-medium">Browser medium quality</option>
|
||||||
@@ -138,6 +137,17 @@ export default class ResizerOptions extends Component<Props, State> {
|
|||||||
</label>
|
</label>
|
||||||
: null
|
: null
|
||||||
}
|
}
|
||||||
|
{isWorkerOptions(options) ?
|
||||||
|
<label class={style.optionInputFirst}>
|
||||||
|
<Checkbox
|
||||||
|
name="linearRGB"
|
||||||
|
checked={options.linearRGB}
|
||||||
|
onChange={this.onChange}
|
||||||
|
/>
|
||||||
|
Linear RGB
|
||||||
|
</label>
|
||||||
|
: null
|
||||||
|
}
|
||||||
</Expander>
|
</Expander>
|
||||||
<label class={style.optionInputFirst}>
|
<label class={style.optionInputFirst}>
|
||||||
<Checkbox
|
<Checkbox
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ export interface BrowserResizeOptions extends ResizeOptionsCommon {
|
|||||||
export interface WorkerResizeOptions extends ResizeOptionsCommon {
|
export interface WorkerResizeOptions extends ResizeOptionsCommon {
|
||||||
method: WorkerResizeMethods;
|
method: WorkerResizeMethods;
|
||||||
premultiply: boolean;
|
premultiply: boolean;
|
||||||
|
linearRGB: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface VectorResizeOptions extends ResizeOptionsCommon {
|
export interface VectorResizeOptions extends ResizeOptionsCommon {
|
||||||
@@ -41,4 +42,5 @@ export const defaultOptions: ResizeOptions = {
|
|||||||
method: 'lanczos3',
|
method: 'lanczos3',
|
||||||
fitMethod: 'stretch',
|
fitMethod: 'stretch',
|
||||||
premultiply: true,
|
premultiply: true,
|
||||||
|
linearRGB: true,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ export async function resize(data: ImageData, opts: WorkerResizeOptions): Promis
|
|||||||
|
|
||||||
const result = wasm_bindgen.resize(
|
const result = wasm_bindgen.resize(
|
||||||
new Uint8Array(input.data.buffer), input.width, input.height, opts.width, opts.height,
|
new Uint8Array(input.data.buffer), input.width, input.height, opts.width, opts.height,
|
||||||
resizeMethods.indexOf(opts.method), opts.premultiply,
|
resizeMethods.indexOf(opts.method), opts.premultiply, opts.linearRGB,
|
||||||
);
|
);
|
||||||
|
|
||||||
return new ImageData(new Uint8ClampedArray(result.buffer), opts.width, opts.height);
|
return new ImageData(new Uint8ClampedArray(result.buffer), opts.width, opts.height);
|
||||||
|
|||||||
Reference in New Issue
Block a user