wasm-image-processor 0.4.0 → 0.6.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 +207 -115
- package/package.json +2 -3
- package/wasm_image_processor.d.ts +151 -0
- package/wasm_image_processor.js +5 -1
- package/wasm_image_processor_bg.js +557 -36
- package/wasm_image_processor_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -1,175 +1,267 @@
|
|
|
1
1
|
# WASM Image Processor
|
|
2
|
-
> Process images offline in the Browser.
|
|
3
2
|
|
|
4
|
-
|
|
3
|
+
> High-performance client-side image processing powered by Rust and WebAssembly
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
Process images entirely in the browser with near-native performance. No server uploads, works offline, respects user privacy.
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
**[Live Demo](https://wasm-ip-demo.vercel.app)** | **[Full Documentation](https://wip-docs.vercel.app)** | **[npm Package](https://www.npmjs.com/package/wasm-image-processor)**
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
- **High Performance**: Powered by Rust and WebAssembly
|
|
12
|
-
- **No Data Transfer**: Images never leave your device
|
|
13
|
-
- **PWA Icon Generation**: Create complete icon sets for Progressive Web Apps
|
|
14
|
-
- **Multiple Formats**: Support for JPEG, PNG, WebP, and more
|
|
15
|
-
- **Batch Processing**: Generate multiple sizes from a single image
|
|
9
|
+
---
|
|
16
10
|
|
|
17
|
-
##
|
|
11
|
+
## Quick Start
|
|
18
12
|
|
|
19
|
-
|
|
13
|
+
### For JavaScript Users
|
|
20
14
|
|
|
21
|
-
|
|
22
|
-
|
|
15
|
+
```bash
|
|
16
|
+
npm install wasm-image-processor
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**Vite users:** Install `vite-plugin-wasm` and add it to your config (see [setup guide](https://wip-docs.vercel.app/getting-started.html#vite-configuration))
|
|
23
20
|
|
|
24
|
-
|
|
21
|
+
```javascript
|
|
22
|
+
import { resize_square, blur, grayscale } from "wasm-image-processor";
|
|
25
23
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
- Maintain aspect ratio or force specific dimensions
|
|
29
|
-
- High-quality filtering algorithms
|
|
24
|
+
// Resize an image to 512x512
|
|
25
|
+
const resizedBytes = resize_square(imageUint8Array, 512);
|
|
30
26
|
|
|
27
|
+
// Apply Gaussian blur
|
|
28
|
+
const blurredBytes = blur(imageUint8Array, 5.0);
|
|
31
29
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
npm i wasm-image-processor
|
|
30
|
+
// Convert to grayscale
|
|
31
|
+
const grayBytes = grayscale(imageUint8Array);
|
|
35
32
|
```
|
|
36
33
|
|
|
37
|
-
|
|
34
|
+
**Key features:**
|
|
35
|
+
- Auto-initializes WASM (no manual setup)
|
|
36
|
+
- ~150KB gzipped bundle size
|
|
37
|
+
- TypeScript types included
|
|
38
|
+
- Supports PNG and JPEG formats
|
|
39
|
+
- See [complete documentation](https://wip-docs.vercel.app) for all functions
|
|
38
40
|
|
|
39
|
-
|
|
41
|
+
---
|
|
40
42
|
|
|
41
|
-
|
|
42
|
-
import { resize_square } from "wasm-image-processor";
|
|
43
|
+
### For Rust Contributors
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
45
|
+
**Project structure:**
|
|
46
|
+
```
|
|
47
|
+
src/
|
|
48
|
+
lib.rs # WASM bindings & public API
|
|
49
|
+
processing/ # Core image processing logic
|
|
50
|
+
utils/ # Helpers
|
|
51
|
+
Cargo.toml
|
|
52
|
+
```
|
|
46
53
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
54
|
+
**Local development:**
|
|
55
|
+
```bash
|
|
56
|
+
# Build for web
|
|
57
|
+
wasm-pack build --target web --out-dir pkg
|
|
50
58
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
const uint8Array = new Uint8Array(arrayBuffer)
|
|
59
|
+
# Run tests
|
|
60
|
+
cargo test
|
|
61
|
+
wasm-pack test --headless --firefox
|
|
55
62
|
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
# Test in browser
|
|
64
|
+
cd example && npm install && npm run dev
|
|
65
|
+
```
|
|
58
66
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
**Key dependencies:**
|
|
68
|
+
- `image = "0.24"` for core processing
|
|
69
|
+
- `wasm-bindgen = "0.2"` for JS interop
|
|
70
|
+
- Safe Rust only, panic-safe for WASM context
|
|
63
71
|
|
|
64
|
-
|
|
65
|
-
}
|
|
72
|
+
**Contributing:** Fork the repo, create a feature branch, and open a PR. See [documentation repo](https://github.com/StanleyWorks/wasm-image-processor-docs) for docs contributions.
|
|
66
73
|
|
|
67
|
-
|
|
68
|
-
})
|
|
69
|
-
```
|
|
74
|
+
---
|
|
70
75
|
|
|
71
|
-
|
|
76
|
+
## Available Functions
|
|
72
77
|
|
|
73
|
-
|
|
78
|
+
**Core Operations:**
|
|
79
|
+
- `resize_square(bytes, size)` - Resize to square dimensions
|
|
80
|
+
- `resize(bytes, width, height)` - Resize to custom dimensions
|
|
81
|
+
- `crop(bytes, x, y, width, height)` - Crop to region
|
|
82
|
+
- `thumbnail(bytes, width, height)` - Generate thumbnail
|
|
74
83
|
|
|
75
|
-
|
|
84
|
+
**Filters & Adjustments:**
|
|
85
|
+
- `blur(bytes, sigma)` - Gaussian blur
|
|
86
|
+
- `fast_blur(bytes, sigma)` - Optimized blur
|
|
87
|
+
- `contrast(bytes, value)` - Adjust contrast (-100 to 100)
|
|
88
|
+
- `brighten(bytes, value)` - Adjust brightness (-100 to 100)
|
|
89
|
+
- `grayscale(bytes)` - Convert to grayscale
|
|
90
|
+
- `invert(bytes)` - Invert colors
|
|
91
|
+
- `hue_rotate(bytes, degrees)` - Rotate hue (0-360)
|
|
76
92
|
|
|
77
|
-
**
|
|
78
|
-
- `
|
|
79
|
-
- `side`: Target width/height in pixels (1-5000)
|
|
93
|
+
**Coming Soon:**
|
|
94
|
+
- `rotate(bytes, degrees)` - Rotate image
|
|
80
95
|
|
|
81
|
-
|
|
82
|
-
- PNG-encoded image data as byte array
|
|
96
|
+
See [full API documentation](https://wip-docs.vercel.app/api.html) with live examples for each function.
|
|
83
97
|
|
|
84
|
-
|
|
85
|
-
```javascript
|
|
86
|
-
const resizedBytes = resize_square(imageBytes, 256);
|
|
87
|
-
const blob = new Blob([new Uint8Array(resizedBytes)], { type: 'image/png' });
|
|
88
|
-
```
|
|
98
|
+
---
|
|
89
99
|
|
|
90
|
-
##
|
|
100
|
+
## Why Use This?
|
|
91
101
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
│ ├── index.html # Basic resizer demo
|
|
98
|
-
│ ├── pwa-generator.html # PWA icon generator
|
|
99
|
-
│ ├── pwa_image_generator.js # Generated JS bindings
|
|
100
|
-
│ └── pwa_image_generator_bg.wasm # Generated WASM binary
|
|
101
|
-
├── pkg/ # wasm-pack output
|
|
102
|
-
├── tests/ # Test files
|
|
103
|
-
├── prep-demo.sh # Copy the build to the demo folder
|
|
104
|
-
├── Cargo.toml
|
|
105
|
-
└── README.md
|
|
106
|
-
```
|
|
102
|
+
**For end users:**
|
|
103
|
+
- Privacy: Images never leave your device
|
|
104
|
+
- Speed: Process images in milliseconds
|
|
105
|
+
- Offline: Works without internet connection
|
|
106
|
+
- Universal: Runs in any modern browser
|
|
107
107
|
|
|
108
|
-
|
|
108
|
+
**For developers:**
|
|
109
|
+
- Rust performance in JavaScript
|
|
110
|
+
- Simple, predictable API
|
|
111
|
+
- Tree-shakeable ES modules
|
|
112
|
+
- No server infrastructure needed
|
|
109
113
|
|
|
110
|
-
|
|
114
|
+
---
|
|
111
115
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
+
## Use Cases
|
|
117
|
+
|
|
118
|
+
**Profile picture editors:**
|
|
119
|
+
Generate multiple sizes for avatars without server round-trips. Resize to 32px, 64px, 128px, 256px instantly in the browser.
|
|
120
|
+
|
|
121
|
+
**Photo galleries & portfolios:**
|
|
122
|
+
Create thumbnails client-side before upload. Apply filters for preview without processing server load.
|
|
123
|
+
|
|
124
|
+
**PWA & offline apps:**
|
|
125
|
+
Process images when users have no internet connection. Perfect for field work apps, travel journals, or offline-first tools.
|
|
116
126
|
|
|
117
|
-
|
|
127
|
+
**Privacy-sensitive applications:**
|
|
128
|
+
Medical imaging viewers, legal document processors, or any app where images contain sensitive data that shouldn't touch external servers.
|
|
118
129
|
|
|
119
|
-
|
|
130
|
+
**Image compression tools:**
|
|
131
|
+
Build "TinyPNG alternatives" that run entirely in the browser. Users maintain full control of their files.
|
|
120
132
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
3. Rebuild with `wasm-pack build --target web`
|
|
124
|
-
4. Update the demo pages to use your new function
|
|
133
|
+
**Batch processing utilities:**
|
|
134
|
+
Resize hundreds of product photos, apply watermarks, or normalize images for e-commerce without server costs or upload time.
|
|
125
135
|
|
|
126
|
-
|
|
136
|
+
**Design tools & editors:**
|
|
137
|
+
Add real-time image adjustments (brightness, contrast, blur) to your web app without heavy JavaScript libraries.
|
|
127
138
|
|
|
128
|
-
**
|
|
129
|
-
|
|
130
|
-
- [x] npm package publication
|
|
131
|
-
- [ ] Comprehensive documentation
|
|
132
|
-
- [x] CI/CD pipeline
|
|
139
|
+
**Form enhancements:**
|
|
140
|
+
Automatically resize large images before form submission to reduce upload size and improve UX.
|
|
133
141
|
|
|
134
|
-
|
|
135
|
-
- [ ] Image format conversion (PNG ↔ JPEG ↔ WebP)
|
|
136
|
-
- [ ] Image compression with quality settings
|
|
137
|
-
- [ ] Batch processing for multiple images
|
|
138
|
-
- [ ] Image filters (blur, sharpen, brightness, contrast)
|
|
139
|
-
- [ ] Custom crop functionality
|
|
140
|
-
- [ ] Image rotation and flipping
|
|
141
|
-
- [ ] Metadata preservation and editing
|
|
142
|
-
- [ ] Advanced resizing algorithms
|
|
142
|
+
---
|
|
143
143
|
|
|
144
144
|
## Browser Support
|
|
145
145
|
|
|
146
146
|
- Chrome/Edge 57+
|
|
147
147
|
- Firefox 52+
|
|
148
148
|
- Safari 11+
|
|
149
|
-
- Any browser with WebAssembly support
|
|
149
|
+
- Any browser with [WebAssembly support](https://caniuse.com/wasm)
|
|
150
|
+
|
|
151
|
+
---
|
|
152
|
+
|
|
153
|
+
## Complete Example
|
|
154
|
+
|
|
155
|
+
```html
|
|
156
|
+
<input type="file" id="fileInput" />
|
|
157
|
+
<button id="downloadBtn" style="display: none;">Download Processed Image</button>
|
|
158
|
+
|
|
159
|
+
<script type="module">
|
|
160
|
+
import { resize_square, blur } from "wasm-image-processor";
|
|
161
|
+
|
|
162
|
+
const input = document.getElementById("fileInput");
|
|
163
|
+
const downloadBtn = document.getElementById("downloadBtn");
|
|
164
|
+
|
|
165
|
+
input.addEventListener("change", async (e) => {
|
|
166
|
+
const file = e.target.files[0];
|
|
167
|
+
if (!file) return;
|
|
168
|
+
|
|
169
|
+
try {
|
|
170
|
+
// Read file
|
|
171
|
+
const arrayBuffer = await file.arrayBuffer();
|
|
172
|
+
const uint8Array = new Uint8Array(arrayBuffer);
|
|
173
|
+
|
|
174
|
+
// Process: resize and blur
|
|
175
|
+
const resized = resize_square(uint8Array, 512);
|
|
176
|
+
const processed = blur(resized, 2.0);
|
|
177
|
+
|
|
178
|
+
// Create downloadable blob
|
|
179
|
+
const blob = new Blob([processed], { type: "image/png" });
|
|
180
|
+
const url = URL.createObjectURL(blob);
|
|
181
|
+
|
|
182
|
+
// Setup download
|
|
183
|
+
downloadBtn.style.display = "block";
|
|
184
|
+
downloadBtn.onclick = () => {
|
|
185
|
+
const a = document.createElement("a");
|
|
186
|
+
a.href = url;
|
|
187
|
+
a.download = "processed-image.png";
|
|
188
|
+
a.click();
|
|
189
|
+
URL.revokeObjectURL(url);
|
|
190
|
+
};
|
|
191
|
+
} catch (error) {
|
|
192
|
+
console.error("Processing failed:", error);
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
</script>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
See [more examples](https://wip-docs.vercel.app/examples.html) including Vue, Nuxt, and React patterns.
|
|
199
|
+
|
|
200
|
+
---
|
|
150
201
|
|
|
151
202
|
## Performance
|
|
152
203
|
|
|
153
|
-
Processing
|
|
154
|
-
-
|
|
155
|
-
-
|
|
156
|
-
-
|
|
157
|
-
-
|
|
204
|
+
Processing happens entirely client-side using WebAssembly, providing:
|
|
205
|
+
- Fast processing with near-native performance
|
|
206
|
+
- Complete privacy - images never uploaded
|
|
207
|
+
- Offline capability
|
|
208
|
+
- Zero server costs
|
|
209
|
+
|
|
210
|
+
**Typical operations:**
|
|
211
|
+
- Resize 4K image: ~45ms
|
|
212
|
+
- Apply blur filter: ~30ms
|
|
213
|
+
- Grayscale conversion: ~10ms
|
|
214
|
+
|
|
215
|
+
Performance varies by device and image size.
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## Documentation
|
|
220
|
+
|
|
221
|
+
- [Getting Started Guide](https://wip-docs.vercel.app/getting-started.html)
|
|
222
|
+
- [Complete API Reference](https://wip-docs.vercel.app/api.html)
|
|
223
|
+
- [Live Examples](https://wip-docs.vercel.app/examples.html)
|
|
224
|
+
- [Changelog](https://wip-docs.vercel.app/changelog.html)
|
|
225
|
+
|
|
226
|
+
---
|
|
227
|
+
|
|
228
|
+
## Common Issues
|
|
229
|
+
|
|
230
|
+
**Import errors:** Ensure your bundler supports WebAssembly. Vite users need `vite-plugin-wasm` installed and configured.
|
|
231
|
+
|
|
232
|
+
**"Failed to read image":** Only PNG and JPEG formats are currently supported.
|
|
233
|
+
|
|
234
|
+
**Memory issues:** Large images may cause problems on mobile devices. Consider resizing or adding file size limits.
|
|
235
|
+
|
|
236
|
+
See [troubleshooting guide](https://wip-docs.vercel.app/getting-started.html#troubleshooting) for more help.
|
|
237
|
+
|
|
238
|
+
---
|
|
158
239
|
|
|
159
240
|
## Contributing
|
|
160
241
|
|
|
242
|
+
Contributions welcome! To contribute:
|
|
243
|
+
|
|
161
244
|
1. Fork the repository
|
|
162
|
-
2. Create a feature branch
|
|
163
|
-
3. Commit your changes
|
|
164
|
-
4. Push to
|
|
245
|
+
2. Create a feature branch: `git checkout -b feature/amazing-feature`
|
|
246
|
+
3. Commit your changes: `git commit -m 'Add amazing feature'`
|
|
247
|
+
4. Push to branch: `git push origin feature/amazing-feature`
|
|
165
248
|
5. Open a Pull Request
|
|
166
249
|
|
|
250
|
+
For documentation improvements, contribute to the [docs repository](https://github.com/StanleyWorks/wasm-image-processor-docs).
|
|
251
|
+
|
|
252
|
+
---
|
|
253
|
+
|
|
167
254
|
## License
|
|
168
255
|
|
|
169
|
-
|
|
256
|
+
MIT License - see [LICENSE](LICENSE) file for details.
|
|
257
|
+
|
|
258
|
+
---
|
|
170
259
|
|
|
171
260
|
## Acknowledgments
|
|
172
261
|
|
|
173
|
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
262
|
+
Built with:
|
|
263
|
+
- [Rust](https://www.rust-lang.org/) and [wasm-bindgen](https://rustwasm.github.io/wasm-bindgen/)
|
|
264
|
+
- [image-rs](https://github.com/image-rs/image) crate for image processing
|
|
265
|
+
- Inspired by the need for privacy-respecting browser-based tools
|
|
266
|
+
|
|
267
|
+
**Questions?** Open an [issue](../../issues) or check the [documentation](https://wip-docs.vercel.app).
|
package/package.json
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "wasm-image-processor",
|
|
3
|
-
"type": "module",
|
|
4
3
|
"collaborators": [
|
|
5
4
|
"Stanley Masinde <hello@stanleymasinde.com>"
|
|
6
5
|
],
|
|
7
6
|
"description": "High-performance client-side image processing toolkit powered by Rust and WebAssembly",
|
|
8
|
-
"version": "0.
|
|
7
|
+
"version": "0.6.0",
|
|
9
8
|
"license": "MIT",
|
|
10
9
|
"repository": {
|
|
11
10
|
"type": "git",
|
|
@@ -17,7 +16,7 @@
|
|
|
17
16
|
"wasm_image_processor_bg.js",
|
|
18
17
|
"wasm_image_processor.d.ts"
|
|
19
18
|
],
|
|
20
|
-
"
|
|
19
|
+
"module": "wasm_image_processor.js",
|
|
21
20
|
"homepage": "https://github.com/StanleyMasinde/wasm-image-processor",
|
|
22
21
|
"types": "wasm_image_processor.d.ts",
|
|
23
22
|
"sideEffects": [
|
|
@@ -1,5 +1,144 @@
|
|
|
1
1
|
/* tslint:disable */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Builder-style image processor for JS/Wasm usage.
|
|
6
|
+
*
|
|
7
|
+
* ```javascript
|
|
8
|
+
* // Browser usage (after wasm-bindgen or bundler setup)
|
|
9
|
+
* // const { ImageProcessor } = await init();
|
|
10
|
+
* const input = document.querySelector("#file");
|
|
11
|
+
* const outputImg = document.querySelector("#output");
|
|
12
|
+
*
|
|
13
|
+
* input.addEventListener("change", async (event) => {
|
|
14
|
+
* const file = event.target.files[0];
|
|
15
|
+
* if (!file) return;
|
|
16
|
+
*
|
|
17
|
+
* const inputBytes = new Uint8Array(await file.arrayBuffer());
|
|
18
|
+
* const outputBytes = new ImageProcessor(inputBytes)
|
|
19
|
+
* .resize(512, 512)
|
|
20
|
+
* .grayscale()
|
|
21
|
+
* .contrast(25.0)
|
|
22
|
+
* .process();
|
|
23
|
+
*
|
|
24
|
+
* const blob = new Blob([outputBytes], { type: file.type });
|
|
25
|
+
* outputImg.src = URL.createObjectURL(blob);
|
|
26
|
+
* });
|
|
27
|
+
* ```
|
|
28
|
+
*
|
|
29
|
+
* ```javascript
|
|
30
|
+
* // Canvas usage (after wasm-bindgen or bundler setup)
|
|
31
|
+
* // const { ImageProcessor } = await init();
|
|
32
|
+
* const input = document.querySelector("#file");
|
|
33
|
+
* const canvas = document.querySelector("#canvas");
|
|
34
|
+
* const ctx = canvas.getContext("2d");
|
|
35
|
+
*
|
|
36
|
+
* input.addEventListener("change", async (event) => {
|
|
37
|
+
* const file = event.target.files[0];
|
|
38
|
+
* if (!file) return;
|
|
39
|
+
*
|
|
40
|
+
* const inputBytes = new Uint8Array(await file.arrayBuffer());
|
|
41
|
+
* const outputBytes = new ImageProcessor(inputBytes)
|
|
42
|
+
* .resize(512, 512)
|
|
43
|
+
* .blur(2.0)
|
|
44
|
+
* .process();
|
|
45
|
+
*
|
|
46
|
+
* const blob = new Blob([outputBytes], { type: file.type });
|
|
47
|
+
* const bitmap = await createImageBitmap(blob);
|
|
48
|
+
* canvas.width = bitmap.width;
|
|
49
|
+
* canvas.height = bitmap.height;
|
|
50
|
+
* ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
51
|
+
* ctx.drawImage(bitmap, 0, 0);
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export class ImageProcessor {
|
|
56
|
+
private constructor();
|
|
57
|
+
free(): void;
|
|
58
|
+
[Symbol.dispose](): void;
|
|
59
|
+
blur(sigma: number): ImageProcessor;
|
|
60
|
+
brighten(value: number): ImageProcessor;
|
|
61
|
+
contrast(value: number): ImageProcessor;
|
|
62
|
+
crop(x: number, y: number, width: number, height: number): ImageProcessor;
|
|
63
|
+
fast_blur(sigma: number): ImageProcessor;
|
|
64
|
+
grayscale(): ImageProcessor;
|
|
65
|
+
hue_rotate(degrees: number): ImageProcessor;
|
|
66
|
+
invert(): ImageProcessor;
|
|
67
|
+
/**
|
|
68
|
+
* Create a new processor from raw image bytes.
|
|
69
|
+
*/
|
|
70
|
+
static new(image: Uint8Array): ImageProcessor;
|
|
71
|
+
/**
|
|
72
|
+
* Calling this returns the final image bytes.
|
|
73
|
+
*/
|
|
74
|
+
process(): Uint8Array;
|
|
75
|
+
resize(width: number, height: number): ImageProcessor;
|
|
76
|
+
resize_square(side: number): ImageProcessor;
|
|
77
|
+
thumbnail(width: number, height: number): ImageProcessor;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Performs a Gaussian blur on this image.
|
|
82
|
+
* `sigma` is a measure of how much to blur by.
|
|
83
|
+
* Use a value of less than 5
|
|
84
|
+
*/
|
|
85
|
+
export function blur(image_data: Uint8Array, sigma: number): Uint8Array;
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Brighten image
|
|
89
|
+
* The value is -100 to 100
|
|
90
|
+
*/
|
|
91
|
+
export function brighten(image_data: Uint8Array, value: number): Uint8Array;
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Adjust the contrast of this image.
|
|
95
|
+
* `contrast` is the amount to adjust the contrast by.
|
|
96
|
+
* Negative values decrease the contrast and positive values increase the contrast.
|
|
97
|
+
*/
|
|
98
|
+
export function contrast(image_data: Uint8Array, value: number): Uint8Array;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Return a cut-out of this image delimited by the bounding rectangle.
|
|
102
|
+
*/
|
|
103
|
+
export function crop(image_data: Uint8Array, x: number, y: number, width: number, height: number): Uint8Array;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Performs a fast blur on this image.
|
|
107
|
+
* `sigma` is the standard deviation of the
|
|
108
|
+
* (approximated) Gaussian
|
|
109
|
+
*/
|
|
110
|
+
export function fast_blur(image_data: Uint8Array, sigma: number): Uint8Array;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Add grayscale effect to image
|
|
114
|
+
* Return a grayscale version of this image.
|
|
115
|
+
* Returns `Luma` images in most cases. However, for `f32` images,
|
|
116
|
+
* this will return a grayscale `Rgb/Rgba` image instead.
|
|
117
|
+
*/
|
|
118
|
+
export function grayscale(image_data: Uint8Array): Uint8Array;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Hue rotate the supplied image.
|
|
122
|
+
* `value` is the degrees to rotate each pixel by.
|
|
123
|
+
* 0 and 360 do nothing, the rest rotates by the given degree value.
|
|
124
|
+
* just like the css webkit filter hue-rotate(180)
|
|
125
|
+
*/
|
|
126
|
+
export function hue_rotate(image_data: Uint8Array, degrees: number): Uint8Array;
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Invert the colors on this image.
|
|
130
|
+
*/
|
|
131
|
+
export function invert(image_data: Uint8Array): Uint8Array;
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Resize an image
|
|
135
|
+
* Take an array of bytes, the len and the width
|
|
136
|
+
* The image's aspect ratio is preserved.
|
|
137
|
+
* The image is scaled to the maximum possible size that fits
|
|
138
|
+
* within the bounds specified by `width` and `height`
|
|
139
|
+
*/
|
|
140
|
+
export function resize(image_data: Uint8Array, width: number, height: number): Uint8Array;
|
|
141
|
+
|
|
3
142
|
/**
|
|
4
143
|
* Resize an image by the given dimension.
|
|
5
144
|
* The first parameter is an array of bytes.
|
|
@@ -9,3 +148,15 @@
|
|
|
9
148
|
* It is is ideal for icon resizing.
|
|
10
149
|
*/
|
|
11
150
|
export function resize_square(image_data: Uint8Array, side: number): Uint8Array;
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Scale this image down to fit within a specific size.
|
|
154
|
+
* Returns a new image. The image's aspect ratio is preserved.
|
|
155
|
+
* The image is scaled to the maximum possible size that fits
|
|
156
|
+
* within the bounds specified by `nwidth` and `nheight`.
|
|
157
|
+
*
|
|
158
|
+
* This method uses a fast integer algorithm where each source
|
|
159
|
+
* pixel contributes to exactly one target pixel.
|
|
160
|
+
* May give aliasing artifacts if new size is close to old size.
|
|
161
|
+
*/
|
|
162
|
+
export function thumbnail(image_data: Uint8Array, width: number, height: number): Uint8Array;
|
package/wasm_image_processor.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
+
/* @ts-self-types="./wasm_image_processor.d.ts" */
|
|
2
|
+
|
|
1
3
|
import * as wasm from "./wasm_image_processor_bg.wasm";
|
|
2
|
-
export * from "./wasm_image_processor_bg.js";
|
|
3
4
|
import { __wbg_set_wasm } from "./wasm_image_processor_bg.js";
|
|
4
5
|
__wbg_set_wasm(wasm);
|
|
5
6
|
wasm.__wbindgen_start();
|
|
7
|
+
export {
|
|
8
|
+
ImageProcessor, blur, brighten, contrast, crop, fast_blur, grayscale, hue_rotate, invert, resize, resize_square, thumbnail
|
|
9
|
+
} from "./wasm_image_processor_bg.js";
|
|
@@ -1,48 +1,413 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Builder-style image processor for JS/Wasm usage.
|
|
3
|
+
*
|
|
4
|
+
* ```javascript
|
|
5
|
+
* // Browser usage (after wasm-bindgen or bundler setup)
|
|
6
|
+
* // const { ImageProcessor } = await init();
|
|
7
|
+
* const input = document.querySelector("#file");
|
|
8
|
+
* const outputImg = document.querySelector("#output");
|
|
9
|
+
*
|
|
10
|
+
* input.addEventListener("change", async (event) => {
|
|
11
|
+
* const file = event.target.files[0];
|
|
12
|
+
* if (!file) return;
|
|
13
|
+
*
|
|
14
|
+
* const inputBytes = new Uint8Array(await file.arrayBuffer());
|
|
15
|
+
* const outputBytes = new ImageProcessor(inputBytes)
|
|
16
|
+
* .resize(512, 512)
|
|
17
|
+
* .grayscale()
|
|
18
|
+
* .contrast(25.0)
|
|
19
|
+
* .process();
|
|
20
|
+
*
|
|
21
|
+
* const blob = new Blob([outputBytes], { type: file.type });
|
|
22
|
+
* outputImg.src = URL.createObjectURL(blob);
|
|
23
|
+
* });
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* ```javascript
|
|
27
|
+
* // Canvas usage (after wasm-bindgen or bundler setup)
|
|
28
|
+
* // const { ImageProcessor } = await init();
|
|
29
|
+
* const input = document.querySelector("#file");
|
|
30
|
+
* const canvas = document.querySelector("#canvas");
|
|
31
|
+
* const ctx = canvas.getContext("2d");
|
|
32
|
+
*
|
|
33
|
+
* input.addEventListener("change", async (event) => {
|
|
34
|
+
* const file = event.target.files[0];
|
|
35
|
+
* if (!file) return;
|
|
36
|
+
*
|
|
37
|
+
* const inputBytes = new Uint8Array(await file.arrayBuffer());
|
|
38
|
+
* const outputBytes = new ImageProcessor(inputBytes)
|
|
39
|
+
* .resize(512, 512)
|
|
40
|
+
* .blur(2.0)
|
|
41
|
+
* .process();
|
|
42
|
+
*
|
|
43
|
+
* const blob = new Blob([outputBytes], { type: file.type });
|
|
44
|
+
* const bitmap = await createImageBitmap(blob);
|
|
45
|
+
* canvas.width = bitmap.width;
|
|
46
|
+
* canvas.height = bitmap.height;
|
|
47
|
+
* ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
48
|
+
* ctx.drawImage(bitmap, 0, 0);
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
export class ImageProcessor {
|
|
53
|
+
static __wrap(ptr) {
|
|
54
|
+
ptr = ptr >>> 0;
|
|
55
|
+
const obj = Object.create(ImageProcessor.prototype);
|
|
56
|
+
obj.__wbg_ptr = ptr;
|
|
57
|
+
ImageProcessorFinalization.register(obj, obj.__wbg_ptr, obj);
|
|
58
|
+
return obj;
|
|
59
|
+
}
|
|
60
|
+
__destroy_into_raw() {
|
|
61
|
+
const ptr = this.__wbg_ptr;
|
|
62
|
+
this.__wbg_ptr = 0;
|
|
63
|
+
ImageProcessorFinalization.unregister(this);
|
|
64
|
+
return ptr;
|
|
65
|
+
}
|
|
66
|
+
free() {
|
|
67
|
+
const ptr = this.__destroy_into_raw();
|
|
68
|
+
wasm.__wbg_imageprocessor_free(ptr, 0);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* @param {number} sigma
|
|
72
|
+
* @returns {ImageProcessor}
|
|
73
|
+
*/
|
|
74
|
+
blur(sigma) {
|
|
75
|
+
const ptr = this.__destroy_into_raw();
|
|
76
|
+
const ret = wasm.imageprocessor_blur(ptr, sigma);
|
|
77
|
+
if (ret[2]) {
|
|
78
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
79
|
+
}
|
|
80
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* @param {number} value
|
|
84
|
+
* @returns {ImageProcessor}
|
|
85
|
+
*/
|
|
86
|
+
brighten(value) {
|
|
87
|
+
const ptr = this.__destroy_into_raw();
|
|
88
|
+
const ret = wasm.imageprocessor_brighten(ptr, value);
|
|
89
|
+
if (ret[2]) {
|
|
90
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
91
|
+
}
|
|
92
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* @param {number} value
|
|
96
|
+
* @returns {ImageProcessor}
|
|
97
|
+
*/
|
|
98
|
+
contrast(value) {
|
|
99
|
+
const ptr = this.__destroy_into_raw();
|
|
100
|
+
const ret = wasm.imageprocessor_contrast(ptr, value);
|
|
101
|
+
if (ret[2]) {
|
|
102
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
103
|
+
}
|
|
104
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* @param {number} x
|
|
108
|
+
* @param {number} y
|
|
109
|
+
* @param {number} width
|
|
110
|
+
* @param {number} height
|
|
111
|
+
* @returns {ImageProcessor}
|
|
112
|
+
*/
|
|
113
|
+
crop(x, y, width, height) {
|
|
114
|
+
const ptr = this.__destroy_into_raw();
|
|
115
|
+
const ret = wasm.imageprocessor_crop(ptr, x, y, width, height);
|
|
116
|
+
if (ret[2]) {
|
|
117
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
118
|
+
}
|
|
119
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* @param {number} sigma
|
|
123
|
+
* @returns {ImageProcessor}
|
|
124
|
+
*/
|
|
125
|
+
fast_blur(sigma) {
|
|
126
|
+
const ptr = this.__destroy_into_raw();
|
|
127
|
+
const ret = wasm.imageprocessor_fast_blur(ptr, sigma);
|
|
128
|
+
if (ret[2]) {
|
|
129
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
130
|
+
}
|
|
131
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* @returns {ImageProcessor}
|
|
135
|
+
*/
|
|
136
|
+
grayscale() {
|
|
137
|
+
const ptr = this.__destroy_into_raw();
|
|
138
|
+
const ret = wasm.imageprocessor_grayscale(ptr);
|
|
139
|
+
if (ret[2]) {
|
|
140
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
141
|
+
}
|
|
142
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* @param {number} degrees
|
|
146
|
+
* @returns {ImageProcessor}
|
|
147
|
+
*/
|
|
148
|
+
hue_rotate(degrees) {
|
|
149
|
+
const ptr = this.__destroy_into_raw();
|
|
150
|
+
const ret = wasm.imageprocessor_hue_rotate(ptr, degrees);
|
|
151
|
+
if (ret[2]) {
|
|
152
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
153
|
+
}
|
|
154
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* @returns {ImageProcessor}
|
|
158
|
+
*/
|
|
159
|
+
invert() {
|
|
160
|
+
const ptr = this.__destroy_into_raw();
|
|
161
|
+
const ret = wasm.imageprocessor_invert(ptr);
|
|
162
|
+
if (ret[2]) {
|
|
163
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
164
|
+
}
|
|
165
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Create a new processor from raw image bytes.
|
|
169
|
+
* @param {Uint8Array} image
|
|
170
|
+
* @returns {ImageProcessor}
|
|
171
|
+
*/
|
|
172
|
+
static new(image) {
|
|
173
|
+
const ptr0 = passArray8ToWasm0(image, wasm.__wbindgen_malloc);
|
|
174
|
+
const len0 = WASM_VECTOR_LEN;
|
|
175
|
+
const ret = wasm.imageprocessor_new(ptr0, len0);
|
|
176
|
+
return ImageProcessor.__wrap(ret);
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Calling this returns the final image bytes.
|
|
180
|
+
* @returns {Uint8Array}
|
|
181
|
+
*/
|
|
182
|
+
process() {
|
|
183
|
+
const ptr = this.__destroy_into_raw();
|
|
184
|
+
const ret = wasm.imageprocessor_process(ptr);
|
|
185
|
+
var v1 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
186
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
187
|
+
return v1;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* @param {number} width
|
|
191
|
+
* @param {number} height
|
|
192
|
+
* @returns {ImageProcessor}
|
|
193
|
+
*/
|
|
194
|
+
resize(width, height) {
|
|
195
|
+
const ptr = this.__destroy_into_raw();
|
|
196
|
+
const ret = wasm.imageprocessor_resize(ptr, width, height);
|
|
197
|
+
if (ret[2]) {
|
|
198
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
199
|
+
}
|
|
200
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* @param {number} side
|
|
204
|
+
* @returns {ImageProcessor}
|
|
205
|
+
*/
|
|
206
|
+
resize_square(side) {
|
|
207
|
+
const ptr = this.__destroy_into_raw();
|
|
208
|
+
const ret = wasm.imageprocessor_resize_square(ptr, side);
|
|
209
|
+
if (ret[2]) {
|
|
210
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
211
|
+
}
|
|
212
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* @param {number} width
|
|
216
|
+
* @param {number} height
|
|
217
|
+
* @returns {ImageProcessor}
|
|
218
|
+
*/
|
|
219
|
+
thumbnail(width, height) {
|
|
220
|
+
const ptr = this.__destroy_into_raw();
|
|
221
|
+
const ret = wasm.imageprocessor_thumbnail(ptr, width, height);
|
|
222
|
+
if (ret[2]) {
|
|
223
|
+
throw takeFromExternrefTable0(ret[1]);
|
|
224
|
+
}
|
|
225
|
+
return ImageProcessor.__wrap(ret[0]);
|
|
226
|
+
}
|
|
4
227
|
}
|
|
228
|
+
if (Symbol.dispose) ImageProcessor.prototype[Symbol.dispose] = ImageProcessor.prototype.free;
|
|
5
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Performs a Gaussian blur on this image.
|
|
232
|
+
* `sigma` is a measure of how much to blur by.
|
|
233
|
+
* Use a value of less than 5
|
|
234
|
+
* @param {Uint8Array} image_data
|
|
235
|
+
* @param {number} sigma
|
|
236
|
+
* @returns {Uint8Array}
|
|
237
|
+
*/
|
|
238
|
+
export function blur(image_data, sigma) {
|
|
239
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
240
|
+
const len0 = WASM_VECTOR_LEN;
|
|
241
|
+
const ret = wasm.blur(ptr0, len0, sigma);
|
|
242
|
+
if (ret[3]) {
|
|
243
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
244
|
+
}
|
|
245
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
246
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
247
|
+
return v2;
|
|
248
|
+
}
|
|
6
249
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
250
|
+
/**
|
|
251
|
+
* Brighten image
|
|
252
|
+
* The value is -100 to 100
|
|
253
|
+
* @param {Uint8Array} image_data
|
|
254
|
+
* @param {number} value
|
|
255
|
+
* @returns {Uint8Array}
|
|
256
|
+
*/
|
|
257
|
+
export function brighten(image_data, value) {
|
|
258
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
259
|
+
const len0 = WASM_VECTOR_LEN;
|
|
260
|
+
const ret = wasm.brighten(ptr0, len0, value);
|
|
261
|
+
if (ret[3]) {
|
|
262
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
263
|
+
}
|
|
264
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
265
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
266
|
+
return v2;
|
|
267
|
+
}
|
|
12
268
|
|
|
13
|
-
|
|
269
|
+
/**
|
|
270
|
+
* Adjust the contrast of this image.
|
|
271
|
+
* `contrast` is the amount to adjust the contrast by.
|
|
272
|
+
* Negative values decrease the contrast and positive values increase the contrast.
|
|
273
|
+
* @param {Uint8Array} image_data
|
|
274
|
+
* @param {number} value
|
|
275
|
+
* @returns {Uint8Array}
|
|
276
|
+
*/
|
|
277
|
+
export function contrast(image_data, value) {
|
|
278
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
279
|
+
const len0 = WASM_VECTOR_LEN;
|
|
280
|
+
const ret = wasm.contrast(ptr0, len0, value);
|
|
281
|
+
if (ret[3]) {
|
|
282
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
283
|
+
}
|
|
284
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
285
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
286
|
+
return v2;
|
|
287
|
+
}
|
|
14
288
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
289
|
+
/**
|
|
290
|
+
* Return a cut-out of this image delimited by the bounding rectangle.
|
|
291
|
+
* @param {Uint8Array} image_data
|
|
292
|
+
* @param {number} x
|
|
293
|
+
* @param {number} y
|
|
294
|
+
* @param {number} width
|
|
295
|
+
* @param {number} height
|
|
296
|
+
* @returns {Uint8Array}
|
|
297
|
+
*/
|
|
298
|
+
export function crop(image_data, x, y, width, height) {
|
|
299
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
300
|
+
const len0 = WASM_VECTOR_LEN;
|
|
301
|
+
const ret = wasm.crop(ptr0, len0, x, y, width, height);
|
|
302
|
+
if (ret[3]) {
|
|
303
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
18
304
|
}
|
|
19
|
-
|
|
305
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
306
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
307
|
+
return v2;
|
|
20
308
|
}
|
|
21
309
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
310
|
+
/**
|
|
311
|
+
* Performs a fast blur on this image.
|
|
312
|
+
* `sigma` is the standard deviation of the
|
|
313
|
+
* (approximated) Gaussian
|
|
314
|
+
* @param {Uint8Array} image_data
|
|
315
|
+
* @param {number} sigma
|
|
316
|
+
* @returns {Uint8Array}
|
|
317
|
+
*/
|
|
318
|
+
export function fast_blur(image_data, sigma) {
|
|
319
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
320
|
+
const len0 = WASM_VECTOR_LEN;
|
|
321
|
+
const ret = wasm.fast_blur(ptr0, len0, sigma);
|
|
322
|
+
if (ret[3]) {
|
|
323
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
324
|
+
}
|
|
325
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
326
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
327
|
+
return v2;
|
|
25
328
|
}
|
|
26
329
|
|
|
27
|
-
|
|
330
|
+
/**
|
|
331
|
+
* Add grayscale effect to image
|
|
332
|
+
* Return a grayscale version of this image.
|
|
333
|
+
* Returns `Luma` images in most cases. However, for `f32` images,
|
|
334
|
+
* this will return a grayscale `Rgb/Rgba` image instead.
|
|
335
|
+
* @param {Uint8Array} image_data
|
|
336
|
+
* @returns {Uint8Array}
|
|
337
|
+
*/
|
|
338
|
+
export function grayscale(image_data) {
|
|
339
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
340
|
+
const len0 = WASM_VECTOR_LEN;
|
|
341
|
+
const ret = wasm.grayscale(ptr0, len0);
|
|
342
|
+
if (ret[3]) {
|
|
343
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
344
|
+
}
|
|
345
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
346
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
347
|
+
return v2;
|
|
348
|
+
}
|
|
28
349
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
350
|
+
/**
|
|
351
|
+
* Hue rotate the supplied image.
|
|
352
|
+
* `value` is the degrees to rotate each pixel by.
|
|
353
|
+
* 0 and 360 do nothing, the rest rotates by the given degree value.
|
|
354
|
+
* just like the css webkit filter hue-rotate(180)
|
|
355
|
+
* @param {Uint8Array} image_data
|
|
356
|
+
* @param {number} degrees
|
|
357
|
+
* @returns {Uint8Array}
|
|
358
|
+
*/
|
|
359
|
+
export function hue_rotate(image_data, degrees) {
|
|
360
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
361
|
+
const len0 = WASM_VECTOR_LEN;
|
|
362
|
+
const ret = wasm.hue_rotate(ptr0, len0, degrees);
|
|
363
|
+
if (ret[3]) {
|
|
364
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
365
|
+
}
|
|
366
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
367
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
368
|
+
return v2;
|
|
34
369
|
}
|
|
35
370
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
371
|
+
/**
|
|
372
|
+
* Invert the colors on this image.
|
|
373
|
+
* @param {Uint8Array} image_data
|
|
374
|
+
* @returns {Uint8Array}
|
|
375
|
+
*/
|
|
376
|
+
export function invert(image_data) {
|
|
377
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
378
|
+
const len0 = WASM_VECTOR_LEN;
|
|
379
|
+
const ret = wasm.invert(ptr0, len0);
|
|
380
|
+
if (ret[3]) {
|
|
381
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
382
|
+
}
|
|
383
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
384
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
385
|
+
return v2;
|
|
40
386
|
}
|
|
41
387
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
388
|
+
/**
|
|
389
|
+
* Resize an image
|
|
390
|
+
* Take an array of bytes, the len and the width
|
|
391
|
+
* The image's aspect ratio is preserved.
|
|
392
|
+
* The image is scaled to the maximum possible size that fits
|
|
393
|
+
* within the bounds specified by `width` and `height`
|
|
394
|
+
* @param {Uint8Array} image_data
|
|
395
|
+
* @param {number} width
|
|
396
|
+
* @param {number} height
|
|
397
|
+
* @returns {Uint8Array}
|
|
398
|
+
*/
|
|
399
|
+
export function resize(image_data, width, height) {
|
|
400
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
401
|
+
const len0 = WASM_VECTOR_LEN;
|
|
402
|
+
const ret = wasm.resize(ptr0, len0, width, height);
|
|
403
|
+
if (ret[3]) {
|
|
404
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
405
|
+
}
|
|
406
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
407
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
408
|
+
return v2;
|
|
45
409
|
}
|
|
410
|
+
|
|
46
411
|
/**
|
|
47
412
|
* Resize an image by the given dimension.
|
|
48
413
|
* The first parameter is an array of bytes.
|
|
@@ -66,19 +431,175 @@ export function resize_square(image_data, side) {
|
|
|
66
431
|
return v2;
|
|
67
432
|
}
|
|
68
433
|
|
|
434
|
+
/**
|
|
435
|
+
* Scale this image down to fit within a specific size.
|
|
436
|
+
* Returns a new image. The image's aspect ratio is preserved.
|
|
437
|
+
* The image is scaled to the maximum possible size that fits
|
|
438
|
+
* within the bounds specified by `nwidth` and `nheight`.
|
|
439
|
+
*
|
|
440
|
+
* This method uses a fast integer algorithm where each source
|
|
441
|
+
* pixel contributes to exactly one target pixel.
|
|
442
|
+
* May give aliasing artifacts if new size is close to old size.
|
|
443
|
+
* @param {Uint8Array} image_data
|
|
444
|
+
* @param {number} width
|
|
445
|
+
* @param {number} height
|
|
446
|
+
* @returns {Uint8Array}
|
|
447
|
+
*/
|
|
448
|
+
export function thumbnail(image_data, width, height) {
|
|
449
|
+
const ptr0 = passArray8ToWasm0(image_data, wasm.__wbindgen_malloc);
|
|
450
|
+
const len0 = WASM_VECTOR_LEN;
|
|
451
|
+
const ret = wasm.thumbnail(ptr0, len0, width, height);
|
|
452
|
+
if (ret[3]) {
|
|
453
|
+
throw takeFromExternrefTable0(ret[2]);
|
|
454
|
+
}
|
|
455
|
+
var v2 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
|
|
456
|
+
wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
|
|
457
|
+
return v2;
|
|
458
|
+
}
|
|
459
|
+
export function __wbg_Error_8c4e43fe74559d73(arg0, arg1) {
|
|
460
|
+
const ret = Error(getStringFromWasm0(arg0, arg1));
|
|
461
|
+
return ret;
|
|
462
|
+
}
|
|
463
|
+
export function __wbg___wbindgen_string_get_72fb696202c56729(arg0, arg1) {
|
|
464
|
+
const obj = arg1;
|
|
465
|
+
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
466
|
+
var ptr1 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
467
|
+
var len1 = WASM_VECTOR_LEN;
|
|
468
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 1, len1, true);
|
|
469
|
+
getDataViewMemory0().setInt32(arg0 + 4 * 0, ptr1, true);
|
|
470
|
+
}
|
|
471
|
+
export function __wbg___wbindgen_throw_be289d5034ed271b(arg0, arg1) {
|
|
472
|
+
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
473
|
+
}
|
|
474
|
+
export function __wbindgen_cast_0000000000000001(arg0, arg1) {
|
|
475
|
+
// Cast intrinsic for `Ref(String) -> Externref`.
|
|
476
|
+
const ret = getStringFromWasm0(arg0, arg1);
|
|
477
|
+
return ret;
|
|
478
|
+
}
|
|
69
479
|
export function __wbindgen_init_externref_table() {
|
|
70
|
-
const table = wasm.
|
|
480
|
+
const table = wasm.__wbindgen_externrefs;
|
|
71
481
|
const offset = table.grow(4);
|
|
72
482
|
table.set(0, undefined);
|
|
73
483
|
table.set(offset + 0, undefined);
|
|
74
484
|
table.set(offset + 1, null);
|
|
75
485
|
table.set(offset + 2, true);
|
|
76
486
|
table.set(offset + 3, false);
|
|
77
|
-
|
|
78
|
-
|
|
487
|
+
}
|
|
488
|
+
const ImageProcessorFinalization = (typeof FinalizationRegistry === 'undefined')
|
|
489
|
+
? { register: () => {}, unregister: () => {} }
|
|
490
|
+
: new FinalizationRegistry(ptr => wasm.__wbg_imageprocessor_free(ptr >>> 0, 1));
|
|
79
491
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
return
|
|
83
|
-
}
|
|
492
|
+
function getArrayU8FromWasm0(ptr, len) {
|
|
493
|
+
ptr = ptr >>> 0;
|
|
494
|
+
return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
let cachedDataViewMemory0 = null;
|
|
498
|
+
function getDataViewMemory0() {
|
|
499
|
+
if (cachedDataViewMemory0 === null || cachedDataViewMemory0.buffer.detached === true || (cachedDataViewMemory0.buffer.detached === undefined && cachedDataViewMemory0.buffer !== wasm.memory.buffer)) {
|
|
500
|
+
cachedDataViewMemory0 = new DataView(wasm.memory.buffer);
|
|
501
|
+
}
|
|
502
|
+
return cachedDataViewMemory0;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
function getStringFromWasm0(ptr, len) {
|
|
506
|
+
ptr = ptr >>> 0;
|
|
507
|
+
return decodeText(ptr, len);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
let cachedUint8ArrayMemory0 = null;
|
|
511
|
+
function getUint8ArrayMemory0() {
|
|
512
|
+
if (cachedUint8ArrayMemory0 === null || cachedUint8ArrayMemory0.byteLength === 0) {
|
|
513
|
+
cachedUint8ArrayMemory0 = new Uint8Array(wasm.memory.buffer);
|
|
514
|
+
}
|
|
515
|
+
return cachedUint8ArrayMemory0;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
function isLikeNone(x) {
|
|
519
|
+
return x === undefined || x === null;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function passArray8ToWasm0(arg, malloc) {
|
|
523
|
+
const ptr = malloc(arg.length * 1, 1) >>> 0;
|
|
524
|
+
getUint8ArrayMemory0().set(arg, ptr / 1);
|
|
525
|
+
WASM_VECTOR_LEN = arg.length;
|
|
526
|
+
return ptr;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
function passStringToWasm0(arg, malloc, realloc) {
|
|
530
|
+
if (realloc === undefined) {
|
|
531
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
532
|
+
const ptr = malloc(buf.length, 1) >>> 0;
|
|
533
|
+
getUint8ArrayMemory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
534
|
+
WASM_VECTOR_LEN = buf.length;
|
|
535
|
+
return ptr;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
let len = arg.length;
|
|
539
|
+
let ptr = malloc(len, 1) >>> 0;
|
|
84
540
|
|
|
541
|
+
const mem = getUint8ArrayMemory0();
|
|
542
|
+
|
|
543
|
+
let offset = 0;
|
|
544
|
+
|
|
545
|
+
for (; offset < len; offset++) {
|
|
546
|
+
const code = arg.charCodeAt(offset);
|
|
547
|
+
if (code > 0x7F) break;
|
|
548
|
+
mem[ptr + offset] = code;
|
|
549
|
+
}
|
|
550
|
+
if (offset !== len) {
|
|
551
|
+
if (offset !== 0) {
|
|
552
|
+
arg = arg.slice(offset);
|
|
553
|
+
}
|
|
554
|
+
ptr = realloc(ptr, len, len = offset + arg.length * 3, 1) >>> 0;
|
|
555
|
+
const view = getUint8ArrayMemory0().subarray(ptr + offset, ptr + len);
|
|
556
|
+
const ret = cachedTextEncoder.encodeInto(arg, view);
|
|
557
|
+
|
|
558
|
+
offset += ret.written;
|
|
559
|
+
ptr = realloc(ptr, len, offset, 1) >>> 0;
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
WASM_VECTOR_LEN = offset;
|
|
563
|
+
return ptr;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function takeFromExternrefTable0(idx) {
|
|
567
|
+
const value = wasm.__wbindgen_externrefs.get(idx);
|
|
568
|
+
wasm.__externref_table_dealloc(idx);
|
|
569
|
+
return value;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
let cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
573
|
+
cachedTextDecoder.decode();
|
|
574
|
+
const MAX_SAFARI_DECODE_BYTES = 2146435072;
|
|
575
|
+
let numBytesDecoded = 0;
|
|
576
|
+
function decodeText(ptr, len) {
|
|
577
|
+
numBytesDecoded += len;
|
|
578
|
+
if (numBytesDecoded >= MAX_SAFARI_DECODE_BYTES) {
|
|
579
|
+
cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
580
|
+
cachedTextDecoder.decode();
|
|
581
|
+
numBytesDecoded = len;
|
|
582
|
+
}
|
|
583
|
+
return cachedTextDecoder.decode(getUint8ArrayMemory0().subarray(ptr, ptr + len));
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
const cachedTextEncoder = new TextEncoder();
|
|
587
|
+
|
|
588
|
+
if (!('encodeInto' in cachedTextEncoder)) {
|
|
589
|
+
cachedTextEncoder.encodeInto = function (arg, view) {
|
|
590
|
+
const buf = cachedTextEncoder.encode(arg);
|
|
591
|
+
view.set(buf);
|
|
592
|
+
return {
|
|
593
|
+
read: arg.length,
|
|
594
|
+
written: buf.length
|
|
595
|
+
};
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
let WASM_VECTOR_LEN = 0;
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
let wasm;
|
|
603
|
+
export function __wbg_set_wasm(val) {
|
|
604
|
+
wasm = val;
|
|
605
|
+
}
|
|
Binary file
|