image-to-pixel 3.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -21
- package/README.md +69 -69
- package/dist/editor.css.map +1 -1
- package/dist/editor.esm.js +1 -1
- package/dist/editor.esm.js.map +1 -1
- package/dist/fonts/README.md +6 -6
- package/dist/fonts/geist-LICENSE.txt +93 -93
- package/dist/image-to-pixel.bundle.esm.js +13 -13
- package/dist/image-to-pixel.bundle.esm.js.map +2 -2
- package/dist/image-to-pixel.cjs +2 -2
- package/dist/image-to-pixel.cjs.map +2 -2
- package/dist/image-to-pixel.esm.js +2 -2
- package/dist/image-to-pixel.esm.js.map +2 -2
- package/dist/image-to-pixel.js +2 -2
- package/dist/image-to-pixel.js.map +2 -2
- package/dist/image-to-pixel.min.js +11 -11
- package/dist/image-to-pixel.min.js.map +2 -2
- package/dist/video.esm.js +1 -1
- package/dist/video.esm.js.map +1 -1
- package/lib/core/color.js +69 -69
- package/lib/core/cpu/pipeline.js +21 -21
- package/lib/core/cpu/stages.js +227 -227
- package/lib/core/dither/bluenoise-data.js +3 -3
- package/lib/core/dither/kernels.js +27 -27
- package/lib/core/dither/matrices.js +95 -95
- package/lib/core/engine.js +158 -158
- package/lib/core/export/canvas.js +22 -22
- package/lib/core/export/crc32.js +15 -15
- package/lib/core/export/gif.js +153 -153
- package/lib/core/export/png.js +94 -94
- package/lib/core/export/scale.js +103 -103
- package/lib/core/export/sheet.js +95 -95
- package/lib/core/export/zip.js +55 -55
- package/lib/core/gpu/backend.js +159 -159
- package/lib/core/gpu/shaders.js +258 -258
- package/lib/core/palette/builtin.js +36 -36
- package/lib/core/palette/extract.js +69 -69
- package/lib/core/palette/lospec.js +24 -24
- package/lib/core/palette/parse.js +112 -112
- package/lib/core/plan.js +58 -58
- package/lib/core/presets.js +42 -42
- package/lib/core/settings.js +274 -274
- package/lib/core/source.js +89 -89
- package/lib/core/video/frames.js +144 -144
- package/lib/core/video/mux-mp4.js +131 -131
- package/lib/core/video/mux-webm.js +127 -127
- package/lib/editor/controls.js +139 -139
- package/lib/editor/dom.js +65 -65
- package/lib/editor/exporter.js +185 -185
- package/lib/editor/icons.js +61 -61
- package/lib/editor/index.js +793 -793
- package/lib/editor/inspector.js +328 -328
- package/lib/editor/library.js +182 -182
- package/lib/editor/persist.js +18 -18
- package/lib/editor/samples.js +90 -90
- package/lib/editor/stage.js +239 -239
- package/lib/editor/store.js +80 -80
- package/lib/editor/styles/editor.css +385 -385
- package/lib/editor/styles/fonts/README.md +6 -6
- package/lib/editor/styles/fonts/geist-LICENSE.txt +93 -93
- package/lib/editor/styles/tokens.css +89 -89
- package/lib/editor/ui.js +97 -97
- package/lib/index.js +3 -1
- package/lib/video.js +92 -92
- package/package.json +92 -92
- package/types/editor.d.ts +34 -34
- package/types/index.d.ts +196 -196
- package/types/video.d.ts +43 -43
package/types/index.d.ts
CHANGED
|
@@ -1,196 +1,196 @@
|
|
|
1
|
-
// Type definitions for image-to-pixel 3.x
|
|
2
|
-
|
|
3
|
-
export type DitherMethod =
|
|
4
|
-
| 'none' | 'bayer2' | 'bayer4' | 'bayer8' | 'bayer16' | 'cluster4' | 'cluster8' | 'lines' | 'bluenoise' | 'custom'
|
|
5
|
-
| 'floyd-steinberg' | 'atkinson' | 'sierra-lite' | 'sierra' | 'burkes' | 'jarvis' | 'stucki';
|
|
6
|
-
|
|
7
|
-
export interface SizeSettings {
|
|
8
|
-
mode: 'width' | 'block';
|
|
9
|
-
/** Output width, 1–2048. */
|
|
10
|
-
width: number;
|
|
11
|
-
/** Output height; 0 keeps the aspect ratio. */
|
|
12
|
-
height: number;
|
|
13
|
-
/** Source pixels per output pixel when mode is 'block'. */
|
|
14
|
-
block: number;
|
|
15
|
-
resample: 'box' | 'nearest';
|
|
16
|
-
}
|
|
17
|
-
export interface AdjustSettings { brightness: number; contrast: number; saturation: number; /** degrees, -180..180 */ hue: number; gamma: number }
|
|
18
|
-
export type AspectId = 'original' | '1:1' | '4:3' | '3:4' | '3:2' | '2:3' | '16:9' | '9:16';
|
|
19
|
-
/** Which part of the source is used: the largest rectangle of `aspect`, divided by `zoom`, placed by x/y (0..1). */
|
|
20
|
-
export interface FrameSettings { aspect: AspectId; zoom: number; x: number; y: number }
|
|
21
|
-
export interface PaletteSettings {
|
|
22
|
-
source: 'builtin' | 'custom' | 'extract' | 'none';
|
|
23
|
-
/** Built-in palette id, e.g. 'pico-8'. */
|
|
24
|
-
id: string;
|
|
25
|
-
name: string;
|
|
26
|
-
/** '#rrggbb' strings. */
|
|
27
|
-
colors: string[];
|
|
28
|
-
/** Colours to extract when source is 'extract'. */
|
|
29
|
-
count: number;
|
|
30
|
-
distance: 'oklab' | 'rgb';
|
|
31
|
-
}
|
|
32
|
-
export interface DitherSettings {
|
|
33
|
-
method: DitherMethod;
|
|
34
|
-
/** 0–1 */
|
|
35
|
-
strength: number;
|
|
36
|
-
/** Threshold matrix for 'custom' (up to 16×16). Only the order of values matters. */
|
|
37
|
-
matrix: number[][] | null;
|
|
38
|
-
}
|
|
39
|
-
export interface Settings {
|
|
40
|
-
version: number;
|
|
41
|
-
size: SizeSettings;
|
|
42
|
-
frame: FrameSettings;
|
|
43
|
-
adjust: AdjustSettings;
|
|
44
|
-
palette: PaletteSettings;
|
|
45
|
-
dither: DitherSettings;
|
|
46
|
-
alpha: { threshold: number };
|
|
47
|
-
cleanup: { orphans: boolean; smooth: boolean };
|
|
48
|
-
outline: { mode: 'none' | 'outer' | 'inner'; color: string; corners: boolean };
|
|
49
|
-
export: { size: 'scale' | 'source'; scale: number; indexed: boolean; grid: boolean; gridColor: string };
|
|
50
|
-
}
|
|
51
|
-
type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? (T[K] extends any[] ? T[K] : Partial<T[K]>) : T[K] };
|
|
52
|
-
export type SettingsInput = DeepPartial<Settings>;
|
|
53
|
-
|
|
54
|
-
export interface RGBAImage { width: number; height: number; data: ArrayLike<number> & { length: number } }
|
|
55
|
-
|
|
56
|
-
export type Source =
|
|
57
|
-
| HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | HTMLVideoElement | VideoFrame
|
|
58
|
-
| ImageData | RGBAImage | Blob | string
|
|
59
|
-
| { canvas: HTMLCanvasElement } | { elt: HTMLCanvasElement };
|
|
60
|
-
|
|
61
|
-
export interface PNGOptions { scale?: number; grid?: boolean; gridColor?: string; indexed?: boolean; /** resize to exactly this size (with height) */ width?: number; height?: number }
|
|
62
|
-
|
|
63
|
-
export interface PixelResult {
|
|
64
|
-
width: number;
|
|
65
|
-
height: number;
|
|
66
|
-
/** RGBA, rows top-down. */
|
|
67
|
-
data: Uint8ClampedArray;
|
|
68
|
-
/** Palette used ('#rrggbb'), or null when colours were kept. */
|
|
69
|
-
palette: string[] | null;
|
|
70
|
-
settings: Settings;
|
|
71
|
-
kind: 'none' | 'ordered' | 'diffusion';
|
|
72
|
-
waves: number;
|
|
73
|
-
/** The framed part of the source, as fractions of its width and height. */
|
|
74
|
-
crop: { x: number; y: number; w: number; h: number };
|
|
75
|
-
backend: 'webgl' | 'cpu';
|
|
76
|
-
ms: number;
|
|
77
|
-
usedColors(): string[];
|
|
78
|
-
toImageData(): ImageData;
|
|
79
|
-
toCanvas(scale?: number, opts?: { grid?: boolean; gridColor?: string; canvas?: HTMLCanvasElement }): HTMLCanvasElement;
|
|
80
|
-
toPNG(opts?: PNGOptions): Promise<Uint8Array>;
|
|
81
|
-
toBlob(opts?: PNGOptions): Promise<Blob>;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
export interface PixelatorOptions {
|
|
85
|
-
backend?: 'auto' | 'webgl' | 'cpu';
|
|
86
|
-
diffusion?: 'auto' | 'gpu' | 'cpu';
|
|
87
|
-
maxSourceSize?: number;
|
|
88
|
-
}
|
|
89
|
-
export interface Pixelator {
|
|
90
|
-
readonly backend: 'webgl' | 'cpu';
|
|
91
|
-
readonly renderer: string;
|
|
92
|
-
readonly fallbackReason: string;
|
|
93
|
-
/** The ShaderMate instance behind the GPU backend (null on the CPU). */
|
|
94
|
-
readonly shader: unknown;
|
|
95
|
-
process(source: Source, settings?: SettingsInput): Promise<PixelResult>;
|
|
96
|
-
invalidate(): void;
|
|
97
|
-
destroy(): void;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
export function createPixelator(options?: PixelatorOptions): Promise<Pixelator>;
|
|
101
|
-
|
|
102
|
-
export interface ClassicOptions {
|
|
103
|
-
image: Source;
|
|
104
|
-
width: number;
|
|
105
|
-
dither?: string;
|
|
106
|
-
/** 0–100 */
|
|
107
|
-
strength?: number;
|
|
108
|
-
palette?: string[] | string | null;
|
|
109
|
-
resolution?: 'original' | 'pixel';
|
|
110
|
-
}
|
|
111
|
-
export function pixelate(options: ClassicOptions): Promise<HTMLCanvasElement>;
|
|
112
|
-
export function pixelate(source: Source, settings?: SettingsInput): Promise<PixelResult>;
|
|
113
|
-
|
|
114
|
-
export const VERSION: string;
|
|
115
|
-
export const SETTINGS_VERSION: number;
|
|
116
|
-
export const MAX_SIZE: number;
|
|
117
|
-
export const DEFAULTS: Readonly<Settings>;
|
|
118
|
-
export const DITHER_METHODS: { id: DitherMethod; label: string; kind: 'none' | 'ordered' | 'diffusion' }[];
|
|
119
|
-
export const LEGACY_DITHER: Record<string, DitherMethod>;
|
|
120
|
-
export function ditherKind(id: DitherMethod): 'none' | 'ordered' | 'diffusion';
|
|
121
|
-
export function defaultSettings(): Settings;
|
|
122
|
-
export function normalizeSettings(input?: SettingsInput): Settings;
|
|
123
|
-
export function mergeSettings(base: SettingsInput, patch: SettingsInput): Settings;
|
|
124
|
-
export const ASPECTS: { id: AspectId; label: string; ratio: number | null }[];
|
|
125
|
-
/** The source pixels a frame keeps. */
|
|
126
|
-
export function cropRect(srcWidth: number, srcHeight: number, frame?: Partial<FrameSettings>): { x: number; y: number; w: number; h: number };
|
|
127
|
-
export function resolveSize(srcWidth: number, srcHeight: number, size: SizeSettings): { width: number; height: number };
|
|
128
|
-
export function encodeSettings(settings: SettingsInput): string;
|
|
129
|
-
export function decodeSettings(stringOrUrl: string): Settings;
|
|
130
|
-
export function compactSettings(settings: SettingsInput): SettingsInput;
|
|
131
|
-
export function settingsToJSON(settings: SettingsInput): string;
|
|
132
|
-
export function settingsFromJSON(json: string | object): Settings;
|
|
133
|
-
|
|
134
|
-
export interface Plan { width: number; height: number; crop: { x: number; y: number; w: number; h: number }; quantize: boolean; kind: 'none' | 'ordered' | 'diffusion'; palette: number[][]; waves: number; settings: Settings }
|
|
135
|
-
export function makePlan(settings: SettingsInput, source: RGBAImage): Plan;
|
|
136
|
-
export function runCPU(plan: Plan, source: RGBAImage): Uint8ClampedArray;
|
|
137
|
-
export function makeResult(plan: Plan, data: Uint8ClampedArray, backend?: 'webgl' | 'cpu', ms?: number): PixelResult;
|
|
138
|
-
|
|
139
|
-
export interface BuiltinPalette { id: string; name: string; author: string; colors: string[] }
|
|
140
|
-
export const PALETTES: BuiltinPalette[];
|
|
141
|
-
export function getPalette(idOrName: string): BuiltinPalette | null;
|
|
142
|
-
export function parsePalette(text: string, filename?: string): { name: string; colors: string[] };
|
|
143
|
-
export function toGPL(name: string, colors: string[]): string;
|
|
144
|
-
export function toHexFile(colors: string[]): string;
|
|
145
|
-
export function toPaletteJSON(name: string, colors: string[]): string;
|
|
146
|
-
export function extractPalette(image: RGBAImage, count?: number, opts?: { maxSamples?: number; alphaThreshold?: number }): string[];
|
|
147
|
-
export function fetchLospec(slugOrUrl: string, opts?: { fetch?: typeof fetch }): Promise<{ name: string; author: string; colors: string[]; slug: string }>;
|
|
148
|
-
export function lospecSlug(input: string): string;
|
|
149
|
-
|
|
150
|
-
export interface ThresholdMap { w: number; h: number; levels: number; values: Uint8Array }
|
|
151
|
-
export function thresholdMap(method: DitherMethod, custom?: number[][] | null): ThresholdMap;
|
|
152
|
-
export function parseMatrix(text: string): number[][];
|
|
153
|
-
export function bayer(n: number): number[][];
|
|
154
|
-
export const KERNELS: Record<string, [number, number, number][]>;
|
|
155
|
-
|
|
156
|
-
export interface Preset { id: string; name: string; description: string; settings: SettingsInput }
|
|
157
|
-
export const PRESETS: Preset[];
|
|
158
|
-
export function getPreset(id: string): Preset | null;
|
|
159
|
-
|
|
160
|
-
export function parseColor(c: string | number[]): [number, number, number];
|
|
161
|
-
export function toHex(rgb: number[]): string;
|
|
162
|
-
export function oklab(r: number, g: number, b: number): [number, number, number];
|
|
163
|
-
|
|
164
|
-
export interface Frame { width: number; height: number; canvas: HTMLCanvasElement | null; data: ArrayLike<number> }
|
|
165
|
-
export function toFrame(source: Source, opts?: { maxSize?: number; canvas?: HTMLCanvasElement }): Promise<Frame>;
|
|
166
|
-
export function loadImage(src: string | Blob): Promise<HTMLImageElement | ImageBitmap>;
|
|
167
|
-
|
|
168
|
-
export function upscale(image: RGBAImage, k?: number, opts?: { grid?: boolean; gridColor?: string; gridAlpha?: number }): { width: number; height: number; data: Uint8ClampedArray };
|
|
169
|
-
export function resizeNearest(image: RGBAImage, width: number, height: number): { width: number; height: number; data: Uint8ClampedArray };
|
|
170
|
-
export function uniqueColors(image: RGBAImage, limit?: number): string[];
|
|
171
|
-
export function detectGrid(image: RGBAImage, tolerance?: number): number;
|
|
172
|
-
export function hasTransparency(image: RGBAImage): boolean;
|
|
173
|
-
export function toCanvas(image: RGBAImage, scale?: number, opts?: { grid?: boolean; gridColor?: string; canvas?: HTMLCanvasElement }): HTMLCanvasElement;
|
|
174
|
-
export function downloadBlob(data: Blob | Uint8Array | string, filename: string, type?: string): void;
|
|
175
|
-
export function encodePNG(image: RGBAImage, opts?: PNGOptions): Promise<Uint8Array>;
|
|
176
|
-
export function encodeGIF(frames: (RGBAImage & { delay?: number })[], opts?: { loop?: number; scale?: number; delay?: number }): Uint8Array;
|
|
177
|
-
export function createZip(entries: { name: string; data: Uint8Array | string; date?: Date }[]): Uint8Array;
|
|
178
|
-
export function packSpriteSheet(frames: (RGBAImage & { name?: string; delay?: number })[], opts?: { columns?: number; padding?: number; name?: string }): { image: { width: number; height: number; data: Uint8ClampedArray }; atlas: any };
|
|
179
|
-
export function buildTileset(image: RGBAImage, opts?: { tileWidth?: number; tileHeight?: number; columns?: number; flips?: boolean }): {
|
|
180
|
-
image: { width: number; height: number; data: Uint8ClampedArray };
|
|
181
|
-
map: { width: number; height: number; tileWidth: number; tileHeight: number; tiles: number[]; flips?: number[] };
|
|
182
|
-
count: number;
|
|
183
|
-
};
|
|
184
|
-
|
|
185
|
-
export function videoReady(video: HTMLVideoElement, opts?: { timeout?: number }): Promise<HTMLVideoElement>;
|
|
186
|
-
/** A readable Error for a <video>'s MediaError; `code` is the MediaError code. */
|
|
187
|
-
export function mediaError(video: HTMLVideoElement): Error & { code: number; detail?: string };
|
|
188
|
-
/** Best-effort codec name read from an MP4/MOV/WebM file's bytes ('' when unknown). */
|
|
189
|
-
export function sniffVideoCodec(file: Blob): Promise<string>;
|
|
190
|
-
export function seekTo(video: HTMLVideoElement, time: number): Promise<void>;
|
|
191
|
-
export function estimateFps(video: HTMLVideoElement, fallback?: number): Promise<number>;
|
|
192
|
-
export function frameTimes(opts: { duration: number; fps: number; start?: number; end?: number; maxFrames?: number }): number[];
|
|
193
|
-
export function forEachFrame(video: HTMLVideoElement, opts: {
|
|
194
|
-
fps: number; start?: number; end?: number; maxFrames?: number; signal?: AbortSignal;
|
|
195
|
-
onFrame: (info: { index: number; time: number; total: number }) => unknown;
|
|
196
|
-
}): Promise<number>;
|
|
1
|
+
// Type definitions for image-to-pixel 3.x
|
|
2
|
+
|
|
3
|
+
export type DitherMethod =
|
|
4
|
+
| 'none' | 'bayer2' | 'bayer4' | 'bayer8' | 'bayer16' | 'cluster4' | 'cluster8' | 'lines' | 'bluenoise' | 'custom'
|
|
5
|
+
| 'floyd-steinberg' | 'atkinson' | 'sierra-lite' | 'sierra' | 'burkes' | 'jarvis' | 'stucki';
|
|
6
|
+
|
|
7
|
+
export interface SizeSettings {
|
|
8
|
+
mode: 'width' | 'block';
|
|
9
|
+
/** Output width, 1–2048. */
|
|
10
|
+
width: number;
|
|
11
|
+
/** Output height; 0 keeps the aspect ratio. */
|
|
12
|
+
height: number;
|
|
13
|
+
/** Source pixels per output pixel when mode is 'block'. */
|
|
14
|
+
block: number;
|
|
15
|
+
resample: 'box' | 'nearest';
|
|
16
|
+
}
|
|
17
|
+
export interface AdjustSettings { brightness: number; contrast: number; saturation: number; /** degrees, -180..180 */ hue: number; gamma: number }
|
|
18
|
+
export type AspectId = 'original' | '1:1' | '4:3' | '3:4' | '3:2' | '2:3' | '16:9' | '9:16';
|
|
19
|
+
/** Which part of the source is used: the largest rectangle of `aspect`, divided by `zoom`, placed by x/y (0..1). */
|
|
20
|
+
export interface FrameSettings { aspect: AspectId; zoom: number; x: number; y: number }
|
|
21
|
+
export interface PaletteSettings {
|
|
22
|
+
source: 'builtin' | 'custom' | 'extract' | 'none';
|
|
23
|
+
/** Built-in palette id, e.g. 'pico-8'. */
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
/** '#rrggbb' strings. */
|
|
27
|
+
colors: string[];
|
|
28
|
+
/** Colours to extract when source is 'extract'. */
|
|
29
|
+
count: number;
|
|
30
|
+
distance: 'oklab' | 'rgb';
|
|
31
|
+
}
|
|
32
|
+
export interface DitherSettings {
|
|
33
|
+
method: DitherMethod;
|
|
34
|
+
/** 0–1 */
|
|
35
|
+
strength: number;
|
|
36
|
+
/** Threshold matrix for 'custom' (up to 16×16). Only the order of values matters. */
|
|
37
|
+
matrix: number[][] | null;
|
|
38
|
+
}
|
|
39
|
+
export interface Settings {
|
|
40
|
+
version: number;
|
|
41
|
+
size: SizeSettings;
|
|
42
|
+
frame: FrameSettings;
|
|
43
|
+
adjust: AdjustSettings;
|
|
44
|
+
palette: PaletteSettings;
|
|
45
|
+
dither: DitherSettings;
|
|
46
|
+
alpha: { threshold: number };
|
|
47
|
+
cleanup: { orphans: boolean; smooth: boolean };
|
|
48
|
+
outline: { mode: 'none' | 'outer' | 'inner'; color: string; corners: boolean };
|
|
49
|
+
export: { size: 'scale' | 'source'; scale: number; indexed: boolean; grid: boolean; gridColor: string };
|
|
50
|
+
}
|
|
51
|
+
type DeepPartial<T> = { [K in keyof T]?: T[K] extends object ? (T[K] extends any[] ? T[K] : Partial<T[K]>) : T[K] };
|
|
52
|
+
export type SettingsInput = DeepPartial<Settings>;
|
|
53
|
+
|
|
54
|
+
export interface RGBAImage { width: number; height: number; data: ArrayLike<number> & { length: number } }
|
|
55
|
+
|
|
56
|
+
export type Source =
|
|
57
|
+
| HTMLImageElement | HTMLCanvasElement | OffscreenCanvas | ImageBitmap | HTMLVideoElement | VideoFrame
|
|
58
|
+
| ImageData | RGBAImage | Blob | string
|
|
59
|
+
| { canvas: HTMLCanvasElement } | { elt: HTMLCanvasElement };
|
|
60
|
+
|
|
61
|
+
export interface PNGOptions { scale?: number; grid?: boolean; gridColor?: string; indexed?: boolean; /** resize to exactly this size (with height) */ width?: number; height?: number }
|
|
62
|
+
|
|
63
|
+
export interface PixelResult {
|
|
64
|
+
width: number;
|
|
65
|
+
height: number;
|
|
66
|
+
/** RGBA, rows top-down. */
|
|
67
|
+
data: Uint8ClampedArray;
|
|
68
|
+
/** Palette used ('#rrggbb'), or null when colours were kept. */
|
|
69
|
+
palette: string[] | null;
|
|
70
|
+
settings: Settings;
|
|
71
|
+
kind: 'none' | 'ordered' | 'diffusion';
|
|
72
|
+
waves: number;
|
|
73
|
+
/** The framed part of the source, as fractions of its width and height. */
|
|
74
|
+
crop: { x: number; y: number; w: number; h: number };
|
|
75
|
+
backend: 'webgl' | 'cpu';
|
|
76
|
+
ms: number;
|
|
77
|
+
usedColors(): string[];
|
|
78
|
+
toImageData(): ImageData;
|
|
79
|
+
toCanvas(scale?: number, opts?: { grid?: boolean; gridColor?: string; canvas?: HTMLCanvasElement }): HTMLCanvasElement;
|
|
80
|
+
toPNG(opts?: PNGOptions): Promise<Uint8Array>;
|
|
81
|
+
toBlob(opts?: PNGOptions): Promise<Blob>;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface PixelatorOptions {
|
|
85
|
+
backend?: 'auto' | 'webgl' | 'cpu';
|
|
86
|
+
diffusion?: 'auto' | 'gpu' | 'cpu';
|
|
87
|
+
maxSourceSize?: number;
|
|
88
|
+
}
|
|
89
|
+
export interface Pixelator {
|
|
90
|
+
readonly backend: 'webgl' | 'cpu';
|
|
91
|
+
readonly renderer: string;
|
|
92
|
+
readonly fallbackReason: string;
|
|
93
|
+
/** The ShaderMate instance behind the GPU backend (null on the CPU). */
|
|
94
|
+
readonly shader: unknown;
|
|
95
|
+
process(source: Source, settings?: SettingsInput): Promise<PixelResult>;
|
|
96
|
+
invalidate(): void;
|
|
97
|
+
destroy(): void;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export function createPixelator(options?: PixelatorOptions): Promise<Pixelator>;
|
|
101
|
+
|
|
102
|
+
export interface ClassicOptions {
|
|
103
|
+
image: Source;
|
|
104
|
+
width: number;
|
|
105
|
+
dither?: string;
|
|
106
|
+
/** 0–100 */
|
|
107
|
+
strength?: number;
|
|
108
|
+
palette?: string[] | string | null;
|
|
109
|
+
resolution?: 'original' | 'pixel';
|
|
110
|
+
}
|
|
111
|
+
export function pixelate(options: ClassicOptions): Promise<HTMLCanvasElement>;
|
|
112
|
+
export function pixelate(source: Source, settings?: SettingsInput): Promise<PixelResult>;
|
|
113
|
+
|
|
114
|
+
export const VERSION: string;
|
|
115
|
+
export const SETTINGS_VERSION: number;
|
|
116
|
+
export const MAX_SIZE: number;
|
|
117
|
+
export const DEFAULTS: Readonly<Settings>;
|
|
118
|
+
export const DITHER_METHODS: { id: DitherMethod; label: string; kind: 'none' | 'ordered' | 'diffusion' }[];
|
|
119
|
+
export const LEGACY_DITHER: Record<string, DitherMethod>;
|
|
120
|
+
export function ditherKind(id: DitherMethod): 'none' | 'ordered' | 'diffusion';
|
|
121
|
+
export function defaultSettings(): Settings;
|
|
122
|
+
export function normalizeSettings(input?: SettingsInput): Settings;
|
|
123
|
+
export function mergeSettings(base: SettingsInput, patch: SettingsInput): Settings;
|
|
124
|
+
export const ASPECTS: { id: AspectId; label: string; ratio: number | null }[];
|
|
125
|
+
/** The source pixels a frame keeps. */
|
|
126
|
+
export function cropRect(srcWidth: number, srcHeight: number, frame?: Partial<FrameSettings>): { x: number; y: number; w: number; h: number };
|
|
127
|
+
export function resolveSize(srcWidth: number, srcHeight: number, size: SizeSettings): { width: number; height: number };
|
|
128
|
+
export function encodeSettings(settings: SettingsInput): string;
|
|
129
|
+
export function decodeSettings(stringOrUrl: string): Settings;
|
|
130
|
+
export function compactSettings(settings: SettingsInput): SettingsInput;
|
|
131
|
+
export function settingsToJSON(settings: SettingsInput): string;
|
|
132
|
+
export function settingsFromJSON(json: string | object): Settings;
|
|
133
|
+
|
|
134
|
+
export interface Plan { width: number; height: number; crop: { x: number; y: number; w: number; h: number }; quantize: boolean; kind: 'none' | 'ordered' | 'diffusion'; palette: number[][]; waves: number; settings: Settings }
|
|
135
|
+
export function makePlan(settings: SettingsInput, source: RGBAImage): Plan;
|
|
136
|
+
export function runCPU(plan: Plan, source: RGBAImage): Uint8ClampedArray;
|
|
137
|
+
export function makeResult(plan: Plan, data: Uint8ClampedArray, backend?: 'webgl' | 'cpu', ms?: number): PixelResult;
|
|
138
|
+
|
|
139
|
+
export interface BuiltinPalette { id: string; name: string; author: string; colors: string[] }
|
|
140
|
+
export const PALETTES: BuiltinPalette[];
|
|
141
|
+
export function getPalette(idOrName: string): BuiltinPalette | null;
|
|
142
|
+
export function parsePalette(text: string, filename?: string): { name: string; colors: string[] };
|
|
143
|
+
export function toGPL(name: string, colors: string[]): string;
|
|
144
|
+
export function toHexFile(colors: string[]): string;
|
|
145
|
+
export function toPaletteJSON(name: string, colors: string[]): string;
|
|
146
|
+
export function extractPalette(image: RGBAImage, count?: number, opts?: { maxSamples?: number; alphaThreshold?: number }): string[];
|
|
147
|
+
export function fetchLospec(slugOrUrl: string, opts?: { fetch?: typeof fetch }): Promise<{ name: string; author: string; colors: string[]; slug: string }>;
|
|
148
|
+
export function lospecSlug(input: string): string;
|
|
149
|
+
|
|
150
|
+
export interface ThresholdMap { w: number; h: number; levels: number; values: Uint8Array }
|
|
151
|
+
export function thresholdMap(method: DitherMethod, custom?: number[][] | null): ThresholdMap;
|
|
152
|
+
export function parseMatrix(text: string): number[][];
|
|
153
|
+
export function bayer(n: number): number[][];
|
|
154
|
+
export const KERNELS: Record<string, [number, number, number][]>;
|
|
155
|
+
|
|
156
|
+
export interface Preset { id: string; name: string; description: string; settings: SettingsInput }
|
|
157
|
+
export const PRESETS: Preset[];
|
|
158
|
+
export function getPreset(id: string): Preset | null;
|
|
159
|
+
|
|
160
|
+
export function parseColor(c: string | number[]): [number, number, number];
|
|
161
|
+
export function toHex(rgb: number[]): string;
|
|
162
|
+
export function oklab(r: number, g: number, b: number): [number, number, number];
|
|
163
|
+
|
|
164
|
+
export interface Frame { width: number; height: number; canvas: HTMLCanvasElement | null; data: ArrayLike<number> }
|
|
165
|
+
export function toFrame(source: Source, opts?: { maxSize?: number; canvas?: HTMLCanvasElement }): Promise<Frame>;
|
|
166
|
+
export function loadImage(src: string | Blob): Promise<HTMLImageElement | ImageBitmap>;
|
|
167
|
+
|
|
168
|
+
export function upscale(image: RGBAImage, k?: number, opts?: { grid?: boolean; gridColor?: string; gridAlpha?: number }): { width: number; height: number; data: Uint8ClampedArray };
|
|
169
|
+
export function resizeNearest(image: RGBAImage, width: number, height: number): { width: number; height: number; data: Uint8ClampedArray };
|
|
170
|
+
export function uniqueColors(image: RGBAImage, limit?: number): string[];
|
|
171
|
+
export function detectGrid(image: RGBAImage, tolerance?: number): number;
|
|
172
|
+
export function hasTransparency(image: RGBAImage): boolean;
|
|
173
|
+
export function toCanvas(image: RGBAImage, scale?: number, opts?: { grid?: boolean; gridColor?: string; canvas?: HTMLCanvasElement }): HTMLCanvasElement;
|
|
174
|
+
export function downloadBlob(data: Blob | Uint8Array | string, filename: string, type?: string): void;
|
|
175
|
+
export function encodePNG(image: RGBAImage, opts?: PNGOptions): Promise<Uint8Array>;
|
|
176
|
+
export function encodeGIF(frames: (RGBAImage & { delay?: number })[], opts?: { loop?: number; scale?: number; delay?: number }): Uint8Array;
|
|
177
|
+
export function createZip(entries: { name: string; data: Uint8Array | string; date?: Date }[]): Uint8Array;
|
|
178
|
+
export function packSpriteSheet(frames: (RGBAImage & { name?: string; delay?: number })[], opts?: { columns?: number; padding?: number; name?: string }): { image: { width: number; height: number; data: Uint8ClampedArray }; atlas: any };
|
|
179
|
+
export function buildTileset(image: RGBAImage, opts?: { tileWidth?: number; tileHeight?: number; columns?: number; flips?: boolean }): {
|
|
180
|
+
image: { width: number; height: number; data: Uint8ClampedArray };
|
|
181
|
+
map: { width: number; height: number; tileWidth: number; tileHeight: number; tiles: number[]; flips?: number[] };
|
|
182
|
+
count: number;
|
|
183
|
+
};
|
|
184
|
+
|
|
185
|
+
export function videoReady(video: HTMLVideoElement, opts?: { timeout?: number }): Promise<HTMLVideoElement>;
|
|
186
|
+
/** A readable Error for a <video>'s MediaError; `code` is the MediaError code. */
|
|
187
|
+
export function mediaError(video: HTMLVideoElement): Error & { code: number; detail?: string };
|
|
188
|
+
/** Best-effort codec name read from an MP4/MOV/WebM file's bytes ('' when unknown). */
|
|
189
|
+
export function sniffVideoCodec(file: Blob): Promise<string>;
|
|
190
|
+
export function seekTo(video: HTMLVideoElement, time: number): Promise<void>;
|
|
191
|
+
export function estimateFps(video: HTMLVideoElement, fallback?: number): Promise<number>;
|
|
192
|
+
export function frameTimes(opts: { duration: number; fps: number; start?: number; end?: number; maxFrames?: number }): number[];
|
|
193
|
+
export function forEachFrame(video: HTMLVideoElement, opts: {
|
|
194
|
+
fps: number; start?: number; end?: number; maxFrames?: number; signal?: AbortSignal;
|
|
195
|
+
onFrame: (info: { index: number; time: number; total: number }) => unknown;
|
|
196
|
+
}): Promise<number>;
|
package/types/video.d.ts
CHANGED
|
@@ -1,43 +1,43 @@
|
|
|
1
|
-
// image-to-pixel/video
|
|
2
|
-
import type { RGBAImage } from './index';
|
|
3
|
-
export { forEachFrame, estimateFps, seekTo, frameTimes, videoReady } from './index';
|
|
4
|
-
|
|
5
|
-
export interface VideoEncoderOptions {
|
|
6
|
-
format: 'mp4' | 'webm';
|
|
7
|
-
fps: number;
|
|
8
|
-
/** Size of the frames you will add. */
|
|
9
|
-
width: number;
|
|
10
|
-
height: number;
|
|
11
|
-
/** Whole-number upscale applied to every frame. */
|
|
12
|
-
scale?: number;
|
|
13
|
-
bitrate?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface PixelVideoEncoder {
|
|
16
|
-
readonly width: number;
|
|
17
|
-
readonly height: number;
|
|
18
|
-
readonly codec: string;
|
|
19
|
-
add(frame: RGBAImage): Promise<void>;
|
|
20
|
-
finish(): Promise<Blob>;
|
|
21
|
-
}
|
|
22
|
-
export function createVideoEncoder(opts: VideoEncoderOptions): Promise<PixelVideoEncoder>;
|
|
23
|
-
export function encodeVideo(frames: RGBAImage[], opts: Omit<VideoEncoderOptions, 'width' | 'height'>): Promise<Blob>;
|
|
24
|
-
export function videoSupport(width?: number, height?: number): Promise<{ mp4: boolean; webm: boolean; webcodecs: boolean }>;
|
|
25
|
-
|
|
26
|
-
/** Minimal MP4 muxer (one H.264 track, fast start). Feed it VideoEncoder output, or AVCC samples. */
|
|
27
|
-
export interface Mp4Muxer {
|
|
28
|
-
addChunk(chunk: EncodedVideoChunk, meta?: EncodedVideoChunkMetadata): void;
|
|
29
|
-
/** timestamp/duration in microseconds; data is length-prefixed NAL units. */
|
|
30
|
-
addSample(data: Uint8Array, info: { key: boolean; timestamp: number; duration?: number }): void;
|
|
31
|
-
/** AVCDecoderConfigurationRecord ('avcC'). */
|
|
32
|
-
setDescription(avcC: Uint8Array): void;
|
|
33
|
-
finish(): Uint8Array;
|
|
34
|
-
}
|
|
35
|
-
export function createMp4Muxer(opts: { width: number; height: number; timescale?: number }): Mp4Muxer;
|
|
36
|
-
/** Minimal WebM muxer (one VP8/VP9/AV1 track, with SeekHead and Cues). */
|
|
37
|
-
export interface WebmMuxer {
|
|
38
|
-
addChunk(chunk: EncodedVideoChunk, meta?: EncodedVideoChunkMetadata): void;
|
|
39
|
-
/** timestamp in microseconds */
|
|
40
|
-
addFrame(data: Uint8Array, info: { key: boolean; timestamp: number }): void;
|
|
41
|
-
finish(): Uint8Array;
|
|
42
|
-
}
|
|
43
|
-
export function createWebmMuxer(opts: { width: number; height: number; codec?: 'vp8' | 'vp9' | 'av1'; fps?: number }): WebmMuxer;
|
|
1
|
+
// image-to-pixel/video
|
|
2
|
+
import type { RGBAImage } from './index';
|
|
3
|
+
export { forEachFrame, estimateFps, seekTo, frameTimes, videoReady } from './index';
|
|
4
|
+
|
|
5
|
+
export interface VideoEncoderOptions {
|
|
6
|
+
format: 'mp4' | 'webm';
|
|
7
|
+
fps: number;
|
|
8
|
+
/** Size of the frames you will add. */
|
|
9
|
+
width: number;
|
|
10
|
+
height: number;
|
|
11
|
+
/** Whole-number upscale applied to every frame. */
|
|
12
|
+
scale?: number;
|
|
13
|
+
bitrate?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface PixelVideoEncoder {
|
|
16
|
+
readonly width: number;
|
|
17
|
+
readonly height: number;
|
|
18
|
+
readonly codec: string;
|
|
19
|
+
add(frame: RGBAImage): Promise<void>;
|
|
20
|
+
finish(): Promise<Blob>;
|
|
21
|
+
}
|
|
22
|
+
export function createVideoEncoder(opts: VideoEncoderOptions): Promise<PixelVideoEncoder>;
|
|
23
|
+
export function encodeVideo(frames: RGBAImage[], opts: Omit<VideoEncoderOptions, 'width' | 'height'>): Promise<Blob>;
|
|
24
|
+
export function videoSupport(width?: number, height?: number): Promise<{ mp4: boolean; webm: boolean; webcodecs: boolean }>;
|
|
25
|
+
|
|
26
|
+
/** Minimal MP4 muxer (one H.264 track, fast start). Feed it VideoEncoder output, or AVCC samples. */
|
|
27
|
+
export interface Mp4Muxer {
|
|
28
|
+
addChunk(chunk: EncodedVideoChunk, meta?: EncodedVideoChunkMetadata): void;
|
|
29
|
+
/** timestamp/duration in microseconds; data is length-prefixed NAL units. */
|
|
30
|
+
addSample(data: Uint8Array, info: { key: boolean; timestamp: number; duration?: number }): void;
|
|
31
|
+
/** AVCDecoderConfigurationRecord ('avcC'). */
|
|
32
|
+
setDescription(avcC: Uint8Array): void;
|
|
33
|
+
finish(): Uint8Array;
|
|
34
|
+
}
|
|
35
|
+
export function createMp4Muxer(opts: { width: number; height: number; timescale?: number }): Mp4Muxer;
|
|
36
|
+
/** Minimal WebM muxer (one VP8/VP9/AV1 track, with SeekHead and Cues). */
|
|
37
|
+
export interface WebmMuxer {
|
|
38
|
+
addChunk(chunk: EncodedVideoChunk, meta?: EncodedVideoChunkMetadata): void;
|
|
39
|
+
/** timestamp in microseconds */
|
|
40
|
+
addFrame(data: Uint8Array, info: { key: boolean; timestamp: number }): void;
|
|
41
|
+
finish(): Uint8Array;
|
|
42
|
+
}
|
|
43
|
+
export function createWebmMuxer(opts: { width: number; height: number; codec?: 'vp8' | 'vp9' | 'av1'; fps?: number }): WebmMuxer;
|