bun-image-turbo 1.0.4 → 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 +63 -49
- package/dist/index.d.mts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +15 -5
- package/dist/index.mjs +15 -5
- package/package.json +12 -9
package/README.md
CHANGED
|
@@ -12,7 +12,8 @@ High-performance image processing for Bun and Node.js, built with Rust and napi-
|
|
|
12
12
|
## Features
|
|
13
13
|
|
|
14
14
|
- **Fast** - Built with Rust for maximum performance
|
|
15
|
-
- **Modern Formats** - JPEG, PNG, WebP, GIF, BMP support
|
|
15
|
+
- **Modern Formats** - JPEG, PNG, WebP, GIF, BMP, **HEIC/HEIF** support
|
|
16
|
+
- **HEIC Support** - Read iPhone photos and HEIC/HEIF files natively
|
|
16
17
|
- **Resize** - High-quality resizing with multiple algorithms (Lanczos3, Mitchell, etc.)
|
|
17
18
|
- **Transform** - Rotate, flip, blur, sharpen, grayscale, brightness, contrast
|
|
18
19
|
- **Blurhash** - Generate compact image placeholders
|
|
@@ -26,55 +27,60 @@ Tested on Apple M1 Pro with Bun 1.3.3 (compared to sharp v0.34.5):
|
|
|
26
27
|
|
|
27
28
|
### Performance Summary
|
|
28
29
|
|
|
30
|
+
```text
|
|
31
|
+
┌──────────────────────────────────────────────────────────────────────────────┐
|
|
32
|
+
│ bun-image-turbo vs sharp Performance │
|
|
33
|
+
├──────────────────────────────────────────────────────────────────────────────┤
|
|
34
|
+
│ WebP Metadata ████████████████████████████████████ 950x faster │
|
|
35
|
+
│ JPEG Metadata ████████████████████████████████████ 38x faster │
|
|
36
|
+
│ Concurrent (50 ops) ██████████████████████████ 2.6x faster │
|
|
37
|
+
│ Transform Pipeline ████████████████████ 1.6x faster │
|
|
38
|
+
│ Thumbnail Resize ████████████████ 1.2x faster │
|
|
39
|
+
│ HEIC Support ████████████████████ EXCLUSIVE N/A in sharp │
|
|
40
|
+
│ Blurhash Generation ████████████████████ EXCLUSIVE N/A in sharp │
|
|
41
|
+
└──────────────────────────────────────────────────────────────────────────────┘
|
|
29
42
|
```
|
|
30
|
-
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
31
|
-
│ bun-image-turbo vs sharp Performance │
|
|
32
|
-
├─────────────────────────────────────────────────────────────────────────────┤
|
|
33
|
-
│ Metadata Extraction ████████████████████████████████████ 36x faster │
|
|
34
|
-
│ Transform Pipeline ████████████████████ 3.4x faster │
|
|
35
|
-
│ Concurrent (50 ops) ██████████████████████████ 4.5x faster │
|
|
36
|
-
│ JPEG Encode ██████████████ 1.9x faster │
|
|
37
|
-
│ Thumbnail Resize ████████████ 1.9x faster │
|
|
38
|
-
│ Blurhash Generation ████████████████████ (4,283 ops/sec) N/A in sharp │
|
|
39
|
-
└─────────────────────────────────────────────────────────────────────────────┘
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### Detailed Benchmarks (ops/sec - higher is better)
|
|
43
|
-
|
|
44
|
-
| Operation | bun-image-turbo | sharp | Winner |
|
|
45
|
-
|-----------|---------------:|------:|:------:|
|
|
46
|
-
| **Metadata Extraction** | 350,000 ops/sec | 9,600 ops/sec | **36x faster** |
|
|
47
|
-
| **Transform Pipeline** | 454 ops/sec | 134 ops/sec | **3.4x faster** |
|
|
48
|
-
| **JPEG Encode** | 553 ops/sec | 287 ops/sec | **1.9x faster** |
|
|
49
|
-
| **Thumbnail (200px)** | 386 ops/sec | 201 ops/sec | **1.9x faster** |
|
|
50
|
-
| **PNG Encode** | 235 ops/sec | 221 ops/sec | **1.06x faster** |
|
|
51
|
-
| **Blurhash** | 4,283 ops/sec | N/A | - |
|
|
52
43
|
|
|
53
|
-
###
|
|
54
|
-
|
|
55
|
-
| Concurrency | bun-image-turbo | sharp | Throughput |
|
|
56
|
-
|------------:|----------------:|------:|:----------:|
|
|
57
|
-
| 50 parallel | 30ms total | 137ms total | **4.5x faster** |
|
|
58
|
-
| **Ops/sec** | **1,653 ops/sec** | 364 ops/sec | - |
|
|
59
|
-
|
|
60
|
-
### Real-World File Tests
|
|
44
|
+
### Detailed Benchmarks
|
|
61
45
|
|
|
62
46
|
| Operation | bun-image-turbo | sharp | Speedup |
|
|
63
47
|
|-----------|---------------:|------:|:-------:|
|
|
64
|
-
|
|
|
65
|
-
|
|
|
66
|
-
|
|
|
48
|
+
| **10MB WebP Metadata** | 0.004ms | 3.4ms | **950x faster** |
|
|
49
|
+
| **10MB JPEG Metadata** | 0.003ms | 0.1ms | **38x faster** |
|
|
50
|
+
| **1MB JPEG Metadata** | 0.003ms | 0.1ms | **30x faster** |
|
|
51
|
+
| **50 Concurrent Ops** | 62ms | 160ms | **2.6x faster** |
|
|
52
|
+
| **Transform Pipeline** | 12.2ms | 19.1ms | **1.6x faster** |
|
|
53
|
+
| **1MB JPEG → 800px** | 12.6ms | 20.3ms | **1.6x faster** |
|
|
54
|
+
| **1MB JPEG → WebP** | 36.4ms | 46.1ms | **1.3x faster** |
|
|
55
|
+
| **Thumbnail (200px)** | 8.8ms | 10.7ms | **1.2x faster** |
|
|
56
|
+
|
|
57
|
+
### HEIC/HEIF Support (Exclusive)
|
|
58
|
+
|
|
59
|
+
bun-image-turbo is the **only** high-performance image library with native HEIC support:
|
|
60
|
+
|
|
61
|
+
| Operation | Time | Notes |
|
|
62
|
+
|-----------|-----:|:------|
|
|
63
|
+
| **HEIC Metadata** | 0.1ms | Instant metadata extraction |
|
|
64
|
+
| **HEIC → JPEG** | 169ms | Full quality conversion |
|
|
65
|
+
| **HEIC → 800px JPEG** | 138ms | Optimized shrink-on-decode |
|
|
66
|
+
| **HEIC → 200px thumbnail** | 137ms | Fast thumbnail generation |
|
|
67
|
+
| **HEIC → WebP** | 798ms | Modern format conversion |
|
|
68
|
+
| **HEIC Blurhash** | 301ms | Placeholder generation |
|
|
69
|
+
|
|
70
|
+
> sharp does **NOT** support HEIC/HEIF files!
|
|
67
71
|
|
|
68
72
|
### Key Strengths
|
|
69
73
|
|
|
70
|
-
- **
|
|
71
|
-
- **
|
|
72
|
-
- **
|
|
73
|
-
- **1.
|
|
74
|
-
-
|
|
74
|
+
- **950x faster** WebP metadata extraction
|
|
75
|
+
- **38x faster** JPEG metadata (header-only parsing)
|
|
76
|
+
- **2.6x faster** under concurrent load (server workloads)
|
|
77
|
+
- **1.6x faster** transform pipelines (resize + rotate + grayscale)
|
|
78
|
+
- **Native HEIC/HEIF support** - Read iPhone photos directly
|
|
79
|
+
- **Shrink-on-decode** optimization for JPEG and HEIC
|
|
80
|
+
- Built-in **Blurhash** generation
|
|
75
81
|
- Zero-copy buffer handling with Rust
|
|
76
82
|
|
|
77
|
-
> Run benchmarks yourself: `bun run
|
|
83
|
+
> Run benchmarks yourself: `bun run benchmarks/final_comparison.ts`
|
|
78
84
|
|
|
79
85
|
## Installation
|
|
80
86
|
|
|
@@ -121,6 +127,11 @@ const result = await transform(buffer, {
|
|
|
121
127
|
|
|
122
128
|
// Save result
|
|
123
129
|
await Bun.write('output.webp', result);
|
|
130
|
+
|
|
131
|
+
// Convert HEIC (iPhone photo) to JPEG
|
|
132
|
+
const heicInput = await Bun.file('photo.heic').arrayBuffer();
|
|
133
|
+
const jpeg = await toJpeg(Buffer.from(heicInput), { quality: 90 });
|
|
134
|
+
await Bun.write('photo.jpg', jpeg);
|
|
124
135
|
```
|
|
125
136
|
|
|
126
137
|
## API Reference
|
|
@@ -274,15 +285,17 @@ console.log(version()); // "1.0.0"
|
|
|
274
285
|
|
|
275
286
|
## Supported Formats
|
|
276
287
|
|
|
277
|
-
| Format | Read | Write |
|
|
278
|
-
|
|
279
|
-
| JPEG | Yes | Yes |
|
|
280
|
-
| PNG | Yes | Yes |
|
|
281
|
-
| WebP | Yes | Yes |
|
|
282
|
-
|
|
|
283
|
-
|
|
|
284
|
-
|
|
|
285
|
-
|
|
|
288
|
+
| Format | Read | Write | Notes |
|
|
289
|
+
|--------|------|-------|-------|
|
|
290
|
+
| JPEG | Yes | Yes | TurboJPEG with SIMD |
|
|
291
|
+
| PNG | Yes | Yes | Adaptive compression |
|
|
292
|
+
| WebP | Yes | Yes | Lossy & lossless |
|
|
293
|
+
| HEIC/HEIF | Yes | No | iPhone photos, via libheif |
|
|
294
|
+
| AVIF | Yes | No | Via libheif |
|
|
295
|
+
| GIF | Yes | Yes | Animated support |
|
|
296
|
+
| BMP | Yes | Yes | - |
|
|
297
|
+
| ICO | Yes | No | Multi-size icons |
|
|
298
|
+
| TIFF | Yes | No | Multi-page support |
|
|
286
299
|
|
|
287
300
|
## Supported Platforms
|
|
288
301
|
|
|
@@ -335,5 +348,6 @@ Aissam Irhir ([@nexus-aissam](https://github.com/nexus-aissam))
|
|
|
335
348
|
- [image](https://crates.io/crates/image) - Rust image processing library
|
|
336
349
|
- [fast_image_resize](https://crates.io/crates/fast_image_resize) - Fast image resizing
|
|
337
350
|
- [webp](https://crates.io/crates/webp) - WebP encoding/decoding
|
|
351
|
+
- [libheif-rs](https://crates.io/crates/libheif-rs) - HEIC/HEIF decoding via libheif
|
|
338
352
|
- [blurhash](https://crates.io/crates/blurhash) - Blurhash generation
|
|
339
353
|
- [napi-rs](https://napi.rs/) - Rust bindings for Node.js
|
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* bun-image-turbo Types
|
|
3
3
|
*/
|
|
4
4
|
/** Supported image formats */
|
|
5
|
-
type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'ico' | 'tiff' | 'avif';
|
|
5
|
+
type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'ico' | 'tiff' | 'heic' | 'avif';
|
|
6
6
|
/** Resize filter/algorithm */
|
|
7
7
|
type ResizeFilter = 'nearest' | 'bilinear' | 'catmullRom' | 'mitchell' | 'lanczos3';
|
|
8
8
|
/** Image fit mode for resize */
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* bun-image-turbo Types
|
|
3
3
|
*/
|
|
4
4
|
/** Supported image formats */
|
|
5
|
-
type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'ico' | 'tiff' | 'avif';
|
|
5
|
+
type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'ico' | 'tiff' | 'heic' | 'avif';
|
|
6
6
|
/** Resize filter/algorithm */
|
|
7
7
|
type ResizeFilter = 'nearest' | 'bilinear' | 'catmullRom' | 'mitchell' | 'lanczos3';
|
|
8
8
|
/** Image fit mode for resize */
|
package/dist/index.js
CHANGED
|
@@ -66,19 +66,23 @@ function loadNativeBinding() {
|
|
|
66
66
|
}
|
|
67
67
|
break;
|
|
68
68
|
case "win32":
|
|
69
|
-
targetName = "win32-x64-msvc";
|
|
69
|
+
targetName = arch === "arm64" ? "win32-arm64-msvc" : "win32-x64-msvc";
|
|
70
70
|
break;
|
|
71
71
|
default:
|
|
72
72
|
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
|
73
73
|
}
|
|
74
74
|
const currentDir = getCurrentDir();
|
|
75
|
+
const binaryName = `image-turbo.${targetName}.node`;
|
|
76
|
+
const optionalPackageName = `bun-image-turbo-${targetName}`;
|
|
75
77
|
const possiblePaths = [
|
|
76
78
|
// Same directory as this file (dist/)
|
|
77
|
-
(0, import_path.join)(currentDir,
|
|
79
|
+
(0, import_path.join)(currentDir, binaryName),
|
|
78
80
|
// Parent directory (package root)
|
|
79
|
-
(0, import_path.join)(currentDir, "..",
|
|
81
|
+
(0, import_path.join)(currentDir, "..", binaryName),
|
|
82
|
+
// Optional dependency package (installed in node_modules)
|
|
83
|
+
(0, import_path.join)(currentDir, "..", "..", optionalPackageName, binaryName),
|
|
80
84
|
// CWD (development)
|
|
81
|
-
(0, import_path.join)(process.cwd(),
|
|
85
|
+
(0, import_path.join)(process.cwd(), binaryName)
|
|
82
86
|
];
|
|
83
87
|
for (const modulePath of possiblePaths) {
|
|
84
88
|
try {
|
|
@@ -89,6 +93,10 @@ function loadNativeBinding() {
|
|
|
89
93
|
continue;
|
|
90
94
|
}
|
|
91
95
|
}
|
|
96
|
+
try {
|
|
97
|
+
return require(optionalPackageName);
|
|
98
|
+
} catch {
|
|
99
|
+
}
|
|
92
100
|
throw new Error(
|
|
93
101
|
`Failed to load native binding for ${platform}-${arch}. Tried: ${possiblePaths.join(", ")}`
|
|
94
102
|
);
|
|
@@ -119,7 +127,9 @@ function toNapiFormat(format) {
|
|
|
119
127
|
gif: "Gif",
|
|
120
128
|
bmp: "Bmp",
|
|
121
129
|
ico: "Ico",
|
|
122
|
-
tiff: "Tiff"
|
|
130
|
+
tiff: "Tiff",
|
|
131
|
+
heic: "Heic",
|
|
132
|
+
avif: "Avif"
|
|
123
133
|
};
|
|
124
134
|
return formatMap[format.toLowerCase()] || format;
|
|
125
135
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -33,19 +33,23 @@ function loadNativeBinding() {
|
|
|
33
33
|
}
|
|
34
34
|
break;
|
|
35
35
|
case "win32":
|
|
36
|
-
targetName = "win32-x64-msvc";
|
|
36
|
+
targetName = arch === "arm64" ? "win32-arm64-msvc" : "win32-x64-msvc";
|
|
37
37
|
break;
|
|
38
38
|
default:
|
|
39
39
|
throw new Error(`Unsupported platform: ${platform}-${arch}`);
|
|
40
40
|
}
|
|
41
41
|
const currentDir = getCurrentDir();
|
|
42
|
+
const binaryName = `image-turbo.${targetName}.node`;
|
|
43
|
+
const optionalPackageName = `bun-image-turbo-${targetName}`;
|
|
42
44
|
const possiblePaths = [
|
|
43
45
|
// Same directory as this file (dist/)
|
|
44
|
-
join(currentDir,
|
|
46
|
+
join(currentDir, binaryName),
|
|
45
47
|
// Parent directory (package root)
|
|
46
|
-
join(currentDir, "..",
|
|
48
|
+
join(currentDir, "..", binaryName),
|
|
49
|
+
// Optional dependency package (installed in node_modules)
|
|
50
|
+
join(currentDir, "..", "..", optionalPackageName, binaryName),
|
|
47
51
|
// CWD (development)
|
|
48
|
-
join(process.cwd(),
|
|
52
|
+
join(process.cwd(), binaryName)
|
|
49
53
|
];
|
|
50
54
|
for (const modulePath of possiblePaths) {
|
|
51
55
|
try {
|
|
@@ -56,6 +60,10 @@ function loadNativeBinding() {
|
|
|
56
60
|
continue;
|
|
57
61
|
}
|
|
58
62
|
}
|
|
63
|
+
try {
|
|
64
|
+
return __require(optionalPackageName);
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
59
67
|
throw new Error(
|
|
60
68
|
`Failed to load native binding for ${platform}-${arch}. Tried: ${possiblePaths.join(", ")}`
|
|
61
69
|
);
|
|
@@ -86,7 +94,9 @@ function toNapiFormat(format) {
|
|
|
86
94
|
gif: "Gif",
|
|
87
95
|
bmp: "Bmp",
|
|
88
96
|
ico: "Ico",
|
|
89
|
-
tiff: "Tiff"
|
|
97
|
+
tiff: "Tiff",
|
|
98
|
+
heic: "Heic",
|
|
99
|
+
avif: "Avif"
|
|
90
100
|
};
|
|
91
101
|
return formatMap[format.toLowerCase()] || format;
|
|
92
102
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bun-image-turbo",
|
|
3
|
-
"version": "1.0
|
|
4
|
-
"description": "High-performance image processing for Bun and Node.js - resize, convert, compress with WebP, AVIF, PNG, JPEG support",
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "High-performance image processing for Bun and Node.js - resize, convert, compress with HEIC, WebP, AVIF, PNG, JPEG support",
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
7
7
|
"types": "./dist/index.d.ts",
|
|
@@ -50,12 +50,15 @@
|
|
|
50
50
|
"image",
|
|
51
51
|
"resize",
|
|
52
52
|
"compress",
|
|
53
|
+
"heic",
|
|
54
|
+
"heif",
|
|
53
55
|
"webp",
|
|
54
56
|
"avif",
|
|
55
57
|
"png",
|
|
56
58
|
"jpeg",
|
|
57
59
|
"jpg",
|
|
58
60
|
"gif",
|
|
61
|
+
"iphone",
|
|
59
62
|
"thumbnail",
|
|
60
63
|
"crop",
|
|
61
64
|
"convert",
|
|
@@ -89,12 +92,12 @@
|
|
|
89
92
|
"typescript": "^5.9.0"
|
|
90
93
|
},
|
|
91
94
|
"optionalDependencies": {
|
|
92
|
-
"bun-image-turbo-darwin-arm64": "1.0
|
|
93
|
-
"bun-image-turbo-darwin-x64": "1.0
|
|
94
|
-
"bun-image-turbo-linux-arm64-gnu": "1.0
|
|
95
|
-
"bun-image-turbo-linux-x64-gnu": "1.0
|
|
96
|
-
"bun-image-turbo-linux-x64-musl": "1.0
|
|
97
|
-
"bun-image-turbo-win32-arm64-msvc": "1.0
|
|
98
|
-
"bun-image-turbo-win32-x64-msvc": "1.0
|
|
95
|
+
"bun-image-turbo-darwin-arm64": "1.2.0",
|
|
96
|
+
"bun-image-turbo-darwin-x64": "1.2.0",
|
|
97
|
+
"bun-image-turbo-linux-arm64-gnu": "1.2.0",
|
|
98
|
+
"bun-image-turbo-linux-x64-gnu": "1.2.0",
|
|
99
|
+
"bun-image-turbo-linux-x64-musl": "1.2.0",
|
|
100
|
+
"bun-image-turbo-win32-arm64-msvc": "1.2.0",
|
|
101
|
+
"bun-image-turbo-win32-x64-msvc": "1.2.0"
|
|
99
102
|
}
|
|
100
103
|
}
|