mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-12 00:37:19 +00:00
Generating processor metadata
This commit is contained in:
@@ -1 +0,0 @@
|
|||||||
The compress folder was moved from src/client/lazy-app.
|
|
||||||
@@ -22,7 +22,7 @@ const autoGenComment =
|
|||||||
|
|
||||||
export default function () {
|
export default function () {
|
||||||
let previousWorkerImports;
|
let previousWorkerImports;
|
||||||
let previousEncoderMetas;
|
let previousJoinedMetas;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the worker file & tsconfig for all features
|
* Generates the worker file & tsconfig for all features
|
||||||
@@ -134,7 +134,7 @@ export default function () {
|
|||||||
const joinedWorkerImports = workerImports.join();
|
const joinedWorkerImports = workerImports.join();
|
||||||
|
|
||||||
// Avoid regenerating if nothing's changed.
|
// Avoid regenerating if nothing's changed.
|
||||||
// This also prevents an infinite look in the watcher.
|
// This also prevents an infinite loop in the watcher.
|
||||||
if (joinedWorkerImports === previousWorkerImports) return;
|
if (joinedWorkerImports === previousWorkerImports) return;
|
||||||
|
|
||||||
previousWorkerImports = joinedWorkerImports;
|
previousWorkerImports = joinedWorkerImports;
|
||||||
@@ -153,6 +153,14 @@ export default function () {
|
|||||||
.filter((tsFile) => !tsFile.endsWith('.d.ts'))
|
.filter((tsFile) => !tsFile.endsWith('.d.ts'))
|
||||||
.map((tsFile) => tsFile.slice(0, -'.ts'.length));
|
.map((tsFile) => tsFile.slice(0, -'.ts'.length));
|
||||||
|
|
||||||
|
const processorMetas = (
|
||||||
|
await globP('src/features/processors/*/shared/meta.ts', {
|
||||||
|
absolute: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.filter((tsFile) => !tsFile.endsWith('.d.ts'))
|
||||||
|
.map((tsFile) => tsFile.slice(0, -'.ts'.length));
|
||||||
|
|
||||||
const featureMetaBasePath = path.join(
|
const featureMetaBasePath = path.join(
|
||||||
process.cwd(),
|
process.cwd(),
|
||||||
'src',
|
'src',
|
||||||
@@ -161,20 +169,24 @@ export default function () {
|
|||||||
'feature-meta',
|
'feature-meta',
|
||||||
);
|
);
|
||||||
|
|
||||||
const joinedEncoderMetas = encoderMetas.join();
|
const joinedMetas = [...encoderMetas, ...processorMetas].join();
|
||||||
|
|
||||||
// Avoid regenerating if nothing's changed.
|
// Avoid regenerating if nothing's changed.
|
||||||
// This also prevents an infinite look in the watcher.
|
// This also prevents an infinite loop in the watcher.
|
||||||
if (joinedEncoderMetas === previousEncoderMetas) return;
|
if (joinedMetas === previousJoinedMetas) return;
|
||||||
previousEncoderMetas = joinedEncoderMetas;
|
previousJoinedMetas = joinedMetas;
|
||||||
|
|
||||||
const encoderMetaTsNames = encoderMetas.map((tsImport) => [
|
const getTsName = (tsImport) => [
|
||||||
path.relative(featureMetaBasePath, tsImport),
|
path.relative(featureMetaBasePath, tsImport),
|
||||||
path.basename(tsImport.slice(0, -'/shared/meta'.length)),
|
path.basename(tsImport.slice(0, -'/shared/meta'.length)),
|
||||||
]);
|
];
|
||||||
|
|
||||||
|
const encoderMetaTsNames = encoderMetas.map(getTsName);
|
||||||
|
const processorMetaTsNames = processorMetas.map(getTsName);
|
||||||
|
|
||||||
const featureMeta = [
|
const featureMeta = [
|
||||||
autoGenComment,
|
autoGenComment,
|
||||||
|
// Encoder stuff
|
||||||
encoderMetaTsNames.map(
|
encoderMetaTsNames.map(
|
||||||
([path, name]) => `import * as ${name}EncoderMeta from '${path}';`,
|
([path, name]) => `import * as ${name}EncoderMeta from '${path}';`,
|
||||||
),
|
),
|
||||||
@@ -194,6 +206,22 @@ export default function () {
|
|||||||
`};`,
|
`};`,
|
||||||
`export type EncoderType = keyof typeof encoderMap`,
|
`export type EncoderType = keyof typeof encoderMap`,
|
||||||
`export const encoders = [...Object.values(encoderMap)];`,
|
`export const encoders = [...Object.values(encoderMap)];`,
|
||||||
|
// Processor stuff
|
||||||
|
processorMetaTsNames.map(
|
||||||
|
([path, name]) => `import * as ${name}ProcessorMeta from '${path}';`,
|
||||||
|
),
|
||||||
|
`interface Enableable { enabled: boolean; }`,
|
||||||
|
`export interface ProcessorState {`,
|
||||||
|
processorMetaTsNames.map(
|
||||||
|
([_, name]) => ` ${name}: Enableable & ${name}ProcessorMeta.Options;`,
|
||||||
|
),
|
||||||
|
`}`,
|
||||||
|
`export const defaultProcessorState: ProcessorState = {`,
|
||||||
|
processorMetaTsNames.map(
|
||||||
|
([_, name]) =>
|
||||||
|
` ${name}: { enabled: false, ...${name}ProcessorMeta.defaultOptions },`,
|
||||||
|
),
|
||||||
|
`}`,
|
||||||
]
|
]
|
||||||
.flat(Infinity)
|
.flat(Infinity)
|
||||||
.join('\n');
|
.join('\n');
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import { EncoderState } from '../feature-meta';
|
import { EncoderState, ProcessorState } from '../feature-meta';
|
||||||
import { shallowEqual } from '../../lib/util';
|
import { shallowEqual } from '../../util';
|
||||||
import { PreprocessorState } from '../../codecs/preprocessors';
|
|
||||||
|
|
||||||
import * as identity from '../../codecs/identity/encoder-meta';
|
import * as identity from '../../codecs/identity/encoder-meta';
|
||||||
|
|
||||||
@@ -11,7 +10,7 @@ interface CacheResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
interface CacheEntry extends CacheResult {
|
interface CacheEntry extends CacheResult {
|
||||||
preprocessorState: PreprocessorState;
|
processorState: ProcessorState;
|
||||||
encoderState: EncoderState;
|
encoderState: EncoderState;
|
||||||
sourceData: ImageData;
|
sourceData: ImageData;
|
||||||
}
|
}
|
||||||
@@ -32,7 +31,7 @@ export default class ResultCache {
|
|||||||
|
|
||||||
match(
|
match(
|
||||||
sourceData: ImageData,
|
sourceData: ImageData,
|
||||||
preprocessorState: PreprocessorState,
|
processorState: ProcessorState,
|
||||||
encoderState: EncoderState,
|
encoderState: EncoderState,
|
||||||
): CacheResult | undefined {
|
): CacheResult | undefined {
|
||||||
const matchingIndex = this._entries.findIndex((entry) => {
|
const matchingIndex = this._entries.findIndex((entry) => {
|
||||||
@@ -41,11 +40,11 @@ export default class ResultCache {
|
|||||||
if (entry.encoderState.type !== encoderState.type) return false;
|
if (entry.encoderState.type !== encoderState.type) return false;
|
||||||
|
|
||||||
// Check that each set of options in the preprocessor are the same
|
// Check that each set of options in the preprocessor are the same
|
||||||
for (const prop in preprocessorState) {
|
for (const prop in processorState) {
|
||||||
if (
|
if (
|
||||||
!shallowEqual(
|
!shallowEqual(
|
||||||
(preprocessorState as any)[prop],
|
(processorState as any)[prop],
|
||||||
(entry.preprocessorState as any)[prop],
|
(entry.processorState as any)[prop],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return false;
|
return false;
|
||||||
@@ -59,3 +59,13 @@ export async function abortable<T>(
|
|||||||
}),
|
}),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare two objects, returning a boolean indicating if they have the same properties and strictly
|
||||||
|
* equal values.
|
||||||
|
*/
|
||||||
|
export function shallowEqual(one: any, two: any) {
|
||||||
|
for (const i in one) if (one[i] !== two[i]) return false;
|
||||||
|
for (const i in two) if (!(i in one)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
23
src/features/processors/quantize/shared/meta.ts
Normal file
23
src/features/processors/quantize/shared/meta.ts
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
export interface Options {
|
||||||
|
zx: number;
|
||||||
|
maxNumColors: number;
|
||||||
|
dither: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const defaultOptions: Options = {
|
||||||
|
zx: 0,
|
||||||
|
maxNumColors: 256,
|
||||||
|
dither: 1.0,
|
||||||
|
};
|
||||||
13
src/features/processors/quantize/shared/missing-types.d.ts
vendored
Normal file
13
src/features/processors/quantize/shared/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" />
|
||||||
7
src/features/processors/quantize/shared/tsconfig.json
Normal file
7
src/features/processors/quantize/shared/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../../../../generic-tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"lib": ["webworker", "esnext"]
|
||||||
|
},
|
||||||
|
"references": [{ "path": "../../../" }]
|
||||||
|
}
|
||||||
@@ -13,18 +13,13 @@
|
|||||||
import imagequant, { QuantizerModule } from 'codecs/imagequant/imagequant';
|
import imagequant, { QuantizerModule } from 'codecs/imagequant/imagequant';
|
||||||
import wasmUrl from 'url:codecs/imagequant/imagequant.wasm';
|
import wasmUrl from 'url:codecs/imagequant/imagequant.wasm';
|
||||||
import { initEmscriptenModule } from 'features/util';
|
import { initEmscriptenModule } from 'features/util';
|
||||||
|
import { Options } from '../shared/meta';
|
||||||
export interface QuantizeOptions {
|
|
||||||
zx: number;
|
|
||||||
maxNumColors: number;
|
|
||||||
dither: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
let emscriptenModule: Promise<QuantizerModule>;
|
let emscriptenModule: Promise<QuantizerModule>;
|
||||||
|
|
||||||
export default async function process(
|
export default async function process(
|
||||||
data: ImageData,
|
data: ImageData,
|
||||||
opts: QuantizeOptions,
|
opts: Options,
|
||||||
): Promise<ImageData> {
|
): Promise<ImageData> {
|
||||||
if (!emscriptenModule) {
|
if (!emscriptenModule) {
|
||||||
emscriptenModule = initEmscriptenModule(imagequant, wasmUrl);
|
emscriptenModule = initEmscriptenModule(imagequant, wasmUrl);
|
||||||
|
|||||||
@@ -3,5 +3,5 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"lib": ["webworker", "esnext"]
|
"lib": ["webworker", "esnext"]
|
||||||
},
|
},
|
||||||
"references": [{ "path": "../../../" }]
|
"references": [{ "path": "../../../" }, { "path": "../shared" }]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import {
|
|||||||
BuiltinResizeMethod,
|
BuiltinResizeMethod,
|
||||||
drawableToImageData,
|
drawableToImageData,
|
||||||
} from 'client/util';
|
} from 'client/util';
|
||||||
import { BrowserResizeOptions, VectorResizeOptions } from '../shared';
|
import { BrowserResizeOptions, VectorResizeOptions } from '../shared/meta';
|
||||||
import { getContainOffsets } from '../shared/util';
|
import { getContainOffsets } from '../shared/util';
|
||||||
|
|
||||||
export function browserResize(
|
export function browserResize(
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type WorkerResizeMethods =
|
|||||||
| 'lanczos3'
|
| 'lanczos3'
|
||||||
| 'hqx';
|
| 'hqx';
|
||||||
|
|
||||||
export type ResizeOptions =
|
export type Options =
|
||||||
| BrowserResizeOptions
|
| BrowserResizeOptions
|
||||||
| WorkerResizeOptions
|
| WorkerResizeOptions
|
||||||
| VectorResizeOptions;
|
| VectorResizeOptions;
|
||||||
@@ -47,3 +47,15 @@ export interface WorkerResizeOptions extends ResizeOptionsCommon {
|
|||||||
export interface VectorResizeOptions extends ResizeOptionsCommon {
|
export interface VectorResizeOptions extends ResizeOptionsCommon {
|
||||||
method: 'vector';
|
method: 'vector';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaultOptions: Options = {
|
||||||
|
// Width and height will always default to the image size.
|
||||||
|
// This is set elsewhere.
|
||||||
|
width: 1,
|
||||||
|
height: 1,
|
||||||
|
// This will be set to 'vector' if the input is SVG.
|
||||||
|
method: 'lanczos3',
|
||||||
|
fitMethod: 'stretch',
|
||||||
|
premultiply: true,
|
||||||
|
linearRGB: true,
|
||||||
|
};
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { WorkerResizeOptions } from '../shared';
|
import type { WorkerResizeOptions } from '../shared/meta';
|
||||||
import { getContainOffsets } from '../shared/util';
|
import { getContainOffsets } from '../shared/util';
|
||||||
import initResizeWasm, { resize as wasmResize } from 'codecs/resize/pkg';
|
import initResizeWasm, { resize as wasmResize } from 'codecs/resize/pkg';
|
||||||
import resizeWasmUrl from 'url:codecs/resize/pkg/squoosh_resize_bg.wasm';
|
import resizeWasmUrl from 'url:codecs/resize/pkg/squoosh_resize_bg.wasm';
|
||||||
|
|||||||
Reference in New Issue
Block a user