73 lines
2.1 KiB
Dart
73 lines
2.1 KiB
Dart
import 'dart:io';
|
|
import 'dart:math' as math;
|
|
import 'dart:typed_data';
|
|
import 'dart:ui' as ui;
|
|
|
|
import 'package:flutter/material.dart';
|
|
import 'package:path_provider/path_provider.dart';
|
|
|
|
class ImageUtils {
|
|
/// 将图片裁剪成圆形,返回 PNG 文件路径
|
|
/// [imageFile] 或 [imageData] 二选一
|
|
static Future<String> toCircleImageFile({
|
|
Uint8List? imageData,
|
|
File? imageFile,
|
|
}) async {
|
|
if (imageData == null && imageFile == null) {
|
|
throw ArgumentError('必须提供 imageData 或 imageFile');
|
|
}
|
|
|
|
// 读取原始字节
|
|
final bytes = imageData ?? await imageFile!.readAsBytes();
|
|
|
|
// 1. 解码图片
|
|
final codec = await ui.instantiateImageCodec(bytes);
|
|
final frame = await codec.getNextFrame();
|
|
final original = frame.image;
|
|
|
|
final width = original.width;
|
|
final height = original.height;
|
|
final size = math.min(width, height);
|
|
|
|
// 2. 画布
|
|
final recorder = ui.PictureRecorder();
|
|
final canvas = Canvas(recorder);
|
|
final paint = Paint()..isAntiAlias = true;
|
|
|
|
// 3. 圆形遮罩
|
|
final center = Offset(size / 2, size / 2);
|
|
canvas.drawCircle(center, size / 2, paint..color = Colors.white);
|
|
|
|
// 4. 设置混合模式为 srcIn
|
|
paint.blendMode = BlendMode.srcIn;
|
|
|
|
// 5. 绘制原图(取正方形区域,保证圆形不变形)
|
|
final srcRect = Rect.fromLTWH(
|
|
(width - size) / 2,
|
|
(height - size) / 2,
|
|
size.toDouble(),
|
|
size.toDouble(),
|
|
);
|
|
final dstRect = Rect.fromLTWH(0, 0, size.toDouble(), size.toDouble());
|
|
|
|
canvas.drawImageRect(original, srcRect, dstRect, paint);
|
|
|
|
// 6. 导出为 Image
|
|
final picture = recorder.endRecording();
|
|
final imgFinal = await picture.toImage(size, size);
|
|
|
|
// 7. 转 PNG 字节
|
|
final byteData = await imgFinal.toByteData(format: ui.ImageByteFormat.png);
|
|
final pngBytes = byteData!.buffer.asUint8List();
|
|
|
|
// 8. 存临时文件
|
|
final tempDir = await getTemporaryDirectory();
|
|
final file = File(
|
|
'${tempDir.path}/circle_${DateTime.now().millisecondsSinceEpoch}.png',
|
|
);
|
|
await file.writeAsBytes(pngBytes);
|
|
|
|
return file.path;
|
|
}
|
|
}
|