Chain 30 Image Operations in a Single API Request — No Infrastructure Required

7 min read Image Transformation

The Sharp Pipeline Problem

You start with Sharp. sharp(input).resize(800, 600).webp({ quality: 85 }).toBuffer(). Clean, fast, works locally. Then the requirements grow.

You need to resize to multiple sizes. Add sharpening after downscaling. Convert to WebP for browsers and JPEG for email. Smart crop for thumbnails. Compress to a target file size for mobile. Suddenly your Sharp pipeline is 50 lines of method chains with conditional logic, error handling, and edge cases for image formats that behave differently.

Now deploy it. You need a server — or a Lambda function — running Node.js with Sharp’s native bindings. Sharp depends on libvips, which needs to be compiled for your platform. ARM deployment? Good luck with the binary compatibility. Scale it? You’re running compute-intensive image processing on servers you maintain.

The Image Transformation API replaces the pipeline and the infrastructure. Send an image with up to 30 operations, and they execute sequentially in the cloud. One API call, no servers, no native dependencies.

A Real Pipeline

Here’s what a typical image processing pipeline looks like as a single API request:

import { IterationLayer } from "iterationlayer";
const client = new IterationLayer({ apiKey: "YOUR_API_KEY" });

const result = await client.transform({
  file: { type: "url", name: "product.jpg", url: "https://cdn.example.com/raw/product-001.jpg" },
  operations: [
    { type: "resize", width_in_px: 2000, height_in_px: 2000, fit: "inside" },
    { type: "auto_contrast" },
    { type: "sharpen", sigma: 0.5 },
    { type: "smart_crop", width_in_px: 1000, height_in_px: 1000 },
    { type: "convert", format: "webp", quality: 85 },
  ],
});

const { data: { buffer: processedImageBase64 } } = result;
const processedImageBuffer = Buffer.from(processedImageBase64, "base64");

Five operations, one API call. The image flows through each step sequentially — the output of resize becomes the input to auto_contrast, which becomes the input to sharpen, and so on.

24 Available Operations

The API supports 24 operations across four categories:

Geometry:

  • resize — scale to target dimensions with 5 fit strategies
  • crop — extract a rectangular region
  • smart_crop — AI-powered subject-aware cropping
  • extend — add padding with a specified color
  • trim — remove border pixels within a color threshold
  • rotate — rotate by any angle
  • flip — vertical flip
  • flop — horizontal mirror

Color and tone:

  • modulate — adjust brightness, saturation, and hue
  • tint — apply a color tint
  • grayscale — convert to grayscale
  • invert_colors — invert all colors
  • auto_contrast — normalize the histogram
  • gamma — apply gamma correction

Quality and cleanup:

  • blur — Gaussian blur
  • sharpen — sharpening
  • denoise — median filter noise reduction
  • threshold — convert to black and white at a threshold value
  • opacity — adjust transparency

Output:

  • convert — change format (PNG, JPEG, WebP, AVIF) with quality control
  • compress_to_size — compress to a target file size in bytes
  • upscale — AI-powered 2x, 3x, or 4x resolution enhancement
  • remove_transparency — replace transparent pixels with a solid color

Operations Are Sequential — Order Matters

The operations execute in array order — each one receives the output of the previous operation. This is not a detail you can ignore. The order of operations directly affects the output.

Sharpen after resize, not before. Sharpening a full-size image and then downscaling it wastes the sharpening effort. Downscaling inherently softens the image, which undoes the sharpening pass. Run the resize first, then sharpen the result.

Convert to the output format last. Format conversion should always be the final step (or second-to-last, before compress_to_size). Converting to a lossy format mid-pipeline means every subsequent operation works on already-compressed data, compounding quality loss.

Smart crop before adding borders or padding. If you add an extend (padding) before smart_crop, the AI will see the padding as part of the image and may include it in its subject detection. Run smart crop on the raw image, then add borders.

compress_to_size at the very end. This operation adjusts quality and dimensions to hit a target file size. Running any operation after it may change the file size, making the compression pointless.

A well-ordered pipeline for a product listing image:

const operations = [
  { type: "resize", width_in_px: 1200, height_in_px: 1200, fit: "inside" },
  { type: "auto_contrast" },
  { type: "sharpen", sigma: 0.5 },
  { type: "remove_transparency", hex_color: "#ffffff" },
  { type: "convert", format: "jpeg", quality: 90 },
];

Constrain dimensions first. Enhance contrast and sharpness on the resized image. Replace transparency (since JPEG doesn’t support it). Convert last.

Replacing Self-Hosted Pipelines

If you’re currently running Sharp, ImageMagick, or libvips on your servers:

Self-hosted API
Install Sharp + libvips npm install @iterationlayer/image-transformation
Handle ARM/x86 binaries Nothing to compile
Scale server capacity Automatically scales
Patch security vulnerabilities Managed for you
Handle OOM kills on large images 50 MB limit, handled gracefully

The API accepts images up to 50 MB and processes up to 30 operations per request. For most image processing workloads, that covers everything you need without any infrastructure.

Practical Pipelines

User avatar processing:

const operations = [
  { type: "smart_crop", width_in_px: 256, height_in_px: 256 },
  { type: "convert", format: "webp", quality: 80 },
];

E-commerce product listing:

const operations = [
  { type: "resize", width_in_px: 1000, height_in_px: 1000, fit: "contain" },
  { type: "remove_transparency", hex_color: "#ffffff" },
  { type: "sharpen", sigma: 0.5 },
  { type: "convert", format: "jpeg", quality: 90 },
];

Email-safe compression:

const operations = [
  { type: "resize", width_in_px: 800, height_in_px: 600, fit: "inside" },
  { type: "compress_to_size", max_file_size_in_bytes: 500_000 },
];

Blog hero image with color correction:

const operations = [
  { type: "resize", width_in_px: 1400, height_in_px: 800, fit: "cover" },
  { type: "modulate", brightness: 1.05, saturation: 1.1 },
  { type: "sharpen", sigma: 0.4 },
  { type: "convert", format: "webp", quality: 85 },
];

Slightly boost brightness and saturation to make the image pop on screen, sharpen after resize, and convert to WebP.

Document scan cleanup:

const operations = [
  { type: "grayscale" },
  { type: "auto_contrast" },
  { type: "sharpen", sigma: 1.0 },
  { type: "threshold", threshold: 128, is_grayscale: true },
  { type: "convert", format: "png" },
];

Convert to grayscale, normalize the histogram, sharpen, then binarize at a threshold. This produces a clean black-and-white scan suitable for OCR or archival.

Social media image with consistent branding:

const operations = [
  { type: "smart_crop", width_in_px: 1080, height_in_px: 1080 },
  { type: "modulate", saturation: 1.15 },
  { type: "sharpen", sigma: 0.3 },
  { type: "convert", format: "jpeg", quality: 92 },
];

Smart crop to a square for Instagram, boost saturation slightly for screen impact, sharpen, and convert to JPEG (Instagram re-encodes everything anyway, so start with high quality).

Get Started

Check the docs for the complete operation reference with parameters and examples for each operation. The TypeScript and Python SDKs handle file input and response parsing.

Sign up for a free account — no credit card required. Replace your first Sharp pipeline with an API call and see how it feels.

Start building in minutes

Free trial included. No credit card required.