使用相机包更改颤振中实时相机的色调和饱和度 我开发了带有相机包的 flutter 应用程序,可以预览实时相机并录制视频或拍摄照片并保存。我想更改预览的颜色和饱和度并将其应用于视频和相机。我怎样才能做到这一点/。
没有发现改变色调和饱和度
这将必须是一个两步过程,除非您想重写相机包的部分内容。您可能能够从相机获取帧并直接处理它们,但我的猜测是,在 dart 中不可能在不出现重大性能问题的情况下做到这一点。
相反,第一步是实时更改预览以显示色调+饱和度变化。为此,您可以使用
ColorFilter
小部件来包装预览小部件。您将需要设置这些 ColorFilters 来执行您想要的操作;我建议您查看 Color Filter Generator pub 包,其中包含一系列不同矩阵的数学运算,包括色调、饱和度、亮度。
这是一个示例 - 您可以粘贴到 dartpad.dev 中查看它的外观。但要点是我使用
hueMatrix
和 saturationMatrix
方法来生成矩阵,然后将其传递给 ImageFilter 对象。如果您愿意,您甚至可以将hueMatrix 和saturationMatrix 合并为一个函数,但我将把它作为练习留给您完成。在示例中,我将过滤器应用于文本,但它对于相机预览应该同样有效。
import 'package:flutter/material.dart';
import 'dart:math';
// from https://github.com/hsbijarniya/colorfilter_generator
List<double> hueMatrix(double value) {
value = value * pi;
if (value == 0) {
return [
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
];
}
var cosVal = cos(value);
var sinVal = sin(value);
var lumR = 0.213;
var lumG = 0.715;
var lumB = 0.072;
return List<double>.from(<double>[
(lumR + (cosVal * (1 - lumR))) + (sinVal * (-lumR)),
(lumG + (cosVal * (-lumG))) + (sinVal * (-lumG)),
(lumB + (cosVal * (-lumB))) + (sinVal * (1 - lumB)),
0,
0,
(lumR + (cosVal * (-lumR))) + (sinVal * 0.143),
(lumG + (cosVal * (1 - lumG))) + (sinVal * 0.14),
(lumB + (cosVal * (-lumB))) + (sinVal * (-0.283)),
0,
0,
(lumR + (cosVal * (-lumR))) + (sinVal * (-(1 - lumR))),
(lumG + (cosVal * (-lumG))) + (sinVal * lumG),
(lumB + (cosVal * (1 - lumB))) + (sinVal * lumB),
0,
0,
0,
0,
0,
1,
0,
]).map((i) => i.toDouble()).toList();
}
// from https://github.com/hsbijarniya/colorfilter_generator
List<double> saturationMatrix(double value) {
value = value * 100;
if (value == 0) {
return [
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
0,
0,
0,
0,
1,
0,
];
}
var x =
((1 + ((value > 0) ? ((3 * value) / 100) : (value / 100)))).toDouble();
var lumR = 0.3086;
var lumG = 0.6094;
var lumB = 0.082;
return List<double>.from(<double>[
(lumR * (1 - x)) + x,
lumG * (1 - x),
lumB * (1 - x),
0,
0,
lumR * (1 - x),
(lumG * (1 - x)) + x,
lumB * (1 - x),
0,
0,
lumR * (1 - x),
lumG * (1 - x),
(lumB * (1 - x)) + x,
0,
0,
0,
0,
0,
1,
0,
]).map((i) => i.toDouble()).toList();
}
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
double hue = 0;
double saturation = 0;
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
MyWidget(hue: hue, saturation: saturation),
Text("Hue:"),
Slider(
value: hue / 2 + .5,
onChanged: (val) => setState(() => hue = val * 2 - 1),
),
Text("Saturation:"),
Slider(
value: saturation / 2 + .5,
onChanged: (val) => setState(() => saturation = val * 2 - 1),
)
],
),
),
);
}
}
class MyWidget extends StatelessWidget {
final double hue;
final double saturation;
const MyWidget({super.key, required this.hue, required this.saturation});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return ColorFiltered(
colorFilter: ColorFilter.matrix(hueMatrix(hue)),
child: ColorFiltered(
colorFilter: ColorFilter.matrix(
saturationMatrix(saturation),
),
child: Text(
'Hello, World!',
style: theme.textTheme.headlineMedium!
.copyWith(color: theme.primaryColor),
),
),
);
}
}
这满足了你问题的第一部分;您现在可以预览显示视频的饱和度、色调或其他应用的内容。
第二部分将更加依赖于许多其他因素,例如您正在录制的格式、您正在对视频执行的操作等。但基本上,一旦您在相机上调用 stopVideoRecording ,您就会将获得一个包含视频数据的 XFile 对象。如果你拍照的话应该是类似的。
tapioca
等视频插件来编辑该文件以添加正确的色调,但我感觉它没有足够的功能。如果是这种情况,您可能需要包含一些第三方 android 特定的(以及 iOS 特定的,如果您正在使用它)包,然后从 flutter 调用它们来编辑实际的色调和饱和度以及其他任何内容视频文件,然后等待其处理,然后执行您要对该文件执行的任何其他操作。
对于图像,您将有一个类似的过程,只不过它可能会更容易,因为有更多可用的插件,并且可能能够为您进行照片处理 - 图像编辑器可能会解决这个问题,因为它似乎支持应用颜色矩阵。