platform_image_converter 2.1.0
platform_image_converter: ^2.1.0 copied to clipboard
A high-performance Flutter plugin for cross-platform image format conversion using native APIs.
platform_image_converter #
A high-performance Flutter plugin for cross-platform image format conversion and resizing using native APIs on iOS, macOS, Android, Windows, Linux, and Web.
Features #
- 🖼️ Versatile Format Conversion: Supports conversion between JPEG, PNG, and WebP. It also handles HEIC/HEIF, allowing conversion from HEIC on all supported platforms and to HEIC on iOS/macOS, Windows (where the OS HEVC/HEIF codec is present), and Linux (where a writable libheif GdkPixbuf loader is installed).
- 📐 High-Quality Resizing: Resize images with different modes (
Fit,Exact) while maintaining aspect ratio or targeting specific dimensions. - 🧭 EXIF Orientation: Bakes the source's EXIF orientation into the output by default (
ExifOrientationPolicy.apply) so camera photos come out upright and consistent on every platform; opt out withExifOrientationPolicy.ignore. - ⚡ Native Performance: Achieves high speed by using platform-native APIs directly:
ImageIOandCore Graphicson iOS/macOS,BitmapFactoryandBitmapmethods on Android, theWindows Imaging Component(WIC) on Windows,GdkPixbuf(GLib/GTK stack) on Linux, and theCanvas APIon the Web. - 🔒 Efficient Native Interop: Employs FFI and JNI to create a fast, type-safe bridge between Dart and native code, ensuring robust and reliable communication.
Platform Support #
| Platform | Minimum Version | API Used |
|---|---|---|
| iOS | 14.0 | ImageIO, Core Graphics |
| macOS | 10.15 | ImageIO, Core Graphics |
| Android | 7 | BitmapFactory, Bitmap compression |
| Windows | 10 | Windows Imaging Component (WIC) |
| Linux | - | GdkPixbuf (GLib/GTK stack) |
| Web | - | Canvas API |
Note:
- On iOS and macOS, WebP input is supported but WebP output is not supported.
- On Android, HEIC input is supported on Android 9+ but HEIC output is not supported.
- On Windows, JPEG and PNG output are always supported. HEIC output is supported where the OS ships the HEVC/HEIF codec (Windows 11 22H2+ out of the box; older Windows via the Microsoft Store "HEVC Video Extensions") — when the codec is absent, HEIC throws
UnsupportedFormatExceptionwith reasoncodecUnavailable. WebP output is not supported (Windows provides a WebP decoder but no encoder). - On Linux, JPEG and PNG output are always supported (built-in GdkPixbuf loaders). WebP and HEIC output require a writable GdkPixbuf loader module (e.g.
webp-pixbuf-loader, or the libheif GdkPixbuf loader), which varies by distribution — when none is installed, output throwsUnsupportedFormatExceptionwith reasoncodecUnavailable. - On Web, HEIC is not supported.
Getting Started #
Basic Usage #
import 'package:platform_image_converter/platform_image_converter.dart';
import 'dart:typed_data';
// Convert HEIC image to JPEG
final jpegData = await ImageConverter.convert(
inputData: heicImageData,
format: OutputFormat.jpeg,
quality: 90,
);
// Convert and resize an image to fit within a width of 200, scaling height proportionally
final resizedData = await ImageConverter.convert(
inputData: imageData,
format: OutputFormat.png,
resizeMode: const FitResizeMode(width: 200),
);
// Convert any format to PNG
final pngData = await ImageConverter.convert(
inputData: imageData,
format: OutputFormat.png,
);
Supported Formats #
Input Formats #
- iOS/macOS: JPEG, PNG, HEIC, WebP, BMP, GIF, TIFF, and more
- Android: JPEG, PNG, WebP, GIF, BMP, HEIC (via BitmapFactory)
- Windows: JPEG, PNG, GIF, BMP, TIFF, and (with the relevant OS codec) HEIC, WebP (via WIC)
- Linux: JPEG, PNG, GIF, BMP, and (where the relevant GdkPixbuf loader is installed) WebP, HEIC
- Web: JPEG, PNG, WebP, GIF, BMP (via Canvas API)
Output Formats #
The supported output formats are defined by the OutputFormat enum, with platform-specific limitations:
- JPEG: Supported on all platforms.
- PNG: Supported on all platforms.
- WebP: Supported on Android and Web, and on Linux where a writable GdkPixbuf WebP loader is installed.
- HEIC: Supported on iOS/macOS, on Windows where the OS HEVC/HEIF codec is present, and on Linux where a writable libheif GdkPixbuf loader is installed.
API Reference #
ImageConverter.convert() #
static Future<Uint8List> convert({
required Uint8List inputData,
OutputFormat format = OutputFormat.jpeg,
int quality = 100,
ResizeMode resizeMode = const OriginalResizeMode(),
ExifOrientationPolicy orientation = ExifOrientationPolicy.apply,
bool runInIsolate = true,
}) async
Parameters:
inputData(Uint8List): Raw image data to convert.format(OutputFormat): Target image format (default: JPEG).quality(int): Compression quality 1-100 (default: 100, only for lossy formats).resizeMode(ResizeMode): The resize mode to apply. Defaults toOriginalResizeMode, which keeps the original dimensions.orientation(ExifOrientationPolicy): How to handle the source's EXIF orientation tag. Defaults toExifOrientationPolicy.apply, which bakes the orientation into the output pixels (a 90°/270° tag swaps the output width/height, and the resize is evaluated against the oriented dimensions). UseExifOrientationPolicy.ignoreto encode the raw decoded buffer instead.runInIsolate(bool): Whether to run the conversion in a background isolate (default:true). Set tofalseonly for very small images where isolate overhead is a concern.
Returns: Future<Uint8List> containing the converted image data.
Throws: (all conversion failures share the ImageConversionException base type)
ArgumentError: Ifqualityis outside the 1-100 range.UnsupportedPlatformException: If the current platform has no conversion backend.UnsupportedFormatException: If the output format is not available in the current environment. Inspectreasonto tell a permanent platform limitation (platformUnsupported) from a missing codec the user could install (codecUnavailable).ImageDecodingException: If the input image data cannot be decoded.ImageEncodingException: If the image cannot be encoded to the target format.ImageConversionException: For other general errors during the conversion process.
OutputFormat Enum #
enum OutputFormat {
jpeg, // .jpg, .jpeg
png, // .png
webp, // .webp
heic, // .heic
}
ResizeMode Sealed Class #
A sealed class representing different ways to resize an image.
OriginalResizeMode(): Keeps the original dimensions of the image.ExactResizeMode({required int width, required int height}): Resizes the image to exact dimensions, possibly changing the aspect ratio.FitResizeMode({int? width, int? height}): Fits the image within the specified dimensions while maintaining the aspect ratio. At least one ofwidthorheightmust be provided. If only one dimension is provided, the other is scaled proportionally. If the image is smaller than the specified dimensions, it will not be scaled up.
ExifOrientationPolicy Enum #
Controls how the source's EXIF orientation tag is handled. Output never carries orientation metadata (this package strips metadata), so the tag must be baked into the pixels to survive conversion.
apply(default): Bakes the EXIF orientation into the output pixels so the result is visually upright on every platform. A 90°/270° rotation swaps the output width and height, and the resize is evaluated against the oriented (display) dimensions.ignore: Encodes the decoded pixel buffer as-is, ignoring the orientation tag. Use this to keep the raw pixel layout when orientation is handled elsewhere.
Implementation Details #
iOS/macOS Implementation #
The iOS/macOS implementation uses the ImageIO and Core Graphics frameworks via FFI bindings:
- Decoding:
CGImageSourceCreateWithDatareads input data. - Resizing:
CGBitmapContextCreatecreates a new bitmap context with the target dimensions.CGContextDrawImagedraws the original image into the context, scaling it in the process.CGContextSetInterpolationQualityis set to high for better quality.CGBitmapContextCreateImagecreates a newCGImagefrom the context.
- Encoding:
CGImageDestinationCreateWithDataencodes the finalCGImageto the target format. - Quality: Uses
kCGImageDestinationLossyCompressionQualityfor JPEG/HEIC.
Note: Every conversion renders through a fixed 8-bit sRGB context — even when no resize is requested — so iOS/macOS output is always 8-bit sRGB. 16-bit and wide-gamut (e.g. Display P3) sources are not preserved, keeping output consistent with the Android and Web backends.
Android Implementation #
The Android implementation uses BitmapFactory and Bitmap.compress:
- Decoding:
BitmapFactory.decodeByteArrayhandles all supported formats. - Resizing:
Bitmap.createScaledBitmapis used to create a new, resized bitmap from the original, with filtering enabled for smoother results. - Compression:
Bitmap.compressencodes the final bitmap to the target format. - Buffer Management:
ByteArrayOutputStreammanages output data.
Windows Implementation #
The Windows implementation uses the Windows Imaging Component (WIC), a COM-based imaging stack in windowscodecs.dll, bound directly via dart:ffi (no native build step):
- Decoding:
IWICImagingFactory::CreateDecoderFromStream→GetFramedecodes the input. - Normalization:
IWICFormatConverterre-renders the frame to a fixed 32bpp BGRA surface, so output is independent of the source's pixel format (8/16-bit, grayscale, indexed, CMYK). - Resizing:
IWICBitmapScalerwith high-quality cubic interpolation, when the target size differs. - Encoding:
CreateEncoder(by container GUID) →IWICBitmapFrameEncode::WriteSourceencodes into an in-memoryIStream. Quality for JPEG/HEIC is set via the encoder'sImageQualityproperty.
Note: HEIC output requires the OS HEVC/HEIF codec. It ships with Windows 11 22H2+; on older Windows the encoder is absent and HEIC throws UnsupportedFormatException with reason codecUnavailable. WebP output is not available (Windows provides a WebP decoder but no encoder). As with the other backends, every conversion renders through the fixed 8-bit surface even when no resize is requested.
Linux Implementation #
The Linux implementation uses GdkPixbuf, the imaging library in the GLib/GTK stack that the Flutter Linux embedder already links, bound directly via dart:ffi (no native build step):
- Decoding:
GdkPixbufLoaderis fed the input bytes in memory and auto-detects the format via the installed loader modules. - Resizing:
gdk_pixbuf_scale_simplewithGDK_INTERP_HYPER(high-quality resampling) when the target size differs from the source. - Encoding:
gdk_pixbuf_save_to_buffervwrites the target format to an in-memory buffer. Quality for lossy formats (JPEG/WebP/HEIC) is passed via thequalityoption.
Note: JPEG and PNG output are always available. WebP and HEIC depend on a writable GdkPixbuf loader module (e.g. webp-pixbuf-loader, or the libheif GdkPixbuf loader), detected at runtime via gdk_pixbuf_get_formats. When none is installed, output throws UnsupportedFormatException with reason codecUnavailable. GdkPixbuf decodes to an 8-bit RGB/RGBA surface (normalising bit depth like the other backends), but it performs no ICC colour management: unlike the iOS/macOS sRGB normalisation, non-sRGB or wide-gamut sources (e.g. Display P3, Adobe RGB) keep their original pixel values instead of being converted to sRGB. For the common case — sRGB or untagged JPEG/PNG, which is the bulk of real input — output matches the other backends; this caveat only affects colour-managed sources.
Web Implementation #
The Web implementation uses the Canvas API for image conversion:
- Decoding:
HTMLImageElementloads image data via a Blob URL. - Resizing & Rendering:
CanvasRenderingContext2D.drawImagerenders the image to a canvas with the target dimensions, effectively resizing it. - Encoding:
HTMLCanvasElement.toBlobencodes the canvas content to the target format. - Quality: Supports quality parameter for JPEG and WebP (0.0-1.0 scale).
Key Limitations:
- HEIC format is not supported on Web platform.
- Output format depends on browser support (JPEG and PNG are universally supported, WebP is widely supported).