smart-downscaler 0.1.0
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 +330 -0
- package/package.json +33 -0
- package/smart_downscaler.d.ts +161 -0
- package/smart_downscaler.js +5 -0
- package/smart_downscaler_bg.js +659 -0
- package/smart_downscaler_bg.wasm +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
# Smart Pixel Art Downscaler
|
|
2
|
+
|
|
3
|
+
A sophisticated Rust library for intelligent image downscaling with focus on pixel art quality. Combines global palette extraction, region-aware segmentation, and iterative refinement for optimal results.
|
|
4
|
+
|
|
5
|
+
**Available as both a native Rust library and a WebAssembly module for browser/Node.js usage.**
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Global Palette Extraction**: Median Cut + K-Means++ refinement in Lab color space for perceptually optimal palettes
|
|
10
|
+
- **Multiple Segmentation Methods**:
|
|
11
|
+
- SLIC superpixels for fast, balanced regions
|
|
12
|
+
- VTracer-style hierarchical clustering for content-aware boundaries
|
|
13
|
+
- Union-find based fast hierarchical clustering
|
|
14
|
+
- **Edge-Aware Processing**: Sobel/Scharr edge detection to preserve boundaries
|
|
15
|
+
- **Neighbor-Coherent Assignment**: Spatial coherence through neighbor and region voting
|
|
16
|
+
- **Two-Pass Refinement**: Iterative optimization for smooth results
|
|
17
|
+
- **Graph-Cut Optimization**: Optional MRF energy minimization for advanced refinement
|
|
18
|
+
- **WebAssembly Support**: Run in browsers with full performance
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
### Native (Rust)
|
|
23
|
+
|
|
24
|
+
Add to your `Cargo.toml`:
|
|
25
|
+
|
|
26
|
+
```toml
|
|
27
|
+
[dependencies]
|
|
28
|
+
smart-downscaler = "0.1"
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### WebAssembly (npm)
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install smart-downscaler
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Or use directly in browser:
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<script type="module">
|
|
41
|
+
import init, { downscale } from './pkg/web/smart_downscaler.js';
|
|
42
|
+
await init();
|
|
43
|
+
</script>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Quick Start
|
|
47
|
+
|
|
48
|
+
### Native Rust
|
|
49
|
+
|
|
50
|
+
```rust
|
|
51
|
+
use smart_downscaler::prelude::*;
|
|
52
|
+
|
|
53
|
+
fn main() {
|
|
54
|
+
let img = image::open("input.png").unwrap().to_rgb8();
|
|
55
|
+
let result = downscale(&img, 64, 64, 16);
|
|
56
|
+
result.save("output.png").unwrap();
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### WebAssembly (Browser)
|
|
61
|
+
|
|
62
|
+
```javascript
|
|
63
|
+
import init, { WasmDownscaleConfig, downscale_rgba } from 'smart-downscaler';
|
|
64
|
+
|
|
65
|
+
// Initialize WASM
|
|
66
|
+
await init();
|
|
67
|
+
|
|
68
|
+
// Get image data from canvas
|
|
69
|
+
const ctx = canvas.getContext('2d');
|
|
70
|
+
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
71
|
+
|
|
72
|
+
// Configure
|
|
73
|
+
const config = new WasmDownscaleConfig();
|
|
74
|
+
config.palette_size = 16;
|
|
75
|
+
config.neighbor_weight = 0.3;
|
|
76
|
+
config.segmentation_method = 'hierarchy_fast';
|
|
77
|
+
|
|
78
|
+
// Downscale
|
|
79
|
+
const result = downscale_rgba(
|
|
80
|
+
imageData.data,
|
|
81
|
+
canvas.width,
|
|
82
|
+
canvas.height,
|
|
83
|
+
64, 64, // target size
|
|
84
|
+
config
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
// Use result
|
|
88
|
+
const outputData = new ImageData(result.data, result.width, result.height);
|
|
89
|
+
outputCtx.putImageData(outputData, 0, 0);
|
|
90
|
+
|
|
91
|
+
// Access palette
|
|
92
|
+
console.log(`Used ${result.palette_size} colors`);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Using the JavaScript Wrapper
|
|
96
|
+
|
|
97
|
+
For an even simpler API, use the included JavaScript wrapper:
|
|
98
|
+
|
|
99
|
+
```javascript
|
|
100
|
+
import { init, downscale, extractPalette, getPresetPalette } from './smart-downscaler.js';
|
|
101
|
+
|
|
102
|
+
await init();
|
|
103
|
+
|
|
104
|
+
// Simple downscale
|
|
105
|
+
const result = downscale(canvas, 64, 64, {
|
|
106
|
+
paletteSize: 16,
|
|
107
|
+
segmentation: 'hierarchy_fast'
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
// With preset palette (Game Boy, NES, PICO-8, CGA)
|
|
111
|
+
const gbPalette = getPresetPalette('gameboy');
|
|
112
|
+
const gbResult = downscaleWithPalette(canvas, 64, 64, gbPalette);
|
|
113
|
+
|
|
114
|
+
// Extract palette only
|
|
115
|
+
const palette = extractPalette(canvas, 16);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Building WebAssembly
|
|
119
|
+
|
|
120
|
+
Requirements: [wasm-pack](https://rustwasm.github.io/wasm-pack/)
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
# Install wasm-pack
|
|
124
|
+
cargo install wasm-pack
|
|
125
|
+
|
|
126
|
+
# Build all targets
|
|
127
|
+
./build-wasm.sh
|
|
128
|
+
|
|
129
|
+
# Or manually:
|
|
130
|
+
wasm-pack build --target web --features wasm --no-default-features --out-dir pkg/web
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
## WASM API Reference
|
|
134
|
+
|
|
135
|
+
### Functions
|
|
136
|
+
|
|
137
|
+
| Function | Description |
|
|
138
|
+
|----------|-------------|
|
|
139
|
+
| `downscale(data, w, h, tw, th, config?)` | Downscale RGBA image data |
|
|
140
|
+
| `downscale_rgba(data, w, h, tw, th, config?)` | Same, for Uint8ClampedArray |
|
|
141
|
+
| `downscale_simple(data, w, h, tw, th, colors)` | Simple API with color count |
|
|
142
|
+
| `downscale_with_palette(data, w, h, tw, th, palette, config?)` | Use custom palette |
|
|
143
|
+
| `extract_palette_from_image(data, w, h, colors, iters)` | Extract palette only |
|
|
144
|
+
| `quantize_to_palette(data, w, h, palette)` | Quantize without resizing |
|
|
145
|
+
|
|
146
|
+
### WasmDownscaleConfig
|
|
147
|
+
|
|
148
|
+
```javascript
|
|
149
|
+
const config = new WasmDownscaleConfig();
|
|
150
|
+
config.palette_size = 16; // Output colors
|
|
151
|
+
config.kmeans_iterations = 5; // Palette refinement
|
|
152
|
+
config.neighbor_weight = 0.3; // Spatial coherence [0-1]
|
|
153
|
+
config.region_weight = 0.2; // Region coherence [0-1]
|
|
154
|
+
config.two_pass_refinement = true; // Enable refinement
|
|
155
|
+
config.refinement_iterations = 3; // Refinement passes
|
|
156
|
+
config.edge_weight = 0.5; // Edge detection weight
|
|
157
|
+
config.segmentation_method = 'hierarchy_fast'; // 'none'|'slic'|'hierarchy'|'hierarchy_fast'
|
|
158
|
+
|
|
159
|
+
// Presets
|
|
160
|
+
const fast = WasmDownscaleConfig.fast();
|
|
161
|
+
const quality = WasmDownscaleConfig.quality();
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### WasmDownscaleResult
|
|
165
|
+
|
|
166
|
+
```javascript
|
|
167
|
+
result.width // Output width
|
|
168
|
+
result.height // Output height
|
|
169
|
+
result.data // Uint8ClampedArray (RGBA for ImageData)
|
|
170
|
+
result.rgb_data() // Uint8Array (RGB only)
|
|
171
|
+
result.palette // Uint8Array (RGB, 3 bytes per color)
|
|
172
|
+
result.indices // Uint8Array (palette index per pixel)
|
|
173
|
+
result.palette_size // Number of colors
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
## Command Line Interface
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Basic usage
|
|
180
|
+
smart-downscaler input.png output.png -w 64 -h 64
|
|
181
|
+
|
|
182
|
+
# With custom palette size
|
|
183
|
+
smart-downscaler input.png output.png -w 128 -h 128 -p 32
|
|
184
|
+
|
|
185
|
+
# Using scale factor
|
|
186
|
+
smart-downscaler input.png output.png -s 0.125 -p 16
|
|
187
|
+
|
|
188
|
+
# With SLIC segmentation
|
|
189
|
+
smart-downscaler input.png output.png -w 64 -h 64 --segmentation slic
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
## Algorithm Details
|
|
193
|
+
|
|
194
|
+
### 1. Global Palette Extraction
|
|
195
|
+
|
|
196
|
+
The traditional per-tile k-means approach causes color drift across the image. We instead:
|
|
197
|
+
|
|
198
|
+
1. Build a weighted color histogram from all source pixels
|
|
199
|
+
2. Apply Median Cut to partition the color space, finding initial centroids with good distribution
|
|
200
|
+
3. Refine centroids using K-Means++ in CIE Lab space for perceptual accuracy
|
|
201
|
+
|
|
202
|
+
### 2. Region Pre-Segmentation
|
|
203
|
+
|
|
204
|
+
Before downscaling, we identify coherent regions to preserve:
|
|
205
|
+
|
|
206
|
+
**SLIC Superpixels:**
|
|
207
|
+
- Iteratively clusters pixels by color and spatial proximity
|
|
208
|
+
- Produces compact, regular regions
|
|
209
|
+
- Fast and predictable
|
|
210
|
+
|
|
211
|
+
**Hierarchical Clustering (VTracer-style):**
|
|
212
|
+
- Bottom-up merging of similar adjacent pixels
|
|
213
|
+
- Content-aware boundaries that follow natural edges
|
|
214
|
+
- Configurable merge threshold and minimum region size
|
|
215
|
+
|
|
216
|
+
**Fast Hierarchical (Union-Find):**
|
|
217
|
+
- O(α(n)) per operation using union by rank + path compression
|
|
218
|
+
- Best for large images where full hierarchical is too slow
|
|
219
|
+
|
|
220
|
+
### 3. Edge-Aware Tile Computation
|
|
221
|
+
|
|
222
|
+
Each output tile's color is computed as a weighted average of source pixels:
|
|
223
|
+
|
|
224
|
+
```
|
|
225
|
+
weight(pixel) = 1 / (1 + edge_strength * edge_weight)
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
This reduces the influence of transitional edge pixels, avoiding muddy colors from averaging across boundaries.
|
|
229
|
+
|
|
230
|
+
### 4. Neighbor-Coherent Assignment
|
|
231
|
+
|
|
232
|
+
When assigning each tile to a palette color, we consider:
|
|
233
|
+
|
|
234
|
+
- **Color distance** to the tile's weighted average (primary factor)
|
|
235
|
+
- **Neighbor votes**: already-assigned neighbors bias toward their colors
|
|
236
|
+
- **Region membership**: tiles in the same source region prefer consistent colors
|
|
237
|
+
|
|
238
|
+
The scoring function:
|
|
239
|
+
```
|
|
240
|
+
score(color) = distance(color, tile_avg) * (1 - neighbor_bias - region_bias)
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
### 5. Two-Pass Refinement
|
|
244
|
+
|
|
245
|
+
After initial assignment, we iteratively refine:
|
|
246
|
+
|
|
247
|
+
1. For each pixel, gather all 8 neighbors
|
|
248
|
+
2. Re-evaluate the best palette color considering neighbor votes
|
|
249
|
+
3. Update if a better assignment is found
|
|
250
|
+
4. Repeat until convergence or max iterations
|
|
251
|
+
|
|
252
|
+
This smooths isolated outliers while preserving intentional edges.
|
|
253
|
+
|
|
254
|
+
### 6. Graph-Cut Optimization (Optional)
|
|
255
|
+
|
|
256
|
+
For highest quality, we offer MRF energy minimization:
|
|
257
|
+
|
|
258
|
+
- **Data term**: color distance between tile and palette color
|
|
259
|
+
- **Smoothness term**: penalty for different labels between neighbors
|
|
260
|
+
- **Alpha-expansion**: iteratively try changing each pixel to each label
|
|
261
|
+
|
|
262
|
+
## Comparison with Existing Tools
|
|
263
|
+
|
|
264
|
+
| Feature | Smart Downscaler | Per-Tile K-Means | Simple Resize |
|
|
265
|
+
|---------|------------------|------------------|---------------|
|
|
266
|
+
| Global color consistency | ✓ | ✗ | ✗ |
|
|
267
|
+
| Edge preservation | ✓ | Partial | ✗ |
|
|
268
|
+
| Region awareness | ✓ | ✗ | ✗ |
|
|
269
|
+
| Spatial coherence | ✓ | ✗ | ✗ |
|
|
270
|
+
| Two-pass refinement | ✓ | ✗ | ✗ |
|
|
271
|
+
| Custom palette support | ✓ | ✓ | ✗ |
|
|
272
|
+
| Perceptual color space | ✓ (Lab) | Often RGB | N/A |
|
|
273
|
+
|
|
274
|
+
## Performance
|
|
275
|
+
|
|
276
|
+
Typical performance on a modern CPU (single-threaded):
|
|
277
|
+
|
|
278
|
+
| Image Size | Target Size | Palette | Time |
|
|
279
|
+
|------------|-------------|---------|------|
|
|
280
|
+
| 256×256 | 32×32 | 16 | ~50ms |
|
|
281
|
+
| 512×512 | 64×64 | 32 | ~200ms |
|
|
282
|
+
| 1024×1024 | 128×128 | 32 | ~800ms |
|
|
283
|
+
| 2048×2048 | 256×256 | 64 | ~3s |
|
|
284
|
+
|
|
285
|
+
Enable the `parallel` feature for multi-threaded processing on large images.
|
|
286
|
+
|
|
287
|
+
## Configuration Reference
|
|
288
|
+
|
|
289
|
+
### DownscaleConfig
|
|
290
|
+
|
|
291
|
+
| Field | Type | Default | Description |
|
|
292
|
+
|-------|------|---------|-------------|
|
|
293
|
+
| `palette_size` | usize | 16 | Number of colors in output palette |
|
|
294
|
+
| `kmeans_iterations` | usize | 5 | K-Means refinement iterations |
|
|
295
|
+
| `neighbor_weight` | f32 | 0.3 | Weight for neighbor coherence [0-1] |
|
|
296
|
+
| `region_weight` | f32 | 0.2 | Weight for region coherence [0-1] |
|
|
297
|
+
| `two_pass_refinement` | bool | true | Enable iterative refinement |
|
|
298
|
+
| `refinement_iterations` | usize | 3 | Max refinement iterations |
|
|
299
|
+
| `segmentation` | SegmentationMethod | Hierarchy | Pre-segmentation method |
|
|
300
|
+
| `edge_weight` | f32 | 0.5 | Edge influence in tile averaging |
|
|
301
|
+
|
|
302
|
+
### HierarchyConfig
|
|
303
|
+
|
|
304
|
+
| Field | Type | Default | Description |
|
|
305
|
+
|-------|------|---------|-------------|
|
|
306
|
+
| `merge_threshold` | f32 | 15.0 | Max color distance for merging |
|
|
307
|
+
| `min_region_size` | usize | 4 | Minimum pixels per region |
|
|
308
|
+
| `max_regions` | usize | 0 | Max regions (0 = unlimited) |
|
|
309
|
+
| `spatial_weight` | f32 | 0.1 | Spatial proximity influence |
|
|
310
|
+
|
|
311
|
+
### SlicConfig
|
|
312
|
+
|
|
313
|
+
| Field | Type | Default | Description |
|
|
314
|
+
|-------|------|---------|-------------|
|
|
315
|
+
| `num_superpixels` | usize | 100 | Approximate superpixel count |
|
|
316
|
+
| `compactness` | f32 | 10.0 | Shape regularity (higher = more compact) |
|
|
317
|
+
| `max_iterations` | usize | 10 | SLIC iterations |
|
|
318
|
+
| `convergence_threshold` | f32 | 1.0 | Early termination threshold |
|
|
319
|
+
|
|
320
|
+
## License
|
|
321
|
+
|
|
322
|
+
MIT
|
|
323
|
+
|
|
324
|
+
## Credits
|
|
325
|
+
|
|
326
|
+
Inspired by:
|
|
327
|
+
- VTracer's hierarchical clustering approach
|
|
328
|
+
- SLIC superpixel algorithm
|
|
329
|
+
- K-Means++ initialization
|
|
330
|
+
- CIE Lab perceptual color space
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "smart-downscaler",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"collaborators": [
|
|
5
|
+
"Pixagram"
|
|
6
|
+
],
|
|
7
|
+
"description": "Intelligent pixel art downscaler with region-aware color quantization",
|
|
8
|
+
"version": "0.1.0",
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "https://github.com/pixagram/smart-downscaler"
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"smart_downscaler_bg.wasm",
|
|
16
|
+
"smart_downscaler.js",
|
|
17
|
+
"smart_downscaler_bg.js",
|
|
18
|
+
"smart_downscaler.d.ts"
|
|
19
|
+
],
|
|
20
|
+
"main": "smart_downscaler.js",
|
|
21
|
+
"types": "smart_downscaler.d.ts",
|
|
22
|
+
"sideEffects": [
|
|
23
|
+
"./smart_downscaler.js",
|
|
24
|
+
"./snippets/*"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"pixel-art",
|
|
28
|
+
"image-processing",
|
|
29
|
+
"downscaling",
|
|
30
|
+
"quantization",
|
|
31
|
+
"wasm"
|
|
32
|
+
]
|
|
33
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/* tslint:disable */
|
|
2
|
+
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
export class WasmDownscaleConfig {
|
|
5
|
+
free(): void;
|
|
6
|
+
[Symbol.dispose](): void;
|
|
7
|
+
/**
|
|
8
|
+
* Create a new configuration with default values
|
|
9
|
+
*/
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Create configuration optimized for speed
|
|
13
|
+
*/
|
|
14
|
+
static fast(): WasmDownscaleConfig;
|
|
15
|
+
/**
|
|
16
|
+
* Create configuration optimized for quality
|
|
17
|
+
*/
|
|
18
|
+
static quality(): WasmDownscaleConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Number of colors in the output palette (default: 16)
|
|
21
|
+
*/
|
|
22
|
+
palette_size: number;
|
|
23
|
+
/**
|
|
24
|
+
* K-Means iterations for palette refinement (default: 5)
|
|
25
|
+
*/
|
|
26
|
+
kmeans_iterations: number;
|
|
27
|
+
/**
|
|
28
|
+
* Weight for neighbor color coherence [0.0, 1.0] (default: 0.3)
|
|
29
|
+
*/
|
|
30
|
+
neighbor_weight: number;
|
|
31
|
+
/**
|
|
32
|
+
* Weight for region membership coherence [0.0, 1.0] (default: 0.2)
|
|
33
|
+
*/
|
|
34
|
+
region_weight: number;
|
|
35
|
+
/**
|
|
36
|
+
* Enable two-pass refinement (default: true)
|
|
37
|
+
*/
|
|
38
|
+
two_pass_refinement: boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Maximum refinement iterations (default: 3)
|
|
41
|
+
*/
|
|
42
|
+
refinement_iterations: number;
|
|
43
|
+
/**
|
|
44
|
+
* Edge weight in tile color computation (default: 0.5)
|
|
45
|
+
*/
|
|
46
|
+
edge_weight: number;
|
|
47
|
+
/**
|
|
48
|
+
* For SLIC: approximate number of superpixels (default: 100)
|
|
49
|
+
*/
|
|
50
|
+
slic_superpixels: number;
|
|
51
|
+
/**
|
|
52
|
+
* For SLIC: compactness factor (default: 10.0)
|
|
53
|
+
*/
|
|
54
|
+
slic_compactness: number;
|
|
55
|
+
/**
|
|
56
|
+
* For hierarchy: merge threshold (default: 15.0)
|
|
57
|
+
*/
|
|
58
|
+
hierarchy_threshold: number;
|
|
59
|
+
/**
|
|
60
|
+
* For hierarchy: minimum region size (default: 4)
|
|
61
|
+
*/
|
|
62
|
+
hierarchy_min_size: number;
|
|
63
|
+
/**
|
|
64
|
+
* Get the segmentation method
|
|
65
|
+
*/
|
|
66
|
+
segmentation_method: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export class WasmDownscaleResult {
|
|
70
|
+
private constructor();
|
|
71
|
+
free(): void;
|
|
72
|
+
[Symbol.dispose](): void;
|
|
73
|
+
/**
|
|
74
|
+
* Get RGB pixel data as Uint8Array (without alpha)
|
|
75
|
+
*/
|
|
76
|
+
rgb_data(): Uint8Array;
|
|
77
|
+
/**
|
|
78
|
+
* Get palette color at index as [r, g, b]
|
|
79
|
+
*/
|
|
80
|
+
get_palette_color(index: number): Uint8Array;
|
|
81
|
+
/**
|
|
82
|
+
* Get output width
|
|
83
|
+
*/
|
|
84
|
+
readonly width: number;
|
|
85
|
+
/**
|
|
86
|
+
* Get output height
|
|
87
|
+
*/
|
|
88
|
+
readonly height: number;
|
|
89
|
+
/**
|
|
90
|
+
* Get RGBA pixel data as Uint8ClampedArray (for ImageData)
|
|
91
|
+
*/
|
|
92
|
+
readonly data: Uint8ClampedArray;
|
|
93
|
+
/**
|
|
94
|
+
* Get palette as Uint8Array (RGB, 3 bytes per color)
|
|
95
|
+
*/
|
|
96
|
+
readonly palette: Uint8Array;
|
|
97
|
+
/**
|
|
98
|
+
* Get palette indices for each pixel
|
|
99
|
+
*/
|
|
100
|
+
readonly indices: Uint8Array;
|
|
101
|
+
/**
|
|
102
|
+
* Get number of colors in palette
|
|
103
|
+
*/
|
|
104
|
+
readonly palette_size: number;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Main downscaling function for WebAssembly
|
|
109
|
+
*
|
|
110
|
+
* # Arguments
|
|
111
|
+
* * `image_data` - RGBA pixel data as Uint8Array or Uint8ClampedArray
|
|
112
|
+
* * `width` - Source image width
|
|
113
|
+
* * `height` - Source image height
|
|
114
|
+
* * `target_width` - Output image width
|
|
115
|
+
* * `target_height` - Output image height
|
|
116
|
+
* * `config` - Optional configuration (uses defaults if not provided)
|
|
117
|
+
*
|
|
118
|
+
* # Returns
|
|
119
|
+
* WasmDownscaleResult containing the downscaled image data
|
|
120
|
+
*/
|
|
121
|
+
export function downscale(image_data: Uint8Array, width: number, height: number, target_width: number, target_height: number, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Downscale with RGBA input directly from ImageData
|
|
125
|
+
*/
|
|
126
|
+
export function downscale_rgba(image_data: Uint8ClampedArray, width: number, height: number, target_width: number, target_height: number, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Simple downscale function with minimal parameters
|
|
130
|
+
*/
|
|
131
|
+
export function downscale_simple(image_data: Uint8Array, width: number, height: number, target_width: number, target_height: number, num_colors: number): WasmDownscaleResult;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Downscale with a pre-defined palette
|
|
135
|
+
*/
|
|
136
|
+
export function downscale_with_palette(image_data: Uint8Array, width: number, height: number, target_width: number, target_height: number, palette_data: Uint8Array, config?: WasmDownscaleConfig | null): WasmDownscaleResult;
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Extract a color palette from an image without downscaling
|
|
140
|
+
*/
|
|
141
|
+
export function extract_palette_from_image(image_data: Uint8Array, _width: number, _height: number, num_colors: number, kmeans_iterations: number): Uint8Array;
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Initialize panic hook for better error messages in browser console
|
|
145
|
+
*/
|
|
146
|
+
export function init(): void;
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Log a message to the browser console (for debugging)
|
|
150
|
+
*/
|
|
151
|
+
export function log(message: string): void;
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Quantize an image to a specific palette without resizing
|
|
155
|
+
*/
|
|
156
|
+
export function quantize_to_palette(image_data: Uint8Array, width: number, height: number, palette_data: Uint8Array): WasmDownscaleResult;
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Get library version
|
|
160
|
+
*/
|
|
161
|
+
export function version(): string;
|
|
@@ -0,0 +1,659 @@
|
|
|
1
|
+
let wasm;
|
|
2
|
+
export function __wbg_set_wasm(val) {
|
|
3
|
+
wasm = val;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function _assertClass(instance, klass) {
|
|
7
|
+
if (!(instance instanceof klass)) {
|
|
8
|
+
throw new Error(`expected instance of ${klass.name}`);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
13
|
+
ptr = ptr >>> 0;
|
|
14
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getStringFromWasm0(ptr, len) {
|
|
18
|
+
ptr = ptr >>> 0;
|
|
19
|
+
return decodeText(ptr, len);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
let cachedUint8ArrayMemory0 = null;
|
|
23
|
+
function getUint8ArrayMemory0() {
|
|
24
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
25
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
26
|
+
}
|
|
27
|
+
return cachedUint8ArrayMemory0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function isLikeNone(x) {
|
|
31
|
+
return x === undefined || x === null;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
35
|
+
if (realloc === undefined) {
|
|
36
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
37
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
38
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
39
|
+
WASM_VECTOR_LEN = buf.length;
|
|
40
|
+
return ptr;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let len = arg.length;
|
|
44
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
45
|
+
|
|
46
|
+
const mem = getUint8ArrayMemory0();
|
|
47
|
+
|
|
48
|
+
let offset = 0;
|
|
49
|
+
|
|
50
|
+
for (; offset < len; offset++) {
|
|
51
|
+
const code = arg.charCodeAt(offset);
|
|
52
|
+
if (code > 0x7F) break;
|
|
53
|
+
mem[ptr + offset] = code;
|
|
54
|
+
}
|
|
55
|
+
if (offset !== len) {
|
|
56
|
+
if (offset !== 0) {
|
|
57
|
+
arg = arg.slice(offset);
|
|
58
|
+
}
|
|
59
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
60
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
61
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
62
|
+
|
|
63
|
+
offset += ret.written;
|
|
64
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
WASM_VECTOR_LEN = offset;
|
|
68
|
+
return ptr;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function takeFromExternrefTable0(idx) {
|
|
72
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
73
|
+
wasm.__externref_table_dealloc(idx);
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
78
|
+
cachedTextDecoder.decode();
|
|
79
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
80
|
+
let numBytesDecoded = 0;
|
|
81
|
+
function decodeText(ptr, len) {
|
|
82
|
+
numBytesDecoded += len;
|
|
83
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
84
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
85
|
+
cachedTextDecoder.decode();
|
|
86
|
+
numBytesDecoded = len;
|
|
87
|
+
}
|
|
88
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const cachedTextEncoder = new TextEncoder();
|
|
92
|
+
|
|
93
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
94
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
95
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
96
|
+
view.set(buf);
|
|
97
|
+
return {
|
|
98
|
+
read: arg.length,
|
|
99
|
+
written: buf.length
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
let WASM_VECTOR_LEN = 0;
|
|
105
|
+
|
|
106
|
+
const WasmDownscaleConfigFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
107
|
+
? { register: () => {}, unregister: () => {} }
|
|
108
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_wasmdownscaleconfig_free(ptr >>> 0, 1));
|
|
109
|
+
|
|
110
|
+
const WasmDownscaleResultFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
111
|
+
? { register: () => {}, unregister: () => {} }
|
|
112
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_wasmdownscaleresult_free(ptr >>> 0, 1));
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Configuration options for the downscaler (JavaScript-compatible)
|
|
116
|
+
*/
|
|
117
|
+
export class WasmDownscaleConfig {
|
|
118
|
+
static __wrap(ptr) {
|
|
119
|
+
ptr = ptr >>> 0;
|
|
120
|
+
const obj = Object.create(WasmDownscaleConfig.prototype);
|
|
121
|
+
obj.__wbg_ptr = ptr;
|
|
122
|
+
WasmDownscaleConfigFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
123
|
+
return obj;
|
|
124
|
+
}
|
|
125
|
+
__destroy_into_raw() {
|
|
126
|
+
const ptr = this.__wbg_ptr;
|
|
127
|
+
this.__wbg_ptr = 0;
|
|
128
|
+
WasmDownscaleConfigFinalization.unregister(this);
|
|
129
|
+
return ptr;
|
|
130
|
+
}
|
|
131
|
+
free() {
|
|
132
|
+
const ptr = this.__destroy_into_raw();
|
|
133
|
+
wasm.__wbg_wasmdownscaleconfig_free(ptr, 0);
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* Number of colors in the output palette (default: 16)
|
|
137
|
+
* @returns {number}
|
|
138
|
+
*/
|
|
139
|
+
get palette_size() {
|
|
140
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_palette_size(this.__wbg_ptr);
|
|
141
|
+
return ret >>> 0;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Number of colors in the output palette (default: 16)
|
|
145
|
+
* @param {number} arg0
|
|
146
|
+
*/
|
|
147
|
+
set palette_size(arg0) {
|
|
148
|
+
wasm.__wbg_set_wasmdownscaleconfig_palette_size(this.__wbg_ptr, arg0);
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* K-Means iterations for palette refinement (default: 5)
|
|
152
|
+
* @returns {number}
|
|
153
|
+
*/
|
|
154
|
+
get kmeans_iterations() {
|
|
155
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_kmeans_iterations(this.__wbg_ptr);
|
|
156
|
+
return ret >>> 0;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* K-Means iterations for palette refinement (default: 5)
|
|
160
|
+
* @param {number} arg0
|
|
161
|
+
*/
|
|
162
|
+
set kmeans_iterations(arg0) {
|
|
163
|
+
wasm.__wbg_set_wasmdownscaleconfig_kmeans_iterations(this.__wbg_ptr, arg0);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Weight for neighbor color coherence [0.0, 1.0] (default: 0.3)
|
|
167
|
+
* @returns {number}
|
|
168
|
+
*/
|
|
169
|
+
get neighbor_weight() {
|
|
170
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_neighbor_weight(this.__wbg_ptr);
|
|
171
|
+
return ret;
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Weight for neighbor color coherence [0.0, 1.0] (default: 0.3)
|
|
175
|
+
* @param {number} arg0
|
|
176
|
+
*/
|
|
177
|
+
set neighbor_weight(arg0) {
|
|
178
|
+
wasm.__wbg_set_wasmdownscaleconfig_neighbor_weight(this.__wbg_ptr, arg0);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Weight for region membership coherence [0.0, 1.0] (default: 0.2)
|
|
182
|
+
* @returns {number}
|
|
183
|
+
*/
|
|
184
|
+
get region_weight() {
|
|
185
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_region_weight(this.__wbg_ptr);
|
|
186
|
+
return ret;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Weight for region membership coherence [0.0, 1.0] (default: 0.2)
|
|
190
|
+
* @param {number} arg0
|
|
191
|
+
*/
|
|
192
|
+
set region_weight(arg0) {
|
|
193
|
+
wasm.__wbg_set_wasmdownscaleconfig_region_weight(this.__wbg_ptr, arg0);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Enable two-pass refinement (default: true)
|
|
197
|
+
* @returns {boolean}
|
|
198
|
+
*/
|
|
199
|
+
get two_pass_refinement() {
|
|
200
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_two_pass_refinement(this.__wbg_ptr);
|
|
201
|
+
return ret !== 0;
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Enable two-pass refinement (default: true)
|
|
205
|
+
* @param {boolean} arg0
|
|
206
|
+
*/
|
|
207
|
+
set two_pass_refinement(arg0) {
|
|
208
|
+
wasm.__wbg_set_wasmdownscaleconfig_two_pass_refinement(this.__wbg_ptr, arg0);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Maximum refinement iterations (default: 3)
|
|
212
|
+
* @returns {number}
|
|
213
|
+
*/
|
|
214
|
+
get refinement_iterations() {
|
|
215
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_refinement_iterations(this.__wbg_ptr);
|
|
216
|
+
return ret >>> 0;
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Maximum refinement iterations (default: 3)
|
|
220
|
+
* @param {number} arg0
|
|
221
|
+
*/
|
|
222
|
+
set refinement_iterations(arg0) {
|
|
223
|
+
wasm.__wbg_set_wasmdownscaleconfig_refinement_iterations(this.__wbg_ptr, arg0);
|
|
224
|
+
}
|
|
225
|
+
/**
|
|
226
|
+
* Edge weight in tile color computation (default: 0.5)
|
|
227
|
+
* @returns {number}
|
|
228
|
+
*/
|
|
229
|
+
get edge_weight() {
|
|
230
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_edge_weight(this.__wbg_ptr);
|
|
231
|
+
return ret;
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Edge weight in tile color computation (default: 0.5)
|
|
235
|
+
* @param {number} arg0
|
|
236
|
+
*/
|
|
237
|
+
set edge_weight(arg0) {
|
|
238
|
+
wasm.__wbg_set_wasmdownscaleconfig_edge_weight(this.__wbg_ptr, arg0);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* For SLIC: approximate number of superpixels (default: 100)
|
|
242
|
+
* @returns {number}
|
|
243
|
+
*/
|
|
244
|
+
get slic_superpixels() {
|
|
245
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_slic_superpixels(this.__wbg_ptr);
|
|
246
|
+
return ret >>> 0;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* For SLIC: approximate number of superpixels (default: 100)
|
|
250
|
+
* @param {number} arg0
|
|
251
|
+
*/
|
|
252
|
+
set slic_superpixels(arg0) {
|
|
253
|
+
wasm.__wbg_set_wasmdownscaleconfig_slic_superpixels(this.__wbg_ptr, arg0);
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* For SLIC: compactness factor (default: 10.0)
|
|
257
|
+
* @returns {number}
|
|
258
|
+
*/
|
|
259
|
+
get slic_compactness() {
|
|
260
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_slic_compactness(this.__wbg_ptr);
|
|
261
|
+
return ret;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* For SLIC: compactness factor (default: 10.0)
|
|
265
|
+
* @param {number} arg0
|
|
266
|
+
*/
|
|
267
|
+
set slic_compactness(arg0) {
|
|
268
|
+
wasm.__wbg_set_wasmdownscaleconfig_slic_compactness(this.__wbg_ptr, arg0);
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* For hierarchy: merge threshold (default: 15.0)
|
|
272
|
+
* @returns {number}
|
|
273
|
+
*/
|
|
274
|
+
get hierarchy_threshold() {
|
|
275
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_hierarchy_threshold(this.__wbg_ptr);
|
|
276
|
+
return ret;
|
|
277
|
+
}
|
|
278
|
+
/**
|
|
279
|
+
* For hierarchy: merge threshold (default: 15.0)
|
|
280
|
+
* @param {number} arg0
|
|
281
|
+
*/
|
|
282
|
+
set hierarchy_threshold(arg0) {
|
|
283
|
+
wasm.__wbg_set_wasmdownscaleconfig_hierarchy_threshold(this.__wbg_ptr, arg0);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* For hierarchy: minimum region size (default: 4)
|
|
287
|
+
* @returns {number}
|
|
288
|
+
*/
|
|
289
|
+
get hierarchy_min_size() {
|
|
290
|
+
const ret = wasm.__wbg_get_wasmdownscaleconfig_hierarchy_min_size(this.__wbg_ptr);
|
|
291
|
+
return ret >>> 0;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* For hierarchy: minimum region size (default: 4)
|
|
295
|
+
* @param {number} arg0
|
|
296
|
+
*/
|
|
297
|
+
set hierarchy_min_size(arg0) {
|
|
298
|
+
wasm.__wbg_set_wasmdownscaleconfig_hierarchy_min_size(this.__wbg_ptr, arg0);
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Create a new configuration with default values
|
|
302
|
+
*/
|
|
303
|
+
constructor() {
|
|
304
|
+
const ret = wasm.wasmdownscaleconfig_new();
|
|
305
|
+
this.__wbg_ptr = ret >>> 0;
|
|
306
|
+
WasmDownscaleConfigFinalization.register(this, this.__wbg_ptr, this);
|
|
307
|
+
return this;
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Set the segmentation method
|
|
311
|
+
* @param {string} method
|
|
312
|
+
*/
|
|
313
|
+
set segmentation_method(method) {
|
|
314
|
+
const ptr0 = passStringToWasm0(method, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
315
|
+
const len0 = WASM_VECTOR_LEN;
|
|
316
|
+
wasm.wasmdownscaleconfig_set_segmentation_method(this.__wbg_ptr, ptr0, len0);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Get the segmentation method
|
|
320
|
+
* @returns {string}
|
|
321
|
+
*/
|
|
322
|
+
get segmentation_method() {
|
|
323
|
+
let deferred1_0;
|
|
324
|
+
let deferred1_1;
|
|
325
|
+
try {
|
|
326
|
+
const ret = wasm.wasmdownscaleconfig_segmentation_method(this.__wbg_ptr);
|
|
327
|
+
deferred1_0 = ret[0];
|
|
328
|
+
deferred1_1 = ret[1];
|
|
329
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
330
|
+
} finally {
|
|
331
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Create configuration optimized for speed
|
|
336
|
+
* @returns {WasmDownscaleConfig}
|
|
337
|
+
*/
|
|
338
|
+
static fast() {
|
|
339
|
+
const ret = wasm.wasmdownscaleconfig_fast();
|
|
340
|
+
return WasmDownscaleConfig.__wrap(ret);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Create configuration optimized for quality
|
|
344
|
+
* @returns {WasmDownscaleConfig}
|
|
345
|
+
*/
|
|
346
|
+
static quality() {
|
|
347
|
+
const ret = wasm.wasmdownscaleconfig_quality();
|
|
348
|
+
return WasmDownscaleConfig.__wrap(ret);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
if (Symbol.dispose) WasmDownscaleConfig.prototype[Symbol.dispose] = WasmDownscaleConfig.prototype.free;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Result of downscaling operation
|
|
355
|
+
*/
|
|
356
|
+
export class WasmDownscaleResult {
|
|
357
|
+
static __wrap(ptr) {
|
|
358
|
+
ptr = ptr >>> 0;
|
|
359
|
+
const obj = Object.create(WasmDownscaleResult.prototype);
|
|
360
|
+
obj.__wbg_ptr = ptr;
|
|
361
|
+
WasmDownscaleResultFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
362
|
+
return obj;
|
|
363
|
+
}
|
|
364
|
+
__destroy_into_raw() {
|
|
365
|
+
const ptr = this.__wbg_ptr;
|
|
366
|
+
this.__wbg_ptr = 0;
|
|
367
|
+
WasmDownscaleResultFinalization.unregister(this);
|
|
368
|
+
return ptr;
|
|
369
|
+
}
|
|
370
|
+
free() {
|
|
371
|
+
const ptr = this.__destroy_into_raw();
|
|
372
|
+
wasm.__wbg_wasmdownscaleresult_free(ptr, 0);
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Get output width
|
|
376
|
+
* @returns {number}
|
|
377
|
+
*/
|
|
378
|
+
get width() {
|
|
379
|
+
const ret = wasm.wasmdownscaleresult_width(this.__wbg_ptr);
|
|
380
|
+
return ret >>> 0;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get output height
|
|
384
|
+
* @returns {number}
|
|
385
|
+
*/
|
|
386
|
+
get height() {
|
|
387
|
+
const ret = wasm.wasmdownscaleresult_height(this.__wbg_ptr);
|
|
388
|
+
return ret >>> 0;
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* Get RGBA pixel data as Uint8ClampedArray (for ImageData)
|
|
392
|
+
* @returns {Uint8ClampedArray}
|
|
393
|
+
*/
|
|
394
|
+
get data() {
|
|
395
|
+
const ret = wasm.wasmdownscaleresult_data(this.__wbg_ptr);
|
|
396
|
+
return ret;
|
|
397
|
+
}
|
|
398
|
+
/**
|
|
399
|
+
* Get RGB pixel data as Uint8Array (without alpha)
|
|
400
|
+
* @returns {Uint8Array}
|
|
401
|
+
*/
|
|
402
|
+
rgb_data() {
|
|
403
|
+
const ret = wasm.wasmdownscaleresult_rgb_data(this.__wbg_ptr);
|
|
404
|
+
return ret;
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Get palette as Uint8Array (RGB, 3 bytes per color)
|
|
408
|
+
* @returns {Uint8Array}
|
|
409
|
+
*/
|
|
410
|
+
get palette() {
|
|
411
|
+
const ret = wasm.wasmdownscaleresult_palette(this.__wbg_ptr);
|
|
412
|
+
return ret;
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* Get palette indices for each pixel
|
|
416
|
+
* @returns {Uint8Array}
|
|
417
|
+
*/
|
|
418
|
+
get indices() {
|
|
419
|
+
const ret = wasm.wasmdownscaleresult_indices(this.__wbg_ptr);
|
|
420
|
+
return ret;
|
|
421
|
+
}
|
|
422
|
+
/**
|
|
423
|
+
* Get number of colors in palette
|
|
424
|
+
* @returns {number}
|
|
425
|
+
*/
|
|
426
|
+
get palette_size() {
|
|
427
|
+
const ret = wasm.wasmdownscaleresult_palette_size(this.__wbg_ptr);
|
|
428
|
+
return ret >>> 0;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Get palette color at index as [r, g, b]
|
|
432
|
+
* @param {number} index
|
|
433
|
+
* @returns {Uint8Array}
|
|
434
|
+
*/
|
|
435
|
+
get_palette_color(index) {
|
|
436
|
+
const ret = wasm.wasmdownscaleresult_get_palette_color(this.__wbg_ptr, index);
|
|
437
|
+
return ret;
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
if (Symbol.dispose) WasmDownscaleResult.prototype[Symbol.dispose] = WasmDownscaleResult.prototype.free;
|
|
441
|
+
|
|
442
|
+
/**
|
|
443
|
+
* Main downscaling function for WebAssembly
|
|
444
|
+
*
|
|
445
|
+
* # Arguments
|
|
446
|
+
* * `image_data` - RGBA pixel data as Uint8Array or Uint8ClampedArray
|
|
447
|
+
* * `width` - Source image width
|
|
448
|
+
* * `height` - Source image height
|
|
449
|
+
* * `target_width` - Output image width
|
|
450
|
+
* * `target_height` - Output image height
|
|
451
|
+
* * `config` - Optional configuration (uses defaults if not provided)
|
|
452
|
+
*
|
|
453
|
+
* # Returns
|
|
454
|
+
* WasmDownscaleResult containing the downscaled image data
|
|
455
|
+
* @param {Uint8Array} image_data
|
|
456
|
+
* @param {number} width
|
|
457
|
+
* @param {number} height
|
|
458
|
+
* @param {number} target_width
|
|
459
|
+
* @param {number} target_height
|
|
460
|
+
* @param {WasmDownscaleConfig | null} [config]
|
|
461
|
+
* @returns {WasmDownscaleResult}
|
|
462
|
+
*/
|
|
463
|
+
export function downscale(image_data, width, height, target_width, target_height, config) {
|
|
464
|
+
let ptr0 = 0;
|
|
465
|
+
if (!isLikeNone(config)) {
|
|
466
|
+
_assertClass(config, WasmDownscaleConfig);
|
|
467
|
+
ptr0 = config.__destroy_into_raw();
|
|
468
|
+
}
|
|
469
|
+
const ret = wasm.downscale(image_data, width, height, target_width, target_height, ptr0);
|
|
470
|
+
if (ret[2]) {
|
|
471
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
472
|
+
}
|
|
473
|
+
return WasmDownscaleResult.__wrap(ret[0]);
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Downscale with RGBA input directly from ImageData
|
|
478
|
+
* @param {Uint8ClampedArray} image_data
|
|
479
|
+
* @param {number} width
|
|
480
|
+
* @param {number} height
|
|
481
|
+
* @param {number} target_width
|
|
482
|
+
* @param {number} target_height
|
|
483
|
+
* @param {WasmDownscaleConfig | null} [config]
|
|
484
|
+
* @returns {WasmDownscaleResult}
|
|
485
|
+
*/
|
|
486
|
+
export function downscale_rgba(image_data, width, height, target_width, target_height, config) {
|
|
487
|
+
let ptr0 = 0;
|
|
488
|
+
if (!isLikeNone(config)) {
|
|
489
|
+
_assertClass(config, WasmDownscaleConfig);
|
|
490
|
+
ptr0 = config.__destroy_into_raw();
|
|
491
|
+
}
|
|
492
|
+
const ret = wasm.downscale_rgba(image_data, width, height, target_width, target_height, ptr0);
|
|
493
|
+
if (ret[2]) {
|
|
494
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
495
|
+
}
|
|
496
|
+
return WasmDownscaleResult.__wrap(ret[0]);
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Simple downscale function with minimal parameters
|
|
501
|
+
* @param {Uint8Array} image_data
|
|
502
|
+
* @param {number} width
|
|
503
|
+
* @param {number} height
|
|
504
|
+
* @param {number} target_width
|
|
505
|
+
* @param {number} target_height
|
|
506
|
+
* @param {number} num_colors
|
|
507
|
+
* @returns {WasmDownscaleResult}
|
|
508
|
+
*/
|
|
509
|
+
export function downscale_simple(image_data, width, height, target_width, target_height, num_colors) {
|
|
510
|
+
const ret = wasm.downscale_simple(image_data, width, height, target_width, target_height, num_colors);
|
|
511
|
+
if (ret[2]) {
|
|
512
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
513
|
+
}
|
|
514
|
+
return WasmDownscaleResult.__wrap(ret[0]);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Downscale with a pre-defined palette
|
|
519
|
+
* @param {Uint8Array} image_data
|
|
520
|
+
* @param {number} width
|
|
521
|
+
* @param {number} height
|
|
522
|
+
* @param {number} target_width
|
|
523
|
+
* @param {number} target_height
|
|
524
|
+
* @param {Uint8Array} palette_data
|
|
525
|
+
* @param {WasmDownscaleConfig | null} [config]
|
|
526
|
+
* @returns {WasmDownscaleResult}
|
|
527
|
+
*/
|
|
528
|
+
export function downscale_with_palette(image_data, width, height, target_width, target_height, palette_data, config) {
|
|
529
|
+
let ptr0 = 0;
|
|
530
|
+
if (!isLikeNone(config)) {
|
|
531
|
+
_assertClass(config, WasmDownscaleConfig);
|
|
532
|
+
ptr0 = config.__destroy_into_raw();
|
|
533
|
+
}
|
|
534
|
+
const ret = wasm.downscale_with_palette(image_data, width, height, target_width, target_height, palette_data, ptr0);
|
|
535
|
+
if (ret[2]) {
|
|
536
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
537
|
+
}
|
|
538
|
+
return WasmDownscaleResult.__wrap(ret[0]);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Extract a color palette from an image without downscaling
|
|
543
|
+
* @param {Uint8Array} image_data
|
|
544
|
+
* @param {number} _width
|
|
545
|
+
* @param {number} _height
|
|
546
|
+
* @param {number} num_colors
|
|
547
|
+
* @param {number} kmeans_iterations
|
|
548
|
+
* @returns {Uint8Array}
|
|
549
|
+
*/
|
|
550
|
+
export function extract_palette_from_image(image_data, _width, _height, num_colors, kmeans_iterations) {
|
|
551
|
+
const ret = wasm.extract_palette_from_image(image_data, _width, _height, num_colors, kmeans_iterations);
|
|
552
|
+
if (ret[2]) {
|
|
553
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
554
|
+
}
|
|
555
|
+
return takeFromExternrefTable0(ret[0]);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
/**
|
|
559
|
+
* Initialize panic hook for better error messages in browser console
|
|
560
|
+
*/
|
|
561
|
+
export function init() {
|
|
562
|
+
wasm.init();
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
/**
|
|
566
|
+
* Log a message to the browser console (for debugging)
|
|
567
|
+
* @param {string} message
|
|
568
|
+
*/
|
|
569
|
+
export function log(message) {
|
|
570
|
+
const ptr0 = passStringToWasm0(message, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
571
|
+
const len0 = WASM_VECTOR_LEN;
|
|
572
|
+
wasm.log(ptr0, len0);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
/**
|
|
576
|
+
* Quantize an image to a specific palette without resizing
|
|
577
|
+
* @param {Uint8Array} image_data
|
|
578
|
+
* @param {number} width
|
|
579
|
+
* @param {number} height
|
|
580
|
+
* @param {Uint8Array} palette_data
|
|
581
|
+
* @returns {WasmDownscaleResult}
|
|
582
|
+
*/
|
|
583
|
+
export function quantize_to_palette(image_data, width, height, palette_data) {
|
|
584
|
+
const ret = wasm.quantize_to_palette(image_data, width, height, palette_data);
|
|
585
|
+
if (ret[2]) {
|
|
586
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
587
|
+
}
|
|
588
|
+
return WasmDownscaleResult.__wrap(ret[0]);
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
/**
|
|
592
|
+
* Get library version
|
|
593
|
+
* @returns {string}
|
|
594
|
+
*/
|
|
595
|
+
export function version() {
|
|
596
|
+
let deferred1_0;
|
|
597
|
+
let deferred1_1;
|
|
598
|
+
try {
|
|
599
|
+
const ret = wasm.version();
|
|
600
|
+
deferred1_0 = ret[0];
|
|
601
|
+
deferred1_1 = ret[1];
|
|
602
|
+
return getStringFromWasm0(ret[0], ret[1]);
|
|
603
|
+
} finally {
|
|
604
|
+
wasm.__wbindgen_free(deferred1_0, deferred1_1, 1);
|
|
605
|
+
}
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
export function __wbg___wbindgen_throw_dd24417ed36fc46e(arg0, arg1) {
|
|
609
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
610
|
+
};
|
|
611
|
+
|
|
612
|
+
export function __wbg_length_22ac23eaec9d8053(arg0) {
|
|
613
|
+
const ret = arg0.length;
|
|
614
|
+
return ret;
|
|
615
|
+
};
|
|
616
|
+
|
|
617
|
+
export function __wbg_log_1d990106d99dacb7(arg0) {
|
|
618
|
+
console.log(arg0);
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
export function __wbg_new_6421f6084cc5bc5a(arg0) {
|
|
622
|
+
const ret = new Uint8Array(arg0);
|
|
623
|
+
return ret;
|
|
624
|
+
};
|
|
625
|
+
|
|
626
|
+
export function __wbg_new_from_slice_de10fccb49c7f3c0(arg0, arg1) {
|
|
627
|
+
const ret = new Uint8ClampedArray(getArrayU8FromWasm0(arg0, arg1));
|
|
628
|
+
return ret;
|
|
629
|
+
};
|
|
630
|
+
|
|
631
|
+
export function __wbg_new_from_slice_f9c22b9153b26992(arg0, arg1) {
|
|
632
|
+
const ret = new Uint8Array(getArrayU8FromWasm0(arg0, arg1));
|
|
633
|
+
return ret;
|
|
634
|
+
};
|
|
635
|
+
|
|
636
|
+
export function __wbg_new_with_length_aa5eaf41d35235e5(arg0) {
|
|
637
|
+
const ret = new Uint8Array(arg0 >>> 0);
|
|
638
|
+
return ret;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
export function __wbg_prototypesetcall_dfe9b766cdc1f1fd(arg0, arg1, arg2) {
|
|
642
|
+
Uint8Array.prototype.set.call(getArrayU8FromWasm0(arg0, arg1), arg2);
|
|
643
|
+
};
|
|
644
|
+
|
|
645
|
+
export function __wbindgen_cast_2241b6af4c4b2941(arg0, arg1) {
|
|
646
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
647
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
648
|
+
return ret;
|
|
649
|
+
};
|
|
650
|
+
|
|
651
|
+
export function __wbindgen_init_externref_table() {
|
|
652
|
+
const table = wasm.__wbindgen_externrefs;
|
|
653
|
+
const offset = table.grow(4);
|
|
654
|
+
table.set(0, undefined);
|
|
655
|
+
table.set(offset + 0, undefined);
|
|
656
|
+
table.set(offset + 1, null);
|
|
657
|
+
table.set(offset + 2, true);
|
|
658
|
+
table.set(offset + 3, false);
|
|
659
|
+
};
|
|
Binary file
|