import { h, Component } from 'preact'; import { bind, inputFieldCheckedAsNumber, inputFieldValueAsNumber } from '../../lib/util'; import { EncodeOptions, WebPImageHint } from './encoder'; import * as styles from './styles.scss'; type Props = { options: EncodeOptions, onChange(newOptions: EncodeOptions): void, }; // From kLosslessPresets in config_enc.c // The format is [method, quality]. const losslessPresets:[number, number][] = [ [0, 0], [1, 20], [2, 25], [3, 30], [3, 50], [4, 50], [4, 75], [4, 90], [5, 90], [6, 100], ]; const losslessPresetDefault = 6; function determineLosslessQuality(quality: number): number { const index = losslessPresets.findIndex(item => item[1] === quality); if (index !== -1) return index; // Quality doesn't match one of the presets. // This can happen when toggling 'lossless'. return losslessPresetDefault; } export default class WebPEncoderOptions extends Component { @bind onChange(event: Event) { const form = (event.currentTarget as HTMLInputElement).closest('form') as HTMLFormElement; const lossless = inputFieldCheckedAsNumber(form.lossless); const losslessPresetInput = (form.lossless_preset as HTMLInputElement); const options: EncodeOptions = { // Copy over options the form doesn't care about, eg emulate_jpeg_size ...this.props.options, // And now stuff from the form: lossless, // Special-cased inputs: // In lossless mode, the quality is derived from the preset. quality: lossless ? losslessPresets[Number(losslessPresetInput.value)][1] : inputFieldValueAsNumber(form.quality), // In lossless mode, the method is derived from the preset. method: lossless ? losslessPresets[Number(losslessPresetInput.value)][0] : inputFieldValueAsNumber(form.method_input), image_hint: (form.image_hint as HTMLInputElement).checked ? WebPImageHint.WEBP_HINT_GRAPH : WebPImageHint.WEBP_HINT_DEFAULT, // .checked exact: inputFieldCheckedAsNumber(form.exact), alpha_compression: inputFieldCheckedAsNumber(form.alpha_compression), autofilter: inputFieldCheckedAsNumber(form.autofilter), filter_type: inputFieldCheckedAsNumber(form.filter_type), use_sharp_yuv: inputFieldCheckedAsNumber(form.use_sharp_yuv), // .value near_lossless: 100 - inputFieldValueAsNumber(form.near_lossless), alpha_quality: inputFieldValueAsNumber(form.alpha_quality), alpha_filtering: inputFieldValueAsNumber(form.alpha_filtering), sns_strength: inputFieldValueAsNumber(form.sns_strength), filter_strength: inputFieldValueAsNumber(form.filter_strength), filter_sharpness: 7 - inputFieldValueAsNumber(form.filter_sharpness), pass: inputFieldValueAsNumber(form.pass), preprocessing: inputFieldValueAsNumber(form.preprocessing), segments: inputFieldValueAsNumber(form.segments), partitions: inputFieldValueAsNumber(form.partitions), }; this.props.onChange(options); } private _losslessSpecificOptions(options: EncodeOptions) { return (
); } private _lossySpecificOptions(options: EncodeOptions) { return (
); } render({ options }: Props) { // I'm rendering both lossy and lossless forms, as it becomes much easier when // gathering the data. return (
{this._losslessSpecificOptions(options)}
{this._lossySpecificOptions(options)}
); } }