dither_it 0.0.4 copy "dither_it: ^0.0.4" to clipboard
dither_it: ^0.0.4 copied to clipboard

A comprehensive Dart library for image dithering with Floyd-Steinberg, Ordered (Bayer), and Riemersma algorithms. Transform images with professional-grade dithering techniques.

DitherIt 🎨 #

License GitHub Stars Dart SDK

DitherIt is a comprehensive Dart library that implements various dithering algorithms for image processing. Transform your images with professional-grade dithering techniques to reduce color depth while maintaining visual quality.

πŸ“Έ Visual Examples #

See the difference dithering makes! Below are examples of each algorithm applied to the same source image:

Original Image #

Original Image
Original image (full color)

Floyd-Steinberg Dithering #

Floyd-Steinberg Result
Floyd-Steinberg algorithm - Classic error diffusion

Ordered Dithering (Bayer Matrix) #

Ordered Dithering Result
Ordered dithering - Regular pattern-based approach

Riemersma Dithering #

Riemersma Result
Riemersma algorithm - Hilbert curve-based natural diffusion

πŸ“· Image Credits

Example image: "Small Copper Butterfly" by Illuvis from Pixabay Used under the Pixabay Content License

See example/IMAGE_CREDITS.md for full attribution details.


✨ Features #

  • Floyd-Steinberg Dithering: Classic error diffusion algorithm with fine-grained results
  • Ordered Dithering: Bayer matrix-based dithering with configurable matrix sizes (2x2, 4x4, 8x8)
  • Riemersma Dithering: Hilbert curve-based error diffusion for natural-looking results
  • High Performance: Optimized algorithms for fast processing
  • Easy to Use: Simple API with comprehensive documentation
  • Well Tested: Extensive test coverage ensuring reliability
  • Pure Dart: No native dependencies, works on all platforms

πŸš€ Getting Started #

Installation #

Add dither_it to your pubspec.yaml:

dependencies:
  image: ^4.2.0  # Required for image processing
  dither_it:
    git:
      url: https://github.com/Penfore/dither_it.git
      ref: main

Then run flutter pub get or dart pub get to install the package.

Run:

dart pub get

Quick Example #

import 'package:dither_it/dither_it.dart';
import 'package:image/image.dart';
import 'dart:io';

void main() async {
  // Load an image
  final bytes = await File('input.jpg').readAsBytes();
  final originalImage = decodeImage(bytes)!;

  // Apply Floyd-Steinberg dithering
  final ditheredImage = DitherIt.floydSteinberg(image: originalImage);

  // Save the result
  await File('output_floyd.png').writeAsBytes(encodePng(ditheredImage));

  print('Dithering complete!');
}

🎯 Algorithms #

Floyd-Steinberg Dithering #

The Floyd-Steinberg algorithm distributes quantization error to neighboring pixels using a specific pattern:

final result = DitherIt.floydSteinberg(image: myImage);

Best for: General purpose dithering, photographs, smooth gradients

Ordered Dithering (Bayer Matrix) #

Uses predefined threshold matrices for consistent, pattern-based dithering:

// 2x2 matrix (fastest, more visible pattern)
final result2x2 = DitherIt.ordered(image: myImage, matrixSize: 2);

// 4x4 matrix (balanced quality/performance)
final result4x4 = DitherIt.ordered(image: myImage, matrixSize: 4);

// 8x8 matrix (finest pattern, slower)
final result8x8 = DitherIt.ordered(image: myImage, matrixSize: 8);

Best for: Animations, real-time processing, consistent patterns

Riemersma Dithering #

Uses a Hilbert curve pattern for more natural-looking error distribution:

// Default history size (16)
final result = DitherIt.riemersma(image: myImage);

// Custom history size for fine-tuning
final resultCustom = DitherIt.riemersma(image: myImage, historySize: 32);

Best for: Natural textures, organic images, artistic effects

πŸ“Š Algorithm Comparison #

Algorithm Speed Quality Pattern Best Use Case
Floyd-Steinberg Medium High Irregular General purpose
Ordered (2x2) Fast Medium Regular Real-time, animations
Ordered (4x4) Fast Good Regular Balanced performance
Ordered (8x8) Medium High Fine High-quality output
Riemersma Slow Very High Organic Artistic, natural images

πŸ”§ Advanced Usage #

Processing Multiple Images #

Future<void> processImageBatch(List<String> imagePaths) async {
  for (final path in imagePaths) {
    final bytes = await File(path).readAsBytes();
    final image = decodeImage(bytes)!;

    // Apply different algorithms
    final floyd = DitherIt.floydSteinberg(image: image);
    final ordered = DitherIt.ordered(image: image, matrixSize: 4);
    final riemersma = DitherIt.riemersma(image: image, historySize: 24);

    // Save results
    await File('${path}_floyd.png').writeAsBytes(encodePng(floyd));
    await File('${path}_ordered.png').writeAsBytes(encodePng(ordered));
    await File('${path}_riemersma.png').writeAsBytes(encodePng(riemersma));
  }
}

🎨 Examples #

Check out our example code to get started quickly:

Basic Example #

See example/dither_it_example.dart for a complete working example that demonstrates all three algorithms:

import 'dart:io';
import 'package:dither_it/dither_it.dart';
import 'package:image/image.dart';

void main() async {
  // Load an image
  final bytes = await File('example/input.png').readAsBytes();
  final image = decodeImage(bytes)!;

  // Apply Floyd-Steinberg dithering
  final floyd = DitherIt.floydSteinberg(image: image);
  await File('example/output_floyd_steinberg.png').writeAsBytes(encodePng(floyd));

  // Apply Ordered dithering
  final ordered = DitherIt.ordered(image: image, matrixSize: 4);
  await File('example/output_ordered.png').writeAsBytes(encodePng(ordered));

  // Apply Riemersma dithering
  final riemersma = DitherIt.riemersma(image: image);
  await File('example/output_riemersma.png').writeAsBytes(encodePng(riemersma));

  print('βœ… Dithering complete! Check the output files.');
}

Visual Results #

The visual examples above show the results of running this code. Compare how each algorithm handles the same input image differently!

Coming Soon #

Additional examples in development:

  • comparison_example.dart - Side-by-side algorithm comparison with metrics (planned)
  • batch_processing.dart - Process multiple images efficiently (planned)
  • flutter_app_example/ - Complete Flutter app with UI (planned)

πŸ”¬ Technical Details #

Algorithm Performance #

Understanding the performance characteristics can help you choose the right algorithm for your use case:

Floyd-Steinberg

  • Processing Speed: Medium - processes each pixel sequentially
  • Memory Usage: Low - only needs to store error values for current and next row
  • Quality: High - excellent error diffusion creates smooth gradients
  • Best for: High-quality results when processing time is not critical

Ordered Dithering

  • Processing Speed: Fast - each pixel is processed independently
  • Memory Usage: Very Low - uses pre-computed threshold matrices
  • Quality: Good - creates consistent patterns, quality depends on matrix size
  • Best for: Real-time applications, animations, or when consistent patterns are desired

Riemersma

  • Processing Speed: Slower - maintains error history for each color channel
  • Memory Usage: Medium - stores error history (default: 16 values Γ— 3 colors = 48 values per pixel)
  • Quality: Very High - natural-looking results with organic error distribution
  • Best for: Artistic applications where quality is more important than speed

Memory Requirements #

Here's what each algorithm needs in terms of additional memory:

  • Floyd-Steinberg: ~4KB extra for a 1920Γ—1080 image (stores one row of error values)
  • Ordered: No extra memory (uses static matrices)
  • Riemersma: ~300KB extra for a 1920Γ—1080 image with default history size

Processing Time Examples #

Approximate processing times for a 1920Γ—1080 image on a modern CPU:

  • Ordered (2Γ—2): ~50ms
  • Ordered (4Γ—4): ~60ms
  • Ordered (8Γ—8): ~80ms
  • Floyd-Steinberg: ~200ms
  • Riemersma: ~400ms

Note: Times vary based on hardware and image complexity

Parallelization Support #

  • Ordered Dithering: βœ… Fully parallelizable - each pixel can be processed independently
  • Floyd-Steinberg: ❌ Sequential processing required due to error propagation
  • Riemersma: ❌ Sequential processing required due to error history dependencies

🀝 Contributing #

We welcome contributions! Here's how you can help:

  1. Bug Reports: Open an issue with detailed reproduction steps
  2. Feature Requests: Suggest new algorithms or improvements
  3. Code Contributions: Fork the repo and submit a pull request
  4. Documentation: Help improve our docs and examples

Development Setup #

# Clone the repository
git clone https://github.com/Penfore/dither_it.git
cd dither_it

# Install dependencies
dart pub get

# Run tests
dart test

# Run example (coming soon)
# cd example
# dart run basic_example.dart

Coding Standards #

  • Follow Dart style guide
  • Maintain 100% test coverage for new features
  • Document public APIs with DartDoc
  • Use meaningful commit messages

πŸ—ΊοΈ Roadmap #

Upcoming Features #

  • ❌ Additional error diffusion algorithms (Jarvis-Judice-Ninke, Stucki, etc.)
  • ❌ Blue noise dithering
  • ❌ Custom color palette support
  • ❌ Performance optimizations with isolates
  • ❌ Web demo application
  • ❌ CLI tool for batch processing

Version History #

See CHANGELOG.md for detailed version history.

πŸ“ License #

This project is licensed under the BSD-3-Clause License - see the LICENSE file for details.

πŸ™ Acknowledgments #

  • Robert Floyd and Louis Steinberg for the pioneering Floyd-Steinberg algorithm
  • Nico Riemersma for the Riemersma dithering technique
  • The Dart team for the excellent image processing foundation
  • Contributors who help improve this library

πŸ“ž Support #


Made with ❀️ by Penfore

Star ⭐ this repository if you find it helpful!

3
likes
155
points
15
downloads

Publisher

unverified uploader

Weekly Downloads

A comprehensive Dart library for image dithering with Floyd-Steinberg, Ordered (Bayer), and Riemersma algorithms. Transform images with professional-grade dithering techniques.

Repository (GitHub)
View/report issues
Contributing

Documentation

Documentation
API reference

License

MIT (license)

Dependencies

image

More

Packages that depend on dither_it