如何检测具有背景模糊的容器的亮度以改变文本的颜色

2023-11-30

模糊容器的亮度根据背景中的图像而变化。有没有办法检测图像或模糊容器的亮度来改变文本颜色?最好不处理图像。

enter image description here


我制作了一个小部件作为一个有趣的练习和概念验证,称为PixelDataOverlay。它有一个background建设者和overlay建设者。

使用时会调用background构建器首先构建底层小部件(图片或其他内容)。然后它会从构建的内容中提取像素数据。然后它会调用overlay构建器并将像素数据传递回给您,以便您可以决定如何构建overlay根据您收到的信息。

关键用法:

PixelDataOverlay(
  background: (BuildContext context) {
    return ImageFiltered( /* ... */ );
  },
  overlay: (BuildContext context, Uint8List? bytes) {
    final score = PixelDataOverlay.getBrightnessFromBytes(bytes);
    return Text('Background is ${score > 0 ? 'bright' : 'dark'}');
  },
)

Demo:

demo gif

完整来源:

import 'dart:typed_data';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        body: Center(
          child: Demo(),
        ),
      ),
    );
  }
}

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

  @override
  _DemoState createState() => _DemoState();
}

class _DemoState extends State<Demo> {
  final List<double> _sliderValues = [0.8, 0.8, 0.2, 1.0];

  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        PixelDataOverlay(
          background: (BuildContext context) {
            return ClipRect(
              child: ImageFiltered(
                imageFilter: ImageFilter.blur(sigmaX: 20.0, sigmaY: 20.0),
                child: Container(
                  color: Color.fromARGB(
                    (_sliderValues[3] * 255).clamp(0, 255).round(),
                    (_sliderValues[0] * 255).clamp(0, 255).round(),
                    (_sliderValues[1] * 255).clamp(0, 255).round(),
                    (_sliderValues[2] * 255).clamp(0, 255).round(),
                  ),
                  child: FlutterLogo(size: 100),
                ),
              ),
            );
          },
          overlay: (BuildContext context, Uint8List bytes) {
            final score = PixelDataOverlay.getBrightnessFromBytes(bytes);
            return Center(
              child: Text(
                'Brightness: \n${score.toStringAsFixed(2)}',
                style: TextStyle(
                  color: score > 0 ? Colors.black : Colors.white,
                ),
              ),
            );
          },
        ),
        const SizedBox(height: 48),
        _buildControls(),
      ],
    );
  }

  _buildControls() {
    return Column(
      children: [
        Text('Adjust the sliders to see the effect of the blur filter.\n'
            'The sliders are: Red, Green, Blue, Alpha.'),
        for (int i = 0; i < 4; i++)
          Slider(
            value: _sliderValues[i],
            onChanged: (v) => setState(() => _sliderValues[i] = v),
          ),
      ],
    );
  }
}

class PixelDataOverlay extends StatefulWidget {
  final WidgetBuilder background;
  final Widget Function(BuildContext context, Uint8List bytes) overlay;

  const PixelDataOverlay(
      {Key? key, required this.background, required this.overlay})
      : super(key: key);

  @override
  _PixelDataOverlayState createState() => _PixelDataOverlayState();

  /// Returns the brightness score for the given [bytes] containing raw image
  /// data. A positive score indicates that the image is (on average) bright,
  /// while a negative score indicates that the image is dark.
  static double getBrightnessFromBytes(Uint8List bytes) {
    // Keep track of total brightness of the image.
    // For each pixel, assign positive value if it's bright.
    // For example: +1 for #FFFFFF, -1 for #000000.
    // So for neutral grey, its score will be close to 0.
    // However, if alpha is not FF, the score is discounted accordingly.
    // For example: `Colors.black.withOpacity(0.5)` has a score of `-0.5`.
    double totalScore = 0.0;

    for (int i = 0; i < bytes.length; i += 4) {
      final r = bytes[i];
      final g = bytes[i + 1];
      final b = bytes[i + 2];
      final a = bytes[i + 3];
      final brightness = (0.2126 * r + 0.7152 * g + 0.0722 * b); // 0 to 255
      final normalized = (brightness / 127.5 - 1) * (a / 255); // -1 to 1
      totalScore += normalized;
    }
    return totalScore;
  }
}

class _PixelDataOverlayState extends State<PixelDataOverlay> {
  final _globalKey = GlobalKey();
  Uint8List? _bytes;

  @override
  void initState() {
    super.initState();
  }

  @override
  void didUpdateWidget(covariant PixelDataOverlay oldWidget) {
    super.didUpdateWidget(oldWidget);
    WidgetsBinding.instance!.addPostFrameCallback((_) {
      _capture();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        RepaintBoundary(
          key: _globalKey,
          child: widget.background(context),
        ),
        if (_bytes != null)
          Positioned(
            top: 0,
            left: 0,
            bottom: 0,
            right: 0,
            child: widget.overlay(context, _bytes!),
          ),
      ],
    );
  }

  void _capture() async {
    final render = (_globalKey.currentContext!.findRenderObject()
        as RenderRepaintBoundary);
    final imageBytes = (await (await render.toImage())
            .toByteData(format: ImageByteFormat.rawStraightRgba))!
        .buffer
        .asUint8List();
    setState(() => _bytes = imageBytes);
  }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何检测具有背景模糊的容器的亮度以改变文本的颜色 的相关文章

随机推荐

  • 模拟时间序列

    在最近的宏观经济预测在线课程中 有一个建模练习 y t 3 0 0 55 y t 1 e t where e t 定义为 et lt c 1 2138662 0 2854597 0 5902700 0 8285463 0 9954260 0
  • n 元函数的 Uncurry

    我有一个类型级别的数字 data Z deriving Typeable data S n deriving Typeable 和 n 元函数 来自固定向量包的代码 Type family for n ary functions type
  • 如何对 data.table 中的 .SD 列进行行明智操作

    虽然我之前已经弄清楚了这一点 但我仍然发现自己在 stackoverflow 上搜索 并且无法找到 这个语法 所以 我想对 data table 列的子集进行行明智操作 使用 SD and SDcols 我永远不记得手术是否需要sapply
  • Pandas 按组计算过去 n 天内发生的事件次数

    我有按 id 发生的事件表 如何计算过去 n 天内每种事件类型在当前行之前发生的次数 例如 事件列表如下 df pd DataFrame id 1 event day 2016 01 01 event type type1 id 1 eve
  • 将 lambda 参数传递给 include 语句

    我正在使用System Data Entity命名空间 因此我可以将 lambda 表达式传递给 Linq Include 方法 public ICollection
  • 容器绑定脚本尝试从侧边栏使用 google.script.run 运行函数时出现权限错误

    我尝试在电子表格上实现侧边栏 以获取用户输入以供我的脚本使用 我无法让它成功调用任何服务器端函数 我将谷歌文档中的一个简单脚本和我读过的几个 stackoverflow 问题放在一起 但我不断收到错误 它能够打印到控制台 但尝试调用时出错日
  • Eclipse 中的 Boost 链接错误

    我一直在尝试将 boost 的线程功能包含在 Ubuntu 上的 Eclipse C 项目中 但毫无结果 到目前为止的步骤 从 boost org 下载 boost configure with libraries system threa
  • 如何正确获取使用 flex-direction:column 显示的块的实际宽度?

    例如 HTML console log container width 600px as we defined in css console log list width 600px console log box eq 1 positio
  • read() 系统调用实际读取的数据量

    假设我有一个文件 其文件描述符在 EOF 之前剩余的字节数超过 n 个字节 并且我调用了 n 个字节的 read 系统调用 该函数是否保证将 n 个字节读入缓冲区 还是可以少读点 The read系统调用保证读取您所要求的尽可能多的字符 除
  • JS:循环遍历div列表以通过onclick添加事件?

    div test div div test div div test div 如果我有一个 div 列表 并且希望在单击每个 div 时将字体大小增加到 20px 我知道我可以执行以下操作 let elements document que
  • SOLR旅游网站:关于日期查询

    我正在寻找为酒店预订网站实施 SOLR 根据位置 酒店名称 设施进行的搜索非常有效 分面也是如此 我不知道如何在给定入住和退房日期的情况下搜索酒店 例如 用户将搜索搜索查询 纽约的酒店 然后从日期选择框中选择入住日期 2012 年 2 月
  • 从非 constexpr 参数创建 constexpr 数组

    我从中学到了here that args不是一个常量表达式 Now 我的问题是 我应该在给定的程序中修改什么 以便我能够在第一个变体中拥有 static assert 而不会出现编译时错误 在下面的代码中 include
  • 如何在 C# 中使用派生类型重写泛型方法

    我有以下课程 public interface IService void ApplyChanges
  • 每次当我的应用程序从后台进入前台时,都会显示 IOS Default.png [重复]

    这个问题在这里已经有答案了 我是IOS开发新手 我设置了一个 Default png 文件 每次应用程序从后台进入前台时都会显示它 但我只想在应用程序启动时显示一次 Default png 我观察到 每当应用程序从后台恢复时 iOS 5 0
  • 为什么我们在“==”比较中指定变量的顺序很重要?

    我注意到 仅更改与 运算符进行比较的变量的顺序就会产生很大的性能差异 例如 variable variable 比variable variable 慢得多 为什么会这样 有类似的案例吗 顺便说一下 我使用的是从 GitHub 下载的 Op
  • 如何在 PowerShell 中从连接字符串获取数据库名称

    我正在尝试从 PowerShell 中的连接字符串获取数据库名称 Server server instance uid User pwd Hello Database SomeName 我可以想到两种方法来做到这一点 要么搜索字符串Data
  • 作曲家在 PHP 中未找到类异常

    我正在尝试包含来自作曲家的包 但我收到了找不到类 error 我已经尝试过以下可能性 supermeteor new Supermeteor Supermeteor XXXXXXXX and use Supermeteor Supermet
  • 如何将句子中第一个单词的第一个字母大写?

    我正在尝试编写一个函数来清理用户输入 我并不想让它变得完美 我宁愿有几个小写的名字和缩写 也不愿有一个完整的大写段落 我认为该函数应该使用正则表达式 但我对这些非常不熟悉 我需要一些帮助 如果以下表达式后跟一个字母 我想将该字母设为大写 f
  • 仅选择一个选项在角度4中显示ID而不显示名称

    我正在研究 Angular 4 Web API 当选择一个选项时 它将显示打包类型名称 其工作正常 但我的问题是 当单击添加按钮时 它只会保存我想要的包装类型ID 包装类型ID 和包装类型名称 这里我想在选择包装类型名称时自动将其ID 传递
  • 如何检测具有背景模糊的容器的亮度以改变文本的颜色

    模糊容器的亮度根据背景中的图像而变化 有没有办法检测图像或模糊容器的亮度来改变文本颜色 最好不处理图像 我制作了一个小部件作为一个有趣的练习和概念验证 称为PixelDataOverlay 它有一个background建设者和overlay