first commit
This commit is contained in:
102
docs/media/image/compress-image/src/adapters/sharp/sharp.md
Normal file
102
docs/media/image/compress-image/src/adapters/sharp/sharp.md
Normal file
@@ -0,0 +1,102 @@
|
||||
# sharp-adapter
|
||||
|
||||
<!-- begin:auto-docs -->
|
||||
_(no submodules)_
|
||||
<!-- end:auto-docs -->
|
||||
## Purpose
|
||||
|
||||
Provides a production-grade `ImageAdapter` implementation backed by the Sharp image processing library. Sharp delivers native-speed JPEG, PNG, WebP, and AVIF encoding through libvips, making it the recommended adapter for server-side workloads where pixel-accurate compression and real resizing are required.
|
||||
|
||||
Sharp is deliberately **not** a direct dependency of this package. The caller supplies a Sharp factory function at construction time, which eliminates the native-addon from the `@suaveplan/compress-image` dependency tree and allows the package to be used in environments where Sharp cannot be installed (e.g., edge runtimes, bundled frontends, or CI test runs).
|
||||
|
||||
## Features
|
||||
|
||||
- Full `ImageAdapter` implementation using the real Sharp pipeline
|
||||
- JPEG progressive encoding, PNG compression levels, WebP lossless, AVIF effort tuning
|
||||
- Metadata stripping by default; opt-in preservation via `stripMetadata: false`
|
||||
- `ResizeMode` mapped to Sharp's `fit` option (cover / contain / fill / inside / outside)
|
||||
- Caller-supplied Sharp factory for dependency injection
|
||||
- Wraps all Sharp errors in `CompressImageError` with cause-chain forwarding
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import sharp from 'sharp';
|
||||
import { SharpAdapter } from '@suaveplan/compress-image/adapters/sharp';
|
||||
import { createCompressor } from '@suaveplan/compress-image/compressor';
|
||||
|
||||
const compressor = createCompressor(new SharpAdapter(sharp));
|
||||
|
||||
const result = await compressor.compress(imageBuffer, {
|
||||
format: 'webp',
|
||||
quality: 75,
|
||||
width: 800,
|
||||
height: 600,
|
||||
});
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import sharp from 'sharp';
|
||||
import { SharpAdapter } from '@suaveplan/compress-image/adapters/sharp';
|
||||
|
||||
const adapter = new SharpAdapter(sharp);
|
||||
|
||||
// Get metadata
|
||||
const info = await adapter.getInfo(jpegBuffer);
|
||||
console.log(info.width, info.height, info.format, info.hasAlpha);
|
||||
|
||||
// Convert JPEG to AVIF with high compression effort
|
||||
const result = await adapter.compress(jpegBuffer, {
|
||||
format: 'avif',
|
||||
quality: 60,
|
||||
effort: 6,
|
||||
stripMetadata: true,
|
||||
});
|
||||
|
||||
// Resize to thumbnail keeping aspect ratio (contain mode)
|
||||
const thumb = await adapter.resize(jpegBuffer, 128, 128, 'contain');
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `interface SharpLike`
|
||||
|
||||
A minimal factory interface matching the Sharp module export signature. Implement this to inject a mock in tests.
|
||||
|
||||
```ts
|
||||
interface SharpLike {
|
||||
(input: Buffer | Uint8Array): SharpInstance;
|
||||
}
|
||||
```
|
||||
|
||||
### `interface SharpInstance`
|
||||
|
||||
The fluent pipeline instance returned by `SharpLike`. Covers the methods used by `SharpAdapter`.
|
||||
|
||||
### `class SharpAdapter implements ImageAdapter`
|
||||
|
||||
#### `constructor(sharp: SharpLike)`
|
||||
|
||||
Stores the provided Sharp factory. No I/O occurs at construction time.
|
||||
|
||||
#### `compress(input: Uint8Array, options: CompressOptions): Promise<CompressResult>`
|
||||
|
||||
Runs the Sharp pipeline with format conversion, quality settings, and optional resize. Returns a `CompressResult` with real output bytes and actual dimensions. Throws `CompressImageError(UNSUPPORTED_FORMAT)` for undetectable inputs; throws `CompressImageError(COMPRESS_FAILED)` for all other Sharp errors.
|
||||
|
||||
#### `getInfo(input: Uint8Array): Promise<ImageInfo>`
|
||||
|
||||
Calls `sharp(input).metadata()` to extract width, height, format, and alpha channel information. Throws `CompressImageError(UNSUPPORTED_FORMAT)` if Sharp returns a format not in the known set.
|
||||
|
||||
#### `resize(input: Uint8Array, width: number, height: number, mode?: ResizeMode): Promise<Uint8Array>`
|
||||
|
||||
Resizes using `sharp.resize()` with the mapped `fit` option. Returns a `Uint8Array` wrapping the Sharp output `Buffer`. Default mode is `'cover'`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
Format encoding options are mapped per-format: JPEG receives `quality` and `progressive`; WebP receives `quality`, `lossless`, and `effort`; AVIF receives `quality` and `effort`; PNG receives `compressionLevel` (mapped from `effort`) but no quality parameter since PNG is lossless.
|
||||
|
||||
A second `.metadata()` pass on the output buffer is used to derive the final `width` and `height` in `CompressResult`. This adds a small overhead but guarantees accuracy after resize operations where the actual output dimensions may differ from the requested values (e.g., when using `inside` or `outside` fit modes).
|
||||
|
||||
Sharp's `Buffer` is wrapped in `new Uint8Array(buffer)` to satisfy the `Uint8Array` contract in `CompressResult.data`, ensuring interoperability with environments that do not use Node.js `Buffer`.
|
||||
Reference in New Issue
Block a user