Flutter图像滤镜处理插件flutter_core_image_filters的使用

发布于 1周前 作者 phonegap100 来自 Flutter

Flutter图像滤镜处理插件flutter_core_image_filters的使用

描述

flutter_core_image_filters 是一个用于iOS和MacOS平台的Flutter包,它允许开发者应用CoreImage滤镜到图片上。这个插件支持大量的CoreImage滤镜,并且可以方便地集成到Flutter项目中。

使用方法

导出处理后的图片

要导出处理后的图片,首先需要指定输入源和配置滤镜参数。以下是一个简单的例子:

final inputSource = AssetInputSource('demo.jpeg');
final configuration = CIPhotoEffectChromeConfiguration();
final image = await configuration.export(inputSource);

CIImagePreview 示例

为了实时预览滤镜效果,可以使用 CIImagePreview 组件。下面的例子展示了如何创建一个包含滤镜预览页面的应用程序:

import 'package:flutter_core_image_filters/flutter_core_image_filters.dart';

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

  @override
  State<PreviewPage> createState() => _PreviewPageState();
}

class _PreviewPageState extends State<PreviewPage> {
  late CIPhotoEffectChromeConfiguration configuration;
  late final CIImagePreviewController controller;
  bool controllerReady = false;

  @override
  void initState() {
    super.initState();
    _prepare().whenComplete(() {
      setState(() {});
    });
  }

  Future<void> _prepare() async {
    configuration = CIPhotoEffectChromeConfiguration();
    controller = await CIImagePreviewController.fromAsset(_assetPath);
    await configuration.prepare();
    await controller.connect(configuration);
    controllerReady = true;
  }

  @override
  void dispose() {
    controller.dispose();
    configuration.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return controllerReady
        ? CIImagePreview(controller: controller)
        : const Offstage();
  }
}

分割预览示例

如果你想同时展示原图和处理后的对比效果,可以使用 BeforeAfter 组件来实现分割预览功能:

import 'package:before_after_image_slider_nullsafty/before_after_image_slider_nullsafty.dart';
import 'package:flutter_core_image_filters/flutter_core_image_filters.dart';

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

  @override
  State<DividedPreviewPage> createState() => _DividedPreviewPageState();
}

class _DividedPreviewPageState extends State<DividedPreviewPage> {
  late CIPhotoEffectChromeConfiguration configuration;
  late final CIImagePreviewController sourceController;
  late final CIImagePreviewController destinationController;
  bool controllersReady = false;

  @override
  void initState() {
    super.initState();
    _prepare().whenComplete(() {
      setState(() {});
    });
  }

  Future<void> _prepare() async {
    configuration = CIPhotoEffectChromeConfiguration();
    sourceController = await CIImagePreviewController.fromAsset('demo.jpeg');
    destinationController = await CIImagePreviewController.fromAsset('demo.jpeg');
    await configuration.prepare();
    await destinationController.connect(configuration);
    controllersReady = true;
  }

  @override
  void dispose() {
    sourceController.dispose();
    destinationController.dispose();
    configuration.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return controllersReady
        ? BeforeAfter(
            thumbRadius: 0.0,
            thumbColor: Colors.transparent,
            beforeImage: CIImagePreview(
              controller: sourceController,
            ),
            afterImage: CIImagePreview(
              controller: destinationController,
            ),
          )
        : const Offstage();
  }
}

导出并保存处理后的图片

如果你想要将处理后的图片保存到本地存储,可以通过如下代码实现:

import 'package:image/image.dart' as img;
import 'package:path_provider/path_provider.dart';

// ... 省略部分代码 ...

final directory = await getTemporaryDirectory();
final output = File('${directory.path}/result.jpeg');

final bytes = await image.toByteData();
final persistedImage = img.Image.fromBytes(
  width: image.width,
  height: image.height,
  bytes: bytes!.buffer,
  numChannels: 4,
);
img.JpegEncoder encoder = img.JpegEncoder();
final data = encoder.encode(persistedImage);
await output.writeAsBytes(data);

核心图像滤镜支持状态

下表列出了当前版本支持的部分CoreImage滤镜:

状态 名称 显示名称
CIAccordionFoldTransition Accordion Fold Transition
CIAreaAverage Area Average
CIAreaHistogram Area Histogram
CIAreaLogarithmicHistogram Area Logarithmic Histogram

…(更多内容请参阅官方文档)

示例结果

以下是几种不同滤镜的效果截图:

Photo Effect Chrome Photo Effect Fade

完整示例

你可以查看 Big Flutter Filters Demo 来获取更详细的用法示例。

维护者

希望这些信息对你有所帮助!如果你有任何问题或需要进一步的帮助,请随时提问。


更多关于Flutter图像滤镜处理插件flutter_core_image_filters的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图像滤镜处理插件flutter_core_image_filters的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用flutter_core_image_filters插件来处理图像滤镜的一个示例。这个插件提供了一系列核心的图像滤镜,类似于iOS的Core Image框架。

首先,确保你已经在pubspec.yaml文件中添加了flutter_core_image_filters依赖:

dependencies:
  flutter:
    sdk: flutter
  flutter_core_image_filters: ^0.1.0  # 请检查最新版本号

然后运行flutter pub get来安装依赖。

接下来是一个完整的示例代码,展示如何使用flutter_core_image_filters应用不同的图像滤镜:

import 'package:flutter/material.dart';
import 'package:flutter_core_image_filters/flutter_core_image_filters.dart';
import 'dart:ui' as ui;

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: ImageFilterScreen(),
    );
  }
}

class ImageFilterScreen extends StatefulWidget {
  @override
  _ImageFilterScreenState createState() => _ImageFilterScreenState();
}

class _ImageFilterScreenState extends State<ImageFilterScreen> {
  final String imageUrl = 'https://via.placeholder.com/600'; // 替换为你的图像URL

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Flutter Core Image Filters Example'),
      ),
      body: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            ImageFilteredNetworkImage(
              imageUrl: imageUrl,
              filter: ui.ImageFilter.blur(sigmaX: 5.0, sigmaY: 5.0),
            ),
            SizedBox(height: 20),
            ImageFilteredNetworkImage(
              imageUrl: imageUrl,
              filter: ui.ImageFilter.matrix(
                [
                  1, 0, 0, 0, 0, // Red scale
                  0, 0, 0, 0, 0, // Green ignored
                  0, 0, 1, 0, 0, // Blue scale
                  0, 0, 0, 1, 0, // Alpha unchanged
                ],
              ),
            ),
            SizedBox(height: 20),
            ImageFilteredNetworkImage(
              imageUrl: imageUrl,
              filter: ui.ImageFilter.grayscale(1.0),
            ),
          ],
        ),
      ),
    );
  }
}

class ImageFilteredNetworkImage extends StatefulWidget {
  final String imageUrl;
  final ui.ImageFilter filter;

  const ImageFilteredNetworkImage({Key key, @required this.imageUrl, @required this.filter}) : super(key: key);

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

class _ImageFilteredNetworkImageState extends State<ImageFilteredNetworkImage> {
  ImageProvider _imageProvider;

  @override
  void initState() {
    super.initState();
    _imageProvider = NetworkImage(widget.imageUrl);
    preloadImage(context, _imageProvider).then((_) {
      setState(() {});
    });
  }

  Future<void> preloadImage(BuildContext context, ImageProvider image) async {
    final Completer<void> completer = Completer<void>();
    final ImageStreamListener listener = ImageStreamListener((ImageInfo imageInfo, bool synchronousCall) {
      completer.complete();
      imageInfo.dispose();
    });

    final ImageStream imageStream = image.resolve(createLocalImageConfiguration(context));
    imageStream.addListener(listener);

    return completer.future;
  }

  @override
  Widget build(BuildContext context) {
    return RepaintBoundary(
      child: CustomPaint(
        painter: ImageFilterPainter(_imageProvider, widget.filter),
        size: Size.infinite, // This ensures the painter paints over the entire available space
      ),
    );
  }
}

class ImageFilterPainter extends CustomPainter {
  final ImageProvider imageProvider;
  final ui.ImageFilter filter;

  ImageFilterPainter(this.imageProvider, this.filter);

  @override
  void paint(Canvas canvas, Size size) async {
    final paint = Paint();
    final image = await _loadImage(imageProvider);
    final filteredImage = await _applyFilter(image, filter);
    canvas.drawImage(filteredImage, Offset.zero, paint);
  }

  Future<ui.Image> _loadImage(ImageProvider imageProvider) async {
    final completer = Completer<ui.Image>();
    imageProvider.resolve(ImageConfiguration()).addListener(
      ImageStreamListener(
        (ImageInfo imageInfo, bool synchronousCall) async {
          final ui.Image image = imageInfo.image;
          if (!mounted) return;
          completer.complete(image);
          imageInfo.dispose();
        },
      ),
    );
    return completer.future;
  }

  Future<ui.Image> _applyFilter(ui.Image image, ui.ImageFilter filter) async {
    final recorder = ui.PictureRecorder();
    final canvas = Canvas(recorder);
    final paint = Paint();
    canvas.drawImage(image, Offset.zero, paint);
    final picture = recorder.endRecording();
    final sceneBuilder = ui.SceneBuilder();
    sceneBuilder.addPicture(Offset.zero, picture);
    final layerTree = sceneBuilder.build();
    final filterLayer = ui.ImageFilterLayer(filter, layerTree);
    final scene = ui.Scene(filterLayer);
    final imageRecorder = ui.PictureRecorder();
    final sceneCanvas = Canvas(imageRecorder);
    scene.rasterize(sceneCanvas);
    final filteredPicture = imageRecorder.endRecording();
    final filteredImage = await filteredPicture.toImage();
    return filteredImage;
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true; // In a real-world scenario, implement a more efficient repaint logic
  }
}

解释

  1. 依赖安装:在pubspec.yaml中添加flutter_core_image_filters依赖。

  2. ImageFilterScreen:主屏幕组件,展示三种不同的滤镜效果(模糊、红通道、灰度)。

  3. ImageFilteredNetworkImage:自定义组件,用于加载网络图片并应用滤镜。

  4. ImageFilterPainter:自定义CustomPainter,用于在画布上绘制经过滤镜处理的图像。

  5. _loadImage:异步加载图像。

  6. _applyFilter:应用滤镜并返回处理后的图像。

请注意,ImageFilterPainter中的shouldRepaint方法返回true,这意味着每次构建都会重新绘制。在实际应用中,你可能需要实现更高效的逻辑来避免不必要的重绘。

希望这个示例代码能帮助你理解如何在Flutter中使用flutter_core_image_filters插件来处理图像滤镜。

回到顶部