如何在Flutter中从图像中获取主要颜色?

10
我希望能够从一张图片中提取出主色调,以便将其应用于其他图片的混合中。我该如何做到这一点?
在我的当前代码中,我已经手动给定颜色,但我想要通过应用程序生成它。
class MyApp extends StatelessWidget {

  Color face = new HexColor("a8a8a8");
  @override
  Widget build(BuildContext context) {

    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Image from assets"),
        ),
        body: Column (
            mainAxisAlignment: MainAxisAlignment.center,
              children:<Widget>[
                Row(
                    mainAxisAlignment: MainAxisAlignment.start,
                    children:<Widget>[
                      new Image.asset('assets/images/6.jpg',
                        color: face, colorBlendMode:BlendMode.modulate ,
                        fit:BoxFit.cover,
                        height: 50,
                        width: 50,
                      ),


                new Image.asset('assets/images/1.jpg',
              color: face, colorBlendMode: BlendMode.modulate,
            fit:BoxFit.cover,
                  height: 200,
                  width: 200,
          ),
                    ]),
                ])),
    );
  }
}


3个回答

17

我发现使用palette_generator包可以解决问题。首先导入库。

import 'package:palette_generator/palette_generator.dart';

在pubspec.yaml文件中也需要添加它

以下函数将返回调色板

Future<PaletteGenerator>_updatePaletteGenerator ()async
{
  paletteGenerator = await PaletteGenerator.fromImageProvider(
    Image.asset("assets/images/8.jfif").image,
  );
return paletteGenerator;
}

现在我们可以在FutureBuilder中获取它

  FutureBuilder<PaletteGenerator>(
                  future: _updatePaletteGenerator(), // async work
                  builder: (BuildContext context, AsyncSnapshot<PaletteGenerator> snapshot) {
                    switch (snapshot.connectionState) {
                      case ConnectionState.waiting: return Center(child:CircularProgressIndicator());
                      default:
                        if (snapshot.hasError)
                          return new Text('Error: ${snapshot.error}');
                        else {
                         // Color color=new Color(snapshot.data.dominantColor.color);
                          face=snapshot.data.dominantColor.color;
                           return new Text('color: ${face.toString()}');
                              }}})

这是如何轻松提取主颜色的方法


2

4
它的文件很差。我读过它,但没有理解。 - KUNAL HIRANI

1
import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;
import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:image/image.dart' as img;
import 'package:flutter/services.dart' show rootBundle;

void main() => runApp(const MaterialApp(home: MyApp()));

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<StatefulWidget> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  String imagePath = 'assets/5.jpg';
  GlobalKey imageKey = GlobalKey();
  GlobalKey paintKey = GlobalKey();

  // CHANGE THIS FLAG TO TEST BASIC IMAGE, AND SNAPSHOT.
  bool useSnapshot = true;

  // based on useSnapshot=true ? paintKey : imageKey ;
  // this key is used in this example to keep the code shorter.
  late GlobalKey currentKey;

  final StreamController<Color> _stateController = StreamController<Color>();
  //late img.Image photo ;
  img.Image? photo;

  @override
  void initState() {
    currentKey = useSnapshot ? paintKey : imageKey;
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    final String title = useSnapshot ? "snapshot" : "basic";
    return SafeArea(
      child: Scaffold(
        appBar: AppBar(title: Text("Color picker $title")),
        body: StreamBuilder(
            initialData: Colors.green[500],
            stream: _stateController.stream,
            builder: (buildContext, snapshot) {
              Color selectedColor = snapshot.data as Color ?? Colors.green;
              return Stack(
                children: <Widget>[
                  RepaintBoundary(
                    key: paintKey,
                    child: GestureDetector(
                      onPanDown: (details) {
                        searchPixel(details.globalPosition);
                      },
                      onPanUpdate: (details) {
                        searchPixel(details.globalPosition);
                      },
                      child: Center(
                        child: Image.asset(
                          imagePath,
                          key: imageKey,
                          //color: Colors.red,
                          //colorBlendMode: BlendMode.hue,
                          //alignment: Alignment.bottomRight,
                          fit: BoxFit.contain,
                          //scale: .8,
                        ),
                      ),
                    ),
                  ),
                  Container(
                    margin: const EdgeInsets.all(70),
                    width: 50,
                    height: 50,
                    decoration: BoxDecoration(
                        shape: BoxShape.circle,
                        color: selectedColor!,
                        border: Border.all(width: 2.0, color: Colors.white),
                        boxShadow: [
                          const BoxShadow(
                              color: Colors.black12,
                              blurRadius: 4,
                              offset: Offset(0, 2))
                        ]),
                  ),
                  Positioned(
                    child: Text('${selectedColor}',
                        style: const TextStyle(
                            color: Colors.white,
                            backgroundColor: Colors.black54)),
                    left: 114,
                    top: 95,
                  ),
                ],
              );
            }),
      ),
    );
  }

  void searchPixel(Offset globalPosition) async {
    if (photo == null) {
      await (useSnapshot ? loadSnapshotBytes() : loadImageBundleBytes());
    }
    _calculatePixel(globalPosition);
  }

  void _calculatePixel(Offset globalPosition) {
    RenderBox box = currentKey.currentContext!.findRenderObject() as RenderBox;
    Offset localPosition = box.globalToLocal(globalPosition);

    double px = localPosition.dx;
    double py = localPosition.dy;

    if (!useSnapshot) {
      double widgetScale = box.size.width / photo!.width;
      print(py);
      px = (px / widgetScale);
      py = (py / widgetScale);
    }

    int pixel32 = photo!.getPixelSafe(px.toInt(), py.toInt());
    int hex = abgrToArgb(pixel32);

    _stateController.add(Color(hex));
  }

  Future<void> loadImageBundleBytes() async {
    ByteData imageBytes = await rootBundle.load(imagePath);
    setImageBytes(imageBytes);
  }

  Future<void> loadSnapshotBytes() async {
    RenderRepaintBoundary boxPaint =
        paintKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
    //RenderObject? boxPaint = paintKey.currentContext.findRenderObject();
    ui.Image capture = await boxPaint.toImage();

    ByteData? imageBytes =
        await capture.toByteData(format: ui.ImageByteFormat.png);
    setImageBytes(imageBytes!);
    capture.dispose();
  }

  void setImageBytes(ByteData imageBytes) {
    List<int> values = imageBytes.buffer.asUint8List();
    photo;
    photo = img.decodeImage(values)!;
  }
}

// image lib uses uses KML color format, convert #AABBGGRR to regular #AARRGGBB
int abgrToArgb(int argbColor) {
  int r = (argbColor >> 16) & 0xFF;
  int b = argbColor & 0xFF;
  return (argbColor & 0xFF00FF00) | (b << 16) | r;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接