Skip to content

Image engine

The @snapotter/image-engine package handles all non-AI image operations. It wraps Sharp and runs entirely in-process with no external dependencies.

Operations

resize

Scale an image to specific dimensions or by percentage.

ParameterTypeDescription
widthnumberTarget width in pixels
heightnumberTarget height in pixels
fitstringcover, contain, fill, inside, or outside
withoutEnlargementbooleanIf true, won't upscale smaller images
percentagenumberScale by percentage instead of absolute dimensions

You can set width, height, or both. If you only set one, the other is calculated to maintain the aspect ratio.

crop

Cut out a rectangular region from the image.

ParameterTypeDescription
leftnumberX offset from the left edge
topnumberY offset from the top edge
widthnumberWidth of the crop area
heightnumberHeight of the crop area
unitstringpx (default) or percent

rotate

Rotate the image by a given angle.

ParameterTypeDescription
anglenumberRotation angle in degrees (0-360)
backgroundstringFill color for exposed area (default: #000000). Only applies to non-90-degree angles.

flip

Mirror the image horizontally, vertically, or both. At least one must be true.

ParameterTypeDescription
horizontalbooleanMirror left to right
verticalbooleanMirror top to bottom

convert

Change the image format.

ParameterTypeDescription
formatstringTarget format: jpg, png, webp, avif, tiff, gif, jxl, heic, heif, bmp, ico, jp2, qoi
qualitynumberCompression quality (1-100, applies to lossy formats)

The first seven formats (jpg through jxl) are encoded by Sharp in-process. The remaining formats use external encoders at the API layer: heic/heif via heif-enc, bmp/ico via ImageMagick, jp2 via opj_compress, and qoi via an inline TypeScript codec.

compress

Reduce file size while keeping the same format.

ParameterTypeDescription
qualitynumberTarget quality (1-100)
targetSizeBytesnumberOptional target file size in bytes
formatstringOptional format override

strip-metadata

Remove EXIF, IPTC, XMP, and ICC metadata from the image. With no parameters (or stripAll: true), strips everything. Pass individual flags for selective stripping.

ParameterTypeDescription
stripAllbooleanStrip all metadata (default when no flags are set)
stripExifbooleanStrip EXIF data (including GPS if stripGps is not separately set)
stripGpsbooleanStrip GPS location data
stripIccbooleanStrip ICC color profile
stripXmpbooleanStrip XMP metadata

Color adjustments

These operations modify the color properties of an image. Each takes a single numeric value.

OperationParameterRangeDescription
brightnessvalue-100 to 100Adjust brightness
contrastvalue-100 to 100Adjust contrast
saturationvalue-100 to 100Adjust color saturation

Color filters

These apply a fixed color transformation. They take no parameters.

OperationDescription
grayscaleConvert to grayscale
sepiaApply a sepia tone
invertInvert all colors

Color channels

Adjust individual RGB color channels. Values are multipliers where 100 = no change.

ParameterTypeDescription
rednumberRed channel multiplier (0 to 200, 100 = unchanged)
greennumberGreen channel multiplier (0 to 200, 100 = unchanged)
bluenumberBlue channel multiplier (0 to 200, 100 = unchanged)

sharpen

Simple sharpening controlled by a single value.

ParameterTypeDescription
valuenumberSharpening intensity (0 to 100). Mapped to a Gaussian sigma of 0.5-10.

sharpen-advanced

Advanced sharpening with three selectable methods and an optional noise-reduction pre-pass.

ParameterTypeDescription
methodstringadaptive, unsharp-mask, or high-pass
sigmanumberGaussian blur radius, 0.5-10 (adaptive)
m1numberFlat-area sharpening, 0-10 (adaptive)
m2numberTextured-area sharpening, 0-20 (adaptive)
x1numberFlat/jagged threshold, 0-10 (adaptive)
y2numberMax brightening (halo clamp), 0-50 (adaptive)
y3numberMax darkening (halo clamp), 0-50 (adaptive)
amountnumberIntensity percentage, 0-500 (unsharp-mask)
radiusnumberBlur radius, 0.1-5.0 (unsharp-mask)
thresholdnumberMinimum edge brightness, 0-255 (unsharp-mask)
strengthnumberBlend strength, 0-100 (high-pass)
kernelSizenumber3 or 5 for 3x3 / 5x5 kernel (high-pass)
denoisestringNoise reduction pre-pass: off, light, medium, or strong

Parameters are method-specific. Only supply the ones relevant to the chosen method.

color-blindness

Simulate a color vision deficiency using a 3x3 color-recombination matrix.

ParameterTypeDescription
typestringOne of: protanopia, deuteranopia, tritanopia, protanomaly, deuteranomaly, tritanomaly, achromatopsia, blueConeMonochromacy

edit-metadata

Write or remove individual EXIF/IPTC metadata fields without stripping the entire block.

ParameterTypeDescription
artiststringEXIF Artist tag
copyrightstringEXIF Copyright tag
imageDescriptionstringEXIF ImageDescription tag
softwarestringEXIF Software tag
dateTimestringEXIF DateTime tag
dateTimeOriginalstringEXIF DateTimeOriginal tag
clearGpsbooleanRemove all GPS tags
fieldsToRemovestring[]List of EXIF field names to delete

All parameters are optional. Fields listed in fieldsToRemove are deleted from the existing EXIF block. Fields set via the named parameters are written (or overwritten). Binary/unsafe keys like MakerNote are silently ignored.

Format detection

The engine detects input formats automatically from file headers, not just file extensions. This means a .jpg file that is actually a PNG will be handled correctly. Detection uses a multi-layer approach: magic bytes first, then file extension as fallback.

SnapOtter supports 55+ input formats and 13 output formats, including 23 camera RAW formats from 20+ brands, professional formats (PSD, EPS, OpenEXR, HDR), modern codecs (JPEG XL, AVIF, HEIC, QOI, JPEG 2000), and scientific/gaming formats (FITS, DDS). Decoding is handled by Sharp natively where possible, with automatic fallback to ImageMagick, LibRaw, and specialized CLI decoders.

See the Supported Formats page for the complete list.

Metadata extraction

The info tool returns image metadata. See Image Info for the full field reference.

json
{
  "filename": "photo.jpg",
  "fileSize": 2450000,
  "width": 4032,
  "height": 3024,
  "format": "jpeg",
  "channels": 3,
  "hasAlpha": false,
  "colorSpace": "srgb",
  "density": 72,
  "isProgressive": false,
  "hasExif": true,
  "hasIcc": true,
  "hasXmp": false,
  "bitDepth": "8",
  "pages": 1,
  "histogram": [
    { "channel": "red", "min": 0, "max": 255, "mean": 128.45, "stdev": 52.31 },
    { "channel": "green", "min": 2, "max": 253, "mean": 115.22, "stdev": 48.76 },
    { "channel": "blue", "min": 0, "max": 250, "mean": 102.89, "stdev": 55.14 }
  ]
}