← Back to Home

How to Crop Images with Sharp Library

Updated January 14, 2026
sharpimage croppingnodejsbuffercomposite

Cropping Images with Sharp Library

Sharp is a high-performance Node.js image processing library for cropping and resizing.

Basic Crop

import sharp from 'sharp';

async function cropImageRegion(
  imageBuffer: Buffer,
  region: {
    left: number;
    top: number;
    width: number;
    height: number;
  }
): Promise<Buffer> {
  return await sharp(imageBuffer)
    .extract(region)
    .png()
    .toBuffer();
}

Crop and Resize

For scaling up during crop (e.g., 4K composites):

async function cropAndResizeImageRegion(
  imageBuffer: Buffer,
  options: {
    region: { left: number; top: number; width: number; height: number };
    targetWidth: number;
    targetHeight: number;
  }
): Promise<Buffer> {
  return await sharp(imageBuffer)
    .extract(options.region)
    .resize(options.targetWidth, options.targetHeight, {
      fit: 'fill',  // Exact dimensions
      kernel: 'lanczos3',  // High quality
    })
    .png()
    .toBuffer();
}

Get Image Dimensions

async function getImageDimensions(imageBuffer: Buffer): Promise<{
  width: number;
  height: number;
}> {
  const metadata = await sharp(imageBuffer).metadata();
  return {
    width: metadata.width || 0,
    height: metadata.height || 0,
  };
}

Validate Image Dimensions

async function validateImageDimensions(
  imageBuffer: Buffer,
  expectedWidth: number,
  expectedHeight: number
): Promise<boolean> {
  const dimensions = await getImageDimensions(imageBuffer);
  return dimensions.width === expectedWidth &&
         dimensions.height === expectedHeight;
}

Cropping Stacked Composite

Example for cropping a 3×3 grid:

async function cropCompositeIntoScenes(
  compositeBuffer: Buffer,
  sceneCount: number
): Promise<Buffer[]> {
  const dimensions = await getImageDimensions(compositeBuffer);
  const cols = Math.ceil(Math.sqrt(sceneCount));

  const cellWidth = Math.floor(dimensions.width / cols);
  const cellHeight = Math.floor(dimensions.height / Math.ceil(sceneCount / cols));

  const results: Buffer[] = [];

  for (let i = 0; i < sceneCount; i++) {
    const col = i % cols;
    const row = Math.floor(i / cols);

    const region = {
      left: col * cellWidth,
      top: row * cellHeight,
      width: cellWidth,
      height: cellHeight,
    };

    const buffer = await cropAndResizeImageRegion(compositeBuffer, {
      region,
      targetWidth: 1080,
      targetHeight: 1920,
    });

    results.push(buffer);
  }

  return results;
}

Performance Tips

Error Handling

try {
  const cropped = await cropImageRegion(buffer, region);
} catch (error) {
  if (error.message.includes('extract area exceeds image dimensions')) {
    throw new Error('Crop region is larger than the image');
  }
  throw error;
}