1. 插件介绍

1.1 功能概述

Palette Generator 是一个 Flutter 包,用于从图像中提取突出的颜色,主要用于为用户界面寻找合适的配色方案。该包通过分析图像的像素数据,使用优化的颜色量化算法提取出最具代表性的颜色,并将这些颜色分类为不同的类型(如鲜艳色、柔和色、暗色等)。

1.2 主要特性

  • 支持从多种图像源提取颜色(ImageProvider、Image、ByteData)
  • 自动识别多种类型的颜色:
    • 鲜艳色(Vibrant)
    • 暗鲜艳色(Dark Vibrant)
    • 亮鲜艳色(Light Vibrant)
    • 柔和色(Muted)
    • 暗柔和色(Dark Muted)
    • 亮柔和色(Light Muted)
  • 支持自定义颜色提取目标
  • 内置颜色过滤功能
  • 提供对比鲜明的标题文字和正文文字颜色建议

1.3 鸿蒙平台支持

该自定义修改版本的 Palette Generator 包已适配鸿蒙平台,支持在鸿蒙设备上从图像中提取颜色,帮助开发者创建与图像内容协调的用户界面。

2. 安装与配置

2.1 Git 依赖引入

由于这是一个自定义修改版本的包,需要通过 Git 形式引入。在项目的 pubspec.yaml 文件中添加以下依赖:

dependencies:
  palette_generator:
    git:
      url: "https://gitcode.com/openharmony-tpc/flutter_packages.git"
      path: "packages/palette_generator"

2.2 版本兼容性

  • 鸿蒙平台:API 9 及以上
  • Flutter 版本:>= 3.7.0
  • Dart 版本:>= 2.19.0 < 4.0.0

3. API 调用示例

3.1 核心类介绍

PaletteGenerator

PaletteGenerator 是该包的核心类,用于从图像中提取颜色。主要方法包括:

  • fromImageProvider(): 从 ImageProvider(如 AssetImage、NetworkImage)创建 PaletteGenerator
  • fromImage(): 从 dart:ui.Image 创建 PaletteGenerator
  • fromByteData(): 从 ByteData 创建 PaletteGenerator

主要属性包括:

  • vibrantColor: 鲜艳色
  • darkVibrantColor: 暗鲜艳色
  • lightVibrantColor: 亮鲜艳色
  • mutedColor: 柔和色
  • darkMutedColor: 暗柔和色
  • lightMutedColor: 亮柔和色
  • dominantColor: 主导色(出现频率最高的颜色)
  • colors: 所有提取的颜色列表
  • paletteColors: 所有提取的颜色样本列表

3.2 基本使用流程

下面是一个基本示例,展示如何从本地资源图像中提取颜色:

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

Future<void> extractColorsFromImage() async {
  // 从 AssetImage 创建 PaletteGenerator
  final PaletteGenerator palette = await PaletteGenerator.fromImageProvider(
    AssetImage('assets/images/landscape.png'),
    size: Size(200, 200), // 可选:调整图像大小以提高性能
    maximumColorCount: 24, // 可选:设置最大颜色数量
  );
  
  // 获取不同类型的颜色
  final vibrant = palette.vibrantColor?.color;
  final darkVibrant = palette.darkVibrantColor?.color;
  final lightVibrant = palette.lightVibrantColor?.color;
  final muted = palette.mutedColor?.color;
  final darkMuted = palette.darkMutedColor?.color;
  final lightMuted = palette.lightMutedColor?.color;
  final dominant = palette.dominantColor?.color;
  
  print('鲜艳色: $vibrant');
  print('暗鲜艳色: $darkVibrant');
  print('亮鲜艳色: $lightVibrant');
  print('柔和色: $muted');
  print('暗柔和色: $darkMuted');
  print('亮柔和色: $lightMuted');
  print('主导色: $dominant');
}

3.3 网络图像颜色提取

Future<void> extractColorsFromNetworkImage() async {
  try {
    final PaletteGenerator palette = await PaletteGenerator.fromImageProvider(
      NetworkImage('https://example.com/image.jpg'),
      timeout: Duration(seconds: 10), // 设置超时时间
    );
    
    // 使用提取的颜色
    final primaryColor = palette.vibrantColor?.color ?? Colors.blue;
    final textColor = palette.vibrantColor?.titleTextColor ?? Colors.white;
    
    print('主色调: $primaryColor');
    print('文字颜色: $textColor');
  } catch (e) {
    print('颜色提取失败: $e');
  }
}

3.4 自定义颜色提取区域

可以指定从图像的特定区域提取颜色:

Future<void> extractColorsFromSpecificRegion() async {
  final PaletteGenerator palette = await PaletteGenerator.fromImageProvider(
    AssetImage('assets/images/landscape.png'),
    size: Size(400, 300),
    region: Rect.fromLTRB(0, 0, 400, 150), // 只从图像上半部分提取颜色
  );
  
  final topColor = palette.dominantColor?.color;
  print('图像上半部分的主导色: $topColor');
}

3.5 自定义颜色过滤

可以使用自定义过滤器来排除不需要的颜色:

// 自定义过滤器:排除太暗的颜色
bool excludeDarkColors(Color color) {
  final double luminance = color.computeLuminance();
  return luminance > 0.1; // 只保留亮度大于 0.1 的颜色
}

Future<void> extractColorsWithCustomFilter() async {
  final PaletteGenerator palette = await PaletteGenerator.fromImageProvider(
    AssetImage('assets/images/landscape.png'),
    filters: [excludeDarkColors], // 使用自定义过滤器
  );
  
  // 处理提取的颜色
}

4. 完整示例应用

下面是一个完整的鸿蒙 Flutter 应用示例,展示如何使用 Palette Generator 包从图像中提取颜色并应用到 UI 中:

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

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Palette Generator 示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const ColorExtractorScreen(),
    );
  }
}

class ColorExtractorScreen extends StatefulWidget {
  const ColorExtractorScreen({super.key});

  
  State<ColorExtractorScreen> createState() => _ColorExtractorScreenState();
}

class _ColorExtractorScreenState extends State<ColorExtractorScreen> {
  PaletteGenerator? _paletteGenerator;
  bool _isLoading = false;

  Future<void> _generatePalette() async {
    setState(() {
      _isLoading = true;
    });

    try {
      final PaletteGenerator palette = await PaletteGenerator.fromImageProvider(
        AssetImage('assets/images/landscape.png'),
        size: Size(300, 200),
        maximumColorCount: 24,
      );

      setState(() {
        _paletteGenerator = palette;
      });
    } catch (e) {
      print('颜色提取失败: $e');
    } finally {
      setState(() {
        _isLoading = false;
      });
    }
  }

  
  void initState() {
    super.initState();
    _generatePalette();
  }

  
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('图像颜色提取'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            // 显示原始图像
            Image.asset(
              'assets/images/landscape.png',
              width: 300,
              height: 200,
              fit: BoxFit.cover,
            ),
            const SizedBox(height: 20),
            
            // 生成颜色按钮
            ElevatedButton(
              onPressed: _isLoading ? null : _generatePalette,
              child: _isLoading 
                  ? const CircularProgressIndicator() 
                  : const Text('重新生成颜色'),
            ),
            const SizedBox(height: 20),
            
            // 显示提取的颜色
            if (_paletteGenerator != null) ...[
              // 显示主要颜色类型
              _buildColorRow(
                '鲜艳色',
                _paletteGenerator!.vibrantColor?.color,
                _paletteGenerator!.vibrantColor?.titleTextColor,
              ),
              _buildColorRow(
                '暗鲜艳色',
                _paletteGenerator!.darkVibrantColor?.color,
                _paletteGenerator!.darkVibrantColor?.titleTextColor,
              ),
              _buildColorRow(
                '亮鲜艳色',
                _paletteGenerator!.lightVibrantColor?.color,
                _paletteGenerator!.lightVibrantColor?.titleTextColor,
              ),
              _buildColorRow(
                '柔和色',
                _paletteGenerator!.mutedColor?.color,
                _paletteGenerator!.mutedColor?.titleTextColor,
              ),
              _buildColorRow(
                '暗柔和色',
                _paletteGenerator!.darkMutedColor?.color,
                _paletteGenerator!.darkMutedColor?.titleTextColor,
              ),
              _buildColorRow(
                '亮柔和色',
                _paletteGenerator!.lightMutedColor?.color,
                _paletteGenerator!.lightMutedColor?.titleTextColor,
              ),
              _buildColorRow(
                '主导色',
                _paletteGenerator!.dominantColor?.color,
                _paletteGenerator!.dominantColor?.titleTextColor,
              ),
              const SizedBox(height: 20),
              
              // 显示所有提取的颜色
              const Text(
                '所有提取的颜色:',
                style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
              ),
              const SizedBox(height: 10),
              SizedBox(
                height: 50,
                child: ListView.builder(
                  scrollDirection: Axis.horizontal,
                  itemCount: _paletteGenerator!.colors.length,
                  itemBuilder: (context, index) {
                    return Container(
                      width: 50,
                      height: 50,
                      color: _paletteGenerator!.colors.elementAt(index),
                      margin: const EdgeInsets.all(2),
                    );
                  },
                ),
              ),
            ],
          ],
        ),
      ),
    );
  }

  Widget _buildColorRow(String label, Color? color, Color? textColor) {
    if (color == null) return Container();
    
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 5),
      child: Row(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          SizedBox(
            width: 100,
            child: Text(label),
          ),
          const SizedBox(width: 10),
          Container(
            width: 150,
            height: 40,
            color: color,
            alignment: Alignment.center,
            child: Text(
              color.toString(),
              style: TextStyle(
                color: textColor ?? Colors.black,
                fontWeight: FontWeight.bold,
              ),
            ),
          ),
        ],
      ),
    );
  }
}

5. 鸿蒙平台注意事项

5.1 性能优化

  • 对于大图像,建议在 fromImageProvider 中指定较小的 size 参数,以提高颜色提取的性能
  • 避免在 UI 线程中处理过大的图像,考虑使用 compute 函数在后台线程中进行颜色提取

5.2 资源管理

  • 确保在 pubspec.yaml 中正确配置了图像资源路径
  • 对于网络图像,确保添加了网络权限

5.3 错误处理

  • 始终使用 try-catch 块包装颜色提取操作,以处理可能的错误(如网络超时、图像加载失败等)
  • fromImageProvider 设置合理的 timeout 参数

5.4 兼容性

  • 确保使用的 Flutter 和 Dart 版本符合要求
  • 在不同型号的鸿蒙设备上测试颜色提取功能,确保一致性

6. 总结

Flutter Palette Generator 包为鸿蒙平台提供了强大的图像颜色提取能力,允许应用程序创建与图像内容协调的用户界面。通过本文的介绍,您应该已经了解了如何:

  1. 以 Git 形式引入自定义修改版本的 Palette Generator 包
  2. 使用核心 API 从不同来源的图像中提取颜色
  3. 应用提取的颜色到用户界面设计中
  4. 实现完整的颜色提取功能

该包在图像浏览、媒体播放器、相册应用等场景中具有广泛的应用前景,能够帮助开发者创建更加视觉吸引力和用户友好的鸿蒙应用程序。

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐