mirror of
https://github.com/GoogleChromeLabs/squoosh.git
synced 2025-11-17 19:19:47 +00:00
Easter egg (#123)
* lol zx quant * Adding ZX option * Improving colour selection so we don't end up with the same colour twice. Also fixing a bug with the colour conflict resolution. * Putting it behind a konami code * Better comments * Adding comment * Removing unnecessary malloc.
This commit is contained in:
@@ -9,6 +9,7 @@ interface ModuleAPI {
|
||||
create_buffer(width: number, height: number): number;
|
||||
destroy_buffer(pointer: number): void;
|
||||
quantize(buffer: number, width: number, height: number, numColors: number, dither: number): void;
|
||||
zx_quantize(buffer: number, width: number, height: number, dither: number): void;
|
||||
free_result(): void;
|
||||
get_result_pointer(): number;
|
||||
}
|
||||
@@ -51,6 +52,7 @@ export default class ImageQuant {
|
||||
create_buffer: m.cwrap('create_buffer', 'number', ['number', 'number']),
|
||||
destroy_buffer: m.cwrap('destroy_buffer', '', ['number']),
|
||||
quantize: m.cwrap('quantize', '', ['number', 'number', 'number', 'number', 'number']),
|
||||
zx_quantize: m.cwrap('zx_quantize', '', ['number', 'number', 'number', 'number']),
|
||||
free_result: m.cwrap('free_result', '', []),
|
||||
get_result_pointer: m.cwrap('get_result_pointer', 'number', []),
|
||||
};
|
||||
@@ -63,7 +65,11 @@ export default class ImageQuant {
|
||||
|
||||
const p = api.create_buffer(data.width, data.height);
|
||||
m.HEAP8.set(new Uint8Array(data.data), p);
|
||||
api.quantize(p, data.width, data.height, opts.maxNumColors, opts.dither);
|
||||
if (opts.zx) {
|
||||
api.zx_quantize(p, data.width, data.height, opts.dither);
|
||||
} else {
|
||||
api.quantize(p, data.width, data.height, opts.maxNumColors, opts.dither);
|
||||
}
|
||||
const resultPointer = api.get_result_pointer();
|
||||
const resultView = new Uint8Array(
|
||||
m.HEAP8.buffer,
|
||||
|
||||
@@ -1,29 +1,55 @@
|
||||
import { h, Component } from 'preact';
|
||||
import { bind, inputFieldValueAsNumber } from '../../lib/util';
|
||||
import { bind, inputFieldValueAsNumber, konami } from '../../lib/util';
|
||||
import { QuantizeOptions } from './quantizer';
|
||||
|
||||
const konamiPromise = konami();
|
||||
|
||||
interface Props {
|
||||
options: QuantizeOptions;
|
||||
onChange(newOptions: QuantizeOptions): void;
|
||||
}
|
||||
|
||||
export default class QuantizerOptions extends Component<Props, {}> {
|
||||
interface State {
|
||||
extendedSettings: boolean;
|
||||
}
|
||||
|
||||
export default class QuantizerOptions extends Component<Props, State> {
|
||||
state: State = { extendedSettings: false };
|
||||
|
||||
componentDidMount() {
|
||||
konamiPromise.then(() => {
|
||||
this.setState({ extendedSettings: true });
|
||||
});
|
||||
}
|
||||
|
||||
@bind
|
||||
onChange(event: Event) {
|
||||
const form = (event.currentTarget as HTMLInputElement).closest('form') as HTMLFormElement;
|
||||
|
||||
const options: QuantizeOptions = {
|
||||
zx: inputFieldValueAsNumber(form.zx),
|
||||
maxNumColors: inputFieldValueAsNumber(form.maxNumColors),
|
||||
dither: inputFieldValueAsNumber(form.dither),
|
||||
};
|
||||
this.props.onChange(options);
|
||||
}
|
||||
|
||||
render({ options }: Props) {
|
||||
render({ options }: Props, { extendedSettings }: State) {
|
||||
return (
|
||||
<form>
|
||||
<label>
|
||||
Pallette Colors:
|
||||
<label style={{ display: extendedSettings ? '' : 'none' }}>
|
||||
Type:
|
||||
<select
|
||||
name="zx"
|
||||
value={'' + options.zx}
|
||||
onChange={this.onChange}
|
||||
>
|
||||
<option value="0">Standard</option>
|
||||
<option value="1">ZX</option>
|
||||
</select>
|
||||
</label>
|
||||
<label style={{ display: options.zx ? 'none' : '' }}>
|
||||
Palette Colors:
|
||||
<input
|
||||
name="maxNumColors"
|
||||
type="range"
|
||||
|
||||
@@ -6,11 +6,13 @@ export async function quantize(data: ImageData, opts: QuantizeOptions): Promise<
|
||||
}
|
||||
|
||||
export interface QuantizeOptions {
|
||||
zx: number;
|
||||
maxNumColors: number;
|
||||
dither: number;
|
||||
}
|
||||
|
||||
export const defaultOptions: QuantizeOptions = {
|
||||
zx: 0,
|
||||
maxNumColors: 256,
|
||||
dither: 1.0,
|
||||
};
|
||||
|
||||
@@ -159,3 +159,25 @@ export function inputFieldValueAsNumber(field: any): number {
|
||||
export function inputFieldCheckedAsNumber(field: any): number {
|
||||
return Number((field as HTMLInputElement).checked);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a promise that resolves when the user types the konami code.
|
||||
*/
|
||||
export function konami(): Promise<void> {
|
||||
return new Promise((resolve) => {
|
||||
// Keycodes for: ↑ ↑ ↓ ↓ ← → ← → B A
|
||||
const expectedPattern = '38384040373937396665';
|
||||
let rollingPattern = '';
|
||||
|
||||
const listener = (event: KeyboardEvent) => {
|
||||
rollingPattern += event.keyCode;
|
||||
rollingPattern = rollingPattern.slice(0, expectedPattern.length);
|
||||
if (rollingPattern === expectedPattern) {
|
||||
window.removeEventListener('keydown', listener);
|
||||
resolve();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', listener);
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user