bun-image-turbo 0.0.2-beta
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 +328 -0
- package/dist/index.d.mts +327 -0
- package/dist/index.d.ts +327 -0
- package/dist/index.js +228 -0
- package/dist/index.mjs +195 -0
- package/package.json +95 -0
package/README.md
ADDED
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# bun-image-turbo
|
|
2
|
+
|
|
3
|
+
High-performance image processing for Bun and Node.js, built with Rust and napi-rs.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/bun-image-turbo)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
7
|
+
|
|
8
|
+
## Features
|
|
9
|
+
|
|
10
|
+
- **Fast** - Built with Rust for maximum performance
|
|
11
|
+
- **Modern Formats** - JPEG, PNG, WebP, GIF, BMP support
|
|
12
|
+
- **Resize** - High-quality resizing with multiple algorithms (Lanczos3, Mitchell, etc.)
|
|
13
|
+
- **Transform** - Rotate, flip, blur, sharpen, grayscale, brightness, contrast
|
|
14
|
+
- **Blurhash** - Generate compact image placeholders
|
|
15
|
+
- **Async & Sync** - Both async and sync APIs available
|
|
16
|
+
- **TypeScript** - Full TypeScript support with strict types
|
|
17
|
+
- **Cross-platform** - macOS, Linux, Windows support
|
|
18
|
+
|
|
19
|
+
## Benchmarks
|
|
20
|
+
|
|
21
|
+
Tested on Apple M1 Pro with Bun 1.3.3 (compared to sharp v0.34.5):
|
|
22
|
+
|
|
23
|
+
### Metadata Extraction
|
|
24
|
+
| Operation | bun-image-turbo | sharp | Speedup |
|
|
25
|
+
|-----------|-----------------|-------|---------|
|
|
26
|
+
| 1MB JPEG Metadata | 0.003ms | 0.1ms | **38x faster** |
|
|
27
|
+
| 10MB JPEG Metadata | 0.003ms | 0.1ms | **37x faster** |
|
|
28
|
+
| 10MB WebP Metadata | 0.003ms | 3.0ms | **950x faster** |
|
|
29
|
+
|
|
30
|
+
### JPEG Resize (Real-world thumbnail generation)
|
|
31
|
+
| Operation | bun-image-turbo | sharp | Speedup |
|
|
32
|
+
|-----------|-----------------|-------|---------|
|
|
33
|
+
| 1MB JPEG → 800px | 12.4ms | 20.0ms | **1.61x faster** |
|
|
34
|
+
| 1MB JPEG → 400px | 9.9ms | 12.3ms | **1.24x faster** |
|
|
35
|
+
| 1MB JPEG → 200px | 8.7ms | 10.5ms | **1.20x faster** |
|
|
36
|
+
| 10MB JPEG → 800px | 96.9ms | 102.5ms | **1.06x faster** |
|
|
37
|
+
|
|
38
|
+
### Format Conversion
|
|
39
|
+
| Operation | bun-image-turbo | sharp | Speedup |
|
|
40
|
+
|-----------|-----------------|-------|---------|
|
|
41
|
+
| 1MB JPEG → WebP | 37.1ms | 45.8ms | **1.23x faster** |
|
|
42
|
+
| 10MB JPEG → WebP | 114.9ms | 119.3ms | **1.04x faster** |
|
|
43
|
+
|
|
44
|
+
### Complex Transform Pipeline
|
|
45
|
+
| Operation | bun-image-turbo | sharp | Speedup |
|
|
46
|
+
|-----------|-----------------|-------|---------|
|
|
47
|
+
| Resize + Grayscale | 11.9ms | 18.1ms | **1.53x faster** |
|
|
48
|
+
| Resize + Rotate + Grayscale | 12.3ms | 19.3ms | **1.57x faster** |
|
|
49
|
+
|
|
50
|
+
### Concurrent Operations (High Load)
|
|
51
|
+
| Concurrency | bun-image-turbo | sharp | Speedup |
|
|
52
|
+
|-------------|-----------------|-------|---------|
|
|
53
|
+
| 10 parallel | 16ms | 30ms | **1.85x faster** |
|
|
54
|
+
| 25 parallel | 42ms | 82ms | **1.96x faster** |
|
|
55
|
+
| 50 parallel | 67ms | 156ms | **2.33x faster** |
|
|
56
|
+
| 100 parallel | 129ms | 303ms | **2.34x faster** |
|
|
57
|
+
|
|
58
|
+
**Key Strengths:**
|
|
59
|
+
- **950x faster** metadata extraction (header-only parsing)
|
|
60
|
+
- **2.3x faster** under concurrent load
|
|
61
|
+
- **1.6x faster** for thumbnail generation
|
|
62
|
+
- **1.5x faster** for transform pipelines
|
|
63
|
+
- Built-in **blurhash** generation
|
|
64
|
+
- Uses **TurboJPEG** (libjpeg-turbo) with SIMD acceleration
|
|
65
|
+
|
|
66
|
+
> Run benchmarks yourself: `bun run benchmarks/final_comparison.ts`
|
|
67
|
+
|
|
68
|
+
## Installation
|
|
69
|
+
|
|
70
|
+
```bash
|
|
71
|
+
# Using Bun (recommended)
|
|
72
|
+
bun add bun-image-turbo
|
|
73
|
+
|
|
74
|
+
# Using npm
|
|
75
|
+
npm install bun-image-turbo
|
|
76
|
+
|
|
77
|
+
# Using yarn
|
|
78
|
+
yarn add bun-image-turbo
|
|
79
|
+
|
|
80
|
+
# Using pnpm
|
|
81
|
+
pnpm add bun-image-turbo
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Quick Start
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
import { resize, toWebp, metadata, transform } from 'bun-image-turbo';
|
|
88
|
+
|
|
89
|
+
// Read image
|
|
90
|
+
const input = await Bun.file('input.jpg').arrayBuffer();
|
|
91
|
+
const buffer = Buffer.from(input);
|
|
92
|
+
|
|
93
|
+
// Get metadata
|
|
94
|
+
const info = await metadata(buffer);
|
|
95
|
+
console.log(`${info.width}x${info.height} ${info.format}`);
|
|
96
|
+
|
|
97
|
+
// Resize image
|
|
98
|
+
const resized = await resize(buffer, { width: 800 });
|
|
99
|
+
|
|
100
|
+
// Convert to WebP
|
|
101
|
+
const webp = await toWebp(buffer, { quality: 85 });
|
|
102
|
+
|
|
103
|
+
// Apply multiple transformations
|
|
104
|
+
const result = await transform(buffer, {
|
|
105
|
+
resize: { width: 400, height: 300 },
|
|
106
|
+
rotate: 90,
|
|
107
|
+
grayscale: true,
|
|
108
|
+
output: { format: 'webp', webp: { quality: 80 } }
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
// Save result
|
|
112
|
+
await Bun.write('output.webp', result);
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
## API Reference
|
|
116
|
+
|
|
117
|
+
### `metadata(input)` / `metadataSync(input)`
|
|
118
|
+
|
|
119
|
+
Get image metadata.
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
const info = await metadata(imageBuffer);
|
|
123
|
+
// { width: 1920, height: 1080, format: 'jpeg', hasAlpha: false, ... }
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### `resize(input, options)` / `resizeSync(input, options)`
|
|
127
|
+
|
|
128
|
+
Resize an image.
|
|
129
|
+
|
|
130
|
+
```typescript
|
|
131
|
+
// Resize by width (maintains aspect ratio)
|
|
132
|
+
const resized = await resize(imageBuffer, { width: 800 });
|
|
133
|
+
|
|
134
|
+
// Resize by height
|
|
135
|
+
const resized = await resize(imageBuffer, { height: 600 });
|
|
136
|
+
|
|
137
|
+
// Resize with specific dimensions
|
|
138
|
+
const resized = await resize(imageBuffer, {
|
|
139
|
+
width: 800,
|
|
140
|
+
height: 600,
|
|
141
|
+
fit: 'cover', // 'cover' | 'contain' | 'fill' | 'inside' | 'outside'
|
|
142
|
+
filter: 'lanczos3' // 'nearest' | 'bilinear' | 'catmullRom' | 'mitchell' | 'lanczos3'
|
|
143
|
+
});
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
### `toJpeg(input, options?)` / `toJpegSync(input, options?)`
|
|
147
|
+
|
|
148
|
+
Convert to JPEG.
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
const jpeg = await toJpeg(imageBuffer, { quality: 85 });
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
### `toPng(input, options?)` / `toPngSync(input, options?)`
|
|
155
|
+
|
|
156
|
+
Convert to PNG.
|
|
157
|
+
|
|
158
|
+
```typescript
|
|
159
|
+
const png = await toPng(imageBuffer, { compression: 6 });
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### `toWebp(input, options?)` / `toWebpSync(input, options?)`
|
|
163
|
+
|
|
164
|
+
Convert to WebP.
|
|
165
|
+
|
|
166
|
+
```typescript
|
|
167
|
+
// Lossy WebP
|
|
168
|
+
const webp = await toWebp(imageBuffer, { quality: 80 });
|
|
169
|
+
|
|
170
|
+
// Lossless WebP
|
|
171
|
+
const lossless = await toWebp(imageBuffer, { lossless: true });
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### `transform(input, options)` / `transformSync(input, options)`
|
|
175
|
+
|
|
176
|
+
Apply multiple transformations in a single operation (most efficient).
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
const result = await transform(imageBuffer, {
|
|
180
|
+
// Resize
|
|
181
|
+
resize: { width: 800, height: 600, fit: 'cover' },
|
|
182
|
+
|
|
183
|
+
// Transformations
|
|
184
|
+
rotate: 90, // 90, 180, or 270 degrees
|
|
185
|
+
flipH: true, // Flip horizontally
|
|
186
|
+
flipV: false, // Flip vertically
|
|
187
|
+
grayscale: true, // Convert to grayscale
|
|
188
|
+
blur: 5, // Blur radius (0-100)
|
|
189
|
+
sharpen: 10, // Sharpen amount (0-100)
|
|
190
|
+
brightness: 10, // Brightness (-100 to 100)
|
|
191
|
+
contrast: 5, // Contrast (-100 to 100)
|
|
192
|
+
|
|
193
|
+
// Output format
|
|
194
|
+
output: {
|
|
195
|
+
format: 'webp',
|
|
196
|
+
webp: { quality: 85 }
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
### `blurhash(input, componentsX?, componentsY?)` / `blurhashSync(...)`
|
|
202
|
+
|
|
203
|
+
Generate a blurhash placeholder string.
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
const { hash, width, height } = await blurhash(imageBuffer, 4, 3);
|
|
207
|
+
console.log(hash); // "LEHV6nWB2yk8pyo0adR*.7kCMdnj"
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
### `version()`
|
|
211
|
+
|
|
212
|
+
Get library version.
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
console.log(version()); // "1.0.0"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Options
|
|
219
|
+
|
|
220
|
+
### Resize Options
|
|
221
|
+
|
|
222
|
+
| Option | Type | Default | Description |
|
|
223
|
+
|--------|------|---------|-------------|
|
|
224
|
+
| `width` | `number` | - | Target width (optional if height provided) |
|
|
225
|
+
| `height` | `number` | - | Target height (optional if width provided) |
|
|
226
|
+
| `filter` | `string` | `'lanczos3'` | Resize algorithm |
|
|
227
|
+
| `fit` | `string` | `'cover'` | How to fit the image |
|
|
228
|
+
|
|
229
|
+
### Filter Types
|
|
230
|
+
|
|
231
|
+
- `nearest` - Fastest, lowest quality
|
|
232
|
+
- `bilinear` - Fast, good quality
|
|
233
|
+
- `catmullRom` - Balanced speed and quality
|
|
234
|
+
- `mitchell` - Good for downscaling
|
|
235
|
+
- `lanczos3` - Highest quality, slower (default)
|
|
236
|
+
|
|
237
|
+
### Fit Modes
|
|
238
|
+
|
|
239
|
+
- `cover` - Resize to cover target dimensions (may crop)
|
|
240
|
+
- `contain` - Resize to fit within target (may have padding)
|
|
241
|
+
- `fill` - Resize to exact dimensions (may distort)
|
|
242
|
+
- `inside` - Resize only if larger than target
|
|
243
|
+
- `outside` - Resize only if smaller than target
|
|
244
|
+
|
|
245
|
+
### JPEG Options
|
|
246
|
+
|
|
247
|
+
| Option | Type | Default | Description |
|
|
248
|
+
|--------|------|---------|-------------|
|
|
249
|
+
| `quality` | `number` | `80` | Quality 1-100 |
|
|
250
|
+
|
|
251
|
+
### PNG Options
|
|
252
|
+
|
|
253
|
+
| Option | Type | Default | Description |
|
|
254
|
+
|--------|------|---------|-------------|
|
|
255
|
+
| `compression` | `number` | `6` | Compression level 0-9 |
|
|
256
|
+
|
|
257
|
+
### WebP Options
|
|
258
|
+
|
|
259
|
+
| Option | Type | Default | Description |
|
|
260
|
+
|--------|------|---------|-------------|
|
|
261
|
+
| `quality` | `number` | `80` | Quality 1-100 (lossy) |
|
|
262
|
+
| `lossless` | `boolean` | `false` | Use lossless compression |
|
|
263
|
+
|
|
264
|
+
## Supported Formats
|
|
265
|
+
|
|
266
|
+
| Format | Read | Write |
|
|
267
|
+
|--------|------|-------|
|
|
268
|
+
| JPEG | Yes | Yes |
|
|
269
|
+
| PNG | Yes | Yes |
|
|
270
|
+
| WebP | Yes | Yes |
|
|
271
|
+
| GIF | Yes | Yes |
|
|
272
|
+
| BMP | Yes | Yes |
|
|
273
|
+
| ICO | Yes | No |
|
|
274
|
+
| TIFF | Yes | No |
|
|
275
|
+
|
|
276
|
+
## Supported Platforms
|
|
277
|
+
|
|
278
|
+
| Platform | Architecture | Support |
|
|
279
|
+
|----------|--------------|---------|
|
|
280
|
+
| macOS | ARM64 (M1/M2/M3) | Yes |
|
|
281
|
+
| macOS | x64 (Intel) | Yes |
|
|
282
|
+
| Linux | x64 (glibc) | Yes |
|
|
283
|
+
| Linux | x64 (musl/Alpine) | Yes |
|
|
284
|
+
| Linux | ARM64 (glibc) | Yes |
|
|
285
|
+
| Linux | ARM64 (musl) | Yes |
|
|
286
|
+
| Windows | x64 | Yes |
|
|
287
|
+
|
|
288
|
+
## Development
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Clone the repository
|
|
292
|
+
git clone https://github.com/nexus-aissam/bun-image-turbo.git
|
|
293
|
+
cd bun-image-turbo
|
|
294
|
+
|
|
295
|
+
# Install dependencies
|
|
296
|
+
bun install
|
|
297
|
+
|
|
298
|
+
# Build native module (requires Rust)
|
|
299
|
+
bun run build
|
|
300
|
+
|
|
301
|
+
# Build TypeScript
|
|
302
|
+
bun run build:ts
|
|
303
|
+
|
|
304
|
+
# Run tests
|
|
305
|
+
bun test
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
### Requirements
|
|
309
|
+
|
|
310
|
+
- Bun 1.0+ or Node.js 18+
|
|
311
|
+
- Rust 1.70+ (for building from source)
|
|
312
|
+
|
|
313
|
+
## License
|
|
314
|
+
|
|
315
|
+
MIT License - see [LICENSE](LICENSE) for details.
|
|
316
|
+
|
|
317
|
+
## Author
|
|
318
|
+
|
|
319
|
+
Aissam Irhir ([@nexus-aissam](https://github.com/nexus-aissam))
|
|
320
|
+
|
|
321
|
+
## Acknowledgments
|
|
322
|
+
|
|
323
|
+
- [turbojpeg](https://crates.io/crates/turbojpeg) - libjpeg-turbo bindings with SIMD
|
|
324
|
+
- [image](https://crates.io/crates/image) - Rust image processing library
|
|
325
|
+
- [fast_image_resize](https://crates.io/crates/fast_image_resize) - Fast image resizing
|
|
326
|
+
- [webp](https://crates.io/crates/webp) - WebP encoding/decoding
|
|
327
|
+
- [blurhash](https://crates.io/crates/blurhash) - Blurhash generation
|
|
328
|
+
- [napi-rs](https://napi.rs/) - Rust bindings for Node.js
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,327 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bun-image-turbo Types
|
|
3
|
+
*/
|
|
4
|
+
/** Supported image formats */
|
|
5
|
+
type ImageFormat = 'jpeg' | 'png' | 'webp' | 'gif' | 'bmp' | 'ico' | 'tiff' | 'avif';
|
|
6
|
+
/** Resize filter/algorithm */
|
|
7
|
+
type ResizeFilter = 'nearest' | 'bilinear' | 'catmullRom' | 'mitchell' | 'lanczos3';
|
|
8
|
+
/** Image fit mode for resize */
|
|
9
|
+
type FitMode = 'cover' | 'contain' | 'fill' | 'inside' | 'outside';
|
|
10
|
+
/** Resize options */
|
|
11
|
+
interface ResizeOptions {
|
|
12
|
+
/** Target width (optional if height is provided) */
|
|
13
|
+
width?: number;
|
|
14
|
+
/** Target height (optional if width is provided) */
|
|
15
|
+
height?: number;
|
|
16
|
+
/** Resize filter/algorithm (default: lanczos3) */
|
|
17
|
+
filter?: ResizeFilter;
|
|
18
|
+
/** Fit mode (default: cover) */
|
|
19
|
+
fit?: FitMode;
|
|
20
|
+
/** Background color for padding [r, g, b, a] (default: transparent) */
|
|
21
|
+
background?: number[];
|
|
22
|
+
}
|
|
23
|
+
/** JPEG encode options */
|
|
24
|
+
interface JpegOptions {
|
|
25
|
+
/** Quality 1-100 (default: 80) */
|
|
26
|
+
quality?: number;
|
|
27
|
+
}
|
|
28
|
+
/** PNG encode options */
|
|
29
|
+
interface PngOptions {
|
|
30
|
+
/** Compression level 0-9 (default: 6) */
|
|
31
|
+
compression?: number;
|
|
32
|
+
}
|
|
33
|
+
/** WebP encode options */
|
|
34
|
+
interface WebPOptions {
|
|
35
|
+
/** Quality 1-100 for lossy, ignored for lossless (default: 80) */
|
|
36
|
+
quality?: number;
|
|
37
|
+
/** Use lossless compression (default: false) */
|
|
38
|
+
lossless?: boolean;
|
|
39
|
+
}
|
|
40
|
+
/** AVIF encode options */
|
|
41
|
+
interface AvifOptions {
|
|
42
|
+
/** Quality 1-100 (default: 80) */
|
|
43
|
+
quality?: number;
|
|
44
|
+
/** Speed 1-10, higher is faster but lower quality (default: 6) */
|
|
45
|
+
speed?: number;
|
|
46
|
+
}
|
|
47
|
+
/** Output format options */
|
|
48
|
+
interface OutputOptions {
|
|
49
|
+
/** Output format */
|
|
50
|
+
format: ImageFormat;
|
|
51
|
+
/** JPEG options (if format is jpeg) */
|
|
52
|
+
jpeg?: JpegOptions;
|
|
53
|
+
/** PNG options (if format is png) */
|
|
54
|
+
png?: PngOptions;
|
|
55
|
+
/** WebP options (if format is webp) */
|
|
56
|
+
webp?: WebPOptions;
|
|
57
|
+
/** AVIF options (if format is avif) */
|
|
58
|
+
avif?: AvifOptions;
|
|
59
|
+
}
|
|
60
|
+
/** Image metadata (sharp-compatible) */
|
|
61
|
+
interface ImageMetadata {
|
|
62
|
+
/** Image width in pixels */
|
|
63
|
+
width: number;
|
|
64
|
+
/** Image height in pixels */
|
|
65
|
+
height: number;
|
|
66
|
+
/** Detected format (jpeg, png, webp, gif, bmp, ico, tiff) */
|
|
67
|
+
format: string;
|
|
68
|
+
/** File size in bytes */
|
|
69
|
+
size?: number;
|
|
70
|
+
/** Color space (srgb, rgb, grayscale) */
|
|
71
|
+
space: string;
|
|
72
|
+
/** Number of channels (1, 2, 3, or 4) */
|
|
73
|
+
channels: number;
|
|
74
|
+
/** Bit depth per sample (uchar = 8-bit, ushort = 16-bit) */
|
|
75
|
+
depth: string;
|
|
76
|
+
/** Whether the image has an alpha channel */
|
|
77
|
+
hasAlpha: boolean;
|
|
78
|
+
/** Bits per sample */
|
|
79
|
+
bitsPerSample: number;
|
|
80
|
+
/** Whether the image is progressive (JPEG) or interlaced (PNG) */
|
|
81
|
+
isProgressive: boolean;
|
|
82
|
+
/** Whether the image uses palette/indexed colors (PNG/GIF) */
|
|
83
|
+
isPalette: boolean;
|
|
84
|
+
/** Whether the image has an embedded ICC profile */
|
|
85
|
+
hasProfile: boolean;
|
|
86
|
+
/** EXIF orientation value (1-8, if present) */
|
|
87
|
+
orientation?: number;
|
|
88
|
+
/** Page/frame count for multi-page images (GIF, TIFF) */
|
|
89
|
+
pages?: number;
|
|
90
|
+
/** Loop count for animated images */
|
|
91
|
+
loopCount?: number;
|
|
92
|
+
/** Delay between frames in ms (for animated images) */
|
|
93
|
+
delay?: number[];
|
|
94
|
+
/** Background color (for GIF) */
|
|
95
|
+
background?: number[];
|
|
96
|
+
/** Compression type used */
|
|
97
|
+
compression?: string;
|
|
98
|
+
/** Density/DPI info */
|
|
99
|
+
density?: number;
|
|
100
|
+
}
|
|
101
|
+
/** Blurhash result */
|
|
102
|
+
interface BlurHashResult {
|
|
103
|
+
/** The blurhash string */
|
|
104
|
+
hash: string;
|
|
105
|
+
/** Original width */
|
|
106
|
+
width: number;
|
|
107
|
+
/** Original height */
|
|
108
|
+
height: number;
|
|
109
|
+
}
|
|
110
|
+
/** Transform options (all-in-one processing) */
|
|
111
|
+
interface TransformOptions {
|
|
112
|
+
/** Resize options */
|
|
113
|
+
resize?: ResizeOptions;
|
|
114
|
+
/** Output options */
|
|
115
|
+
output?: OutputOptions;
|
|
116
|
+
/** Rotate degrees (90, 180, 270) */
|
|
117
|
+
rotate?: number;
|
|
118
|
+
/** Flip horizontally */
|
|
119
|
+
flipH?: boolean;
|
|
120
|
+
/** Flip vertically */
|
|
121
|
+
flipV?: boolean;
|
|
122
|
+
/** Grayscale conversion */
|
|
123
|
+
grayscale?: boolean;
|
|
124
|
+
/** Blur radius (0-100) */
|
|
125
|
+
blur?: number;
|
|
126
|
+
/** Sharpen amount (0-100) */
|
|
127
|
+
sharpen?: number;
|
|
128
|
+
/** Brightness adjustment (-100 to 100) */
|
|
129
|
+
brightness?: number;
|
|
130
|
+
/** Contrast adjustment (-100 to 100) */
|
|
131
|
+
contrast?: number;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* bun-image-turbo - High-performance image processing for Bun and Node.js
|
|
136
|
+
*
|
|
137
|
+
* @module bun-image-turbo
|
|
138
|
+
* @author Aissam Irhir <aissamirhir@gmail.com>
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* import { resize, toWebp, metadata } from 'bun-image-turbo';
|
|
143
|
+
*
|
|
144
|
+
* // Read image
|
|
145
|
+
* const input = await Bun.file('input.jpg').arrayBuffer();
|
|
146
|
+
*
|
|
147
|
+
* // Resize image
|
|
148
|
+
* const resized = await resize(Buffer.from(input), { width: 800, height: 600 });
|
|
149
|
+
*
|
|
150
|
+
* // Convert to WebP
|
|
151
|
+
* const webp = await toWebp(Buffer.from(input), { quality: 85 });
|
|
152
|
+
*
|
|
153
|
+
* // Get metadata
|
|
154
|
+
* const info = await metadata(Buffer.from(input));
|
|
155
|
+
* console.log(info.width, info.height, info.format);
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Get image metadata asynchronously
|
|
161
|
+
*
|
|
162
|
+
* @param input - Image buffer
|
|
163
|
+
* @returns Promise resolving to image metadata
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ```typescript
|
|
167
|
+
* const info = await metadata(imageBuffer);
|
|
168
|
+
* console.log(`${info.width}x${info.height} ${info.format}`);
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
declare function metadata(input: Buffer): Promise<ImageMetadata>;
|
|
172
|
+
/**
|
|
173
|
+
* Resize image asynchronously
|
|
174
|
+
*
|
|
175
|
+
* @param input - Image buffer
|
|
176
|
+
* @param options - Resize options
|
|
177
|
+
* @returns Promise resolving to resized image buffer (PNG)
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```typescript
|
|
181
|
+
* // Resize to specific dimensions
|
|
182
|
+
* const resized = await resize(imageBuffer, { width: 800, height: 600 });
|
|
183
|
+
*
|
|
184
|
+
* // Resize maintaining aspect ratio
|
|
185
|
+
* const thumb = await resize(imageBuffer, { width: 200 });
|
|
186
|
+
*
|
|
187
|
+
* // High-quality resize
|
|
188
|
+
* const hq = await resize(imageBuffer, {
|
|
189
|
+
* width: 1920,
|
|
190
|
+
* filter: 'lanczos3',
|
|
191
|
+
* fit: 'contain'
|
|
192
|
+
* });
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
declare function resize(input: Buffer, options: ResizeOptions): Promise<Buffer>;
|
|
196
|
+
/**
|
|
197
|
+
* Convert image to JPEG asynchronously
|
|
198
|
+
*
|
|
199
|
+
* @param input - Image buffer
|
|
200
|
+
* @param options - JPEG encoding options
|
|
201
|
+
* @returns Promise resolving to JPEG buffer
|
|
202
|
+
*
|
|
203
|
+
* @example
|
|
204
|
+
* ```typescript
|
|
205
|
+
* const jpeg = await toJpeg(imageBuffer, { quality: 85 });
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
declare function toJpeg(input: Buffer, options?: JpegOptions): Promise<Buffer>;
|
|
209
|
+
/**
|
|
210
|
+
* Convert image to PNG asynchronously
|
|
211
|
+
*
|
|
212
|
+
* @param input - Image buffer
|
|
213
|
+
* @param options - PNG encoding options
|
|
214
|
+
* @returns Promise resolving to PNG buffer
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const png = await toPng(imageBuffer, { compression: 9 });
|
|
219
|
+
* ```
|
|
220
|
+
*/
|
|
221
|
+
declare function toPng(input: Buffer, options?: PngOptions): Promise<Buffer>;
|
|
222
|
+
/**
|
|
223
|
+
* Convert image to WebP asynchronously
|
|
224
|
+
*
|
|
225
|
+
* @param input - Image buffer
|
|
226
|
+
* @param options - WebP encoding options
|
|
227
|
+
* @returns Promise resolving to WebP buffer
|
|
228
|
+
*
|
|
229
|
+
* @example
|
|
230
|
+
* ```typescript
|
|
231
|
+
* // Lossy WebP
|
|
232
|
+
* const webp = await toWebp(imageBuffer, { quality: 80 });
|
|
233
|
+
*
|
|
234
|
+
* // Lossless WebP
|
|
235
|
+
* const lossless = await toWebp(imageBuffer, { lossless: true });
|
|
236
|
+
* ```
|
|
237
|
+
*/
|
|
238
|
+
declare function toWebp(input: Buffer, options?: WebPOptions): Promise<Buffer>;
|
|
239
|
+
/**
|
|
240
|
+
* Transform image with multiple operations asynchronously
|
|
241
|
+
*
|
|
242
|
+
* This is the most efficient way to apply multiple transformations
|
|
243
|
+
* as it processes the image only once.
|
|
244
|
+
*
|
|
245
|
+
* @param input - Image buffer
|
|
246
|
+
* @param options - Transform options
|
|
247
|
+
* @returns Promise resolving to transformed image buffer
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* const result = await transform(imageBuffer, {
|
|
252
|
+
* resize: { width: 800, height: 600 },
|
|
253
|
+
* rotate: 90,
|
|
254
|
+
* grayscale: true,
|
|
255
|
+
* output: { format: 'webp', webp: { quality: 85 } }
|
|
256
|
+
* });
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
declare function transform(input: Buffer, options: TransformOptions): Promise<Buffer>;
|
|
260
|
+
/**
|
|
261
|
+
* Generate blurhash from image asynchronously
|
|
262
|
+
*
|
|
263
|
+
* Blurhash is a compact representation of a placeholder for an image.
|
|
264
|
+
*
|
|
265
|
+
* @param input - Image buffer
|
|
266
|
+
* @param componentsX - Number of X components (default: 4)
|
|
267
|
+
* @param componentsY - Number of Y components (default: 3)
|
|
268
|
+
* @returns Promise resolving to blurhash result
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* ```typescript
|
|
272
|
+
* const { hash, width, height } = await blurhash(imageBuffer);
|
|
273
|
+
* console.log(hash); // "LEHV6nWB2yk8pyo0adR*.7kCMdnj"
|
|
274
|
+
* ```
|
|
275
|
+
*/
|
|
276
|
+
declare function blurhash(input: Buffer, componentsX?: number, componentsY?: number): Promise<BlurHashResult>;
|
|
277
|
+
/**
|
|
278
|
+
* Get image metadata synchronously
|
|
279
|
+
*/
|
|
280
|
+
declare function metadataSync(input: Buffer): ImageMetadata;
|
|
281
|
+
/**
|
|
282
|
+
* Resize image synchronously
|
|
283
|
+
*/
|
|
284
|
+
declare function resizeSync(input: Buffer, options: ResizeOptions): Buffer;
|
|
285
|
+
/**
|
|
286
|
+
* Convert image to JPEG synchronously
|
|
287
|
+
*/
|
|
288
|
+
declare function toJpegSync(input: Buffer, options?: JpegOptions): Buffer;
|
|
289
|
+
/**
|
|
290
|
+
* Convert image to PNG synchronously
|
|
291
|
+
*/
|
|
292
|
+
declare function toPngSync(input: Buffer, options?: PngOptions): Buffer;
|
|
293
|
+
/**
|
|
294
|
+
* Convert image to WebP synchronously
|
|
295
|
+
*/
|
|
296
|
+
declare function toWebpSync(input: Buffer, options?: WebPOptions): Buffer;
|
|
297
|
+
/**
|
|
298
|
+
* Transform image with multiple operations synchronously
|
|
299
|
+
*/
|
|
300
|
+
declare function transformSync(input: Buffer, options: TransformOptions): Buffer;
|
|
301
|
+
/**
|
|
302
|
+
* Generate blurhash from image synchronously
|
|
303
|
+
*/
|
|
304
|
+
declare function blurhashSync(input: Buffer, componentsX?: number, componentsY?: number): BlurHashResult;
|
|
305
|
+
/**
|
|
306
|
+
* Get library version
|
|
307
|
+
*/
|
|
308
|
+
declare function version(): string;
|
|
309
|
+
declare const _default: {
|
|
310
|
+
metadata: typeof metadata;
|
|
311
|
+
metadataSync: typeof metadataSync;
|
|
312
|
+
resize: typeof resize;
|
|
313
|
+
resizeSync: typeof resizeSync;
|
|
314
|
+
toJpeg: typeof toJpeg;
|
|
315
|
+
toJpegSync: typeof toJpegSync;
|
|
316
|
+
toPng: typeof toPng;
|
|
317
|
+
toPngSync: typeof toPngSync;
|
|
318
|
+
toWebp: typeof toWebp;
|
|
319
|
+
toWebpSync: typeof toWebpSync;
|
|
320
|
+
transform: typeof transform;
|
|
321
|
+
transformSync: typeof transformSync;
|
|
322
|
+
blurhash: typeof blurhash;
|
|
323
|
+
blurhashSync: typeof blurhashSync;
|
|
324
|
+
version: typeof version;
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
export { type AvifOptions, type BlurHashResult, type FitMode, type ImageFormat, type ImageMetadata, type JpegOptions, type OutputOptions, type PngOptions, type ResizeFilter, type ResizeOptions, type TransformOptions, type WebPOptions, blurhash, blurhashSync, _default as default, metadata, metadataSync, resize, resizeSync, toJpeg, toJpegSync, toPng, toPngSync, toWebp, toWebpSync, transform, transformSync, version };
|