Files
2026-05-27 23:29:53 +01:00

38 lines
2.0 KiB
Markdown

# Capability Spec: compress-image
**Package**: `@suaveplan/compress-image`
**Version**: 0.0.0 (genesis)
**Status**: ADDED
---
## ADDED Requirements
### CI-01 — Format coverage
`VALID_FORMATS` MUST include `'jpeg' | 'png' | 'webp' | 'avif'`. Each format MUST have a working adapter invoked by the dispatcher.
### CI-02 — Compression API
`ImageCompressor.compress(input, options?)` MUST accept `Uint8Array | ArrayBuffer | Blob`, resolve options to a `ResolvedCompressionOptions`, build a `CompressionPlan`, and execute it to produce `CompressionResult { format, bytes, width, height, durationMs, steps: CompressionStep[], inputBytes, outputBytes, savedBytes }`.
### CI-03 — Quality presets
`QUALITY_PRESETS` MUST define `'maximum' | 'high' | 'balanced' | 'fast' | 'aggressive'` with deterministic per-format quality values obeying `FORMAT_QUALITY_RANGES`. Custom `options.quality` numeric values outside the format range MUST throw `COMPRESS_IMAGE.INVALID_QUALITY`.
### CI-04 — Max dimension
`options.maxDimension` MUST resize the longest side to at most the given pixel count. A resize step MUST appear in `CompressionPlan.steps`. Inputs exceeding `MAX_DIMENSION` (default 20 000) MUST throw `COMPRESS_IMAGE.DIMENSION_TOO_LARGE`.
### CI-05 — Degenerate output
If `outputBytes > inputBytes` and `options.preserveSmaller` is `true` (default), the compressor MUST return the original input with a `CompressionStep { action: 'skip', reason: 'output-larger-than-input' }`. Otherwise the larger compressed output is returned.
### CI-06 — Format selection
When `options.format` is omitted, the compressor MUST keep the input format. `options.format: 'auto'` MUST choose based on input type (`jpeg` → `webp` at lower size if supported; `png` with alpha → `webp`/`avif`; etc.).
### CI-07 — Observability
Every compress call MUST record `compress_image.compress.duration_ms{format, preset}`, `compress_image.compress.total{format, outcome}`, and `compress_image.bytes.saved{format}` gauge.