palette_generator_master 1.1.0
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 #
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 #
- Use appropriate color space: RGB for speed, LAB for accuracy
- Limit maximum colors: 16 colors usually sufficient for most use cases
- Use region parameter: Process only relevant parts of large images
- Use filters: Filter out unwanted colors early in the process
- Cache results: Store generated palettes for reuse
- 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_generatorpackage authors - Android Palette API for inspiration
- WCAG guidelines documentation
- Flutter community for feedback and contributions
📞 Support #
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Email: support@palettegenerator.dev
🤝 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.