dsharp 0.1.1
dsharp: ^0.1.1 copied to clipboard
Pure Dart Sharp.js-style image processing for resize, codecs, metadata, compositing, raw pixels, streams, and optional IO.
dsharp
Overview #
dsharp is a pure Dart image processing package for web-safe byte, stream,
raw-pixel, generated-image, and optional file IO workflows. The core library
does not import dart:io.
Use package:dsharp/dsharp.dart on VM and web. Use
package:dsharp/dsharp_io.dart only when native file IO is available.
Install #
dart pub add dsharp
Quick Example #
final png = await ImagePipeline.fromBytes(inputBytes)
.resize(const ResizeOptions(width: 320))
.png()
.toBytes();
Supported Features #
| Area | Support |
|---|---|
| Inputs | Encoded bytes, ByteBuffer, ByteData, bounded byte streams, raw pixels, decoded PixelImage, generated solid/noise images, and deterministic text image descriptors. |
| Core safety | Web-safe core entrypoint with no dart:io, typed exceptions, input byte/pixel limits, cancellation tokens, and output timeouts. |
| Decode | Raw, PNG, JPEG, GIF, TIFF, WebP, PPM/PGM/PBM Netpbm, Radiance HDR/RGBE, and FITS. |
| Encode | Raw, PNG, JPEG, GIF, TIFF, WebP, PPM/PGM/PBM Netpbm, Radiance HDR/RGBE, and FITS. |
| Animation | GIF and WebP frame metadata, delays, loops, retained canvas compositing, frame joins, and animated output paths. |
| Metadata | Encoded header metadata, image dimensions, pages/frames, density, orientation, alpha, comments, XMP, EXIF, ICC payload handling, and per-channel stats. |
| Geometry | Resize, fit modes, extract, extend, trim, flip, flop, rotate, affine transforms, crop strategies, and resampling kernels. |
| Pixel operations | Alpha/channel changes, grayscale, negate, normalize, gamma, tint, linear math, modulation, threshold, convolution, blur, sharpen, median, dilate, erode, and boolean operations. |
| Compositing | Ordered overlays, Porter-Duff and artistic blend modes, alpha handling, exact offsets, gravity placement, tiling, and multi-image joins. |
| Output APIs | toBytes, toBytesWithInfo, toImageBytesResult, format-specific chain methods, typed encoder options, and metadata write options. |
| VM-only IO | imagePipelineFromFile, imagePipelineFromPath, ImageSource.file, writeToFile, and toFile through package:dsharp/dsharp_io.dart. |
Supported Format Matrix #
| Format | Decode | Encode | Animation | Metadata |
|---|---|---|---|---|
| Raw pixels | Yes | Yes | No | Yes |
| PNG | Yes | Yes | No | Yes |
| JPEG/JPG | Yes | Yes | No | Yes |
| GIF | Yes | Yes | Yes | Yes |
| TIFF/TIF | Yes | Yes | Multi-page | Yes |
| WebP | Yes | Yes | Yes | Yes |
| PPM/PGM/PBM | Yes | Yes | No | Yes |
| Radiance HDR/RGBE | Yes | Yes | No | Yes |
| FITS | Yes | Yes | No | Yes |
Unsupported native-only or advanced formats such as AVIF, HEIF, JP2, JXL, PDF,
OpenEXR, OpenSlide, Magick, camera raw, native V, deep zoom, and SVG
rasterization fail with typed UnsupportedCodecExceptions.
Usage #
Bytes #
final output = await ImagePipeline.fromBytes(inputBytes)
.resize(const ResizeOptions(width: 320))
.webp()
.toBytesWithInfo();
Stream #
final source = ImageSource.stream(byteStream, maxBytes: 10 * 1024 * 1024);
final info = await ImagePipeline.fromSource(source).metadata();
Raw Pixels #
final raw = RawPixels(
bytes: pixels,
width: 64,
height: 64,
channels: ChannelCount.four,
);
final jpeg = await ImagePipeline.fromRawPixels(raw).jpeg().toBytes();
Composite #
final output = await ImagePipeline.fromRawPixels(base)
.composite([
CompositeLayer(image: PixelImage.fromRawPixels(overlay), left: 8, top: 8),
])
.png()
.toBytesWithInfo();
Metadata and Stats #
final pipeline = ImagePipeline.fromBytes(inputBytes);
final metadata = await pipeline.metadata();
final stats = await pipeline.stats();
Metadata Writes #
final output = await ImagePipeline.fromBytes(inputBytes)
.withMetadata(
MetadataWriteOptions(
xmp: XmpMetadata.parse('<x:xmpmeta></x:xmpmeta>'),
keepExif: true,
keepIcc: true,
),
)
.png()
.toBytes();
Cancellation and Timeout #
final token = CancellationToken();
final bytes = await ImagePipeline.fromBytes(inputBytes)
.timeout(const Duration(seconds: 2))
.resize(const ResizeOptions(width: 640))
.jpeg()
.toBytes(cancellationToken: token);
Native File IO #
import 'package:dsharp/dsharp_io.dart';
final pipeline = await imagePipelineFromPath('input.png');
await pipeline.resize(const ResizeOptions(width: 256)).png().writeToFile(
File('output.png'),
);
More runnable examples live in example/.
Security Limits #
Use InputSafetyLimits with byte, stream, raw, decoded, and generated sources
for untrusted input. Raw pixel descriptors validate layout before processing.
Unsupported codecs, malformed images, invalid operations, and cancelled
pipelines throw typed ImageProcessingException subclasses.
Contributing #
See CONTRIBUTING.md.
Development #
dart pub get
dart run melos bootstrap
dart run melos run format
dart run melos run analyze
dart run melos run test
dart run melos run coverage
Benchmark Results #
| Scenario | Time |
|---|---|
jpeg_decode_resize_encode |
17728.39 us |
png_rgba_resize |
8597.63 us |
random_dimension_resize |
5838.42 us |
raw_operation_chain |
5113.07 us |
composite_over |
5156.09 us |