90 lines
2.2 KiB
Dart
90 lines
2.2 KiB
Dart
import 'dart:io';
|
||
|
||
import 'package:path/path.dart';
|
||
|
||
class Vips {
|
||
String? vipsExecuteFile;
|
||
final String cacheDir;
|
||
|
||
Vips({this.vipsExecuteFile, required this.cacheDir});
|
||
|
||
/// 生成图片预览(WebP 格式)
|
||
///
|
||
/// [imgPath] 原图路径
|
||
/// [w] 预览图宽度(可选)
|
||
/// [h] 预览图高度(可选)
|
||
///
|
||
/// 如果同时指定 [w] 和 [h],图片将按比例缩放以适应指定尺寸
|
||
Future<File> generatePreview(
|
||
String imgPath, {
|
||
int? w,
|
||
int? h,
|
||
}) async {
|
||
// 生成缓存文件名:包含原图 hash 和尺寸信息
|
||
final baseName = basename(imgPath).hashCode.toString();
|
||
final sizeSuffix = _buildSizeSuffix(w, h);
|
||
final imgOut = "$cacheDir/preview/$baseName$sizeSuffix.webp";
|
||
final outFile = File(imgOut);
|
||
|
||
// 缓存命中:直接返回已存在的预览图
|
||
if (outFile.existsSync()) {
|
||
return outFile;
|
||
}
|
||
|
||
// 确保缓存目录存在
|
||
await outFile.parent.create(recursive: true);
|
||
|
||
// 构建 vips 命令参数
|
||
if (w != null || h != null) {
|
||
final thumbnailArgs = <String>[
|
||
"thumbnail",
|
||
imgPath,
|
||
imgOut,
|
||
w?.toString() ?? "0",
|
||
"--height",
|
||
h?.toString() ?? "0",
|
||
];
|
||
|
||
final thumbnailResult = await Process.run("vips", thumbnailArgs);
|
||
if (thumbnailResult.exitCode != 0) {
|
||
print(thumbnailResult.stderr);
|
||
throw Exception("vips thumbnail failed!");
|
||
}
|
||
return outFile;
|
||
} else {
|
||
// 不缩放,直接转换为 WebP 格式
|
||
final args = <String>[
|
||
"webpsave",
|
||
imgPath,
|
||
imgOut,
|
||
"--Q",
|
||
"80",
|
||
"--effort",
|
||
"6",
|
||
"--smart-subsample",
|
||
];
|
||
|
||
final result = await Process.run("vips", args);
|
||
if (result.exitCode == 0) {
|
||
return outFile;
|
||
}
|
||
print(result.stderr);
|
||
throw Exception("vips image transcode failed!");
|
||
}
|
||
}
|
||
|
||
/// 构建尺寸后缀
|
||
///
|
||
/// 例如:
|
||
/// - w=200, h=150 => "_200x150"
|
||
/// - w=200, h=null => "_200x0"
|
||
/// - w=null, h=150 => "_0x150"
|
||
/// - w=null, h=null => ""
|
||
String _buildSizeSuffix(int? w, int? h) {
|
||
if (w == null && h == null) {
|
||
return "";
|
||
}
|
||
return "_${w ?? 0}x${h ?? 0}";
|
||
}
|
||
}
|