smart-downscaler 0.6.2 → 0.6.3
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/README.md +148 -31
- package/package.json +2 -8
- package/smart_downscaler.d.ts +47 -0
- package/smart_downscaler.js +1179 -6
- package/smart_downscaler_bg.wasm +0 -0
- package/smart_downscaler_bg.js +0 -986
package/README.md
CHANGED
|
@@ -35,7 +35,10 @@ A high-performance Rust library for intelligent image downscaling with pixel art
|
|
|
35
35
|
| **Edge-Aware Processing** | Sobel/Scharr detection preserves boundaries |
|
|
36
36
|
| **Spatial Coherence** | Neighbor and region voting for smooth results |
|
|
37
37
|
| **K-Centroid Tile Logic** | Advanced dominant color extraction per tile |
|
|
38
|
-
| **Rare-Color Preservation** | Saliency weighting + slot reservation keeps small
|
|
38
|
+
| **Rare-Color Preservation** | Saliency weighting + slot reservation keeps small important colors (lips, eyes) |
|
|
39
|
+
| **Chroma Recovery** | Restores saturation lost to color merging, by perceptual difference |
|
|
40
|
+
| **Skin-Tone Isolation** | Keeps skin and non-skin colors in separate palette domains |
|
|
41
|
+
| **Reusable Preprocessing** | Prepare an image once, downscale to many sizes cheaply |
|
|
39
42
|
| **Performance Preprocessing** | Resolution capping and color pre-quantization |
|
|
40
43
|
| **WebAssembly Support** | Full browser compatibility with near-native speed |
|
|
41
44
|
|
|
@@ -171,10 +174,12 @@ println!("Palette: {} colors", result.palette.len());
|
|
|
171
174
|
| **Tile Processing** |||||
|
|
172
175
|
| `k_centroid` | `usize` | `1` | `1`, `2`, `3`, `4` | Tile color extraction mode |
|
|
173
176
|
| `k_centroid_iterations` | `usize` | `0` | `0-10` | K-Means iterations for tile color |
|
|
174
|
-
| **Rare-Color
|
|
175
|
-
| `color_rarity` | `f32` | `0.0` | `0.0-1.0` | Damps frequency vote so
|
|
176
|
-
| `detail_boost` | `f32` | `0.0` | `0.0-2.0` | Boosts colors in detail-rich regions via
|
|
177
|
-
| `reserve_colors` | `usize` | `0` | `0 - palette_size` | Reserve N
|
|
177
|
+
| **Rare-Color & Saturation** |||||
|
|
178
|
+
| `color_rarity` | `f32` | `0.0` | `0.0-1.0` | Damps frequency vote so flat areas stop dominating (`0`=area, `1`=`count^0.5`) |
|
|
179
|
+
| `detail_boost` | `f32` | `0.0` | `0.0-2.0` | Boosts colors in detail-rich regions via local-contrast saliency (`0`=off) |
|
|
180
|
+
| `reserve_colors` | `usize` | `0` | `0 - palette_size` | Reserve N slots for distinct, important, under-represented source colors (`0`=off) |
|
|
181
|
+
| `chroma_recovery` | `f32` | `0.0` | `0.0-1.0+` | Restore chroma lost to merging toward source mean chroma, constant hue, gamut-clamped (`0`=off) |
|
|
182
|
+
| `skin_protection` | `f32` | `0.0` | `0.0-1.0` | Isolate skin vs non-skin into separate palette domains + quantization penalty (`0`=off) |
|
|
178
183
|
|
|
179
184
|
---
|
|
180
185
|
|
|
@@ -231,7 +236,7 @@ Controls how each source tile is reduced to a single representative color:
|
|
|
231
236
|
| **Foremost** | `3` | K-Means (k=3), finer dominant detection | Complex textures, detailed sprites |
|
|
232
237
|
| **Salient** | `4` | K-Means (k=2), keeps a distinctly-more-chromatic minority | Thin colorful features (lips, eyes, makeup) |
|
|
233
238
|
|
|
234
|
-
> **Note:** Mode `2` (Dominant) snaps a mixed tile to its *larger* cluster,
|
|
239
|
+
> **Note:** Mode `2` (Dominant) snaps a mixed tile to its *larger* cluster, discarding thin minority colors — a tile that is 60% skin / 40% lip becomes pure skin. For faces and artwork with small colorful features, prefer mode `4`, which keeps the colorful minority when it is non-trivial (≥22% of the tile) and clearly more chromatic than the majority.
|
|
235
240
|
|
|
236
241
|
```javascript
|
|
237
242
|
// Mode 1: Average (default) - smooth results
|
|
@@ -323,6 +328,36 @@ const result = downscale_with_palette(
|
|
|
323
328
|
|
|
324
329
|
---
|
|
325
330
|
|
|
331
|
+
### Prepare / Reuse Functions
|
|
332
|
+
|
|
333
|
+
#### `prepare(data, width, height, config?)` / `prepare_rgba(data, width, height, config?)`
|
|
334
|
+
|
|
335
|
+
Run target-independent work (resolution cap, color pre-quantization, segmentation)
|
|
336
|
+
once and return a reusable handle. `prepare` takes `Uint8Array`; `prepare_rgba` takes
|
|
337
|
+
`Uint8ClampedArray` (from canvas `getImageData`).
|
|
338
|
+
|
|
339
|
+
```javascript
|
|
340
|
+
const prepared = prepare_rgba(imageData.data, imageData.width, imageData.height, config);
|
|
341
|
+
// prepared.width / prepared.height — dimensions after any resolution cap
|
|
342
|
+
prepared.free(); // release WASM memory when finished
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
#### `downscale_prepared(prepared, targetWidth, targetHeight, config?)`
|
|
346
|
+
|
|
347
|
+
Downscale a prepared image. The optional `config` overrides per-target knobs
|
|
348
|
+
(`palette_size`, `k_centroid`, `chroma_recovery`, `skin_protection`, …); preprocess
|
|
349
|
+
and segmentation settings always come from prepare time.
|
|
350
|
+
|
|
351
|
+
```javascript
|
|
352
|
+
const result = downscale_prepared(prepared, 128, 128, sizeConfig);
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### `downscale_prepared_with_palette(prepared, targetWidth, targetHeight, palette, config?)`
|
|
356
|
+
|
|
357
|
+
As above, with a caller-supplied `Uint8Array` RGB palette.
|
|
358
|
+
|
|
359
|
+
---
|
|
360
|
+
|
|
326
361
|
### Palette Functions
|
|
327
362
|
|
|
328
363
|
#### `extract_palette_from_image(data, width, height, numColors, iterations, strategy?)`
|
|
@@ -508,58 +543,140 @@ const exact = WasmDownscaleConfig.exact_colors();
|
|
|
508
543
|
|
|
509
544
|
### Preset Comparison
|
|
510
545
|
|
|
511
|
-
| Preset | Palette | K-Means | Segmentation | K-Centroid | Rare
|
|
512
|
-
|
|
546
|
+
| Preset | Palette | K-Means | Segmentation | K-Centroid | Rare/Sat/Skin¹ | Speed |
|
|
547
|
+
|--------|---------|---------|--------------|------------|----------------|-------|
|
|
513
548
|
| `fast()` | 16 | 3 | none | 1 (avg) | off | ⚡⚡⚡ |
|
|
514
549
|
| `default` | 16 | 5 | hierarchy_fast | 1 (avg) | off | ⚡⚡ |
|
|
515
|
-
| `vibrant()` | 24 | 8 | hierarchy_fast | 2 (dom) |
|
|
516
|
-
| `quality()` | 32 | 10 | hierarchy | 2 (dom) |
|
|
550
|
+
| `vibrant()` | 24 | 8 | hierarchy_fast | 2 (dom) | reserve+rarity+chroma(0.7) | ⚡ |
|
|
551
|
+
| `quality()` | 32 | 10 | hierarchy | 2 (dom) | reserve+rarity+chroma(0.6)+skin(0.5) | 🐢 |
|
|
517
552
|
| `exact_colors()` | 16 | 0 | hierarchy_fast | 1 (avg) | off | ⚡⚡ |
|
|
518
553
|
|
|
519
|
-
¹
|
|
554
|
+
¹ For the strongest thin-feature retention on faces, additionally set `k_centroid = 4`.
|
|
520
555
|
|
|
521
556
|
---
|
|
522
557
|
|
|
523
558
|
## Advanced Usage
|
|
524
559
|
|
|
560
|
+
### Reusing Preprocessing Across Sizes (Performance)
|
|
561
|
+
|
|
562
|
+
Resolution capping, color pre-quantization, and region segmentation depend only on
|
|
563
|
+
the **source** image, not the target size. When you downscale the same source to
|
|
564
|
+
several sizes (e.g. multiple previews), repeating that work each time is wasted.
|
|
565
|
+
`prepare` runs it **once**; `downscale_prepared` then only does palette extraction
|
|
566
|
+
and tiling per size.
|
|
567
|
+
|
|
568
|
+
```javascript
|
|
569
|
+
import init, { prepare_rgba, downscale_prepared, WasmDownscaleConfig } from 'smart-downscaler';
|
|
570
|
+
await init();
|
|
571
|
+
|
|
572
|
+
const base = new WasmDownscaleConfig();
|
|
573
|
+
base.segmentation_method = 'hierarchy_fast';
|
|
574
|
+
base.max_resolution_mp = 2.048;
|
|
575
|
+
base.max_color_preprocess = 4096;
|
|
576
|
+
|
|
577
|
+
// Once per source image:
|
|
578
|
+
const prepared = prepare_rgba(imageData.data, imageData.width, imageData.height, base);
|
|
579
|
+
|
|
580
|
+
// Many times, cheaply — palette_size and target size may differ each call:
|
|
581
|
+
for (const { w, h, colors } of sizes) {
|
|
582
|
+
const cfg = new WasmDownscaleConfig();
|
|
583
|
+
cfg.palette_size = colors;
|
|
584
|
+
cfg.k_centroid = 4;
|
|
585
|
+
cfg.reserve_colors = Math.round(colors / 8);
|
|
586
|
+
cfg.chroma_recovery = 0.6;
|
|
587
|
+
cfg.skin_protection = 0.5;
|
|
588
|
+
const result = downscale_prepared(prepared, w, h, cfg);
|
|
589
|
+
// ... use result ...
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
prepared.free(); // release WASM memory when done (also freed on GC)
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
**Contract:** the prepared image fixes `max_resolution_mp`, `max_color_preprocess`,
|
|
596
|
+
and `segmentation_*` at prepare time. `downscale_prepared` overlays per-target knobs
|
|
597
|
+
(`palette_size`, `k_centroid`, `chroma_recovery`, `skin_protection`, …) but never
|
|
598
|
+
re-runs preprocessing or segmentation. Change any of the prepare-time settings →
|
|
599
|
+
call `prepare` again. `prepare` / `prepare_rgba` and `downscale_prepared` /
|
|
600
|
+
`downscale_prepared_with_palette` mirror the one-shot functions.
|
|
601
|
+
|
|
602
|
+
In Rust:
|
|
603
|
+
|
|
604
|
+
```rust
|
|
605
|
+
use smart_downscaler::{prepare_image, smart_downscale_prepared, DownscaleConfig};
|
|
606
|
+
|
|
607
|
+
let prepared = prepare_image(&pixels, w, h, &config); // once
|
|
608
|
+
let small = smart_downscale_prepared(&prepared, 128, 128, &config_s); // reuse
|
|
609
|
+
let large = smart_downscale_prepared(&prepared, 256, 256, &config_l); // reuse
|
|
610
|
+
```
|
|
611
|
+
|
|
525
612
|
### Preserving Rare / Important Colors
|
|
526
613
|
|
|
527
|
-
Palette extraction is **area-weighted**: a color
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
skin) at low palette sizes (16–64). Three knobs counteract this:
|
|
614
|
+
Palette extraction is **area-weighted**: a color covering a large region gets many
|
|
615
|
+
"votes", so small but important colors — lips, eyes, a logo, a highlight — easily
|
|
616
|
+
merge into dominant tones at low palette sizes (16–64). Counteract this with:
|
|
531
617
|
|
|
532
618
|
| Knob | What it does | When to raise it |
|
|
533
619
|
|------|--------------|------------------|
|
|
534
|
-
| `reserve_colors` | **Hard guarantee.** Reserves N slots
|
|
535
|
-
| `detail_boost` | Weights extraction toward
|
|
620
|
+
| `reserve_colors` | **Hard guarantee.** Reserves N slots filled with exact source colors that are far from the rest of the palette *and* important. Most reliable fix. | Always, for portraits. ~`palette_size / 8`. |
|
|
621
|
+
| `detail_boost` | Weights extraction toward **detail-rich regions** via a local-contrast saliency map (measured at the downscale radius, so it targets features thin enough to be averaged away). | When the important color is in a high-detail area. `0.8–1.0`. |
|
|
536
622
|
| `color_rarity` | Damps the frequency vote (`count^p`, `p = 1 − 0.5·rarity`) so large flat regions stop monopolizing the palette. | Mild assist alongside the above. `0.3–0.4`. |
|
|
537
623
|
|
|
538
|
-
Pair these with `k_centroid = 4` (Salient)
|
|
539
|
-
|
|
540
|
-
|
|
624
|
+
Pair these with `k_centroid = 4` (Salient) so the *tile* stage doesn't discard the
|
|
625
|
+
same minority colors a correct palette preserved.
|
|
626
|
+
|
|
627
|
+
### Restoring Saturation (Chroma Recovery)
|
|
628
|
+
|
|
629
|
+
Averaging colors in Oklab during median-cut/k-means pulls the result *inward* — the
|
|
630
|
+
mean of two hues is less colorful than either. `chroma_recovery` undoes this **by
|
|
631
|
+
perceptual difference**: each palette color is pushed back toward the count-weighted
|
|
632
|
+
**mean chroma of the source colors it represents**, at constant hue and lightness,
|
|
633
|
+
then clamped to the sRGB gamut. It only ever *increases* saturation, never reduces it.
|
|
634
|
+
|
|
635
|
+
```javascript
|
|
636
|
+
config.chroma_recovery = 0.6; // 0 = off, ~0.6 natural, 1.0 = full restoration, >1 = punchy
|
|
637
|
+
```
|
|
638
|
+
|
|
639
|
+
This is a global de-wash that fixes the "muddy" look of low-palette output; it is
|
|
640
|
+
independent of (and composes with) the rare-color knobs above.
|
|
641
|
+
|
|
642
|
+
### Isolating Skin Tones
|
|
643
|
+
|
|
644
|
+
Skin clusters tightly in the YCbCr chroma plane (`80 ≤ Cb ≤ 120`, `133 ≤ Cr ≤ 173`).
|
|
645
|
+
With `skin_protection > 0`, skin and non-skin colors are extracted in **separate
|
|
646
|
+
domains** — a single palette bucket never mixes the two, so skin never picks up a
|
|
647
|
+
muddy blend with hair/background and vice-versa. Palette slots are split between the
|
|
648
|
+
domains by population (each guaranteed at least one). The same value also acts as a
|
|
649
|
+
**quantization penalty**: a skin tile prefers skin palette colors, a non-skin tile
|
|
650
|
+
prefers non-skin.
|
|
651
|
+
|
|
652
|
+
```javascript
|
|
653
|
+
config.skin_protection = 0.5; // 0 = off, ~0.5 typical
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
> Lips are reddish and usually pass the skin test, so they live in the *skin* domain
|
|
657
|
+
> — `skin_protection` won't separate lips from skin. Use `reserve_colors` /
|
|
658
|
+
> `k_centroid = 4` for that; they operate *within* the skin domain, so the two
|
|
659
|
+
> features compose: skin gets its own budget, and a distinct lip is preserved inside it.
|
|
660
|
+
|
|
661
|
+
### Recommended Config for Faces / Portraits
|
|
541
662
|
|
|
542
663
|
```javascript
|
|
543
|
-
// Recommended for faces / portraits at 16–64 colors
|
|
544
664
|
const config = new WasmDownscaleConfig();
|
|
545
665
|
config.palette_size = 32;
|
|
546
|
-
config.palette_strategy = 'oklab'; // honors color_rarity / detail_boost
|
|
547
|
-
config.k_centroid = 4; // salient tile color
|
|
666
|
+
config.palette_strategy = 'oklab'; // honors color_rarity / detail_boost
|
|
667
|
+
config.k_centroid = 4; // salient tile color
|
|
548
668
|
config.k_centroid_iterations = 2;
|
|
549
669
|
config.reserve_colors = 4; // ~palette_size / 8 — the guarantee
|
|
550
670
|
config.detail_boost = 0.9; // saliency targeting
|
|
551
671
|
config.color_rarity = 0.35; // frequency damping
|
|
672
|
+
config.chroma_recovery = 0.6; // restore saturation lost to merging
|
|
673
|
+
config.skin_protection = 0.5; // separate skin / non-skin
|
|
552
674
|
config.neighbor_weight = 0.18; // lower = less erosion of thin features
|
|
553
675
|
```
|
|
554
676
|
|
|
555
|
-
> **
|
|
556
|
-
>
|
|
557
|
-
>
|
|
558
|
-
>
|
|
559
|
-
> **Strategy note:** `bitmask` ignores frequency weights during its initial
|
|
560
|
-
> split, so with `bitmask` only `reserve_colors` is active. Use `oklab` (or
|
|
561
|
-
> `saturation`) if you also want `color_rarity` / `detail_boost` to shape the
|
|
562
|
-
> main palette.
|
|
677
|
+
> **Strategy note:** `bitmask` ignores frequency weights during its initial split, so
|
|
678
|
+
> with `bitmask` only `reserve_colors` is active. Use `oklab` (or `saturation`) if you
|
|
679
|
+
> also want `color_rarity` / `detail_boost` to shape the main palette.
|
|
563
680
|
|
|
564
681
|
### Custom Palette Workflow
|
|
565
682
|
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "smart-downscaler",
|
|
3
|
-
"type": "module",
|
|
4
3
|
"collaborators": [
|
|
5
4
|
"Pixagram"
|
|
6
5
|
],
|
|
7
6
|
"description": "Intelligent pixel art downscaler with region-aware color quantization",
|
|
8
|
-
"version": "0.6.
|
|
7
|
+
"version": "0.6.3",
|
|
9
8
|
"license": "MIT",
|
|
10
9
|
"repository": {
|
|
11
10
|
"type": "git",
|
|
@@ -14,15 +13,10 @@
|
|
|
14
13
|
"files": [
|
|
15
14
|
"smart_downscaler_bg.wasm",
|
|
16
15
|
"smart_downscaler.js",
|
|
17
|
-
"smart_downscaler_bg.js",
|
|
18
16
|
"smart_downscaler.d.ts"
|
|
19
17
|
],
|
|
20
18
|
"main": "smart_downscaler.js",
|
|
21
19
|
"types": "smart_downscaler.d.ts",
|
|
22
|
-
"sideEffects": [
|
|
23
|
-
"./smart_downscaler.js",
|
|
24
|
-
"./snippets/*"
|
|
25
|
-
],
|
|
26
20
|
"keywords": [
|
|
27
21
|
"pixel-art",
|
|
28
22
|
"image-processing",
|
|
@@ -30,4 +24,4 @@
|
|
|
30
24
|
"quantization",
|
|
31
25
|
"wasm"
|
|
32
26
|
]
|
|
33
|
-
}
|
|
27
|
+
}
|
package/smart_downscaler.d.ts
CHANGED
|
@@ -33,6 +33,10 @@ export class WasmDownscaleConfig {
|
|
|
33
33
|
constructor();
|
|
34
34
|
static quality(): WasmDownscaleConfig;
|
|
35
35
|
static vibrant(): WasmDownscaleConfig;
|
|
36
|
+
/**
|
|
37
|
+
* Restore chroma lost to merging (constant hue, gamut-clamped). 0.0 = off, ~0.6 natural.
|
|
38
|
+
*/
|
|
39
|
+
chroma_recovery: number;
|
|
36
40
|
/**
|
|
37
41
|
* Rare-color preservation: 0.0 = pure area weighting, 1.0 = strong (count^0.5).
|
|
38
42
|
*/
|
|
@@ -57,6 +61,10 @@ export class WasmDownscaleConfig {
|
|
|
57
61
|
* Reserve N palette slots for distinct, important, under-represented colors. 0 = off.
|
|
58
62
|
*/
|
|
59
63
|
reserve_colors: number;
|
|
64
|
+
/**
|
|
65
|
+
* Isolate skin tones from non-skin (separate domains + mismatch penalty). 0.0 = off, ~0.5.
|
|
66
|
+
*/
|
|
67
|
+
skin_protection: number;
|
|
60
68
|
slic_compactness: number;
|
|
61
69
|
slic_superpixels: number;
|
|
62
70
|
two_pass_refinement: boolean;
|
|
@@ -77,6 +85,22 @@ export class WasmDownscaleResult {
|
|
|
77
85
|
readonly width: number;
|
|
78
86
|
}
|
|
79
87
|
|
|
88
|
+
/**
|
|
89
|
+
* Opaque handle holding the prepared (preprocessed + segmented) source image.
|
|
90
|
+
* Build with [`prepare`] / [`prepare_rgba`], reuse with [`downscale_prepared`].
|
|
91
|
+
*
|
|
92
|
+
* The segmentation is fixed at prepare time from the config you pass. Palette
|
|
93
|
+
* size and target dimensions may differ on every [`downscale_prepared`] call.
|
|
94
|
+
* If you change resolution / color-preprocess / segmentation settings, prepare again.
|
|
95
|
+
*/
|
|
96
|
+
export class WasmPreparedImage {
|
|
97
|
+
private constructor();
|
|
98
|
+
free(): void;
|
|
99
|
+
[Symbol.dispose](): void;
|
|
100
|
+
readonly height: number;
|
|
101
|
+
readonly width: number;
|
|
102
|
+
}
|
|
103
|
+
|
|
80
104
|
/**
|
|
81
105
|
* Analyze colors — FIX: uses HashMap<u32, usize> for O(1) lookup (was O(n) linear scan)
|
|
82
106
|
*/
|
|
@@ -86,6 +110,19 @@ export function color_distance(r1: number, g1: number, b1: number, r2: number, g
|
|
|
86
110
|
|
|
87
111
|
export function downscale(image_data: Uint8Array, width: number, height: number, target_width: number, target_height: number, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
88
112
|
|
|
113
|
+
/**
|
|
114
|
+
* Downscale a prepared image. Pass an optional `config` to override per-target
|
|
115
|
+
* knobs (palette_size, k_centroid, chroma_recovery, skin_protection, …). The
|
|
116
|
+
* preprocess/segmentation settings always come from prepare time. When `config`
|
|
117
|
+
* is omitted, the prepare-time config is reused as-is.
|
|
118
|
+
*/
|
|
119
|
+
export function downscale_prepared(prepared: WasmPreparedImage, target_width: number, target_height: number, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Downscale a prepared image with a caller-supplied palette.
|
|
123
|
+
*/
|
|
124
|
+
export function downscale_prepared_with_palette(prepared: WasmPreparedImage, target_width: number, target_height: number, palette_data: Uint8Array, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
125
|
+
|
|
89
126
|
export function downscale_rgba(image_data: Uint8ClampedArray, width: number, height: number, target_width: number, target_height: number, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
90
127
|
|
|
91
128
|
export function downscale_simple(image_data: Uint8Array, width: number, height: number, target_width: number, target_height: number, num_colors: number): WasmDownscaleResult;
|
|
@@ -106,6 +143,16 @@ export function log(message: string): void;
|
|
|
106
143
|
|
|
107
144
|
export function oklab_to_rgb(l: number, a: number, b: number): Uint8Array;
|
|
108
145
|
|
|
146
|
+
/**
|
|
147
|
+
* Prepare from a `Uint8Array` (RGBA).
|
|
148
|
+
*/
|
|
149
|
+
export function prepare(image_data: Uint8Array, width: number, height: number, config?: WasmDownscaleConfig | null): WasmPreparedImage;
|
|
150
|
+
|
|
151
|
+
/**
|
|
152
|
+
* Prepare from a `Uint8ClampedArray` (canvas `getImageData`).
|
|
153
|
+
*/
|
|
154
|
+
export function prepare_rgba(image_data: Uint8ClampedArray, width: number, height: number, config?: WasmDownscaleConfig | null): WasmPreparedImage;
|
|
155
|
+
|
|
109
156
|
/**
|
|
110
157
|
* Quantize to palette — FIX: compute Oklab once per pixel (was twice)
|
|
111
158
|
*/
|