simple_native_image_compress

A simple native image compression library for Flutter written in rust using flutter_rust_bridge, image, cargokit, kamadak-exif and anyhow

Why?

  1. For some reason, image compression in Dart is slow. Even with isolate.
  2. There is no native libraries that supports WINDOWS & LINUX when it comes to image compression.

What does it do?

  • If path for an image file is given, it will resize and return Jpeg/WebP image as Uint8List.

What it does not do

  • Web Support with WASM. Since I use Angular for Web not Flutter

Prerequisite

  1. Rust
  2. Android NDK for Android

Setup

  1. Follow the instructions here and install Rust
  2. If installed already
rustup update

Android

  1. Install rust tools for Android
cargo install cargo-ndk
rustup target add aarch64-linux-android armv7-linux-androideabi x86_64-linux-android i686-linux-android
  1. Since simple_native_image_compress requires Android NDK, install Android NDK via Android Studio and add ndkVersion in android/app/build.gradle.
android {
    // by default the project uses NDK version from flutter plugin.
    ndkVersion flutter.ndkVersion

Apple

  1. Install rust tools for Apple
cargo install cargo-xcode
cargo install cargo-lipo
  1. If you are targeting iOS
rustup target add aarch64-apple-ios x86_64-apple-ios aarch64-apple-ios-sim

Supported Output Formats

  • Jpeg
  • WebP
    • lossless only
  • AVIF
    • lossy only
    • speed parameter can be given in the range 1-10, where 1 is the slowest and 10 is the fastest. Default is 10.

Sampling Filter Types

  • 5 types of sampling filters are available and can be selected
    1. Nearest, // Nearest Neighbor
    2. Triangle, // Linear Filter (DEFAULT)
    3. CatmullRom, // Cubic Filter
    4. Gaussian, // Gaussian Filter
    5. Lanczos3, // Lanczos with window 3
  • you can read more about sampling filters here image crate doc

Example

  1. Initialize Simple Native Image Compress in main function
Future<void> main() async {
  await NativeImageCompress.init();
  runApp(const MaterialApp(home: MyApp()));
}
  1. After initialization call static methods from ImageCompress class

"contain" will make the image fit into the given max width/height.

try{
  final bytes = await ImageCompress.contain(
    filePath: yourFilePath,
    compressFormat: CompressFormat.avif,
    speed: 3, // only for AVIF
    quality: 90,
    maxWidth: 512,
    maxHeight: 512,
    samplingFilter: FilterType.Lanczos3
  );
} catch (e) {
  print(e);
}

"fitWidth" will make the image fit into the given max width.

try{
  final bytes = await ImageCompress.fitWidth(
    filePath: yourFilePath,
    compressFormat: CompressFormat.webP,
    maxWidth: 512,
    samplingFilter: FilterType.Lanczos3
  );
} catch (e) {
  print(e);
}

"fitHeight" will make the image fit into the given max height.

try{
  final bytes = await ImageCompress.fitHeight(
    filePath: yourFilePath,
    compressFormat: CompressFormat.jpeg,
    maxHeight: 512,
    samplingFilter: FilterType.Lanczos3
  );
} catch (e) {
  print(e);
}

Default values

  • Default value for width and/or height is 1024 px
  • Default value for Jpeg/AVIF quality is 80 (For webP Quality does nothing)
  • Default value for samplingFilter is FilterType.Triangle
  • Default value for AVIF speed is 10