doc: README

This commit is contained in:
Koji Wakamiya 2025-12-08 11:07:00 +09:00
parent af7d73d086
commit aa0f5b0fdc
No known key found for this signature in database
1 changed files with 113 additions and 66 deletions

179
README.md
View File

@ -1,92 +1,139 @@
# image_ffi # image_ffi
A new Flutter FFI plugin project. A high-performance Flutter plugin for cross-platform image format conversion using native APIs.
## 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.
- ⚡ **Native Performance**: Achieves high speed by using platform-native APIs directly: ImageIO on iOS/macOS and BitmapFactory on Android.
- 🔒 **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 (CoreFoundation, CoreGraphics) |
| macOS | 10.15 | ImageIO (CoreFoundation, CoreGraphics) |
| Android | 7 | BitmapFactory, Bitmap compression |
| Web | N/A | Not supported |
on Android, HEIC input is supported on Android 9+ but HEIC output is not supported.
## Getting Started ## Getting Started
This project is a starting point for a Flutter ### Installation
[FFI plugin](https://flutter.dev/to/ffi-package),
a specialized package that includes native code directly invoked with Dart FFI.
## Project structure Add `image_ffi` to your `pubspec.yaml`:
This template uses the following structure:
* `src`: Contains the native source code, and a CmakeFile.txt file for building
that source code into a dynamic library.
* `lib`: Contains the Dart code that defines the API of the plugin, and which
calls into the native code using `dart:ffi`.
* platform folders (`android`, `ios`, `windows`, etc.): Contains the build files
for building and bundling the native code library with the platform application.
## Building and bundling native code
The `pubspec.yaml` specifies FFI plugins as follows:
```yaml ```yaml
plugin: dependencies:
platforms: image_ffi: ^0.0.1
some_platform:
ffiPlugin: true
``` ```
This configuration invokes the native build for the various target platforms ### Basic Usage
and bundles the binaries in Flutter applications using these FFI plugins.
This can be combined with dartPluginClass, such as when FFI is used for the ```dart
implementation of one platform in a federated plugin: import 'package:image_ffi/image_ffi.dart';
import 'dart:typed_data';
```yaml // Convert HEIC image to JPEG
plugin: final jpegData = await ImageConverter.convert(
implements: some_other_plugin inputData: heicImageData,
platforms: format: OutputFormat.jpeg,
some_platform: quality: 90,
dartPluginClass: SomeClass );
ffiPlugin: true
// Convert any format to PNG
final pngData = await ImageConverter.convert(
inputData: imageData,
format: OutputFormat.png,
);
``` ```
A plugin can have both FFI and method channels: ## Supported Formats
```yaml ### Input Formats
plugin: - **iOS/macOS**: JPEG, PNG, HEIC, WebP, BMP, GIF, TIFF, and more
platforms: - **Android**: JPEG, PNG, WebP, GIF, BMP, HEIC (via BitmapFactory)
some_platform:
pluginClass: SomeName ### Output Formats
ffiPlugin: true 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 only.
- **HEIC**: Supported on iOS/macOS only.
## API Reference
### `ImageConverter.convert()`
```dart
static Future<Uint8List> convert({
required Uint8List inputData,
OutputFormat format = OutputFormat.jpeg,
int quality = 100,
}) async
``` ```
The native build systems that are invoked by FFI (and method channel) plugins are: **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)
* For Android: Gradle, which invokes the Android NDK for native builds. **Returns:** `Future<Uint8List>` containing the converted image data
* See the documentation in android/build.gradle.
* For iOS and MacOS: Xcode, via CocoaPods.
* See the documentation in ios/image_ffi.podspec.
* See the documentation in macos/image_ffi.podspec.
* For Linux and Windows: CMake.
* See the documentation in linux/CMakeLists.txt.
* See the documentation in windows/CMakeLists.txt.
## Binding to native code **Throws:**
- `UnsupportedError`: If the platform or format is not supported
- `Exception`: If conversion fails
To use the native code, bindings in Dart are needed. ### `OutputFormat` Enum
To avoid writing these by hand, they are generated from the header file
(`src/image_ffi.h`) by `package:ffigen`.
Regenerate the bindings by running `dart run ffigen --config ffigen.yaml`.
## Invoking native code ```dart
enum OutputFormat {
/// JPEG format (.jpg, .jpeg)
/// Lossy compression, suitable for photos
jpeg,
Very short-running native functions can be directly invoked from any isolate. /// PNG format (.png)
For example, see `sum` in `lib/image_ffi.dart`. /// Lossless compression, supports transparency
png,
Longer-running functions should be invoked on a helper isolate to avoid /// WebP format (.webp)
dropping frames in Flutter applications. /// Modern format with superior compression (not supported on Darwin)
For example, see `sumAsync` in `lib/image_ffi.dart`. webp,
## Flutter help /// HEIC format (.heic)
/// High Efficiency Image Format (not supported on Android)
heic,
}
```
For help getting started with Flutter, view our ## Implementation Details
[online documentation](https://docs.flutter.dev), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
### iOS/macOS Implementation
The iOS/macOS implementation uses the [ImageIO](https://developer.apple.com/documentation/imageio) framework via FFI bindings:
1. **Decoding**: `CGImageSourceCreateWithData` reads input data
2. **Rendering**: `CGImageSourceCreateImageAtIndex` decodes to `CGImage`
3. **Encoding**: `CGImageDestinationCreateWithData` encodes to target format
4. **Quality**: Uses `kCGImageDestinationLossyCompressionQuality` for JPEG/WebP
**Key Functions:**
- `CFDataCreate`: Create immutable data from input bytes
- `CGImageSourceCreateWithData`: Create image source from data
- `CGImageDestinationCreateWithData`: Create image destination
- `CGImageDestinationAddImage`: Add image to destination
- `CGImageDestinationFinalize`: Complete encoding
### Android Implementation
The Android implementation uses [BitmapFactory](https://developer.android.com/reference/android/graphics/BitmapFactory) and [Bitmap.compress](https://developer.android.com/reference/android/graphics/Bitmap#compress(android.graphics.Bitmap.CompressFormat,%20int,%20java.io.OutputStream)):
1. **Decoding**: `BitmapFactory.decodeByteArray` handles all supported formats
2. **Compression**: `Bitmap.compress` encodes to target format
3. **Buffer Management**: `ByteArrayOutputStream` manages output data
**Key Limitations:**
- HEIC can be read (input only) but cannot be written (output format not supported)
- Requires Android 9+ for full HEIC support