forked from external-repos/squoosh
Add Hq{2,3,4}x (#624)
* Scaling works on native * It works in wasm * Integrate with UI * Remove benchmark * Integrate Hqx into Resizer module * Link against repo for hqx * Remove unused defaultOpts * Re-add test file * Adding size dropdown * Chrome: go and sit on the naughty step * Better docs * Review * Add link to crbug * Update src/codecs/processor-worker/index.ts Co-Authored-By: Jake Archibald <jaffathecake@gmail.com> * Terminate worker inbetween resize jobs
This commit is contained in:
@@ -12,8 +12,9 @@ import Select from '../../components/select';
|
||||
|
||||
interface Props {
|
||||
isVector: Boolean;
|
||||
inputWidth: number;
|
||||
inputHeight: number;
|
||||
options: ResizeOptions;
|
||||
aspect: number;
|
||||
onChange(newOptions: ResizeOptions): void;
|
||||
}
|
||||
|
||||
@@ -21,12 +22,34 @@ interface State {
|
||||
maintainAspect: boolean;
|
||||
}
|
||||
|
||||
const sizePresets = [0.25, 0.3333, 0.5, 1, 2, 3, 4];
|
||||
|
||||
/**
|
||||
* Should we allow the user to select hqx? Chrome currently has a wasm bug, so we currently avoid it
|
||||
* there, unless overridden.
|
||||
* crbug.com/974804
|
||||
*/
|
||||
const allowHqx: boolean = (() => {
|
||||
const url = new URL(location.href);
|
||||
return url.searchParams.has('allow-hqx')
|
||||
// Yep. UA sniffing. Let's hope we can remove this soon.
|
||||
// Block browsers with Chrome/, unless they also have Edge/ (since the Edge UA includes Chrome/)
|
||||
|| !navigator.userAgent.includes('Chrome/') || navigator.userAgent.includes('Edge/');
|
||||
})();
|
||||
|
||||
export default class ResizerOptions extends Component<Props, State> {
|
||||
state: State = {
|
||||
maintainAspect: true,
|
||||
};
|
||||
|
||||
form?: HTMLFormElement;
|
||||
private form?: HTMLFormElement;
|
||||
private presetWidths: { [idx: number]: number } = {};
|
||||
private presetHeights: { [idx: number]: number } = {};
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.generatePresetValues(props.inputWidth, props.inputHeight);
|
||||
}
|
||||
|
||||
private reportOptions() {
|
||||
const form = this.form!;
|
||||
@@ -53,18 +76,31 @@ export default class ResizerOptions extends Component<Props, State> {
|
||||
this.reportOptions();
|
||||
}
|
||||
|
||||
private getAspect() {
|
||||
return this.props.inputWidth / this.props.inputHeight;
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props, prevState: State) {
|
||||
if (!prevState.maintainAspect && this.state.maintainAspect) {
|
||||
this.form!.height.value = Math.round(Number(this.form!.width.value) / this.props.aspect);
|
||||
this.form!.height.value = Math.round(Number(this.form!.width.value) / this.getAspect());
|
||||
this.reportOptions();
|
||||
}
|
||||
}
|
||||
|
||||
componentWillReceiveProps(nextProps: Props) {
|
||||
if (
|
||||
this.props.inputWidth !== nextProps.inputWidth ||
|
||||
this.props.inputHeight !== nextProps.inputHeight
|
||||
) {
|
||||
this.generatePresetValues(nextProps.inputWidth, nextProps.inputHeight);
|
||||
}
|
||||
}
|
||||
|
||||
@bind
|
||||
private onWidthInput() {
|
||||
if (this.state.maintainAspect) {
|
||||
const width = inputFieldValueAsNumber(this.form!.width);
|
||||
this.form!.height.value = Math.round(width / this.props.aspect);
|
||||
this.form!.height.value = Math.round(width / this.getAspect());
|
||||
}
|
||||
|
||||
this.reportOptions();
|
||||
@@ -74,12 +110,44 @@ export default class ResizerOptions extends Component<Props, State> {
|
||||
private onHeightInput() {
|
||||
if (this.state.maintainAspect) {
|
||||
const height = inputFieldValueAsNumber(this.form!.height);
|
||||
this.form!.width.value = Math.round(height * this.props.aspect);
|
||||
this.form!.width.value = Math.round(height * this.getAspect());
|
||||
}
|
||||
|
||||
this.reportOptions();
|
||||
}
|
||||
|
||||
private generatePresetValues(width: number, height: number) {
|
||||
for (const preset of sizePresets) {
|
||||
this.presetWidths[preset] = Math.round(width * preset);
|
||||
this.presetHeights[preset] = Math.round(height * preset);
|
||||
}
|
||||
}
|
||||
|
||||
private getPreset(): number | string {
|
||||
const { width, height } = this.props.options;
|
||||
|
||||
for (const preset of sizePresets) {
|
||||
if (
|
||||
width === this.presetWidths[preset] &&
|
||||
height === this.presetHeights[preset]
|
||||
) return preset;
|
||||
}
|
||||
|
||||
return 'custom';
|
||||
}
|
||||
|
||||
@bind
|
||||
private onPresetChange(event: Event) {
|
||||
const select = event.target as HTMLSelectElement;
|
||||
if (select.value === 'custom') return;
|
||||
const multiplier = Number(select.value);
|
||||
(this.form!.width as HTMLInputElement).value =
|
||||
Math.round(this.props.inputWidth * multiplier) + '';
|
||||
(this.form!.height as HTMLInputElement).value =
|
||||
Math.round(this.props.inputHeight * multiplier) + '';
|
||||
this.reportOptions();
|
||||
}
|
||||
|
||||
render({ options, isVector }: Props, { maintainAspect }: State) {
|
||||
return (
|
||||
<form ref={linkRef(this, 'form')} class={style.optionsSection} onSubmit={preventDefault}>
|
||||
@@ -95,12 +163,22 @@ export default class ResizerOptions extends Component<Props, State> {
|
||||
<option value="mitchell">Mitchell</option>
|
||||
<option value="catrom">Catmull-Rom</option>
|
||||
<option value="triangle">Triangle (bilinear)</option>
|
||||
{allowHqx && <option value="hqx">hqx (pixel art)</option>}
|
||||
<option value="browser-pixelated">Browser pixelated</option>
|
||||
<option value="browser-low">Browser low quality</option>
|
||||
<option value="browser-medium">Browser medium quality</option>
|
||||
<option value="browser-high">Browser high quality</option>
|
||||
</Select>
|
||||
</label>
|
||||
<label class={style.optionTextFirst}>
|
||||
Preset:
|
||||
<Select value={this.getPreset()} onChange={this.onPresetChange}>
|
||||
{sizePresets.map(preset =>
|
||||
<option value={preset}>{preset * 100}%</option>,
|
||||
)}
|
||||
<option value="custom">Custom</option>
|
||||
</Select>
|
||||
</label>
|
||||
<label class={style.optionTextFirst}>
|
||||
Width:
|
||||
<input
|
||||
|
||||
Reference in New Issue
Block a user