Transforms

Node Browser

Geometric operations: resize, crop, rotate, flip, and flop.

resize

.resize(width?: number, height?: number, options?: ResizeOptions): Pipeline
.resize(width?: number, height?: number, options?: ResizeOptions): Pipeline

Scale an image to a target size. Pass only width or only height to resize proportionally.

Options

PropTypeDefaultDescription
fit'cover' | 'contain' | 'fill' | 'inside' | 'outside''cover'How the image fits the target dimensions
withoutEnlargementbooleanfalseNever upscale beyond the original size
backgroundstring | { r, g, b, alpha? }'#000000'Fill colour used with contain

Fit modes

ModeBehaviour
coverCrop to fill exact dimensions, preserving aspect ratio
containLetterbox to fit within dimensions, preserving aspect ratio
fillStretch to exact dimensions, ignoring aspect ratio
insideResize to fit within dimensions, never cropping
outsideResize to fit outside dimensions, never adding padding

Examples

// Proportional resize — width only
await img('photo.jpg').resize(800).toBuffer()

// Exact dimensions, crop to cover
await img('photo.jpg').resize(800, 600, { fit: 'cover' }).toBuffer()

// Letterbox with white background
await img('photo.jpg')
  .resize(800, 600, { fit: 'contain', background: '#ffffff' })
  .toBuffer()

// Never enlarge small images
await img('thumbnail.jpg')
  .resize(400, 400, { fit: 'inside', withoutEnlargement: true })
  .toBuffer()
// Proportional resize — width only
await img('photo.jpg').resize(800).toBuffer()

// Exact dimensions, crop to cover
await img('photo.jpg').resize(800, 600, { fit: 'cover' }).toBuffer()

// Letterbox with white background
await img('photo.jpg')
  .resize(800, 600, { fit: 'contain', background: '#ffffff' })
  .toBuffer()

// Never enlarge small images
await img('thumbnail.jpg')
  .resize(400, 400, { fit: 'inside', withoutEnlargement: true })
  .toBuffer()

crop

.crop(left: number, top: number, width: number, height: number): Pipeline
.crop(left: number, top: number, width: number, height: number): Pipeline

Extract a rectangular region. Coordinates are in pixels from the top-left corner.

// Extract a 400x300 region starting at (100, 50)
await img('photo.jpg').crop(100, 50, 400, 300).toBuffer()

// Crop then resize
await img('photo.jpg')
  .crop(0, 0, 800, 600)
  .resize(400, 300)
  .toBuffer()
// Extract a 400x300 region starting at (100, 50)
await img('photo.jpg').crop(100, 50, 400, 300).toBuffer()

// Crop then resize
await img('photo.jpg')
  .crop(0, 0, 800, 600)
  .resize(400, 300)
  .toBuffer()

crop extracts a fixed region. For subject-aware cropping use smartCrop.


rotate

.rotate(angle: number, options?: RotateOptions): Pipeline
.rotate(angle: number, options?: RotateOptions): Pipeline

Rotate by degrees. Any angle is accepted; non-right-angle rotations add padding.

OptionTypeDefaultDescription
backgroundstring | { r, g, b, alpha? }'#000000'Fill colour for exposed areas
// 90° clockwise
await img('photo.jpg').rotate(90).toBuffer()

// 45° with white fill
await img('photo.jpg').rotate(45, { background: '#ffffff' }).toBuffer()

// Auto-rotate based on EXIF orientation
await img('photo.jpg').rotate(0).toBuffer()
// 90° clockwise
await img('photo.jpg').rotate(90).toBuffer()

// 45° with white fill
await img('photo.jpg').rotate(45, { background: '#ffffff' }).toBuffer()

// Auto-rotate based on EXIF orientation
await img('photo.jpg').rotate(0).toBuffer()

flip

.flip(): Pipeline
.flip(): Pipeline

Flip vertically (top ↔ bottom).

await img('photo.jpg').flip().toBuffer()
await img('photo.jpg').flip().toBuffer()

flop

.flop(): Pipeline
.flop(): Pipeline

Flip horizontally (left ↔ right, mirror).

await img('photo.jpg').flop().toBuffer()
await img('photo.jpg').flop().toBuffer()

Combining transforms

// Crop to subject, resize for web, mirror
await img('photo.jpg')
  .crop(200, 100, 600, 600)
  .resize(400, 400, { fit: 'cover' })
  .flop()
  .webp({ quality: 85 })
  .toBuffer()
// Crop to subject, resize for web, mirror
await img('photo.jpg')
  .crop(200, 100, 600, 600)
  .resize(400, 400, { fit: 'cover' })
  .flop()
  .webp({ quality: 85 })
  .toBuffer()