从图片中选择主要颜色

安德里亚

我是Dart / Flutter框架的新手,我仍在探索它们的可能性。

我知道在Android中可以拍照并以编程方式从中提取主要颜色值。(以Android为例

我想知道,在纯Dart中如何实现?我希望它与iOS和Android操作系统兼容。

艾克·毛维拉

我可能认为您已解决问题,但为了以后对此问题进行搜索,建议您Flutter团队检查Pallete Generator我将尝试对代码的工作方式进行简单说明,但有关详细示例,请转到插件的GitHub repo

下面的示例将要拍摄图像,然后从图像中选择主要颜色,然后显示颜色

首先,我们添加所需的导入

import 'package:palette_generator/palette_generator.dart';

之后,让我们创建主应用程序类。

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      ...
      home: const HomePage(
        title: 'Colors from image',
        image: AssetImage('assets/images/artwork_default.png',),
        imageSize: Size(256.0, 170.0),
      ...

      ),
    );
  }
}

在上面的图像字段中,放置您要从中提取主色的图像,我使用了此处显示的图像

接下来,我们创建HomePage类

@immutable
class HomePage extends StatefulWidget {
  /// Creates the home page.
  const HomePage({
    Key key,
    this.title,
    this.image,
    this.imageSize,
  }) : super(key: key);

  final String title; //App title
  final ImageProvider image; //Image provider to load the colors from
  final Size imageSize; //Image dimensions

  @override
  _HomePageState createState() {
    return _HomePageState();
  }
}

让我们也创建_HomePageState

class _HomePageState extends State<HomePage> {
  Rect region;
  PaletteGenerator paletteGenerator;

  final GlobalKey imageKey = GlobalKey();

  @override
  void initState() {
    super.initState();
    region = Offset.zero & widget.imageSize;
    _updatePaletteGenerator(region);
  }

  Future<void> _updatePaletteGenerator(Rect newRegion) async {
    paletteGenerator = await PaletteGenerator.fromImageProvider(
      widget.image,
      size: widget.imageSize,
      region: newRegion,
      maximumColorCount: 20,
    );
    setState(() {});
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: _kBackgroundColor,
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Column(
        mainAxisSize: MainAxisSize.max,
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: <Widget>[
          new AspectRatio(
            aspectRatio: 15 / 15,
            child: Image(
              key: imageKey,
              image: widget.image,
            ),
          ),
          Expanded(child: Swatches(generator: paletteGenerator)),
        ],
      ),
    );
  }
}

上面的代码仅列出了图像和Swatches,这是下面定义的类。在initState中,我们首先选择一个区域,从中得出颜色,在我们的例子中是整个图像。

之后,我们创建一个Swatches类,该类接收一个PalleteGenerator并为其绘制色板。

class Swatches extends StatelessWidget {

  const Swatches({Key key, this.generator}) : super(key: key);

  // The PaletteGenerator that contains all of the swatches that we're going
  // to display.
  final PaletteGenerator generator;

  @override
  Widget build(BuildContext context) {
    final List<Widget> swatches = <Widget>[];
    //The generator field can be null, if so, we return an empty container
    if (generator == null || generator.colors.isEmpty) {
      return Container();
    }
    //Loop through the colors in the PaletteGenerator and add them to the list of swatches above
    for (Color color in generator.colors) {
      swatches.add(PaletteSwatch(color: color));
    }
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      mainAxisSize: MainAxisSize.min,
      crossAxisAlignment: CrossAxisAlignment.center,
      children: <Widget>[
        //All the colors,
        Wrap(
          children: swatches,
        ),
        //The colors with ranking
        Container(height: 30.0),
        PaletteSwatch(label: 'Dominant', color: generator.dominantColor?.color),
        PaletteSwatch(
            label: 'Light Vibrant', color: generator.lightVibrantColor?.color),
        PaletteSwatch(label: 'Vibrant', color: generator.vibrantColor?.color),
        PaletteSwatch(
            label: 'Dark Vibrant', color: generator.darkVibrantColor?.color),
        PaletteSwatch(
            label: 'Light Muted', color: generator.lightMutedColor?.color),
        PaletteSwatch(label: 'Muted', color: generator.mutedColor?.color),
        PaletteSwatch(
            label: 'Dark Muted', color: generator.darkMutedColor?.color),
      ],
    );
  }
}

之后,让我们创建一个PaletteSwatch类。调色板样本只是带有可选标签的颜色正方形

@immutable
class PaletteSwatch extends StatelessWidget {
  // Creates a PaletteSwatch.
  //
  // If the [color] argument is omitted, then the swatch will show a
  // placeholder instead, to indicate that there is no color.
  const PaletteSwatch({
    Key key,
    this.color,
    this.label,
  }) : super(key: key);

  // The color of the swatch. May be null.
  final Color color;

  // The optional label to display next to the swatch.
  final String label;

  @override
  Widget build(BuildContext context) {
    // Compute the "distance" of the color swatch and the background color
    // so that we can put a border around those color swatches that are too
    // close to the background's saturation and lightness. We ignore hue for
    // the comparison.
    final HSLColor hslColor = HSLColor.fromColor(color ?? Colors.transparent);
    final HSLColor backgroundAsHsl = HSLColor.fromColor(_kBackgroundColor);
    final double colorDistance = math.sqrt(
        math.pow(hslColor.saturation - backgroundAsHsl.saturation, 2.0) +
            math.pow(hslColor.lightness - backgroundAsHsl.lightness, 2.0));

    Widget swatch = Padding(
      padding: const EdgeInsets.all(2.0),
      child: color == null
          ? const Placeholder(
              fallbackWidth: 34.0,
              fallbackHeight: 20.0,
              color: Color(0xff404040),
              strokeWidth: 2.0,
            )
          : Container(
              decoration: BoxDecoration(
                  color: color,
                  border: Border.all(
                    width: 1.0,
                    color: _kPlaceholderColor,
                    style: colorDistance < 0.2
                        ? BorderStyle.solid
                        : BorderStyle.none,
                  )),
              width: 34.0,
              height: 20.0,
            ),
    );

    if (label != null) {
      swatch = ConstrainedBox(
        constraints: const BoxConstraints(maxWidth: 130.0, minWidth: 130.0),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          children: <Widget>[
            swatch,
            Container(width: 5.0),
            Text(label),
          ],
        ),
      );
    }
    return swatch;
  }
}

希望对您有所帮助,谢谢。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章