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.
@@ -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 };
package/dist/index.js ADDED
@@ -0,0 +1,228 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ blurhash: () => blurhash,
24
+ blurhashSync: () => blurhashSync,
25
+ default: () => index_default,
26
+ metadata: () => metadata,
27
+ metadataSync: () => metadataSync,
28
+ resize: () => resize,
29
+ resizeSync: () => resizeSync,
30
+ toJpeg: () => toJpeg,
31
+ toJpegSync: () => toJpegSync,
32
+ toPng: () => toPng,
33
+ toPngSync: () => toPngSync,
34
+ toWebp: () => toWebp,
35
+ toWebpSync: () => toWebpSync,
36
+ transform: () => transform,
37
+ transformSync: () => transformSync,
38
+ version: () => version
39
+ });
40
+ module.exports = __toCommonJS(index_exports);
41
+ var import_fs = require("fs");
42
+ var import_path = require("path");
43
+ var import_url = require("url");
44
+ var import_meta = {};
45
+ var getCurrentDir = () => {
46
+ try {
47
+ return (0, import_path.dirname)((0, import_url.fileURLToPath)(import_meta.url));
48
+ } catch {
49
+ return __dirname;
50
+ }
51
+ };
52
+ function loadNativeBinding() {
53
+ const platform = process.platform;
54
+ const arch = process.arch;
55
+ let targetName;
56
+ switch (platform) {
57
+ case "darwin":
58
+ targetName = arch === "arm64" ? "darwin-arm64" : "darwin-x64";
59
+ break;
60
+ case "linux":
61
+ const isMusl = (0, import_fs.existsSync)("/etc/alpine-release") || process.env.npm_config_libc === "musl";
62
+ if (arch === "arm64") {
63
+ targetName = isMusl ? "linux-arm64-musl" : "linux-arm64-gnu";
64
+ } else {
65
+ targetName = isMusl ? "linux-x64-musl" : "linux-x64-gnu";
66
+ }
67
+ break;
68
+ case "win32":
69
+ targetName = "win32-x64-msvc";
70
+ break;
71
+ default:
72
+ throw new Error(`Unsupported platform: ${platform}-${arch}`);
73
+ }
74
+ const currentDir = getCurrentDir();
75
+ const possiblePaths = [
76
+ // Same directory as this file (dist/)
77
+ (0, import_path.join)(currentDir, `image-turbo.${targetName}.node`),
78
+ // Parent directory (package root)
79
+ (0, import_path.join)(currentDir, "..", `image-turbo.${targetName}.node`),
80
+ // CWD (development)
81
+ (0, import_path.join)(process.cwd(), `image-turbo.${targetName}.node`)
82
+ ];
83
+ for (const modulePath of possiblePaths) {
84
+ try {
85
+ if ((0, import_fs.existsSync)(modulePath)) {
86
+ return require(modulePath);
87
+ }
88
+ } catch {
89
+ continue;
90
+ }
91
+ }
92
+ throw new Error(
93
+ `Failed to load native binding for ${platform}-${arch}. Tried: ${possiblePaths.join(", ")}`
94
+ );
95
+ }
96
+ var native = loadNativeBinding();
97
+ function toNapiFilter(filter) {
98
+ if (!filter) return void 0;
99
+ return filter.charAt(0).toUpperCase() + filter.slice(1);
100
+ }
101
+ function toNapiFit(fit) {
102
+ if (!fit) return void 0;
103
+ return fit.charAt(0).toUpperCase() + fit.slice(1);
104
+ }
105
+ function toNapiResizeOptions(options) {
106
+ return {
107
+ width: options.width,
108
+ height: options.height,
109
+ filter: toNapiFilter(options.filter),
110
+ fit: toNapiFit(options.fit),
111
+ background: options.background
112
+ };
113
+ }
114
+ function toNapiFormat(format) {
115
+ const formatMap = {
116
+ jpeg: "Jpeg",
117
+ png: "Png",
118
+ webp: "WebP",
119
+ gif: "Gif",
120
+ bmp: "Bmp",
121
+ ico: "Ico",
122
+ tiff: "Tiff"
123
+ };
124
+ return formatMap[format.toLowerCase()] || format;
125
+ }
126
+ function toNapiTransformOptions(options) {
127
+ const result = {};
128
+ if (options.resize) {
129
+ result.resize = toNapiResizeOptions(options.resize);
130
+ }
131
+ if (options.output) {
132
+ result.output = {
133
+ format: toNapiFormat(options.output.format),
134
+ jpeg: options.output.jpeg,
135
+ png: options.output.png,
136
+ webp: options.output.webp
137
+ };
138
+ }
139
+ result.rotate = options.rotate;
140
+ result.flipH = options.flipH;
141
+ result.flipV = options.flipV;
142
+ result.grayscale = options.grayscale;
143
+ result.blur = options.blur;
144
+ result.sharpen = options.sharpen;
145
+ result.brightness = options.brightness;
146
+ result.contrast = options.contrast;
147
+ return result;
148
+ }
149
+ async function metadata(input) {
150
+ return native.metadata(input);
151
+ }
152
+ async function resize(input, options) {
153
+ return native.resize(input, toNapiResizeOptions(options));
154
+ }
155
+ async function toJpeg(input, options) {
156
+ return native.toJpeg(input, options);
157
+ }
158
+ async function toPng(input, options) {
159
+ return native.toPng(input, options);
160
+ }
161
+ async function toWebp(input, options) {
162
+ return native.toWebp(input, options);
163
+ }
164
+ async function transform(input, options) {
165
+ return native.transform(input, toNapiTransformOptions(options));
166
+ }
167
+ async function blurhash(input, componentsX, componentsY) {
168
+ return native.blurhash(input, componentsX, componentsY);
169
+ }
170
+ function metadataSync(input) {
171
+ return native.metadataSync(input);
172
+ }
173
+ function resizeSync(input, options) {
174
+ return native.resizeSync(input, toNapiResizeOptions(options));
175
+ }
176
+ function toJpegSync(input, options) {
177
+ return native.toJpegSync(input, options);
178
+ }
179
+ function toPngSync(input, options) {
180
+ return native.toPngSync(input, options);
181
+ }
182
+ function toWebpSync(input, options) {
183
+ return native.toWebpSync(input, options);
184
+ }
185
+ function transformSync(input, options) {
186
+ return native.transformSync(input, toNapiTransformOptions(options));
187
+ }
188
+ function blurhashSync(input, componentsX, componentsY) {
189
+ return native.blurhashSync(input, componentsX, componentsY);
190
+ }
191
+ function version() {
192
+ return native.version();
193
+ }
194
+ var index_default = {
195
+ metadata,
196
+ metadataSync,
197
+ resize,
198
+ resizeSync,
199
+ toJpeg,
200
+ toJpegSync,
201
+ toPng,
202
+ toPngSync,
203
+ toWebp,
204
+ toWebpSync,
205
+ transform,
206
+ transformSync,
207
+ blurhash,
208
+ blurhashSync,
209
+ version
210
+ };
211
+ // Annotate the CommonJS export names for ESM import in node:
212
+ 0 && (module.exports = {
213
+ blurhash,
214
+ blurhashSync,
215
+ metadata,
216
+ metadataSync,
217
+ resize,
218
+ resizeSync,
219
+ toJpeg,
220
+ toJpegSync,
221
+ toPng,
222
+ toPngSync,
223
+ toWebp,
224
+ toWebpSync,
225
+ transform,
226
+ transformSync,
227
+ version
228
+ });