Skip to content

transform

Apply multiple image transformations in a single operation. This is the most efficient way to combine resize, rotate, flip, filters, and format conversion.

Signature

typescript
function transform(input: Buffer, options: TransformOptions): Promise<Buffer>
function transformSync(input: Buffer, options: TransformOptions): Buffer

Parameters

ParameterTypeDescription
inputBufferImage buffer
optionsTransformOptionsTransform configuration

TransformOptions

typescript
interface TransformOptions {
  /** Resize configuration */
  resize?: ResizeOptions;

  /** Output format and options (default: PNG) */
  output?: OutputOptions;

  /** Rotate degrees (90, 180, or 270) */
  rotate?: number;

  /** Flip horizontally */
  flipH?: boolean;

  /** Flip vertically */
  flipV?: boolean;

  /** Convert to grayscale */
  grayscale?: boolean;

  /** Blur radius (0-100) */
  blur?: number;

  /** Sharpen amount (0-100) */
  sharpen?: number;

  /** Brightness adjustment (-100 to 100) */
  brightness?: number;

  /** Contrast adjustment (-100 to 100) */
  contrast?: number;
}

ResizeOptions

typescript
interface ResizeOptions {
  /** Target width (optional if height provided) */
  width?: number;

  /** Target height (optional if width provided) */
  height?: number;

  /** How to fit image into dimensions (default: 'Cover') */
  fit?: FitMode;

  /** Resampling algorithm (default: 'Lanczos3') */
  filter?: ResizeFilter;

  /** Background color for padding [r, g, b, a] (default: transparent) */
  background?: number[];
}

/** Resize filter/algorithm */
enum ResizeFilter {
  Nearest = 'Nearest',
  Bilinear = 'Bilinear',
  CatmullRom = 'CatmullRom',
  Mitchell = 'Mitchell',
  Lanczos3 = 'Lanczos3'
}

/** Image fit mode */
enum FitMode {
  Cover = 'Cover',
  Contain = 'Contain',
  Fill = 'Fill',
  Inside = 'Inside',
  Outside = 'Outside'
}

OutputOptions

typescript
interface OutputOptions {
  /** Output format */
  format: ImageFormat;

  /** JPEG options (if format is Jpeg) */
  jpeg?: { quality?: number };  // 1-100, default: 80

  /** PNG options (if format is Png) */
  png?: { compression?: number };  // 0-9, default: 6

  /** WebP options (if format is WebP) */
  webp?: { quality?: number; lossless?: boolean };  // quality: 1-100, default: 80
}

/** Image format enum */
enum ImageFormat {
  Jpeg = 'Jpeg',
  Png = 'Png',
  WebP = 'WebP',
  Gif = 'Gif',
  Bmp = 'Bmp'
}

Case Sensitivity

All enum values are PascalCase:

  • Formats: 'Jpeg', 'Png', 'WebP', 'Gif', 'Bmp'
  • Fit modes: 'Cover', 'Contain', 'Fill', 'Inside', 'Outside'
  • Filters: 'Nearest', 'Bilinear', 'CatmullRom', 'Mitchell', 'Lanczos3'

Returns

Buffer - Transformed image in the specified format (default: PNG)

Examples

Basic Transform

typescript
import { transform } from 'bun-image-turbo';

const result = await transform(buffer, {
  resize: { width: 800 },
  output: { format: 'WebP', webp: { quality: 85 } }
});

Resize and Convert

typescript
const result = await transform(buffer, {
  resize: {
    width: 800,
    height: 600,
    fit: 'Cover'
  },
  output: {
    format: 'Jpeg',
    jpeg: { quality: 85 }
  }
});

Full Pipeline

typescript
const result = await transform(buffer, {
  // Resize to 800x600 with cover fit
  resize: {
    width: 800,
    height: 600,
    fit: 'Cover',
    filter: 'Lanczos3'
  },

  // Rotate 90 degrees clockwise
  rotate: 90,

  // Flip
  flipH: true,
  flipV: false,

  // Color adjustments
  grayscale: true,
  brightness: 10,
  contrast: 5,

  // Effects
  blur: 2,
  sharpen: 10,

  // Output as WebP
  output: {
    format: 'WebP',
    webp: { quality: 85 }
  }
});

await Bun.write('output.webp', result);

Rotation

typescript
// Rotate 90 degrees clockwise
const rotated90 = await transform(buffer, {
  rotate: 90,
  output: { format: 'Jpeg' }
});

// Rotate 180 degrees
const rotated180 = await transform(buffer, {
  rotate: 180,
  output: { format: 'Jpeg' }
});

// Rotate 270 degrees (90 counter-clockwise)
const rotated270 = await transform(buffer, {
  rotate: 270,
  output: { format: 'Jpeg' }
});

Flipping

typescript
// Horizontal mirror
const mirrored = await transform(buffer, {
  flipH: true,
  output: { format: 'Jpeg' }
});

// Vertical flip
const flipped = await transform(buffer, {
  flipV: true,
  output: { format: 'Jpeg' }
});

// Both
const both = await transform(buffer, {
  flipH: true,
  flipV: true,
  output: { format: 'Png' }
});

Grayscale

typescript
const bw = await transform(buffer, {
  grayscale: true,
  output: { format: 'Jpeg', jpeg: { quality: 85 } }
});

Blur

typescript
const blurred = await transform(buffer, {
  blur: 10,  // 0-100
  output: { format: 'Jpeg' }
});

Sharpen

typescript
const sharpened = await transform(buffer, {
  sharpen: 15,  // 0-100
  output: { format: 'Jpeg', jpeg: { quality: 95 } }
});

Brightness and Contrast

typescript
// Brighten
const brighter = await transform(buffer, {
  brightness: 20,  // -100 to 100
  output: { format: 'Jpeg' }
});

// Darken
const darker = await transform(buffer, {
  brightness: -20,
  output: { format: 'Jpeg' }
});

// Increase contrast
const highContrast = await transform(buffer, {
  contrast: 30,  // -100 to 100
  output: { format: 'Jpeg' }
});

// Combined
const adjusted = await transform(buffer, {
  brightness: 10,
  contrast: 15,
  output: { format: 'Jpeg', jpeg: { quality: 90 } }
});

Thumbnail Generation

typescript
const thumb = await transform(buffer, {
  resize: {
    width: 150,
    height: 150,
    fit: 'Cover'
  },
  sharpen: 5,  // Slight sharpen after resize
  output: {
    format: 'WebP',
    webp: { quality: 70 }
  }
});

Output Formats

typescript
// JPEG output
const jpeg = await transform(buffer, {
  resize: { width: 800 },
  output: { format: 'Jpeg', jpeg: { quality: 85 } }
});

// PNG output
const png = await transform(buffer, {
  resize: { width: 800 },
  output: { format: 'Png', png: { compression: 6 } }
});

// WebP lossy output
const webpLossy = await transform(buffer, {
  resize: { width: 800 },
  output: { format: 'WebP', webp: { quality: 80 } }
});

// WebP lossless output
const webpLossless = await transform(buffer, {
  resize: { width: 800 },
  output: { format: 'WebP', webp: { lossless: true } }
});

// GIF output
const gif = await transform(buffer, {
  resize: { width: 400 },
  output: { format: 'Gif' }
});

// BMP output
const bmp = await transform(buffer, {
  resize: { width: 400 },
  output: { format: 'Bmp' }
});

Default Output (PNG)

typescript
// If output is not specified, defaults to PNG
const png = await transform(buffer, {
  resize: { width: 800 },
  grayscale: true
});
// Result is PNG format

Sync Version

typescript
import { transformSync } from 'bun-image-turbo';

const result = transformSync(buffer, {
  resize: { width: 400 },
  output: { format: 'WebP', webp: { quality: 80 } }
});

HEIC Conversion (macOS ARM64)

typescript
// Convert HEIC to JPEG
const heicBuffer = Buffer.from(await Bun.file('photo.HEIC').arrayBuffer());
const jpeg = await transform(heicBuffer, {
  output: { format: 'Jpeg', jpeg: { quality: 90 } }
});

// Convert HEIC to WebP with resize
const webp = await transform(heicBuffer, {
  resize: { width: 1200 },
  output: { format: 'WebP', webp: { quality: 85 } }
});

Transformation Order

Operations are applied in this order:

  1. Resize - Scale the image
  2. Rotate - Rotate by 90/180/270 degrees
  3. Flip - Horizontal and/or vertical flip
  4. Grayscale - Convert to grayscale
  5. Blur - Apply Gaussian blur
  6. Sharpen - Apply unsharp mask
  7. Brightness - Adjust brightness
  8. Contrast - Adjust contrast
  9. Encode - Output to specified format

Option Ranges

OptionRangeDefaultNotes
rotate90, 180, 270-Clockwise rotation
blur0-100-Higher = more blur
sharpen0-100-Higher = sharper
brightness-100 to 1000Negative = darker
contrast-100 to 1000Negative = less contrast

Performance Tips

  1. Use transform() for multiple operations - Single decode/encode is faster than chaining functions
  2. Resize first - Reduces pixels for subsequent operations
  3. Choose appropriate filter - 'Bilinear' is fast, 'Lanczos3' is high quality

Notes

  • output is optional - defaults to PNG if not specified
  • JPEG encoding uses TurboJPEG with SIMD acceleration
  • Grayscale + JPEG = smaller file sizes
  • Sharpen is applied using unsharp mask algorithm

See Also