optiq-image / index
index
optiq-image — compress images in a Web Worker and get the smallest output that meets a lossless or perceptual (SSIM) constraint. Start with compressImage.
Classes
OptiqError
Extends
Error
Constructors
Constructor
new OptiqError(
code,
message,
details?
): OptiqError;Parameters
| Parameter | Type |
|---|---|
code | OptiqErrorCode |
message | string |
details? | Record<string, unknown> |
Returns
Overrides
Error.constructor
Properties
code
readonly code: OptiqErrorCode;details?
readonly details?: Record<string, unknown>;Interfaces
CandidateReport
Properties
| Property | Type | Description |
|---|---|---|
bytes | number | - |
codec | string | - |
durationMs | number | - |
format | "jpeg" | "png" | "webp" | "avif" | "gif" | "heif" | "svg" | - |
note? | string | - |
passed | boolean | Satisfies the quality constraint (and is exact, for lossless). |
proxy? | boolean | Encoded from the tile mosaic used for quality search on large images; never selected as output. |
quality? | number | SSIM for perceptual candidates, 1 for verified-exact candidates. Undefined if not evaluated. |
qualityMetric? | QualityMetricName | - |
settings | Record<string, number | boolean | string> | - |
CompressCallOptions
Extends
Properties
| Property | Type | Description | Inherited from |
|---|---|---|---|
allowFormatConversion? | boolean | Default true when targetFormat is auto. When false, the output keeps the input format. | OptiqOptions.allowFormatConversion |
allowLossyResize? | boolean | Explicitly permit resizing in lossless mode (the result is then no longer pixel-identical to the input). | OptiqOptions.allowLossyResize |
autoFormats? | OutputFormat[] | Formats considered when targetFormat is auto. Default: jpeg, png, webp, avif. Remove avif if your audience includes browsers without AVIF decoding or encode time matters most. | OptiqOptions.autoFormats |
markOutput? | boolean | Mark lossy JPEG/WebP outputs with a small comment/chunk (~20 bytes) so a later run recognises them and does not re-encode them again (each lossy pass is checked against its own input, so repeated passes compound the loss). Default false in the library; the CLI enables it. AVIF and lossless outputs are not marked. | OptiqOptions.markOutput |
maxCandidates? | number | Maximum number of encodes (candidates) per image. Defaults: visually-lossless 18, balanced 10, lossless 4. | OptiqOptions.maxCandidates |
maxInputBytes? | number | Reject inputs larger than this many bytes before reading them. Default 100 MiB. | OptiqOptions.maxInputBytes |
maxInputPixels? | number | Reject inputs whose header declares more pixels than this (decompression-bomb guard). Default 50 MP. | OptiqOptions.maxInputPixels |
maxOutputBytes? | number | Upper bound for output size. Not a promise: reported in unmetConstraints if impossible. | OptiqOptions.maxOutputBytes |
maxWidthOrHeight? | number | Downscale so that the longest side is at most this. Never applied in lossless mode unless allowLossyResize. | OptiqOptions.maxWidthOrHeight |
minQuality? | number | Minimum SSIM (0..1) for perceptual modes. Defaults: visually-lossless 0.99, balanced 0.975. Ignored in lossless mode. | OptiqOptions.minQuality |
minSavingsRatio? | number | Return the original when the best candidate saves less than this fraction. Default 0.02. | OptiqOptions.minSavingsRatio |
mode? | CompressionMode | Default balanced. | OptiqOptions.mode |
onProgress? | (event) => void | - | - |
onUnmetConstraints? | "best-effort" | "throw" | What to do when no candidate meets all constraints. Default best-effort (result lists unmetConstraints). | OptiqOptions.onUnmetConstraints |
preserveAnimation? | boolean | Default true. When false, animated inputs may be flattened to their first frame (with a warning). | OptiqOptions.preserveAnimation |
preserveMetadata? | boolean | Keep EXIF/XMP and non-sRGB/sRGB ICC profiles. Default true. Setting false strips them (privacy: removes GPS etc). | OptiqOptions.preserveMetadata |
reoptimize? | boolean | Re-encode inputs that carry the Optiq marker anyway. Default false: in perceptual modes a marked input is only optimised at container level (metadata), unless it is resized or converted to an explicitly requested format. | OptiqOptions.reoptimize |
searchStrategy? | SearchStrategy | binary (default) searches quality per codec; fixed encodes each codec once at a preset quality. | OptiqOptions.searchStrategy |
signal? | AbortSignal | - | - |
targetFormat? | TargetFormat | Default auto. | OptiqOptions.targetFormat |
CompressionResult
Properties
| Property | Type | Description |
|---|---|---|
blob | Blob | - |
candidates | CandidateReport[] | - |
category? | ImageCategory | - |
codec? | string | - |
constraintsMet | boolean | - |
durationMs | number | - |
fallbacks | string[] | Codec/runtime fallbacks used (e.g. canvas encoder instead of WASM). Empty when none. |
fileName | string | Suggested file name with the extension matching outputFormat. |
height? | number | - |
metadata | MetadataReport | - |
mimeType | string | - |
mode | CompressionMode | - |
originalBytes | number | - |
originalFormat | DetectedFormat | - |
originalHeight? | number | - |
originalWidth? | number | - |
outputBytes | number | - |
outputFormat | "jpeg" | "png" | "webp" | "avif" | "gif" | "heif" | "svg" | - |
qualityMetric? | number | Quality of the chosen output vs. the reference (input, or resized input). |
qualityMetricName? | QualityMetricName | - |
settings? | Record<string, string | number | boolean> | - |
sizeReductionRatio | number | 1 - outputBytes/originalBytes (negative if larger). |
unmetConstraints | UnmetConstraint[] | - |
usedOriginal | boolean | True when blob is the unmodified input. |
warnings | string[] | - |
width? | number | Dimensions of the output as displayed (after orientation). |
Compressor
Methods
compress()
compress(input, options?): Promise<CompressionResult>;Parameters
| Parameter | Type |
|---|---|
input | Blob |
options? | CompressCallOptions |
Returns
Promise<CompressionResult>
terminate()
terminate(): void;Terminate all workers and reject queued/running jobs.
Returns
void
CompressorConfig
Properties
| Property | Type | Description |
|---|---|---|
allowMainThread? | boolean | Run on the main thread when Workers are unavailable. Default false (throws UNSUPPORTED_ENVIRONMENT): this blocks the UI. |
codecFallback? | CodecFallbackPolicy | Codec fallback when a WASM codec cannot load: canvas (default) uses the browser's own encoders via OffscreenCanvas and reports it in result.fallbacks; none fails with an error instead. |
idleTimeoutMs? | number | Terminate workers idle for this long. Default 30 s. |
maxWorkers? | number | Concurrent jobs (= worker count). Default: min(2, max(1, hardwareConcurrency - 1)). Each job holds a few copies of the decoded image. |
recycleAfterPixels? | number | Terminate the worker after a job whose image had more pixels than this. WebAssembly memory never shrinks, so this is how the codec heaps grown by a large image are returned to the system. Default 8 MP. |
workerFactory? | () => Worker | Custom worker construction (e.g. a bundler-specific ?worker import, or a CDN URL). |
MetadataReport
Properties
OptiqOptions
Extended by
Properties
| Property | Type | Description |
|---|---|---|
allowFormatConversion? | boolean | Default true when targetFormat is auto. When false, the output keeps the input format. |
allowLossyResize? | boolean | Explicitly permit resizing in lossless mode (the result is then no longer pixel-identical to the input). |
autoFormats? | OutputFormat[] | Formats considered when targetFormat is auto. Default: jpeg, png, webp, avif. Remove avif if your audience includes browsers without AVIF decoding or encode time matters most. |
markOutput? | boolean | Mark lossy JPEG/WebP outputs with a small comment/chunk (~20 bytes) so a later run recognises them and does not re-encode them again (each lossy pass is checked against its own input, so repeated passes compound the loss). Default false in the library; the CLI enables it. AVIF and lossless outputs are not marked. |
maxCandidates? | number | Maximum number of encodes (candidates) per image. Defaults: visually-lossless 18, balanced 10, lossless 4. |
maxInputBytes? | number | Reject inputs larger than this many bytes before reading them. Default 100 MiB. |
maxInputPixels? | number | Reject inputs whose header declares more pixels than this (decompression-bomb guard). Default 50 MP. |
maxOutputBytes? | number | Upper bound for output size. Not a promise: reported in unmetConstraints if impossible. |
maxWidthOrHeight? | number | Downscale so that the longest side is at most this. Never applied in lossless mode unless allowLossyResize. |
minQuality? | number | Minimum SSIM (0..1) for perceptual modes. Defaults: visually-lossless 0.99, balanced 0.975. Ignored in lossless mode. |
minSavingsRatio? | number | Return the original when the best candidate saves less than this fraction. Default 0.02. |
mode? | CompressionMode | Default balanced. |
onUnmetConstraints? | "best-effort" | "throw" | What to do when no candidate meets all constraints. Default best-effort (result lists unmetConstraints). |
preserveAnimation? | boolean | Default true. When false, animated inputs may be flattened to their first frame (with a warning). |
preserveMetadata? | boolean | Keep EXIF/XMP and non-sRGB/sRGB ICC profiles. Default true. Setting false strips them (privacy: removes GPS etc). |
reoptimize? | boolean | Re-encode inputs that carry the Optiq marker anyway. Default false: in perceptual modes a marked input is only optimised at container level (metadata), unless it is resized or converted to an explicitly requested format. |
searchStrategy? | SearchStrategy | binary (default) searches quality per codec; fixed encodes each codec once at a preset quality. |
targetFormat? | TargetFormat | Default auto. |
ProgressEvent
Properties
| Property | Type | Description |
|---|---|---|
bestBytes? | number | Smallest valid candidate so far, in bytes. |
candidateBudget | number | - |
candidatesTried | number | Encodes done so far / allowed budget. |
progress | number | Rough overall progress 0..1. |
stage | ProgressStage | - |
Type Aliases
CodecFallbackPolicy
type CodecFallbackPolicy = "canvas" | "none";CompressionMode
type CompressionMode = "lossless" | "visually-lossless" | "balanced" | "fast";lossless: decoded pixels (incl. alpha) of the output are verified to be identical to the input.visually-lossless: decoded pixels may differ; the perceptual difference (SSIM) is kept above a strict threshold.balanced: lower SSIM threshold and smaller search budget; trades some quality for size and speed.fast: same threshold asbalanced, but no AVIF, no oxipng and at most 5 encodes; for phones and batches.
DecodableFormat
type DecodableFormat = "jpeg" | "png" | "webp" | "avif" | "gif";Formats that can be decoded to pixels and re-encoded.
DetectedFormat
type DetectedFormat = "jpeg" | "png" | "webp" | "avif" | "gif" | "heif" | "svg";Formats Optiq can recognise from magic bytes. Recognition is not the same as support.
ImageCategory
type ImageCategory =
| "photo"
| "screenshot"
| "text-graphic"
| "illustration"
| "transparent-illustration"
| "gradient";OptiqErrorCode
type OptiqErrorCode =
| "INVALID_INPUT"
| "UNSUPPORTED_FORMAT"
| "MALFORMED_INPUT"
| "INPUT_TOO_LARGE"
| "INVALID_OPTIONS"
| "INCOMPATIBLE_OPTIONS"
| "CONSTRAINTS_UNSATISFIABLE"
| "CODEC_UNAVAILABLE"
| "UNSUPPORTED_ENVIRONMENT"
| "WORKER_ERROR"
| "ABORTED";OutputFormat
type OutputFormat = "jpeg" | "png" | "webp" | "avif";Formats Optiq can encode.
ProgressStage
type ProgressStage =
| "reading"
| "probing"
| "decoding"
| "analyzing"
| "resizing"
| "encoding"
| "finalizing"
| "done";QualityMetricName
type QualityMetricName = "exact" | "ssim";SearchStrategy
type SearchStrategy = "binary" | "fixed";TargetFormat
type TargetFormat = "auto" | "original" | OutputFormat;UnmetConstraint
type UnmetConstraint =
| {
actual: number;
constraint: "maxOutputBytes";
limit: number;
}
| {
actual: number;
constraint: "minQuality";
limit: number;
}
| {
constraint: "targetFormat";
reason: string;
requested: string;
};Functions
compressImage()
function compressImage(input, options?): Promise<CompressionResult>;Compress an image in a background Web Worker using a shared compressor. Rejects with OptiqError (code), or an AbortError (code ABORTED) when signal aborts.
Parameters
| Parameter | Type |
|---|---|
input | Blob | File |
options? | CompressCallOptions |
Returns
Promise<CompressionResult>
createCompressor()
function createCompressor(config?): Compressor;Parameters
| Parameter | Type |
|---|---|
config? | CompressorConfig |
Returns
fileNameFor()
function fileNameFor(name, format): string;Replace the extension of name with the one matching format.
Parameters
| Parameter | Type |
|---|---|
name | string | undefined |
format | "jpeg" | "png" | "webp" | "avif" | "gif" | "heif" | "svg" |
Returns
string
isOptiqError()
function isOptiqError(e): e is OptiqError;Parameters
| Parameter | Type |
|---|---|
e | unknown |
Returns
e is OptiqError
sniffFormat()
function sniffFormat(b): DetectedFormat | undefined;Identify the format from content only. Extensions and MIME types are never consulted.
Parameters
| Parameter | Type |
|---|---|
b | Uint8Array |
Returns
DetectedFormat | undefined
toFile()
function toFile(result, lastModified?): File;Wrap a result as a File with a name, type and extension that match the encoded bytes.
Parameters
| Parameter | Type |
|---|---|
result | CompressionResult |
lastModified? | number |
Returns
File