Flutter图片裁剪插件images_crop的使用

Flutter图片裁剪插件images_crop的使用

一个用于在iOS和Android上进行图片裁剪的Flutter插件。

![Image Cropping Preview]

该插件包含一个Crop小部件。该小部件仅渲染图像、覆盖层和处理程序以裁剪图像。因此它可以与其他小部件组合来构建自定义的图片裁剪体验。

该插件通过文件进行工作,以避免通过方法通道传递大量数据。文件存储在iOS和Android的缓存文件夹中。因此,如果需要保存实际裁剪后的图像,请确保将其复制到其他位置。

所有计算密集型工作都是通过iOS上的调度队列和Android上的缓存线程池在主线程之外完成的。

注意:此插件仍在开发中,部分功能尚未可用且测试有限。

安装

pubspec.yaml文件中添加image_crop依赖项:

dependencies:
  image_crop:

使用

创建一个小部件以加载和编辑图像:

final cropKey = GlobalKey<CropState>();

Widget _buildCropImage() {
  return Container(
      color: Colors.black,
      padding: const EdgeInsets.all(20.0),
      child: Crop(
        key: cropKey,
        image: Image.file(imageFile),
        aspectRatio: 4.0 / 3.0,
      ),
  );
}

访问裁剪值:

  • scale是一个比例因子,用于按比例缩放裁剪图像的宽度和高度。1.0表示不需要缩放。
  • area是一个矩形,指示要从图像中裁剪的分数位置。
final crop = cropKey.currentState;
// 或者
// final crop = Crop.of(context);
final scale = crop.scale;
final area = crop.area;

if (area == null) {
    // 无法裁剪,小部件未设置好
    // ...
}

访问和处理图像。作为方便函数,请求访问照片的权限:

final permissionsGranted = await ImageCrop.requestPermissions();

读取图像选项,例如:宽度和高度。这是一种高效的实现方式,不会解码或加载实际图像到内存中。

final options = await getImageOptions(file: file);
debugPrint('image width: ${options.width}, height: ${options.height}');

如果需要将大图像加载到内存中,有一个采样函数依赖于原生平台,在加载到内存之前按比例缩小图像。例如,将图像重新采样为尽可能接近1024x4096尺寸。如果是一个正方形的preferredSize可以用来指定宽度和高度。建议在显示图像时利用此功能。

final sampleFile = await ImageCrop.sampleImage(
    file: originalFile,
    preferredWidth: 1024,
    preferredHeight: 4096,
);

一旦Crop小部件准备好,就可以使用本机支持进行裁剪和缩放图像。为了生成高质量的裁剪图像,可以依赖于使用预设的最大宽度和高度进行采样图像。放大采样的图像分辨率。裁剪时,图像具有更高的分辨率。示例如下:

final sampledFile = await ImageCrop.sampleImage(
    file: originalFile,
    preferredWidth: (1024 / crop.scale).round(),
    preferredHeight: (4096 / crop.scale).round(),
);

final croppedFile = await ImageCrop.cropImage(
    file: sampledFile,
    area: crop.area,
);

示例代码

以下是在example/lib/main.dart中的完整示例代码:

import 'dart:io';
import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:images_crop/images_crop.dart';
import 'package:image_picker/image_picker.dart';

void main() {
  SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle(
    statusBarColor: Colors.transparent,
    statusBarBrightness: Brightness.dark,
    statusBarIconBrightness: Brightness.light,
    systemNavigationBarIconBrightness: Brightness.light,
  ));

  runApp(new MyApp());
}

class MyApp extends StatefulWidget {
  [@override](/user/override)
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final cropKey = GlobalKey<CropState>();
  File? _file;
  File? _sample;
  File? _lastCropped;

  [@override](/user/override)
  void dispose() {
    super.dispose();
    _file?.delete();
    _sample?.delete();
    _lastCropped?.delete();
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: SafeArea(
        child: Container(
          color: Colors.black,
          padding: const EdgeInsets.symmetric(vertical: 40.0, horizontal: 20.0),
          child: _sample == null ? _buildOpeningImage() : _buildCroppingImage(),
        ),
      ),
    );
  }

  Widget _buildOpeningImage() {
    return Center(child: _buildOpenImage());
  }

  Widget _buildCroppingImage() {
    return Column(
      children: <Widget>[
        Expanded(
          child: Crop.file(_sample!, key: cropKey),
        ),
        Container(
          padding: const EdgeInsets.only(top: 20.0),
          alignment: AlignmentDirectional.center,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              TextButton(
                child: Text(
                  'Crop Image',
                  style: Theme.of(context)
                      .textTheme
                      .labelLarge
                      ?.copyWith(color: Colors.white),
                ),
                onPressed: () => _cropImage(),
              ),
              _buildOpenImage(),
            ],
          ),
        )
      ],
    );
  }

  Widget _buildOpenImage() {
    return TextButton(
      child: Text(
        'Open Image',
        style: Theme.of(context)
            .textTheme
            .labelLarge
            ?.copyWith(color: Colors.white),
      ),
      onPressed: () => _openImage(),
    );
  }

  Future<void> _openImage() async {
    final pickedFile = await ImagePicker().getImage(source: ImageSource.gallery);
    if (pickedFile == null) return;
    final file = File(pickedFile.path);
    final sample = await ImageCrop.sampleImage(
      file: file,
      preferredSize: context.size?.longestSide.ceil(),
    );

    _sample?.delete();
    _file?.delete();

    setState(() {
      _sample = sample;
      _file = file;
    });
  }

  Future<void> _cropImage() async {
    final scale = cropKey.currentState?.scale ?? 1.0;
    final area = cropKey.currentState?.area;
    if (_file == null) {
      // 无法裁剪,小部件未设置好
      return;
    }
    if (area == null) {
      // 无法裁剪,小部件未设置好
      return;
    }

    // 放大到使用可能的最大像素数
    // 这将在更高分辨率下采样图像以使裁剪图像更大
    final sample = await ImageCrop.sampleImage(
      file: _file!,
      preferredSize: (2000 / scale).round(),
    );

    final file = await ImageCrop.cropImage(
      file: sample,
      area: area,
    );

    sample.delete();

    _lastCropped?.delete();
    _lastCropped = file;

    debugPrint('$file');
  }
}

更多关于Flutter图片裁剪插件images_crop的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter图片裁剪插件images_crop的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


images_crop 是一个用于在 Flutter 应用中裁剪图片的插件。它提供了一个简单的接口,允许用户从图库中选择图片并进行裁剪。以下是如何在 Flutter 项目中使用 images_crop 插件的步骤:

1. 添加依赖

首先,你需要在 pubspec.yaml 文件中添加 images_crop 插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  images_crop: ^1.3.0  # 确保使用最新版本

然后运行 flutter pub get 来获取依赖。

2. 导入插件

在你的 Dart 文件中导入 images_crop 插件:

import 'package:images_crop/images_crop.dart';

3. 请求权限

在 Android 和 iOS 上,你可能需要请求访问相册的权限。你可以使用 permission_handler 插件来处理权限请求。

首先,添加 permission_handler 插件的依赖:

dependencies:
  permission_handler: ^10.0.0  # 确保使用最新版本

然后,在代码中请求权限:

import 'package:permission_handler/permission_handler.dart';

Future<void> requestPermissions() async {
  if (await Permission.storage.request().isGranted) {
    // 权限已授予
  } else {
    // 权限被拒绝
  }
}

4. 选择并裁剪图片

使用 ImagesCrop 插件选择并裁剪图片。以下是一个简单的示例:

import 'package:flutter/material.dart';
import 'package:images_crop/images_crop.dart';
import 'package:permission_handler/permission_handler.dart';

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

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

class ImageCropExample extends StatefulWidget {
  @override
  _ImageCropExampleState createState() => _ImageCropExampleState();
}

class _ImageCropExampleState extends State<ImageCropExample> {
  String _croppedImagePath = '';

  Future<void> _cropImage() async {
    // 请求权限
    if (await Permission.storage.request().isGranted) {
      // 选择图片
      final imagePath = await ImagesCrop.pickImage();

      if (imagePath != null) {
        // 裁剪图片
        final croppedImagePath = await ImagesCrop.crop(
          imagePath: imagePath,
          aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1), // 设置裁剪比例
        );

        setState(() {
          _croppedImagePath = croppedImagePath;
        });
      }
    } else {
      // 处理权限被拒绝的情况
      print('Permission denied');
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Image Crop Example'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            if (_croppedImagePath.isNotEmpty)
              Image.file(
                File(_croppedImagePath),
                width: 200,
                height: 200,
              ),
            ElevatedButton(
              onPressed: _cropImage,
              child: Text('Crop Image'),
            ),
          ],
        ),
      ),
    );
  }
}

5. 运行应用

现在你可以运行你的 Flutter 应用,点击按钮选择并裁剪图片。裁剪后的图片将会显示在应用中。

6. 处理错误

在实际应用中,你可能需要处理各种错误,例如权限被拒绝、图片选择失败等。你可以使用 try-catch 块来捕获并处理这些错误。

try {
  final imagePath = await ImagesCrop.pickImage();
  if (imagePath != null) {
    final croppedImagePath = await ImagesCrop.crop(
      imagePath: imagePath,
      aspectRatio: CropAspectRatio(ratioX: 1, ratioY: 1),
    );
    setState(() {
      _croppedImagePath = croppedImagePath;
    });
  }
} catch (e) {
  print('Error: $e');
}
回到顶部