k-centroid-scaler 1.0.0 → 1.2.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 +259 -73
- package/k_centroid_scaler.js +286 -4
- package/k_centroid_scaler_bg.wasm +0 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,22 +1,47 @@
|
|
|
1
|
-
# K-Centroid Image Scaler - WebAssembly Module
|
|
1
|
+
# K-Centroid Image Scaler & Color Quantizer - WebAssembly Module
|
|
2
2
|
|
|
3
|
-
A Rust/WebAssembly implementation of the K-Centroid image downscaling algorithm, converted from the original Lua/Aseprite script.
|
|
3
|
+
A Rust/WebAssembly implementation of the K-Centroid image downscaling algorithm and advanced color quantization tools, converted from the original Lua/Aseprite script.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### 1. K-Centroid Image Scaling
|
|
8
|
+
Intelligent downscaling using K-means clustering on image tiles to preserve important colors.
|
|
9
|
+
|
|
10
|
+
### 2. Color Quantization
|
|
11
|
+
Two high-quality algorithms for reducing color palettes:
|
|
12
|
+
- **Median Cut**: Best quality, ideal for photographs and complex images
|
|
13
|
+
- **K-Means**: Faster processing, great for graphics and illustrations
|
|
6
14
|
|
|
7
|
-
|
|
15
|
+
### 3. Color Analysis with Spatial Sorting
|
|
16
|
+
Advanced color analysis with multiple sorting algorithms:
|
|
17
|
+
- **Z-Order (Morton)**: Groups similar colors using space-filling curves
|
|
18
|
+
- **Hilbert Curve**: Superior locality preservation for color relationships
|
|
19
|
+
- **Hue-based**: Sort by color wheel position
|
|
20
|
+
- **Luminance**: Sort by brightness
|
|
21
|
+
- **Frequency**: Sort by usage percentage
|
|
8
22
|
|
|
23
|
+
### 4. Dominant Color Extraction
|
|
24
|
+
Automatically identifies and quantizes dominant colors with configurable minimum coverage thresholds.
|
|
25
|
+
|
|
26
|
+
### 5. Palette Extraction
|
|
27
|
+
Extract dominant colors from any image for analysis or design purposes.
|
|
28
|
+
|
|
29
|
+
## Algorithm Overview
|
|
30
|
+
|
|
31
|
+
### K-Centroid Scaling
|
|
9
32
|
1. **Tile Division**: The image is divided into tiles based on the target dimensions
|
|
10
33
|
2. **K-Means Clustering**: Each tile undergoes K-means clustering to identify dominant colors
|
|
11
34
|
3. **Color Selection**: The most dominant color (centroid with most pixels) represents each tile
|
|
12
35
|
4. **Downscaling**: Each pixel in the output image uses the dominant color from its corresponding tile
|
|
13
36
|
|
|
14
|
-
|
|
37
|
+
### Color Quantization
|
|
38
|
+
- **Median Cut**: Recursively divides the color space to find optimal palette
|
|
39
|
+
- **K-Means**: Clusters similar colors together for palette reduction
|
|
40
|
+
- **Floyd-Steinberg Dithering**: Optional error diffusion for smoother gradients
|
|
15
41
|
|
|
16
42
|
## Module Interface
|
|
17
43
|
|
|
18
|
-
###
|
|
19
|
-
|
|
44
|
+
### K-Centroid Resize
|
|
20
45
|
```rust
|
|
21
46
|
k_centroid_resize(
|
|
22
47
|
image_data: &[u8], // RGBA image buffer
|
|
@@ -29,110 +54,271 @@ k_centroid_resize(
|
|
|
29
54
|
) -> ImageResult
|
|
30
55
|
```
|
|
31
56
|
|
|
32
|
-
###
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
57
|
+
### Color Quantization (Median Cut)
|
|
58
|
+
```rust
|
|
59
|
+
quantize_colors_median_cut(
|
|
60
|
+
image_data: &[u8], // RGBA image buffer
|
|
61
|
+
width: u32, // Image width
|
|
62
|
+
height: u32, // Image height
|
|
63
|
+
num_colors: u32, // Target color count (2-256)
|
|
64
|
+
dithering: bool, // Apply Floyd-Steinberg dithering
|
|
65
|
+
) -> ImageResult
|
|
40
66
|
```
|
|
41
67
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
68
|
+
### Color Quantization (K-Means)
|
|
69
|
+
```rust
|
|
70
|
+
quantize_colors_kmeans(
|
|
71
|
+
image_data: &[u8], // RGBA image buffer
|
|
72
|
+
width: u32, // Image width
|
|
73
|
+
height: u32, // Image height
|
|
74
|
+
num_colors: u32, // Target color count (2-256)
|
|
75
|
+
iterations: u32, // K-means iterations
|
|
76
|
+
dithering: bool, // Apply Floyd-Steinberg dithering
|
|
77
|
+
) -> ImageResult
|
|
78
|
+
```
|
|
45
79
|
|
|
46
|
-
|
|
47
|
-
|
|
80
|
+
### Palette Extraction
|
|
81
|
+
```rust
|
|
82
|
+
extract_palette(
|
|
83
|
+
image_data: &[u8], // RGBA image buffer
|
|
84
|
+
max_colors: u32, // Maximum colors to extract
|
|
85
|
+
) -> ColorPalette
|
|
86
|
+
```
|
|
48
87
|
|
|
49
|
-
###
|
|
88
|
+
### Color Analysis with Sorting
|
|
89
|
+
```rust
|
|
90
|
+
analyze_colors(
|
|
91
|
+
image_data: &[u8], // RGBA image buffer
|
|
92
|
+
max_colors: u32, // Maximum colors to return (capped at 256)
|
|
93
|
+
sort_method: &str, // Sorting algorithm
|
|
94
|
+
) -> ColorAnalysis
|
|
95
|
+
```
|
|
50
96
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
97
|
+
**Sort Methods:**
|
|
98
|
+
- `"z-order"` or `"morton"`: Space-filling curve for color grouping
|
|
99
|
+
- `"hilbert"`: Hilbert curve for better locality preservation
|
|
100
|
+
- `"hue"`: Sort by hue value (color wheel position)
|
|
101
|
+
- `"luminance"` or `"brightness"`: Sort by perceived brightness
|
|
102
|
+
- `"frequency"`: Sort by usage percentage (most to least common)
|
|
54
103
|
|
|
55
|
-
|
|
56
|
-
|
|
104
|
+
**Return Structure:**
|
|
105
|
+
```javascript
|
|
106
|
+
{
|
|
107
|
+
colors: [{
|
|
108
|
+
hex: string, // "#RRGGBB" format
|
|
109
|
+
percentage: number, // % of image (0-100)
|
|
110
|
+
count: number, // Pixel count
|
|
111
|
+
r: number, // Red (0-255)
|
|
112
|
+
g: number, // Green (0-255)
|
|
113
|
+
b: number // Blue (0-255)
|
|
114
|
+
}],
|
|
115
|
+
totalColors: number, // Unique colors found
|
|
116
|
+
totalPixels: number // Pixels analyzed
|
|
117
|
+
}
|
|
118
|
+
```
|
|
57
119
|
|
|
58
|
-
|
|
59
|
-
|
|
120
|
+
### Dominant Colors with Auto-Quantization
|
|
121
|
+
```rust
|
|
122
|
+
get_dominant_colors(
|
|
123
|
+
image_data: &[u8], // RGBA image buffer
|
|
124
|
+
num_colors: u32, // Target dominant colors
|
|
125
|
+
min_coverage: f32, // Minimum % coverage threshold
|
|
126
|
+
) -> ColorAnalysis
|
|
60
127
|
```
|
|
61
128
|
|
|
62
|
-
## Usage
|
|
129
|
+
## Usage Examples
|
|
63
130
|
|
|
131
|
+
### Basic Color Quantization
|
|
64
132
|
```javascript
|
|
65
|
-
import init, {
|
|
133
|
+
import init, { quantize_colors_median_cut } from './pkg/k_centroid_scaler.js';
|
|
66
134
|
|
|
67
|
-
async function
|
|
68
|
-
// Initialize the WASM module
|
|
135
|
+
async function reduceColors() {
|
|
69
136
|
await init();
|
|
70
137
|
|
|
71
|
-
// Get
|
|
72
|
-
const canvas = document.getElementById('
|
|
138
|
+
// Get image data
|
|
139
|
+
const canvas = document.getElementById('canvas');
|
|
73
140
|
const ctx = canvas.getContext('2d');
|
|
74
141
|
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
|
75
142
|
|
|
76
|
-
//
|
|
77
|
-
const result =
|
|
143
|
+
// Reduce to 16 colors with dithering
|
|
144
|
+
const result = quantize_colors_median_cut(
|
|
78
145
|
imageData.data,
|
|
79
146
|
canvas.width,
|
|
80
147
|
canvas.height,
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
4, // 4 centroids per tile
|
|
84
|
-
5 // 5 iterations
|
|
148
|
+
16, // 16 colors
|
|
149
|
+
true // Enable dithering
|
|
85
150
|
);
|
|
86
151
|
|
|
87
|
-
//
|
|
152
|
+
// Display result
|
|
88
153
|
const outputImageData = new ImageData(
|
|
89
154
|
new Uint8ClampedArray(result.data),
|
|
90
155
|
result.width,
|
|
91
156
|
result.height
|
|
92
157
|
);
|
|
158
|
+
ctx.putImageData(outputImageData, 0, 0);
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### Complete Processing Pipeline
|
|
163
|
+
```javascript
|
|
164
|
+
async function processImage(imageData, width, height) {
|
|
165
|
+
// Step 1: Downscale
|
|
166
|
+
const scaled = await downscaleImage(
|
|
167
|
+
imageData, width, height,
|
|
168
|
+
width / 2, height / 2,
|
|
169
|
+
{ centroids: 4, iterations: 5 }
|
|
170
|
+
);
|
|
171
|
+
|
|
172
|
+
// Step 2: Quantize colors
|
|
173
|
+
const quantized = await quantizeColorsMedianCut(
|
|
174
|
+
scaled.data,
|
|
175
|
+
scaled.width,
|
|
176
|
+
scaled.height,
|
|
177
|
+
{ numColors: 8, dithering: true }
|
|
178
|
+
);
|
|
179
|
+
|
|
180
|
+
return quantized;
|
|
181
|
+
}
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Extract Color Palette
|
|
185
|
+
```javascript
|
|
186
|
+
async function getPalette(imageData) {
|
|
187
|
+
const palette = await extractColorPalette(imageData, 16);
|
|
188
|
+
console.log(`Found ${palette.count} colors:`, palette.colors);
|
|
189
|
+
// Returns array of {r, g, b} objects
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Analyze Colors with Z-Order Sorting
|
|
194
|
+
```javascript
|
|
195
|
+
async function analyzeColors(imageData) {
|
|
196
|
+
const { analyze_colors } = await init();
|
|
197
|
+
|
|
198
|
+
// Get up to 256 colors sorted by Z-order (groups similar colors)
|
|
199
|
+
const analysis = analyze_colors(imageData, 256, 'z-order');
|
|
200
|
+
|
|
201
|
+
// Access color information
|
|
202
|
+
analysis.colors.forEach(color => {
|
|
203
|
+
console.log(`${color.hex}: ${color.percentage.toFixed(2)}% (${color.count} pixels)`);
|
|
204
|
+
});
|
|
93
205
|
|
|
94
|
-
//
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
outputCtx.putImageData(outputImageData, 0, 0);
|
|
206
|
+
// Generate CSS variables
|
|
207
|
+
const cssVars = analysis.colors
|
|
208
|
+
.slice(0, 10) // Top 10 colors
|
|
209
|
+
.map((c, i) => `--color-${i+1}: ${c.hex};`)
|
|
210
|
+
.join('\n');
|
|
100
211
|
}
|
|
101
212
|
```
|
|
102
213
|
|
|
103
|
-
|
|
214
|
+
### Get Dominant Colors
|
|
215
|
+
```javascript
|
|
216
|
+
async function getDominantPalette(imageData) {
|
|
217
|
+
const { get_dominant_colors } = await init();
|
|
218
|
+
|
|
219
|
+
// Get 16 dominant colors, ignoring colors below 0.1% coverage
|
|
220
|
+
const dominant = get_dominant_colors(imageData, 16, 0.1);
|
|
221
|
+
|
|
222
|
+
// Create HTML palette display
|
|
223
|
+
const paletteHTML = dominant.colors
|
|
224
|
+
.map(c => `
|
|
225
|
+
<div style="display: inline-block;">
|
|
226
|
+
<div style="width: 50px; height: 50px; background: ${c.hex};"></div>
|
|
227
|
+
<small>${c.percentage.toFixed(1)}%</small>
|
|
228
|
+
</div>
|
|
229
|
+
`)
|
|
230
|
+
.join('');
|
|
231
|
+
}
|
|
232
|
+
```
|
|
104
233
|
|
|
105
|
-
###
|
|
106
|
-
|
|
107
|
-
|
|
234
|
+
### Export Color Analysis Results
|
|
235
|
+
```javascript
|
|
236
|
+
// Export as JSON
|
|
237
|
+
const colorData = {
|
|
238
|
+
palette: analysis.colors.map(c => ({
|
|
239
|
+
hex: c.hex,
|
|
240
|
+
rgb: [c.r, c.g, c.b],
|
|
241
|
+
usage: c.percentage
|
|
242
|
+
}))
|
|
243
|
+
};
|
|
108
244
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
245
|
+
// Export as CSS custom properties
|
|
246
|
+
const css = `:root {
|
|
247
|
+
${analysis.colors.slice(0, 20).map((c, i) =>
|
|
248
|
+
` --palette-${i}: ${c.hex}; /* ${c.percentage.toFixed(1)}% */`
|
|
249
|
+
).join('\n')}
|
|
250
|
+
}`;
|
|
112
251
|
|
|
113
|
-
|
|
252
|
+
// Export as SCSS/Sass variables
|
|
253
|
+
const scss = analysis.colors.slice(0, 20)
|
|
254
|
+
.map((c, i) => `$color-${i}: ${c.hex};`)
|
|
255
|
+
.join('\n');
|
|
256
|
+
```
|
|
114
257
|
|
|
115
|
-
|
|
116
|
-
2. **Dominant Color Selection**: Always selects the centroid with the most assigned pixels
|
|
117
|
-
3. **Tile Processing**: Each tile is processed independently, maintaining local color characteristics
|
|
118
|
-
4. **Edge Handling**: Properly handles edge tiles that may be smaller than the standard tile size
|
|
258
|
+
## Parameter Guidelines
|
|
119
259
|
|
|
120
|
-
|
|
260
|
+
### Quantization Method Selection
|
|
261
|
+
- **Median Cut**: Use for photographs, natural images, gradients
|
|
262
|
+
- **K-Means**: Use for graphics, logos, illustrations with flat colors
|
|
121
263
|
|
|
122
|
-
|
|
123
|
-
- **
|
|
124
|
-
- **
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
- Optional wasm-opt post-processing
|
|
264
|
+
### `num_colors` (2-256)
|
|
265
|
+
- **2-4**: Extreme stylization, poster effect
|
|
266
|
+
- **8-16**: Retro gaming aesthetic
|
|
267
|
+
- **32-64**: Good balance of quality and compression
|
|
268
|
+
- **128-256**: Near-original quality with reduced file size
|
|
128
269
|
|
|
129
|
-
|
|
270
|
+
### `dithering` (true/false)
|
|
271
|
+
- **Enable**: For smooth gradients and photographs
|
|
272
|
+
- **Disable**: For pixel art or when crisp edges are needed
|
|
130
273
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
274
|
+
### `iterations` (K-Means only, 1-50)
|
|
275
|
+
- **5-10**: Fast processing, good results
|
|
276
|
+
- **20-30**: Better color accuracy
|
|
277
|
+
- **40-50**: Maximum quality, slower processing
|
|
135
278
|
|
|
136
|
-
##
|
|
279
|
+
## Performance Optimizations
|
|
137
280
|
|
|
138
|
-
|
|
281
|
+
### Algorithm Complexity
|
|
282
|
+
- **Median Cut**: O(n log n) where n = unique colors
|
|
283
|
+
- **K-Means**: O(n × k × i) where n = pixels, k = colors, i = iterations
|
|
284
|
+
- **Dithering**: O(w × h) single pass through image
|
|
285
|
+
|
|
286
|
+
### WebAssembly Optimizations
|
|
287
|
+
- K-means++ initialization for better convergence
|
|
288
|
+
- Weighted color averaging based on pixel frequency
|
|
289
|
+
- Efficient color distance calculations
|
|
290
|
+
- Floyd-Steinberg dithering with minimal memory overhead
|
|
291
|
+
|
|
292
|
+
## Build Instructions
|
|
293
|
+
|
|
294
|
+
### Prerequisites
|
|
295
|
+
- Rust toolchain (`curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh`)
|
|
296
|
+
- wasm-pack (`curl https://rustwasm.github.io/wasm-pack/installer/init.sh -sSf | sh`)
|
|
297
|
+
|
|
298
|
+
### Building
|
|
299
|
+
```bash
|
|
300
|
+
chmod +x build.sh
|
|
301
|
+
./build.sh
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Comparison: Quantization Methods
|
|
305
|
+
|
|
306
|
+
| Method | Best For | Speed | Quality | Dithering Support |
|
|
307
|
+
|--------|----------|-------|---------|-------------------|
|
|
308
|
+
| Median Cut | Photos, gradients | Medium | Excellent | Yes |
|
|
309
|
+
| K-Means | Graphics, logos | Fast | Very Good | Yes |
|
|
310
|
+
| K-Centroid Resize | Downscaling | Fast | Good | No |
|
|
311
|
+
|
|
312
|
+
## Advanced Features
|
|
313
|
+
|
|
314
|
+
### Custom Initialization
|
|
315
|
+
The K-means algorithm uses K-means++ initialization for optimal starting centroids, ensuring better convergence and more consistent results.
|
|
316
|
+
|
|
317
|
+
### Weighted Clustering
|
|
318
|
+
Colors are weighted by their frequency in the image, ensuring common colors are better represented in the final palette.
|
|
319
|
+
|
|
320
|
+
### Error Diffusion
|
|
321
|
+
Floyd-Steinberg dithering distributes quantization errors to neighboring pixels, creating smoother gradients with limited colors.
|
|
322
|
+
|
|
323
|
+
## License
|
|
324
|
+
Converted to Rust/WebAssembly for web usage. Original K-Centroid algorithm from Aseprite Lua script.
|
package/k_centroid_scaler.js
CHANGED
|
@@ -200,6 +200,16 @@ function takeObject(idx) {
|
|
|
200
200
|
return ret;
|
|
201
201
|
}
|
|
202
202
|
|
|
203
|
+
function getArrayJsValueFromWasm0(ptr, len) {
|
|
204
|
+
ptr = ptr >>> 0;
|
|
205
|
+
const mem = getDataViewMemory0();
|
|
206
|
+
const result = [];
|
|
207
|
+
for (let i = ptr; i < ptr + 4 * len; i += 4) {
|
|
208
|
+
result.push(takeObject(mem.getUint32(i, true)));
|
|
209
|
+
}
|
|
210
|
+
return result;
|
|
211
|
+
}
|
|
212
|
+
|
|
203
213
|
function passArray8ToWasm0(arg, malloc) {
|
|
204
214
|
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
205
215
|
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
@@ -223,6 +233,77 @@ export function k_centroid_resize(image_data, original_width, original_height, t
|
|
|
223
233
|
return ImageResult.__wrap(ret);
|
|
224
234
|
}
|
|
225
235
|
|
|
236
|
+
/**
|
|
237
|
+
* @param {Uint8Array} image_data
|
|
238
|
+
* @param {number} width
|
|
239
|
+
* @param {number} height
|
|
240
|
+
* @param {number} num_colors
|
|
241
|
+
* @param {boolean} dithering
|
|
242
|
+
* @returns {ImageResult}
|
|
243
|
+
*/
|
|
244
|
+
export function quantize_colors_median_cut(image_data, width, height, num_colors, dithering) {
|
|
245
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_export_1);
|
|
246
|
+
const len0 = WASM_VECTOR_LEN;
|
|
247
|
+
const ret = wasm.quantize_colors_median_cut(ptr0, len0, width, height, num_colors, dithering);
|
|
248
|
+
return ImageResult.__wrap(ret);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* @param {Uint8Array} image_data
|
|
253
|
+
* @param {number} width
|
|
254
|
+
* @param {number} height
|
|
255
|
+
* @param {number} num_colors
|
|
256
|
+
* @param {number} iterations
|
|
257
|
+
* @param {boolean} dithering
|
|
258
|
+
* @returns {ImageResult}
|
|
259
|
+
*/
|
|
260
|
+
export function quantize_colors_kmeans(image_data, width, height, num_colors, iterations, dithering) {
|
|
261
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_export_1);
|
|
262
|
+
const len0 = WASM_VECTOR_LEN;
|
|
263
|
+
const ret = wasm.quantize_colors_kmeans(ptr0, len0, width, height, num_colors, iterations, dithering);
|
|
264
|
+
return ImageResult.__wrap(ret);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* @param {Uint8Array} image_data
|
|
269
|
+
* @param {number} max_colors
|
|
270
|
+
* @returns {ColorPalette}
|
|
271
|
+
*/
|
|
272
|
+
export function extract_palette(image_data, max_colors) {
|
|
273
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_export_1);
|
|
274
|
+
const len0 = WASM_VECTOR_LEN;
|
|
275
|
+
const ret = wasm.extract_palette(ptr0, len0, max_colors);
|
|
276
|
+
return ColorPalette.__wrap(ret);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* @param {Uint8Array} image_data
|
|
281
|
+
* @param {number} max_colors
|
|
282
|
+
* @param {string} sort_method
|
|
283
|
+
* @returns {ColorAnalysis}
|
|
284
|
+
*/
|
|
285
|
+
export function analyze_colors(image_data, max_colors, sort_method) {
|
|
286
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_export_1);
|
|
287
|
+
const len0 = WASM_VECTOR_LEN;
|
|
288
|
+
const ptr1 = passStringToWasm0(sort_method, wasm.__wbindgen_export_1, wasm.__wbindgen_export_2);
|
|
289
|
+
const len1 = WASM_VECTOR_LEN;
|
|
290
|
+
const ret = wasm.analyze_colors(ptr0, len0, max_colors, ptr1, len1);
|
|
291
|
+
return ColorAnalysis.__wrap(ret);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* @param {Uint8Array} image_data
|
|
296
|
+
* @param {number} num_colors
|
|
297
|
+
* @param {number} min_coverage
|
|
298
|
+
* @returns {ColorAnalysis}
|
|
299
|
+
*/
|
|
300
|
+
export function get_dominant_colors(image_data, num_colors, min_coverage) {
|
|
301
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_export_1);
|
|
302
|
+
const len0 = WASM_VECTOR_LEN;
|
|
303
|
+
const ret = wasm.get_dominant_colors(ptr0, len0, num_colors, min_coverage);
|
|
304
|
+
return ColorAnalysis.__wrap(ret);
|
|
305
|
+
}
|
|
306
|
+
|
|
226
307
|
/**
|
|
227
308
|
* @param {Uint8Array} data
|
|
228
309
|
* @param {number} width
|
|
@@ -240,6 +321,207 @@ export function process_image(data, width, height, target_width, target_height,
|
|
|
240
321
|
return takeObject(ret);
|
|
241
322
|
}
|
|
242
323
|
|
|
324
|
+
const ColorAnalysisFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
325
|
+
? { register: () => {}, unregister: () => {} }
|
|
326
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_coloranalysis_free(ptr >>> 0, 1));
|
|
327
|
+
|
|
328
|
+
export class ColorAnalysis {
|
|
329
|
+
|
|
330
|
+
static __wrap(ptr) {
|
|
331
|
+
ptr = ptr >>> 0;
|
|
332
|
+
const obj = Object.create(ColorAnalysis.prototype);
|
|
333
|
+
obj.__wbg_ptr = ptr;
|
|
334
|
+
ColorAnalysisFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
335
|
+
return obj;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
__destroy_into_raw() {
|
|
339
|
+
const ptr = this.__wbg_ptr;
|
|
340
|
+
this.__wbg_ptr = 0;
|
|
341
|
+
ColorAnalysisFinalization.unregister(this);
|
|
342
|
+
return ptr;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
free() {
|
|
346
|
+
const ptr = this.__destroy_into_raw();
|
|
347
|
+
wasm.__wbg_coloranalysis_free(ptr, 0);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* @returns {number}
|
|
351
|
+
*/
|
|
352
|
+
get total_colors() {
|
|
353
|
+
const ret = wasm.__wbg_get_coloranalysis_total_colors(this.__wbg_ptr);
|
|
354
|
+
return ret >>> 0;
|
|
355
|
+
}
|
|
356
|
+
/**
|
|
357
|
+
* @param {number} arg0
|
|
358
|
+
*/
|
|
359
|
+
set total_colors(arg0) {
|
|
360
|
+
wasm.__wbg_set_coloranalysis_total_colors(this.__wbg_ptr, arg0);
|
|
361
|
+
}
|
|
362
|
+
/**
|
|
363
|
+
* @returns {number}
|
|
364
|
+
*/
|
|
365
|
+
get total_pixels() {
|
|
366
|
+
const ret = wasm.__wbg_get_coloranalysis_total_pixels(this.__wbg_ptr);
|
|
367
|
+
return ret >>> 0;
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* @param {number} arg0
|
|
371
|
+
*/
|
|
372
|
+
set total_pixels(arg0) {
|
|
373
|
+
wasm.__wbg_set_coloranalysis_total_pixels(this.__wbg_ptr, arg0);
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* @returns {any[]}
|
|
377
|
+
*/
|
|
378
|
+
get colors() {
|
|
379
|
+
try {
|
|
380
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
381
|
+
wasm.coloranalysis_colors(retptr, this.__wbg_ptr);
|
|
382
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
383
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
384
|
+
var v1 = getArrayJsValueFromWasm0(r0, r1).slice();
|
|
385
|
+
wasm.__wbindgen_export_3(r0, r1 * 4, 4);
|
|
386
|
+
return v1;
|
|
387
|
+
} finally {
|
|
388
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
if (Symbol.dispose) ColorAnalysis.prototype[Symbol.dispose] = ColorAnalysis.prototype.free;
|
|
393
|
+
|
|
394
|
+
const ColorInfoFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
395
|
+
? { register: () => {}, unregister: () => {} }
|
|
396
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_colorinfo_free(ptr >>> 0, 1));
|
|
397
|
+
|
|
398
|
+
export class ColorInfo {
|
|
399
|
+
|
|
400
|
+
__destroy_into_raw() {
|
|
401
|
+
const ptr = this.__wbg_ptr;
|
|
402
|
+
this.__wbg_ptr = 0;
|
|
403
|
+
ColorInfoFinalization.unregister(this);
|
|
404
|
+
return ptr;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
free() {
|
|
408
|
+
const ptr = this.__destroy_into_raw();
|
|
409
|
+
wasm.__wbg_colorinfo_free(ptr, 0);
|
|
410
|
+
}
|
|
411
|
+
/**
|
|
412
|
+
* @returns {string}
|
|
413
|
+
*/
|
|
414
|
+
get hex() {
|
|
415
|
+
let deferred1_0;
|
|
416
|
+
let deferred1_1;
|
|
417
|
+
try {
|
|
418
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
419
|
+
wasm.colorinfo_hex(retptr, this.__wbg_ptr);
|
|
420
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
421
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
422
|
+
deferred1_0 = r0;
|
|
423
|
+
deferred1_1 = r1;
|
|
424
|
+
return getStringFromWasm0(r0, r1);
|
|
425
|
+
} finally {
|
|
426
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
427
|
+
wasm.__wbindgen_export_3(deferred1_0, deferred1_1, 1);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* @returns {number}
|
|
432
|
+
*/
|
|
433
|
+
get percentage() {
|
|
434
|
+
const ret = wasm.colorinfo_percentage(this.__wbg_ptr);
|
|
435
|
+
return ret;
|
|
436
|
+
}
|
|
437
|
+
/**
|
|
438
|
+
* @returns {number}
|
|
439
|
+
*/
|
|
440
|
+
get count() {
|
|
441
|
+
const ret = wasm.colorinfo_count(this.__wbg_ptr);
|
|
442
|
+
return ret >>> 0;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* @returns {number}
|
|
446
|
+
*/
|
|
447
|
+
get r() {
|
|
448
|
+
const ret = wasm.colorinfo_r(this.__wbg_ptr);
|
|
449
|
+
return ret;
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* @returns {number}
|
|
453
|
+
*/
|
|
454
|
+
get g() {
|
|
455
|
+
const ret = wasm.colorinfo_g(this.__wbg_ptr);
|
|
456
|
+
return ret;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* @returns {number}
|
|
460
|
+
*/
|
|
461
|
+
get b() {
|
|
462
|
+
const ret = wasm.colorinfo_b(this.__wbg_ptr);
|
|
463
|
+
return ret;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
if (Symbol.dispose) ColorInfo.prototype[Symbol.dispose] = ColorInfo.prototype.free;
|
|
467
|
+
|
|
468
|
+
const ColorPaletteFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
469
|
+
? { register: () => {}, unregister: () => {} }
|
|
470
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_colorpalette_free(ptr >>> 0, 1));
|
|
471
|
+
|
|
472
|
+
export class ColorPalette {
|
|
473
|
+
|
|
474
|
+
static __wrap(ptr) {
|
|
475
|
+
ptr = ptr >>> 0;
|
|
476
|
+
const obj = Object.create(ColorPalette.prototype);
|
|
477
|
+
obj.__wbg_ptr = ptr;
|
|
478
|
+
ColorPaletteFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
479
|
+
return obj;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
__destroy_into_raw() {
|
|
483
|
+
const ptr = this.__wbg_ptr;
|
|
484
|
+
this.__wbg_ptr = 0;
|
|
485
|
+
ColorPaletteFinalization.unregister(this);
|
|
486
|
+
return ptr;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
free() {
|
|
490
|
+
const ptr = this.__destroy_into_raw();
|
|
491
|
+
wasm.__wbg_colorpalette_free(ptr, 0);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* @returns {number}
|
|
495
|
+
*/
|
|
496
|
+
get count() {
|
|
497
|
+
const ret = wasm.__wbg_get_coloranalysis_total_colors(this.__wbg_ptr);
|
|
498
|
+
return ret >>> 0;
|
|
499
|
+
}
|
|
500
|
+
/**
|
|
501
|
+
* @param {number} arg0
|
|
502
|
+
*/
|
|
503
|
+
set count(arg0) {
|
|
504
|
+
wasm.__wbg_set_colorpalette_count(this.__wbg_ptr, arg0);
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* @returns {Uint8Array}
|
|
508
|
+
*/
|
|
509
|
+
get colors() {
|
|
510
|
+
try {
|
|
511
|
+
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
512
|
+
wasm.colorpalette_colors(retptr, this.__wbg_ptr);
|
|
513
|
+
var r0 = getDataViewMemory0().getInt32(retptr + 4 * 0, true);
|
|
514
|
+
var r1 = getDataViewMemory0().getInt32(retptr + 4 * 1, true);
|
|
515
|
+
var v1 = getArrayU8FromWasm0(r0, r1).slice();
|
|
516
|
+
wasm.__wbindgen_export_3(r0, r1 * 1, 1);
|
|
517
|
+
return v1;
|
|
518
|
+
} finally {
|
|
519
|
+
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
520
|
+
}
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
if (Symbol.dispose) ColorPalette.prototype[Symbol.dispose] = ColorPalette.prototype.free;
|
|
524
|
+
|
|
243
525
|
const ImageResultFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
244
526
|
? { register: () => {}, unregister: () => {} }
|
|
245
527
|
: new FinalizationRegistry(ptr => wasm.__wbg_imageresult_free(ptr >>> 0, 1));
|
|
@@ -269,27 +551,27 @@ export class ImageResult {
|
|
|
269
551
|
* @returns {number}
|
|
270
552
|
*/
|
|
271
553
|
get width() {
|
|
272
|
-
const ret = wasm.
|
|
554
|
+
const ret = wasm.__wbg_get_coloranalysis_total_colors(this.__wbg_ptr);
|
|
273
555
|
return ret >>> 0;
|
|
274
556
|
}
|
|
275
557
|
/**
|
|
276
558
|
* @param {number} arg0
|
|
277
559
|
*/
|
|
278
560
|
set width(arg0) {
|
|
279
|
-
wasm.
|
|
561
|
+
wasm.__wbg_set_coloranalysis_total_colors(this.__wbg_ptr, arg0);
|
|
280
562
|
}
|
|
281
563
|
/**
|
|
282
564
|
* @returns {number}
|
|
283
565
|
*/
|
|
284
566
|
get height() {
|
|
285
|
-
const ret = wasm.
|
|
567
|
+
const ret = wasm.__wbg_get_coloranalysis_total_pixels(this.__wbg_ptr);
|
|
286
568
|
return ret >>> 0;
|
|
287
569
|
}
|
|
288
570
|
/**
|
|
289
571
|
* @param {number} arg0
|
|
290
572
|
*/
|
|
291
573
|
set height(arg0) {
|
|
292
|
-
wasm.
|
|
574
|
+
wasm.__wbg_set_coloranalysis_total_pixels(this.__wbg_ptr, arg0);
|
|
293
575
|
}
|
|
294
576
|
/**
|
|
295
577
|
* @returns {Uint8Array}
|
|
Binary file
|
package/package.json
CHANGED