advanced_image_processing_toolkit 0.2.0 copy "advanced_image_processing_toolkit: ^0.2.0" to clipboard
advanced_image_processing_toolkit: ^0.2.0 copied to clipboard

Flutter image processing toolkit with filters, geometric transforms, watermarking, ML-powered detection (objects, faces, text, pose), and AR hooks.

Advanced Image Processing Toolkit #

Advanced Image Processing Toolkit Features

Filters, geometric transforms, watermarking, ML-powered detection, and AR hooks for Flutter.

A Flutter package that combines:

  • Filters — grayscale, blur, brightness, sepia, invert, vignette, watercolor, oil-painting, contrast, saturation
  • Geometric transforms — resize, rotate, crop, flip
  • Watermarking — image overlay compositing
  • ML detection — objects, faces, text (OCR), human pose via Google ML Kit
  • Augmented reality — method-channel bindings (BYO ARKit/ARCore plugins)

Installation #

dependencies:
  advanced_image_processing_toolkit: ^0.2.0

Filters and transforms run on Android, iOS, and Web. ML Kit detection requires Android or iOS (Google ML Kit is mobile-only).

Optional: AR support #

AR is not bundled — it would balloon the install for every consumer. To use AugmentedReality.*, add the platform AR plugins yourself:

dependencies:
  arkit_plugin: ^1.1.0          # iOS
  arcore_flutter_plugin: ^0.1.0 # Android (community-maintained)

Quick start #

import 'package:advanced_image_processing_toolkit/advanced_image_processing_toolkit.dart';

await AdvancedImageProcessingToolkit.initialize(
  enableObjectDetection: true,
  enableAR: false,
);

Filters #

All filter methods are static on ImageFilters, take a Uint8List, and return a Future<Uint8List>.

// Basic
final gray   = await ImageFilters.applyGrayscale(bytes);
final blur   = await ImageFilters.applyBlur(bytes, 5.0);        // sigma
final sepia  = await ImageFilters.applySepia(bytes);
final invert = await ImageFilters.applyInvert(bytes);

// Brightness (delta, -1.0 .. 1.0)
final brighter = await ImageFilters.adjustBrightness(bytes, 0.5);
final darker   = await ImageFilters.adjustBrightness(bytes, -0.5);

// Contrast / saturation (multiplier, 1.0 is neutral)
final contrasty = await ImageFilters.adjustContrast(bytes, 1.5);
final vivid     = await ImageFilters.adjustSaturation(bytes, 1.2);

Artistic effects #

final vignette = await ImageFilters.applyVignette(
  bytes,
  intensity: 0.5,  // 0..1
  radius: 0.5,     // 0..1
);

final watercolor = await ImageFilters.applyWatercolor(
  bytes,
  radius: 5,       // blur radius
  intensity: 0.6,
);

final oil = await ImageFilters.applyOilPainting(
  bytes,
  radius: 4,       // brush size
  levels: 20,      // colour quantisation
);

Geometric transforms #

final resized = await ImageFilters.applyResize(bytes, width: 800); // height auto
final rotated = await ImageFilters.applyRotate(bytes, 90.0);
final cropped = await ImageFilters.applyCrop(bytes, 100, 100, 400, 400);
final flipped = await ImageFilters.applyFlip(bytes, horizontal: true);

Watermarking #

final watermarked = await ImageFilters.applyWatermark(
  baseBytes,
  logoBytes,
  x: 50,
  y: 50,
  opacity: 0.5,
);

Filter chains #

Filters compose by simply passing the output of one into the next:

var out = await ImageFilters.applyGrayscale(bytes);
out     = await ImageFilters.adjustContrast(out, 1.2);
out     = await ImageFilters.applyVignette(out, intensity: 0.3);

ML Kit detection #

ObjectRecognition.detectObjectsFromPath runs object detection, face detection, pose estimation, and text recognition in parallel and returns a unified list of DetectedObject. Filter by label to slice the kind of detection you want.

final detections =
    await ObjectRecognition.detectObjectsFromPath('/path/to/photo.jpg');

for (final d in detections) {
  switch (d.label) {
    case 'Face':
      final smiling = d.additionalData?['smilingProbability'] as double?;
      print('Face (smile=$smiling) at ${d.boundingBox}');
    case 'Text':
      print('OCR: ${d.additionalData?['text']}');
    case 'Person':
      print('Pose with ${(d.additionalData?['landmarks'] as List).length} landmarks');
    default:
      print('${d.label} (${(d.confidence * 100).toStringAsFixed(0)}%) at ${d.boundingBox}');
  }
}

ML Kit requires a file path or accurate InputImageMetadata. If you have raw bytes and you know the image's width/height/stride/format:

final detections = await ObjectRecognition.detectObjectsFromBytes(
  bytes,
  InputImageMetadata(
    size: Size(width.toDouble(), height.toDouble()),
    rotation: InputImageRotation.rotation0deg,
    format: InputImageFormat.bgra8888,
    bytesPerRow: width * 4,
  ),
);

Call ObjectRecognition.dispose() when your app is shutting down to release the underlying ML Kit detectors.

Augmented reality #

if (AugmentedReality.isARSupported()) {
  await AugmentedReality.startARSession();
  await AugmentedReality.placeModel(
    modelPath: 'assets/models/chair.glb',
    position: [0, 0, -1],   // x, y, z
    scale: 1.0,
    rotation: [0, 0, 0],
  );
  // ...
  await AugmentedReality.stopARSession();
}

isARSupported() only checks the OS — it does not verify the consumer app has actually added arkit_plugin / arcore_flutter_plugin. AR calls return false and log a warning if the channel isn't wired.

Platform support #

Platform Filters & transforms ML detection AR
Android Yes Yes Yes (with ARCore plugin)
iOS Yes Yes Yes (with ARKit plugin)
Web Yes No (throws UnsupportedError) No
Desktop Yes No No

Performance tips #

Run heavy filters off the UI thread with compute:

final out = await compute(_grayscale, bytes);
Uint8List _grayscale(Uint8List b) =>
    /* call ImageFilters.applyGrayscale here */;

Resize first, then process — Gaussian blur and oil-painting are quadratic in pixel count:

final small = await ImageFilters.applyResize(huge, width: 1920);
final out   = await ImageFilters.applyBlur(small, 5);

API reference #

See API_REFERENCE.md.

Author #

Godfrey Lebo — Fullstack Developer & Technical PM

License #

MIT — see LICENSE.