palette_generator_master 1.1.0 copy "palette_generator_master: ^1.1.0" to clipboard
palette_generator_master: ^1.1.0 copied to clipboard

A powerful Flutter package for extracting prominent colors from images with advanced features and accessibility compliance.

Palette Generator Master #

Pub Version Flutter Dart License

A powerful Flutter package for extracting prominent colors from images with advanced features including multi-color space support, accessibility compliance, and color harmony generation.

This package is a complete rewrite and enhancement of the discontinued palette_generator package (0.3.3+7) with modern Flutter development practices, enhanced performance, and new capabilities.

✨ Features #

🎨 Advanced Color Extraction #

  • Multi-color space support: RGB, HSV, and LAB color spaces for more accurate analysis
  • Enhanced quantization algorithms for better color clustering
  • Improved dominant color detection with advanced scoring
  • Customizable target colors (vibrant, muted, light, dark variations)

♿ Accessibility First #

  • WCAG 2.1 compliance checking for color contrast
  • Automatic contrast ratio calculation between color pairs
  • Best text color selection for any background color
  • Accessible color pair generation with customizable contrast thresholds

🌈 Color Harmony #

  • Automatic harmony generation based on color theory principles
  • Complementary, analogous, triadic, and split-complementary color schemes
  • Customizable harmony algorithms for different design needs

⚡ Performance & Quality #

  • Optimized algorithms for faster processing
  • Memory-efficient color analysis with 5-bit quantization
  • Null safety throughout the codebase
  • Modern Flutter practices with comprehensive error handling
  • Timeout management for network images

🚀 Getting Started #

Installation #

Add this package to your pubspec.yaml:

dependencies:
  palette_generator_master: ^1.1.0

Then run:

flutter pub get

Basic Usage #

import 'package:flutter/material.dart';
import 'package:palette_generator_master/palette_generator_master.dart';

// Generate palette from an image
Future<void> generatePalette() async {
  // Load your image
  final ImageProvider imageProvider = AssetImage('assets/my_image.jpg');
  
  // Generate palette
  final PaletteGeneratorMaster paletteGenerator = 
      await PaletteGeneratorMaster.fromImageProvider(
    imageProvider,
    maximumColorCount: 16,
    generateHarmony: true,      // Generate color harmony
  );
  
  // Access extracted colors
  final Color? dominantColor = paletteGenerator.dominantColor?.color;
  final Color? vibrantColor = paletteGenerator.vibrantColor?.color;
  final Color? mutedColor = paletteGenerator.mutedColor?.color;
  
  // Get all extracted colors
  final List<PaletteColorMaster> allColors = paletteGenerator.paletteColors;
  
  // Get harmony colors
  final List<ColorHarmonyMaster> harmonyColors = paletteGenerator.harmonyColors;
  
  // Use colors in your UI
  return Container(
    color: dominantColor,
    child: Text(
      'Dominant Color',
      style: TextStyle(
        color: paletteGenerator.getBestTextColorFor(dominantColor!),
      ),
    ),
  );
}

📖 Advanced Usage #

Custom Color Targets #

final PaletteGeneratorMaster generator = 
    await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  targets: [
    PaletteTargetMaster.vibrant,
    PaletteTargetMaster.darkVibrant,
    PaletteTargetMaster.lightMuted,
    // Create custom target
    PaletteTargetMaster(
      saturationWeight: 0.8,
      lightnessWeight: 0.6,
      populationWeight: 0.4,
      minimumSaturation: 0.3,
      maximumSaturation: 0.9,
      minimumLightness: 0.2,
      maximumLightness: 0.8,
      targetSaturation: 0.6,
      targetLightness: 0.5,
      isExclusive: true,
    ),
  ],
);

Accessibility Features #

// Get accessible color pairs
final List<AccessibleColorPair> accessiblePairs = 
    generator.getAccessibleColorPairs(
  minimumContrast: 4.5, // WCAG AA standard
);

// Check each pair
for (var pair in accessiblePairs) {
  print('Foreground: ${pair.foreground}');
  print('Background: ${pair.background}');
  print('Contrast Ratio: ${pair.contrastRatio}');
  print('Meets WCAG AA: ${pair.meetsWcagAA}');
  print('Meets WCAG AAA: ${pair.meetsWcagAAA}');
}

// Get best text color for a background
final Color backgroundColor = Colors.blue;
final Color textColor = generator.getBestTextColorFor(
  backgroundColor,
  minimumContrast: 4.5,
);

// Check contrast ratio between two colors
final double contrastRatio = AccessibilityHelperMaster.calculateContrastRatio(
  Colors.white,
  Colors.blue,
);

Working with Different Image Sources #

// From asset image
final generator1 = await PaletteGeneratorMaster.fromImageProvider(
  AssetImage('assets/image.jpg'),
);

// From network image with custom timeout
final generator2 = await PaletteGeneratorMaster.fromImageProvider(
  NetworkImage('https://example.com/image.jpg'),
  timeout: Duration(seconds: 30),
  maximumColorCount: 24,
);

// From ui.Image
final ui.Image image = await loadImageFromSomewhere();
final generator3 = await PaletteGeneratorMaster.fromImage(
  image,
  region: Rect.fromLTWH(0, 0, 100, 100), // Process only a region
);

// From byte data
final ByteData imageData = await loadImageBytes();
final generator4 = await PaletteGeneratorMaster.fromByteData(
  EncodedImageMaster(
    imageData,
    width: 800,
    height: 600,
    name: 'my_image',
  ),
  maximumColorCount: 16,
);

// From network with error handling
try {
  final generator = await PaletteGeneratorMaster.fromImageProvider(
    NetworkImage('https://example.com/image.jpg'),
    timeout: Duration(seconds: 10),
  );
} catch (e) {
  print('Failed to load image: $e');
  // Handle error gracefully
}

Color Analysis and Information #

// Get detailed color information
final PaletteColorMaster dominant = generator.dominantColor!;
print('Color: ${dominant.color}');
print('Population: ${dominant.population}');
print('Luminance: ${dominant.luminance}');
print('Is Dark: ${dominant.isDark}');
print('Is Light: ${dominant.isLight}');

// Get all colors with their populations
for (var color in generator.paletteColors) {
  print('Color: ${color.color}, Population: ${color.population}');
}

// Get specific target colors
final vibrant = generator.vibrantColor;
final lightVibrant = generator.lightVibrantColor;
final darkVibrant = generator.darkVibrantColor;
final muted = generator.mutedColor;
final lightMuted = generator.lightMutedColor;
final darkMuted = generator.darkMutedColor;

Color Harmony Examples #

// Generate harmony colors
final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  generateHarmony: true,
);

// Use different harmony types
for (var harmony in generator.harmonyColors) {
  switch (harmony.type) {
    case HarmonyType.complementary:
      print('Complementary colors: ${harmony.colors}');
      break;
    case HarmonyType.analogous:
      print('Analogous colors: ${harmony.colors}');
      break;
    case HarmonyType.triadic:
      print('Triadic colors: ${harmony.colors}');
      break;
    case HarmonyType.splitComplementary:
      print('Split complementary colors: ${harmony.colors}');
      break;
  }
}

// Create a color scheme widget
Widget buildColorScheme(PaletteGeneratorMaster generator) {
  final dominant = generator.dominantColor!.color;
  final harmonies = generator.harmonyColors;
  
  return Column(
    children: [
      Container(color: dominant, height: 50),
      if (harmonies.isNotEmpty)
        for (var harmony in harmonies.first.colors)
          Container(color: harmony, height: 50),
    ],
  );
}

Custom Filters #

// Create custom filter to exclude specific colors
bool excludeRedColors(HSLColor color) {
  // Exclude colors with high red saturation
  return color.hue < 350 && color.hue > 10;
}

// Create filter for pastel colors only
bool pastelColorsOnly(HSLColor color) {
  return color.saturation < 0.3 && color.lightness > 0.7;
}

// Use custom filters
final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  filters: [
    avoidRedBlackWhitePaletteFilterMaster,
    excludeRedColors,
    pastelColorsOnly,
  ],
);

🎯 API Reference #

PaletteGeneratorMaster #

The main class for generating color palettes from images.

Static Methods

// Generate from ImageProvider
static Future<PaletteGeneratorMaster> fromImageProvider(
  ImageProvider imageProvider, {
  Size? size,
  Rect? region,
  int maximumColorCount = 16,
  List<PaletteFilterMaster> filters = const [avoidRedBlackWhitePaletteFilterMaster],
  List<PaletteTargetMaster> targets = const [],
  Duration timeout = const Duration(seconds: 15),
  ColorSpace colorSpace = ColorSpace.rgb,
  bool generateHarmony = true,
})

// Generate from ui.Image
static Future<PaletteGeneratorMaster> fromImage(
  ui.Image image, {
  Rect? region,
  int maximumColorCount = 16,
  List<PaletteFilterMaster> filters = const [avoidRedBlackWhitePaletteFilterMaster],
  List<PaletteTargetMaster> targets = const [],
  ColorSpace colorSpace = ColorSpace.rgb,
  bool generateHarmony = true,
})

// Generate from encoded image data
static Future<PaletteGeneratorMaster> fromByteData(
  EncodedImageMaster encodedImage, {
  Rect? region,
  int maximumColorCount = 16,
  List<PaletteFilterMaster> filters = const [avoidRedBlackWhitePaletteFilterMaster],
  List<PaletteTargetMaster> targets = const [],
  ColorSpace colorSpace = ColorSpace.rgb,
  bool generateHarmony = true,
})

Properties

// Target colors
PaletteColorMaster? get vibrantColor;
PaletteColorMaster? get lightVibrantColor;
PaletteColorMaster? get darkVibrantColor;
PaletteColorMaster? get mutedColor;
PaletteColorMaster? get lightMutedColor;
PaletteColorMaster? get darkMutedColor;
PaletteColorMaster? get dominantColor;

// All extracted colors
List<PaletteColorMaster> get paletteColors;
Iterable<Color> get colors;

// Harmony colors (if generated)
List<ColorHarmonyMaster> get harmonyColors;

// Source image info
ImageInfoMaster? get sourceImageInfo;

Methods

// Get accessible color pairs
List<AccessibleColorPair> getAccessibleColorPairs({
  double minimumContrast = 4.5,
});

// Get best text color for background
Color getBestTextColorFor(
  Color backgroundColor, {
  double minimumContrast = 4.5,
});

PaletteColorMaster #

Represents a color in the palette with additional information.

class PaletteColorMaster {
  final Color color;
  final int population;
  
  // Properties
  double get luminance;
  bool get isDark;
  bool get isLight;
}

PaletteTargetMaster #

Defines target characteristics for color extraction.

class PaletteTargetMaster {
  final double saturationWeight;
  final double lightnessWeight;
  final double populationWeight;
  final double minimumSaturation;
  final double maximumSaturation;
  final double targetSaturation;
  final double minimumLightness;
  final double maximumLightness;
  final double targetLightness;
  final bool isExclusive;
  
  // Predefined targets
  static const PaletteTargetMaster vibrant;
  static const PaletteTargetMaster lightVibrant;
  static const PaletteTargetMaster darkVibrant;
  static const PaletteTargetMaster muted;
  static const PaletteTargetMaster lightMuted;
  static const PaletteTargetMaster darkMuted;
  static const List<PaletteTargetMaster> baseTargets;
}

EncodedImageMaster #

Container for encoded image data.

class EncodedImageMaster {
  const EncodedImageMaster(
    ByteData byteData, {
    required int width,
    required int height,
    ImageByteFormat format = ImageByteFormat.rawRgba,
    String? name,
  });
  
  final ByteData byteData;
  final int width;
  final int height;
  final ImageByteFormat format;
  final String? name;
  
  int get pixelCount;
  double get aspectRatio;
}

ColorHarmonyMaster #

Represents a color harmony scheme.

class ColorHarmonyMaster {
  const ColorHarmonyMaster(HarmonyType type, List<Color> colors);
  
  final HarmonyType type;
  final List<Color> colors;
  
  static List<ColorHarmonyMaster> generateHarmonyColors(Color base);
}

HarmonyType #

enum HarmonyType { 
  complementary,    // 180° apart
  triadic,         // 120° apart
  analogous,       // 30° apart
  splitComplementary  // Base + complement neighbors
}

AccessibilityHelperMaster #

Static utility class for accessibility features.

class AccessibilityHelperMaster {
  static Color getBestTextColor(Color background);
  static bool meetsWcagAA(double contrastRatio, {bool isLargeText = false});
  static bool meetsWcagAAA(double contrastRatio, {bool isLargeText = false});
  static double calculateContrastRatio(Color foreground, Color background);
  static List<AccessibleColorPair> generateAccessiblePairs(
    List<PaletteColorMaster> colors, {
    double minimumContrast = 4.5
  });
}

AccessibleColorPair #

Represents a pair of colors with contrast information.

class AccessibleColorPair {
  const AccessibleColorPair(Color foreground, Color background, double contrastRatio);
  
  final Color foreground;
  final Color background;
  final double contrastRatio;
  
  bool get meetsWcagAA;
  bool get meetsWcagAAA;
  bool get meetsWcagAALarge;
  bool get meetsWcagAAALarge;
}

🎨 Color Spaces #

RGB (Red, Green, Blue) #

  • Best for: General purpose, web colors
  • Characteristics: Device-dependent, intuitive for developers
  • Use when: Working with standard web/mobile colors

HSV (Hue, Saturation, Value) #

  • Best for: Color manipulation, artistic applications
  • Characteristics: More intuitive for humans, easier color adjustments
  • Use when: Need to adjust brightness/saturation programmatically

LAB (Lightness, A*, B*) #

  • Best for: Perceptually uniform color analysis
  • Characteristics: Device-independent, perceptually uniform
  • Use when: Need most accurate color analysis (recommended)

♿ Accessibility Guidelines #

This package follows WCAG 2.1 guidelines:

Contrast Ratios #

  • AA Level: 4.5:1 for normal text, 3:1 for large text
  • AAA Level: 7:1 for normal text, 4.5:1 for large text

Usage Examples #

// Check if colors meet WCAG AA
final bool isAccessible = AccessibilityHelperMaster.meetsWcagAA(
  contrastRatio,
  isLargeText: false,
);

// Generate only AA compliant pairs
final accessiblePairs = generator.getAccessibleColorPairs(
  minimumContrast: 4.5,
);

// Get best text color with custom logic
final textColor = generator.getBestTextColorFor(backgroundColor);

🔄 Migration from palette_generator #

If you're migrating from the discontinued palette_generator package:

Class Name Changes #

Old Class New Class
PaletteGenerator PaletteGeneratorMaster
PaletteColor PaletteColorMaster
PaletteTarget PaletteTargetMaster
EncodedImage EncodedImageMaster

API Changes #

// Old way
final PaletteGenerator generator = await PaletteGenerator.fromImageProvider(
  AssetImage('image.jpg'),
);

// New way
final PaletteGeneratorMaster generator = await PaletteGeneratorMaster.fromImageProvider(
  AssetImage('image.jpg'),
  generateHarmony: true,      // New: harmony generation
);

Property Changes #

// Old
Color? dominantColor = generator.dominantColor;

// New
PaletteColorMaster? dominant = generator.dominantColor;
Color? dominantColor = generator.dominantColor?.color;

New Features Not in Original #

  • Multi-color space support (RGB, HSV, LAB)
  • Accessibility features and WCAG compliance
  • Color harmony generation with 4 different schemes
  • Enhanced performance and accuracy with 5-bit quantization
  • Modern null-safe API
  • Region-based processing
  • Custom filters support
  • Timeout handling for network images

📱 Example App #

The package includes a comprehensive example app that demonstrates all features:

  • Interactive color space selection
  • Real-time accessibility information
  • Color harmony visualization
  • Detailed color information with copy-to-clipboard
  • Modern Material 3 design
  • Image picker integration
  • Custom target configuration

To run the example:

cd example
flutter run

⚡ Performance Tips #

  1. Use appropriate color space: RGB for speed, LAB for accuracy
  2. Limit maximum colors: 16 colors usually sufficient for most use cases
  3. Use region parameter: Process only relevant parts of large images
  4. Use filters: Filter out unwanted colors early in the process
  5. Cache results: Store generated palettes for reuse
  6. Adjust sampling rate: The package uses step 2 sampling by default for balance
// Optimized for performance
final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  maximumColorCount: 12,     // Reasonable limit
  generateHarmony: false,     // Skip if not needed
  filters: [avoidRedBlackWhitePaletteFilterMaster], // Filter unwanted colors
);

// Optimized for accuracy
final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  maximumColorCount: 24,
  generateHarmony: true,
  colorSpace: ColorSpace.lab, // Most accurate
);

// Cache the result
final cachedGenerator = generator;

🐛 Troubleshooting #

Common Issues #

Q: Colors look different than expected A: Try using LAB color space for more perceptually accurate results.

final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  colorSpace: ColorSpace.lab,
);

Q: Performance is slow A: Reduce maximumColorCount or use RGB color space instead of LAB.

final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  maximumColorCount: 8,
  colorSpace: ColorSpace.rgb,
);

Q: Not getting vibrant colors A: Adjust the target parameters or use a custom PaletteTargetMaster.

final customVibrant = PaletteTargetMaster(
  minimumSaturation: 0.5,
  targetSaturation: 0.8,
  saturationWeight: 0.7,
  // ... other parameters
);

Q: Accessibility pairs are empty A: Lower the minimumContrast threshold or ensure your image has sufficient color variety.

final pairs = generator.getAccessibleColorPairs(
  minimumContrast: 3.0, // Lower threshold
);

Q: Network images timeout A: Increase the timeout duration for large images or slow connections.

final generator = await PaletteGeneratorMaster.fromImageProvider(
  NetworkImage('https://example.com/large-image.jpg'),
  timeout: Duration(seconds: 30),
);

Q: Memory issues with large images A: Use region parameter to process only a portion of the image.

final generator = await PaletteGeneratorMaster.fromImageProvider(
  imageProvider,
  region: Rect.fromLTWH(0, 0, 500, 500),
  maximumColorCount: 12,
);

📄 License #

This package is licensed under the BSD 3-Clause License. See the LICENSE file for details.

🙏 Acknowledgements #

  • Original palette_generator package authors
  • Android Palette API for inspiration
  • WCAG guidelines documentation
  • Flutter community for feedback and contributions

📞 Support #

🤝 Contributing #

Contributions are welcome! Please read our Contributing Guide for details.

DME is written in clear, professional English with proper formatting and structure suitable for pub.dev publication.

11
likes
160
points
3.69k
downloads

Documentation

Documentation
API reference

Publisher

verified publisherswanflutterdev.com

Weekly Downloads

A powerful Flutter package for extracting prominent colors from images with advanced features and accessibility compliance.

Repository (GitHub)
View/report issues

Topics

#color #palette #image #accessibility #ui

License

MIT (license)

Dependencies

collection, flutter

More

Packages that depend on palette_generator_master