mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-16 18:49:50 +00:00
Rollup build
This commit is contained in:
13
src/features/processors/resize/worker/missing-types.d.ts
vendored
Normal file
13
src/features/processors/resize/worker/missing-types.d.ts
vendored
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Copyright 2020 Google Inc. All Rights Reserved.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
/// <reference path="../../../../../missing-types.d.ts" />
|
||||
142
src/features/processors/resize/worker/resize.ts
Normal file
142
src/features/processors/resize/worker/resize.ts
Normal file
@@ -0,0 +1,142 @@
|
||||
import type { WorkerResizeOptions } from '../shared/meta';
|
||||
import { getContainOffsets } from '../shared/util';
|
||||
import initResizeWasm, { resize as wasmResize } from 'codecs/resize/pkg';
|
||||
import resizeWasmUrl from 'url:codecs/resize/pkg/squoosh_resize_bg.wasm';
|
||||
import hqxWasmUrl from 'url:codecs/hqx/pkg/squooshhqx_bg.wasm';
|
||||
import initHqxWasm, { resize as wasmHqx } from 'codecs/hqx/pkg';
|
||||
|
||||
interface HqxResizeOptions extends WorkerResizeOptions {
|
||||
method: 'hqx';
|
||||
}
|
||||
|
||||
function optsIsHqxOpts(opts: WorkerResizeOptions): opts is HqxResizeOptions {
|
||||
return opts.method === 'hqx';
|
||||
}
|
||||
|
||||
function crop(
|
||||
data: ImageData,
|
||||
sx: number,
|
||||
sy: number,
|
||||
sw: number,
|
||||
sh: number,
|
||||
): ImageData {
|
||||
const inputPixels = new Uint32Array(data.data.buffer);
|
||||
|
||||
// Copy within the same buffer for speed and memory efficiency.
|
||||
for (let y = 0; y < sh; y += 1) {
|
||||
const start = (y + sy) * data.width + sx;
|
||||
inputPixels.copyWithin(y * sw, start, start + sw);
|
||||
}
|
||||
|
||||
return new ImageData(
|
||||
new Uint8ClampedArray(inputPixels.buffer.slice(0, sw * sh * 4)),
|
||||
sw,
|
||||
sh,
|
||||
);
|
||||
}
|
||||
|
||||
interface ClampOpts {
|
||||
min?: number;
|
||||
max?: number;
|
||||
}
|
||||
|
||||
function clamp(
|
||||
num: number,
|
||||
{ min = Number.MIN_VALUE, max = Number.MAX_VALUE }: ClampOpts,
|
||||
): number {
|
||||
return Math.min(Math.max(num, min), max);
|
||||
}
|
||||
|
||||
/** Resize methods by index */
|
||||
const resizeMethods: WorkerResizeOptions['method'][] = [
|
||||
'triangle',
|
||||
'catrom',
|
||||
'mitchell',
|
||||
'lanczos3',
|
||||
];
|
||||
|
||||
let resizeWasmReady: Promise<unknown>;
|
||||
let hqxWasmReady: Promise<unknown>;
|
||||
|
||||
async function hqx(
|
||||
input: ImageData,
|
||||
opts: HqxResizeOptions,
|
||||
): Promise<ImageData> {
|
||||
if (!hqxWasmReady) {
|
||||
hqxWasmReady = initHqxWasm(hqxWasmUrl);
|
||||
}
|
||||
|
||||
await hqxWasmReady;
|
||||
|
||||
const widthRatio = opts.width / input.width;
|
||||
const heightRatio = opts.height / input.height;
|
||||
const ratio = Math.max(widthRatio, heightRatio);
|
||||
const factor = clamp(Math.ceil(ratio), { min: 1, max: 4 }) as 1 | 2 | 3 | 4;
|
||||
|
||||
if (factor === 1) return input;
|
||||
|
||||
const result = wasmHqx(
|
||||
new Uint32Array(input.data.buffer),
|
||||
input.width,
|
||||
input.height,
|
||||
factor,
|
||||
);
|
||||
|
||||
return new ImageData(
|
||||
new Uint8ClampedArray(result.buffer),
|
||||
input.width * factor,
|
||||
input.height * factor,
|
||||
);
|
||||
}
|
||||
|
||||
export default async function resize(
|
||||
data: ImageData,
|
||||
opts: WorkerResizeOptions,
|
||||
): Promise<ImageData> {
|
||||
let input = data;
|
||||
|
||||
if (!resizeWasmReady) {
|
||||
resizeWasmReady = initResizeWasm(resizeWasmUrl);
|
||||
}
|
||||
|
||||
if (optsIsHqxOpts(opts)) {
|
||||
input = await hqx(input, opts);
|
||||
// Regular resize to make up the difference
|
||||
opts = { ...opts, method: 'catrom' };
|
||||
}
|
||||
|
||||
await resizeWasmReady;
|
||||
|
||||
if (opts.fitMethod === 'contain') {
|
||||
const { sx, sy, sw, sh } = getContainOffsets(
|
||||
data.width,
|
||||
data.height,
|
||||
opts.width,
|
||||
opts.height,
|
||||
);
|
||||
input = crop(
|
||||
input,
|
||||
Math.round(sx),
|
||||
Math.round(sy),
|
||||
Math.round(sw),
|
||||
Math.round(sh),
|
||||
);
|
||||
}
|
||||
|
||||
const result = wasmResize(
|
||||
new Uint8Array(input.data.buffer),
|
||||
input.width,
|
||||
input.height,
|
||||
opts.width,
|
||||
opts.height,
|
||||
resizeMethods.indexOf(opts.method),
|
||||
opts.premultiply,
|
||||
opts.linearRGB,
|
||||
);
|
||||
|
||||
return new ImageData(
|
||||
new Uint8ClampedArray(result.buffer),
|
||||
opts.width,
|
||||
opts.height,
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user