bun-image-turbo 1.4.0 → 1.4.6
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 +197 -263
- package/dist/index.js +4 -2
- package/dist/index.mjs +4 -2
- package/package.json +16 -9
package/README.md
CHANGED
|
@@ -1,62 +1,33 @@
|
|
|
1
|
-
|
|
2
|
-
⚡ bun-image-turbo
|
|
3
|
-
</h1>
|
|
4
|
-
|
|
5
|
-
<p align="center">
|
|
6
|
-
<strong>High-performance image processing for Bun and Node.js</strong><br>
|
|
7
|
-
Built with Rust and napi-rs for maximum speed
|
|
8
|
-
</p>
|
|
9
|
-
|
|
10
|
-
<p align="center">
|
|
11
|
-
<a href="https://www.npmjs.com/package/bun-image-turbo"><img src="https://badge.fury.io/js/bun-image-turbo.svg" alt="npm version"></a>
|
|
12
|
-
<a href="https://github.com/nexus-aissam/bun-image-turbo/actions/workflows/build.yml"><img src="https://github.com/nexus-aissam/bun-image-turbo/actions/workflows/build.yml/badge.svg" alt="Build & Publish"></a>
|
|
13
|
-
<a href="https://opensource.org/licenses/MIT"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
|
|
14
|
-
<a href="https://www.typescriptlang.org/"><img src="https://img.shields.io/badge/TypeScript-5.0+-blue.svg" alt="TypeScript"></a>
|
|
15
|
-
<a href="https://nodejs.org/"><img src="https://img.shields.io/badge/Node.js-18+-green.svg" alt="Node.js"></a>
|
|
16
|
-
<a href="https://bun.sh/"><img src="https://img.shields.io/badge/Bun-1.0+-orange.svg" alt="Bun"></a>
|
|
17
|
-
</p>
|
|
18
|
-
|
|
19
|
-
<p align="center">
|
|
20
|
-
<a href="https://nexus-aissam.github.io/bun-image-turbo/"><img src="https://img.shields.io/badge/📖_Documentation-Visit_Docs-blue?style=for-the-badge" alt="Documentation"></a>
|
|
21
|
-
<a href="https://nexus-aissam.github.io/bun-image-turbo/api/"><img src="https://img.shields.io/badge/📚_API-Reference-green?style=for-the-badge" alt="API Reference"></a>
|
|
22
|
-
<a href="https://www.npmjs.com/package/bun-image-turbo"><img src="https://img.shields.io/badge/📦_npm-Package-red?style=for-the-badge" alt="npm Package"></a>
|
|
23
|
-
</p>
|
|
24
|
-
|
|
25
|
-
<p align="center">
|
|
26
|
-
<b>Up to 950x faster</b> than alternatives • <b>Native HEIC support</b> • <b>EXIF metadata writing</b> • <b>SIMD-accelerated</b>
|
|
27
|
-
</p>
|
|
1
|
+
# bun-image-turbo
|
|
28
2
|
|
|
29
|
-
|
|
3
|
+
**High-performance image processing for Bun and Node.js** — Built with Rust and napi-rs for maximum speed.
|
|
30
4
|
|
|
31
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/bun-image-turbo)
|
|
6
|
+
[](https://github.com/nexus-aissam/bun-image-turbo/actions/workflows/build.yml)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://www.typescriptlang.org/)
|
|
9
|
+
[](https://nodejs.org/)
|
|
10
|
+
[](https://bun.sh/)
|
|
32
11
|
|
|
33
|
-
|
|
34
|
-
|----------|:-------:|-----|
|
|
35
|
-
| WebP Metadata | **950x** | Header-only parsing, no decode |
|
|
36
|
-
| JPEG Metadata | **38x** | Optimized marker extraction |
|
|
37
|
-
| WebP Resize | **1.25x** | Shrink-on-load optimization (NEW in v1.4.0) |
|
|
38
|
-
| 50 Concurrent Ops | **2.6x** | Rayon thread pool |
|
|
39
|
-
| Transform Pipeline | **1.6x** | Single-pass processing |
|
|
40
|
-
| EXIF Write | **<0.3ms** | Native EXIF embedding |
|
|
41
|
-
| HEIC Support | **Exclusive** | Only lib with native HEIC |
|
|
12
|
+
---
|
|
42
13
|
|
|
43
|
-
|
|
14
|
+
## Why bun-image-turbo?
|
|
44
15
|
|
|
45
|
-
|
|
16
|
+
- **Up to 950x faster** than alternatives for metadata extraction
|
|
17
|
+
- **Native HEIC/HEIF support** — The only high-performance library with Apple format decoding
|
|
18
|
+
- **EXIF metadata writing** — Perfect for AI-generated image attribution
|
|
19
|
+
- **SIMD-accelerated** — TurboJPEG with SSE2/AVX2/NEON
|
|
20
|
+
- **Zero dependencies** — Prebuilt binaries, no compilation needed
|
|
46
21
|
|
|
47
|
-
|
|
22
|
+
### Performance Highlights
|
|
48
23
|
|
|
49
|
-
|
|
|
50
|
-
|
|
51
|
-
| **
|
|
52
|
-
| **
|
|
53
|
-
| **
|
|
54
|
-
| **
|
|
55
|
-
| **
|
|
56
|
-
| **Performance** | [Benchmarks & Optimization](https://nexus-aissam.github.io/bun-image-turbo/guide/performance) |
|
|
57
|
-
| **npm Package** | [npmjs.com/package/bun-image-turbo](https://www.npmjs.com/package/bun-image-turbo) |
|
|
58
|
-
| **GitHub** | [nexus-aissam/bun-image-turbo](https://github.com/nexus-aissam/bun-image-turbo) |
|
|
59
|
-
| **Changelog** | [Release Notes](https://nexus-aissam.github.io/bun-image-turbo/changelog) |
|
|
24
|
+
| Operation | vs sharp | Details |
|
|
25
|
+
|-----------|:--------:|---------|
|
|
26
|
+
| WebP Metadata | **950x faster** | Header-only parsing |
|
|
27
|
+
| JPEG Metadata | **38x faster** | Optimized marker extraction |
|
|
28
|
+
| WebP Resize | **1.25x faster** | Shrink-on-load optimization |
|
|
29
|
+
| Concurrent Ops | **2.6x faster** | Rayon thread pool |
|
|
30
|
+
| HEIC Support | **Exclusive** | Only lib with native HEIC |
|
|
60
31
|
|
|
61
32
|
---
|
|
62
33
|
|
|
@@ -76,19 +47,33 @@ yarn add bun-image-turbo
|
|
|
76
47
|
pnpm add bun-image-turbo
|
|
77
48
|
```
|
|
78
49
|
|
|
79
|
-
|
|
50
|
+
### Verified Package Managers
|
|
51
|
+
|
|
52
|
+
| Package Manager | Status | Tests |
|
|
53
|
+
|-----------------|:------:|------:|
|
|
54
|
+
| Bun | ✅ | 39 pass |
|
|
55
|
+
| npm | ✅ | 32 pass |
|
|
56
|
+
| yarn | ✅ | 32 pass |
|
|
57
|
+
| pnpm | ✅ | 32 pass |
|
|
80
58
|
|
|
81
59
|
---
|
|
82
60
|
|
|
83
61
|
## Quick Start
|
|
84
62
|
|
|
85
63
|
```typescript
|
|
86
|
-
import {
|
|
87
|
-
|
|
88
|
-
|
|
64
|
+
import {
|
|
65
|
+
metadata,
|
|
66
|
+
resize,
|
|
67
|
+
transform,
|
|
68
|
+
toWebp,
|
|
69
|
+
blurhash,
|
|
70
|
+
writeExif
|
|
71
|
+
} from 'bun-image-turbo';
|
|
72
|
+
|
|
73
|
+
// Load image
|
|
89
74
|
const buffer = Buffer.from(await Bun.file('photo.jpg').arrayBuffer());
|
|
90
75
|
|
|
91
|
-
// Get metadata (ultra-fast, header-only)
|
|
76
|
+
// Get metadata (ultra-fast, header-only parsing)
|
|
92
77
|
const info = await metadata(buffer);
|
|
93
78
|
console.log(`${info.width}x${info.height} ${info.format}`);
|
|
94
79
|
|
|
@@ -100,270 +85,207 @@ const webp = await toWebp(buffer, { quality: 85 });
|
|
|
100
85
|
|
|
101
86
|
// Full transform pipeline
|
|
102
87
|
const result = await transform(buffer, {
|
|
103
|
-
resize: { width: 800, height: 600, fit: '
|
|
88
|
+
resize: { width: 800, height: 600, fit: 'Cover' },
|
|
104
89
|
rotate: 90,
|
|
105
90
|
grayscale: true,
|
|
106
|
-
|
|
107
|
-
output: { format: 'webp', webp: { quality: 85 } }
|
|
91
|
+
output: { format: 'Webp', webp: { quality: 85 } }
|
|
108
92
|
});
|
|
109
93
|
|
|
110
94
|
// Generate blurhash placeholder
|
|
111
95
|
const { hash } = await blurhash(buffer, 4, 3);
|
|
112
96
|
|
|
113
|
-
// Add EXIF metadata (perfect for AI images)
|
|
97
|
+
// Add EXIF metadata (perfect for AI-generated images)
|
|
114
98
|
const withExif = await writeExif(webp, {
|
|
115
|
-
imageDescription: 'AI-generated
|
|
99
|
+
imageDescription: 'AI-generated landscape',
|
|
116
100
|
artist: 'Stable Diffusion XL',
|
|
117
101
|
software: 'ComfyUI',
|
|
118
102
|
userComment: JSON.stringify({ prompt: '...', seed: 12345 })
|
|
119
103
|
});
|
|
120
|
-
|
|
121
|
-
// Save result
|
|
122
|
-
await Bun.write('output.webp', withExif);
|
|
123
104
|
```
|
|
124
105
|
|
|
125
|
-
**[See more examples →](https://nexus-aissam.github.io/bun-image-turbo/examples/)**
|
|
126
|
-
|
|
127
106
|
---
|
|
128
107
|
|
|
129
|
-
##
|
|
130
|
-
|
|
131
|
-
Tested on Apple M1 Pro with Bun 1.3.3 (compared to sharp v0.34.5):
|
|
108
|
+
## API Reference
|
|
132
109
|
|
|
133
|
-
###
|
|
110
|
+
### Core Functions
|
|
134
111
|
|
|
135
|
-
|
|
|
136
|
-
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
112
|
+
| Function | Description | Async | Sync |
|
|
113
|
+
|----------|-------------|:-----:|:----:|
|
|
114
|
+
| `metadata()` | Get image dimensions, format, color info | ✅ | ✅ |
|
|
115
|
+
| `resize()` | Resize image (outputs PNG) | ✅ | ✅ |
|
|
116
|
+
| `transform()` | Multi-operation pipeline | ✅ | ✅ |
|
|
117
|
+
| `toJpeg()` | Convert to JPEG | ✅ | ✅ |
|
|
118
|
+
| `toPng()` | Convert to PNG | ✅ | ✅ |
|
|
119
|
+
| `toWebp()` | Convert to WebP | ✅ | ✅ |
|
|
120
|
+
| `blurhash()` | Generate placeholder hash | ✅ | ✅ |
|
|
121
|
+
| `writeExif()` | Write EXIF metadata | ✅ | ✅ |
|
|
122
|
+
| `stripExif()` | Remove EXIF metadata | ✅ | ✅ |
|
|
140
123
|
|
|
141
|
-
###
|
|
124
|
+
### Sync Variants
|
|
142
125
|
|
|
143
|
-
|
|
144
|
-
|-----------|---------------:|------:|:-------:|
|
|
145
|
-
| 50 Concurrent Ops | **62ms** | 160ms | **2.6x** |
|
|
146
|
-
| Transform Pipeline | **12.2ms** | 19.1ms | **1.6x** |
|
|
147
|
-
| 1MB JPEG → 800px | **12.6ms** | 20.3ms | **1.6x** |
|
|
148
|
-
| Thumbnail (200px) | **8.8ms** | 10.7ms | **1.2x** |
|
|
126
|
+
All functions have synchronous versions: `metadataSync()`, `resizeSync()`, `transformSync()`, etc.
|
|
149
127
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
| Source Size | Target | bun-image-turbo | sharp | Speedup |
|
|
153
|
-
|-------------|--------|---------------:|------:|:-------:|
|
|
154
|
-
| 800x600 | 200px | **3.1ms** | 4.3ms | **1.40x** |
|
|
155
|
-
| 1600x1200 | 200px | **6.4ms** | 8.0ms | **1.24x** |
|
|
156
|
-
| 2000x1500 | 200px | **8.6ms** | 10.1ms | **1.18x** |
|
|
157
|
-
| 3000x2000 | 200px | **14.7ms** | 16.1ms | **1.10x** |
|
|
158
|
-
| 4000x3000 | 400px | **32.4ms** | 33.1ms | **1.02x** |
|
|
159
|
-
|
|
160
|
-
> **v1.4.0** introduces WebP shrink-on-load optimization using libwebp's native scaling, making WebP resize operations **1.02-1.40x faster** than sharp across all sizes.
|
|
161
|
-
|
|
162
|
-
### HEIC Support (Exclusive)
|
|
128
|
+
---
|
|
163
129
|
|
|
164
|
-
|
|
165
|
-
|-----------|-----:|:------|
|
|
166
|
-
| HEIC Metadata | **0.1ms** | Header-only parsing |
|
|
167
|
-
| HEIC → JPEG | **169ms** | Full quality conversion |
|
|
168
|
-
| HEIC → 800px | **138ms** | Shrink-on-decode |
|
|
169
|
-
| HEIC → Thumbnail | **137ms** | Fast 200px generation |
|
|
130
|
+
## Supported Formats
|
|
170
131
|
|
|
171
|
-
|
|
132
|
+
| Format | Read | Write | Notes |
|
|
133
|
+
|--------|:----:|:-----:|-------|
|
|
134
|
+
| JPEG | ✅ | ✅ | TurboJPEG with SIMD acceleration |
|
|
135
|
+
| PNG | ✅ | ✅ | Adaptive compression |
|
|
136
|
+
| WebP | ✅ | ✅ | Lossy & lossless modes |
|
|
137
|
+
| HEIC/HEIF | ✅ | — | macOS ARM64 only |
|
|
138
|
+
| AVIF | ✅ | — | Via libheif |
|
|
139
|
+
| GIF | ✅ | ✅ | Full support |
|
|
140
|
+
| BMP | ✅ | ✅ | Full support |
|
|
141
|
+
| TIFF | ✅ | — | Read-only |
|
|
142
|
+
| ICO | ✅ | — | Read-only |
|
|
172
143
|
|
|
173
|
-
|
|
144
|
+
---
|
|
174
145
|
|
|
175
|
-
|
|
176
|
-
|-----------|-----:|-----:|:------|
|
|
177
|
-
| writeExif (simple) | **0.24ms** | **0.10ms** | 3 fields |
|
|
178
|
-
| writeExif (full) | **0.20ms** | **0.05ms** | 10 fields + JSON |
|
|
179
|
-
| stripExif | **0.26ms** | **0.08ms** | Remove all metadata |
|
|
146
|
+
## Platform Support
|
|
180
147
|
|
|
181
|
-
|
|
148
|
+
| Platform | Architecture | Status | HEIC |
|
|
149
|
+
|----------|--------------|:------:|:----:|
|
|
150
|
+
| macOS | ARM64 (M1/M2/M3/M4) | ✅ | ✅ |
|
|
151
|
+
| macOS | x64 (Intel) | ✅ | — |
|
|
152
|
+
| Linux | x64 (glibc) | ✅ | — |
|
|
153
|
+
| Linux | x64 (musl/Alpine) | ✅ | — |
|
|
154
|
+
| Linux | ARM64 | ✅ | — |
|
|
155
|
+
| Windows | x64 | ✅ | — |
|
|
156
|
+
| Windows | ARM64 | ✅ | — |
|
|
182
157
|
|
|
183
|
-
**
|
|
158
|
+
> **Note:** HEIC/HEIF decoding requires macOS ARM64 with libheif installed via Homebrew.
|
|
184
159
|
|
|
185
160
|
---
|
|
186
161
|
|
|
187
|
-
##
|
|
188
|
-
|
|
189
|
-
| Component | Technology | Benefit |
|
|
190
|
-
|-----------|------------|---------|
|
|
191
|
-
| **JPEG Codec** | TurboJPEG (libjpeg-turbo) | SIMD acceleration (SSE2/AVX2/NEON) |
|
|
192
|
-
| **Resize Engine** | fast_image_resize + Rayon | Multi-threaded with adaptive algorithms |
|
|
193
|
-
| **WebP Codec** | libwebp bindings | Google's optimized encoder/decoder |
|
|
194
|
-
| **HEIC Decoder** | libheif-rs | Native Apple format support |
|
|
195
|
-
| **Node Bindings** | napi-rs | Zero-copy buffer handling |
|
|
196
|
-
|
|
197
|
-
**[Architecture deep dive →](https://nexus-aissam.github.io/bun-image-turbo/guide/architecture)**
|
|
162
|
+
## Benchmarks
|
|
198
163
|
|
|
199
|
-
|
|
164
|
+
Tested on Apple M1 Pro, Bun 1.3.3, compared to sharp v0.34.5:
|
|
200
165
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
- **TurboJPEG with SIMD** - 2-6x faster JPEG encoding/decoding via libjpeg-turbo
|
|
204
|
-
- **Shrink-on-Decode** - Decode JPEG/WebP/HEIC at reduced resolution for faster thumbnails
|
|
205
|
-
- **WebP Shrink-on-Load** - NEW in v1.4.0: Native libwebp scaling for 1.25x faster WebP resize
|
|
206
|
-
- **Adaptive Algorithms** - Auto-selects optimal resize filter based on scale factor
|
|
207
|
-
- **Native HEIC Support** - The only high-performance library with HEIC/HEIF decoding
|
|
208
|
-
- **EXIF Metadata Writing** - Write/strip EXIF data for AI image attribution
|
|
209
|
-
- **Blurhash Generation** - Built-in compact placeholder generation
|
|
210
|
-
- **Multi-Step Resize** - Progressive halving for large scale reductions
|
|
211
|
-
- **Zero-Copy Optimizations** - Minimal memory copies for lower memory usage
|
|
212
|
-
- **Async & Sync APIs** - Both async and sync versions available
|
|
213
|
-
- **TypeScript First** - Full TypeScript support with strict types
|
|
214
|
-
- **Cross-Platform** - macOS, Linux, Windows support
|
|
166
|
+
### Metadata Extraction
|
|
215
167
|
|
|
216
|
-
|
|
168
|
+
| Format | bun-image-turbo | sharp | Speedup |
|
|
169
|
+
|--------|----------------:|------:|:-------:|
|
|
170
|
+
| WebP | 0.004ms | 3.4ms | **950x** |
|
|
171
|
+
| JPEG | 0.003ms | 0.1ms | **38x** |
|
|
172
|
+
| PNG | 0.002ms | 0.08ms | **40x** |
|
|
217
173
|
|
|
218
|
-
|
|
174
|
+
### Image Processing
|
|
219
175
|
|
|
220
|
-
|
|
|
221
|
-
|
|
222
|
-
|
|
|
223
|
-
|
|
|
224
|
-
|
|
|
225
|
-
| `toJpeg()` | Convert to JPEG | [→](https://nexus-aissam.github.io/bun-image-turbo/api/to-jpeg) |
|
|
226
|
-
| `toPng()` | Convert to PNG | [→](https://nexus-aissam.github.io/bun-image-turbo/api/to-png) |
|
|
227
|
-
| `toWebp()` | Convert to WebP | [→](https://nexus-aissam.github.io/bun-image-turbo/api/to-webp) |
|
|
228
|
-
| `blurhash()` | Generate placeholder hash | [→](https://nexus-aissam.github.io/bun-image-turbo/api/blurhash) |
|
|
229
|
-
| `writeExif()` | Write EXIF metadata | [→](https://nexus-aissam.github.io/bun-image-turbo/api/exif) |
|
|
230
|
-
| `stripExif()` | Remove EXIF metadata | [→](https://nexus-aissam.github.io/bun-image-turbo/api/exif) |
|
|
176
|
+
| Operation | bun-image-turbo | sharp | Speedup |
|
|
177
|
+
|-----------|----------------:|------:|:-------:|
|
|
178
|
+
| 50 Concurrent Ops | 62ms | 160ms | **2.6x** |
|
|
179
|
+
| Transform Pipeline | 12.2ms | 19.1ms | **1.6x** |
|
|
180
|
+
| 1MB JPEG → 800px | 12.6ms | 20.3ms | **1.6x** |
|
|
231
181
|
|
|
232
|
-
|
|
182
|
+
### WebP Resize (v1.4.0+)
|
|
233
183
|
|
|
234
|
-
|
|
184
|
+
| Source → Target | bun-image-turbo | sharp | Speedup |
|
|
185
|
+
|-----------------|----------------:|------:|:-------:|
|
|
186
|
+
| 800x600 → 200px | 3.1ms | 4.3ms | **1.40x** |
|
|
187
|
+
| 1600x1200 → 200px | 6.4ms | 8.0ms | **1.24x** |
|
|
188
|
+
| 4000x3000 → 400px | 32.4ms | 33.1ms | **1.02x** |
|
|
235
189
|
|
|
236
190
|
---
|
|
237
191
|
|
|
238
|
-
##
|
|
192
|
+
## Examples
|
|
239
193
|
|
|
240
|
-
|
|
241
|
-
|--------|:----:|:-----:|-------|
|
|
242
|
-
| JPEG | ✅ | ✅ | TurboJPEG with SIMD |
|
|
243
|
-
| PNG | ✅ | ✅ | Adaptive compression |
|
|
244
|
-
| WebP | ✅ | ✅ | Lossy & lossless |
|
|
245
|
-
| HEIC/HEIF | ✅ | ❌ | macOS ARM64 only |
|
|
246
|
-
| AVIF | ✅ | ❌ | Via libheif |
|
|
247
|
-
| GIF | ✅ | ✅ | Animated support |
|
|
248
|
-
| BMP | ✅ | ✅ | Full support |
|
|
249
|
-
| TIFF | ✅ | ❌ | Multi-page support |
|
|
250
|
-
| ICO | ✅ | ❌ | Multi-size icons |
|
|
194
|
+
### Basic Usage
|
|
251
195
|
|
|
252
|
-
|
|
196
|
+
```typescript
|
|
197
|
+
import { metadata, resize, toWebp } from 'bun-image-turbo';
|
|
253
198
|
|
|
254
|
-
|
|
199
|
+
const buffer = await Bun.file('input.jpg').arrayBuffer();
|
|
200
|
+
const input = Buffer.from(buffer);
|
|
255
201
|
|
|
256
|
-
|
|
202
|
+
// Get image info
|
|
203
|
+
const info = await metadata(input);
|
|
204
|
+
console.log(info); // { width: 1920, height: 1080, format: 'Jpeg', ... }
|
|
257
205
|
|
|
258
|
-
|
|
206
|
+
// Create thumbnail
|
|
207
|
+
const thumb = await resize(input, { width: 200, height: 200, fit: 'Cover' });
|
|
259
208
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
| Linux | x64 (glibc) | ✅ | ❌ |
|
|
265
|
-
| Linux | x64 (musl/Alpine) | ✅ | ❌ |
|
|
266
|
-
| Linux | ARM64 (glibc) | ✅ | ❌ |
|
|
267
|
-
| Windows | x64 | ✅ | ❌ |
|
|
268
|
-
| Windows | ARM64 | ✅ | ❌ |
|
|
209
|
+
// Convert to WebP
|
|
210
|
+
const webp = await toWebp(input, { quality: 85 });
|
|
211
|
+
await Bun.write('output.webp', webp);
|
|
212
|
+
```
|
|
269
213
|
|
|
270
|
-
|
|
214
|
+
### HEIC Conversion (macOS ARM64)
|
|
271
215
|
|
|
272
|
-
|
|
216
|
+
```typescript
|
|
217
|
+
import { metadata, transform } from 'bun-image-turbo';
|
|
273
218
|
|
|
274
|
-
|
|
219
|
+
const heic = Buffer.from(await Bun.file('IMG_1234.HEIC').arrayBuffer());
|
|
275
220
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
221
|
+
// Check format
|
|
222
|
+
const info = await metadata(heic);
|
|
223
|
+
console.log(info.format); // 'Heic'
|
|
279
224
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
225
|
+
// Convert to JPEG
|
|
226
|
+
const jpeg = await transform(heic, {
|
|
227
|
+
output: { format: 'Jpeg', jpeg: { quality: 90 } }
|
|
228
|
+
});
|
|
284
229
|
```
|
|
285
230
|
|
|
286
|
-
|
|
287
|
-
|---------|-------------|
|
|
288
|
-
| [basic-usage.ts](./examples/basic-usage.ts) | Metadata, resize, convert, transform |
|
|
289
|
-
| [heic-conversion.ts](./examples/heic-conversion.ts) | iPhone photo conversion |
|
|
290
|
-
| [api-endpoint.ts](./examples/api-endpoint.ts) | HTTP image processing server |
|
|
291
|
-
| [batch-processing.ts](./examples/batch-processing.ts) | Parallel multi-file processing |
|
|
292
|
-
|
|
293
|
-
### EXIF Metadata Example
|
|
231
|
+
### EXIF Metadata for AI Images
|
|
294
232
|
|
|
295
233
|
```typescript
|
|
296
|
-
import { writeExif, toWebp
|
|
234
|
+
import { writeExif, toWebp } from 'bun-image-turbo';
|
|
235
|
+
|
|
236
|
+
const webp = await toWebp(aiGeneratedImage, { quality: 90 });
|
|
297
237
|
|
|
298
|
-
// Add AI generation metadata to WebP
|
|
299
|
-
const webp = await toWebp(imageBuffer, { quality: 90 });
|
|
300
238
|
const withMetadata = await writeExif(webp, {
|
|
301
239
|
imageDescription: 'A sunset over mountains',
|
|
302
240
|
artist: 'Stable Diffusion XL',
|
|
303
|
-
software: 'ComfyUI',
|
|
241
|
+
software: 'ComfyUI v1.0',
|
|
242
|
+
copyright: '© 2024 Your Name',
|
|
304
243
|
userComment: JSON.stringify({
|
|
305
|
-
prompt: 'sunset over mountains, 8k',
|
|
244
|
+
prompt: 'sunset over mountains, golden hour, 8k',
|
|
245
|
+
negativePrompt: 'blur, noise',
|
|
306
246
|
seed: 12345,
|
|
307
247
|
steps: 30,
|
|
308
248
|
cfg_scale: 7.5
|
|
309
249
|
})
|
|
310
250
|
});
|
|
311
|
-
|
|
312
|
-
// Strip metadata for privacy
|
|
313
|
-
const clean = await stripExif(photoWithGPS);
|
|
314
251
|
```
|
|
315
252
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
---
|
|
319
|
-
|
|
320
|
-
## Documentation
|
|
321
|
-
|
|
322
|
-
<table>
|
|
323
|
-
<tr>
|
|
324
|
-
<td width="50%">
|
|
253
|
+
### HTTP Image Server
|
|
325
254
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
Full documentation with examples, API reference, and guides:
|
|
329
|
-
|
|
330
|
-
**[nexus-aissam.github.io/bun-image-turbo](https://nexus-aissam.github.io/bun-image-turbo/)**
|
|
331
|
-
|
|
332
|
-
- [Getting Started](https://nexus-aissam.github.io/bun-image-turbo/guide/)
|
|
333
|
-
- [API Reference](https://nexus-aissam.github.io/bun-image-turbo/api/)
|
|
334
|
-
- [Examples](https://nexus-aissam.github.io/bun-image-turbo/examples/)
|
|
335
|
-
- [Architecture](https://nexus-aissam.github.io/bun-image-turbo/guide/architecture)
|
|
336
|
-
- [Performance](https://nexus-aissam.github.io/bun-image-turbo/guide/performance)
|
|
255
|
+
```typescript
|
|
256
|
+
import { resize, toWebp, metadata } from 'bun-image-turbo';
|
|
337
257
|
|
|
338
|
-
|
|
339
|
-
|
|
258
|
+
Bun.serve({
|
|
259
|
+
port: 3000,
|
|
260
|
+
async fetch(req) {
|
|
261
|
+
const url = new URL(req.url);
|
|
340
262
|
|
|
341
|
-
|
|
263
|
+
if (url.pathname === '/resize') {
|
|
264
|
+
const imageUrl = url.searchParams.get('url');
|
|
265
|
+
const width = parseInt(url.searchParams.get('w') || '400');
|
|
342
266
|
|
|
343
|
-
|
|
267
|
+
const response = await fetch(imageUrl!);
|
|
268
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
344
269
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
- [Examples](./docs/examples/)
|
|
270
|
+
const resized = await resize(buffer, { width });
|
|
271
|
+
const webp = await toWebp(resized, { quality: 85 });
|
|
348
272
|
|
|
349
|
-
|
|
273
|
+
return new Response(webp, {
|
|
274
|
+
headers: { 'Content-Type': 'image/webp' }
|
|
275
|
+
});
|
|
276
|
+
}
|
|
350
277
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
bun run docs:dev
|
|
278
|
+
return new Response('Not Found', { status: 404 });
|
|
279
|
+
}
|
|
280
|
+
});
|
|
355
281
|
```
|
|
356
282
|
|
|
357
|
-
</td>
|
|
358
|
-
</tr>
|
|
359
|
-
</table>
|
|
360
|
-
|
|
361
283
|
---
|
|
362
284
|
|
|
363
|
-
##
|
|
285
|
+
## Development
|
|
364
286
|
|
|
365
287
|
```bash
|
|
366
|
-
# Clone
|
|
288
|
+
# Clone repository
|
|
367
289
|
git clone https://github.com/nexus-aissam/bun-image-turbo.git
|
|
368
290
|
cd bun-image-turbo
|
|
369
291
|
|
|
@@ -377,44 +299,56 @@ bun run build
|
|
|
377
299
|
bun run build:ts
|
|
378
300
|
|
|
379
301
|
# Run tests
|
|
380
|
-
bun test
|
|
302
|
+
bun run test # Local tests
|
|
303
|
+
bun run test:packages # Package manager tests
|
|
304
|
+
bun run test:all # All tests
|
|
381
305
|
```
|
|
382
306
|
|
|
383
307
|
### Requirements
|
|
384
308
|
|
|
385
|
-
- Bun 1.0+ or Node.js 18+
|
|
386
|
-
- Rust 1.70+ (for building from source)
|
|
309
|
+
- **Runtime:** Bun 1.0+ or Node.js 18+
|
|
310
|
+
- **Build:** Rust 1.70+ (only for building from source)
|
|
387
311
|
|
|
388
312
|
---
|
|
389
313
|
|
|
390
|
-
##
|
|
314
|
+
## Documentation
|
|
391
315
|
|
|
392
|
-
|
|
316
|
+
- **[Full Documentation](https://nexus-aissam.github.io/bun-image-turbo/)** — Complete guide with examples
|
|
317
|
+
- **[API Reference](https://nexus-aissam.github.io/bun-image-turbo/api/)** — Detailed function documentation
|
|
318
|
+
- **[Examples](https://nexus-aissam.github.io/bun-image-turbo/examples/)** — Code samples
|
|
319
|
+
- **[Performance Guide](https://nexus-aissam.github.io/bun-image-turbo/guide/performance)** — Optimization tips
|
|
320
|
+
- **[Architecture](https://nexus-aissam.github.io/bun-image-turbo/guide/architecture)** — Technical deep dive
|
|
321
|
+
- **[Changelog](https://nexus-aissam.github.io/bun-image-turbo/changelog)** — Release notes
|
|
393
322
|
|
|
394
323
|
---
|
|
395
324
|
|
|
396
|
-
##
|
|
325
|
+
## Technology Stack
|
|
326
|
+
|
|
327
|
+
| Component | Technology | Benefit |
|
|
328
|
+
|-----------|------------|---------|
|
|
329
|
+
| JPEG Codec | TurboJPEG | SIMD acceleration (SSE2/AVX2/NEON) |
|
|
330
|
+
| Resize Engine | fast_image_resize | Multi-threaded with Rayon |
|
|
331
|
+
| WebP Codec | libwebp | Google's optimized encoder |
|
|
332
|
+
| HEIC Decoder | libheif-rs | Native Apple format support |
|
|
333
|
+
| Node Bindings | napi-rs | Zero-copy buffer handling |
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
337
|
+
## License
|
|
397
338
|
|
|
398
|
-
|
|
339
|
+
MIT License — see [LICENSE](LICENSE) for details.
|
|
399
340
|
|
|
400
341
|
---
|
|
401
342
|
|
|
402
|
-
##
|
|
343
|
+
## Author
|
|
403
344
|
|
|
404
|
-
|
|
405
|
-
- [image](https://crates.io/crates/image) - Rust image processing library
|
|
406
|
-
- [fast_image_resize](https://crates.io/crates/fast_image_resize) - Fast image resizing with Rayon
|
|
407
|
-
- [webp](https://crates.io/crates/webp) - WebP encoding/decoding
|
|
408
|
-
- [libheif-rs](https://crates.io/crates/libheif-rs) - HEIC/HEIF decoding via libheif
|
|
409
|
-
- [img-parts](https://crates.io/crates/img-parts) - EXIF/XMP metadata manipulation
|
|
410
|
-
- [blurhash](https://crates.io/crates/blurhash) - Blurhash generation
|
|
411
|
-
- [napi-rs](https://napi.rs/) - Rust bindings for Node.js
|
|
345
|
+
**Aissam Irhir** — [@nexus-aissam](https://github.com/nexus-aissam)
|
|
412
346
|
|
|
413
347
|
---
|
|
414
348
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
349
|
+
## Links
|
|
350
|
+
|
|
351
|
+
- [npm Package](https://www.npmjs.com/package/bun-image-turbo)
|
|
352
|
+
- [GitHub Repository](https://github.com/nexus-aissam/bun-image-turbo)
|
|
353
|
+
- [Documentation](https://nexus-aissam.github.io/bun-image-turbo/)
|
|
354
|
+
- [Issue Tracker](https://github.com/nexus-aissam/bun-image-turbo/issues)
|
package/dist/index.js
CHANGED
|
@@ -47,7 +47,9 @@ module.exports = __toCommonJS(index_exports);
|
|
|
47
47
|
var import_fs = require("fs");
|
|
48
48
|
var import_path = require("path");
|
|
49
49
|
var import_url = require("url");
|
|
50
|
+
var import_module = require("module");
|
|
50
51
|
var import_meta = {};
|
|
52
|
+
var nativeRequire = typeof import_meta?.url === "string" ? (0, import_module.createRequire)(import_meta.url) : typeof require !== "undefined" ? require : null;
|
|
51
53
|
function getCurrentDir() {
|
|
52
54
|
try {
|
|
53
55
|
return (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
|
|
@@ -93,14 +95,14 @@ function loadNativeBinding() {
|
|
|
93
95
|
for (const modulePath of possiblePaths) {
|
|
94
96
|
try {
|
|
95
97
|
if ((0, import_fs.existsSync)(modulePath)) {
|
|
96
|
-
return
|
|
98
|
+
return nativeRequire(modulePath);
|
|
97
99
|
}
|
|
98
100
|
} catch {
|
|
99
101
|
continue;
|
|
100
102
|
}
|
|
101
103
|
}
|
|
102
104
|
try {
|
|
103
|
-
return
|
|
105
|
+
return nativeRequire(optionalPackageName);
|
|
104
106
|
} catch {
|
|
105
107
|
}
|
|
106
108
|
throw new Error(
|
package/dist/index.mjs
CHANGED
|
@@ -9,6 +9,8 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
|
|
|
9
9
|
import { existsSync } from "fs";
|
|
10
10
|
import { join, dirname } from "path";
|
|
11
11
|
import { fileURLToPath } from "url";
|
|
12
|
+
import { createRequire } from "module";
|
|
13
|
+
var nativeRequire = typeof import.meta?.url === "string" ? createRequire(import.meta.url) : typeof __require !== "undefined" ? __require : null;
|
|
12
14
|
function getCurrentDir() {
|
|
13
15
|
try {
|
|
14
16
|
return dirname(fileURLToPath(import.meta.url));
|
|
@@ -54,14 +56,14 @@ function loadNativeBinding() {
|
|
|
54
56
|
for (const modulePath of possiblePaths) {
|
|
55
57
|
try {
|
|
56
58
|
if (existsSync(modulePath)) {
|
|
57
|
-
return
|
|
59
|
+
return nativeRequire(modulePath);
|
|
58
60
|
}
|
|
59
61
|
} catch {
|
|
60
62
|
continue;
|
|
61
63
|
}
|
|
62
64
|
}
|
|
63
65
|
try {
|
|
64
|
-
return
|
|
66
|
+
return nativeRequire(optionalPackageName);
|
|
65
67
|
} catch {
|
|
66
68
|
}
|
|
67
69
|
throw new Error(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-image-turbo",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.6",
|
|
4
4
|
"author": "Aissam Irhir <aissamirhir@gmail.com>",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -65,13 +65,13 @@
|
|
|
65
65
|
],
|
|
66
66
|
"license": "MIT",
|
|
67
67
|
"optionalDependencies": {
|
|
68
|
-
"bun-image-turbo-darwin-arm64": "1.4.
|
|
69
|
-
"bun-image-turbo-darwin-x64": "1.4.
|
|
70
|
-
"bun-image-turbo-linux-arm64-gnu": "1.4.
|
|
71
|
-
"bun-image-turbo-linux-x64-gnu": "1.4.
|
|
72
|
-
"bun-image-turbo-linux-x64-musl": "1.4.
|
|
73
|
-
"bun-image-turbo-win32-arm64-msvc": "1.4.
|
|
74
|
-
"bun-image-turbo-win32-x64-msvc": "1.4.
|
|
68
|
+
"bun-image-turbo-darwin-arm64": "1.4.6",
|
|
69
|
+
"bun-image-turbo-darwin-x64": "1.4.6",
|
|
70
|
+
"bun-image-turbo-linux-arm64-gnu": "1.4.6",
|
|
71
|
+
"bun-image-turbo-linux-x64-gnu": "1.4.6",
|
|
72
|
+
"bun-image-turbo-linux-x64-musl": "1.4.6",
|
|
73
|
+
"bun-image-turbo-win32-arm64-msvc": "1.4.6",
|
|
74
|
+
"bun-image-turbo-win32-x64-msvc": "1.4.6"
|
|
75
75
|
},
|
|
76
76
|
"napi": {
|
|
77
77
|
"name": "image-turbo",
|
|
@@ -94,7 +94,14 @@
|
|
|
94
94
|
"build:all": "bun run build && bun run build:ts",
|
|
95
95
|
"artifacts": "napi artifacts",
|
|
96
96
|
"version": "napi version",
|
|
97
|
-
"test": "bun test",
|
|
97
|
+
"test": "bun test test/local",
|
|
98
|
+
"test:local": "bun test test/local",
|
|
99
|
+
"test:bun": "cd test/packages/bun && bun install && bun test",
|
|
100
|
+
"test:npm": "cd test/packages/npm && npm install && npm test",
|
|
101
|
+
"test:yarn": "cd test/packages/yarn && yarn install && yarn test",
|
|
102
|
+
"test:pnpm": "cd test/packages/pnpm && pnpm install && pnpm test",
|
|
103
|
+
"test:packages": "bun run test:bun && bun run test:npm && bun run test:yarn && bun run test:pnpm",
|
|
104
|
+
"test:all": "bun run test:local && bun run test:packages",
|
|
98
105
|
"bench": "bun run benchmarks/bench.ts",
|
|
99
106
|
"lint": "eslint src",
|
|
100
107
|
"clean": "rm -rf dist *.node npm"
|