增强预览机制

This commit is contained in:
2026-03-13 23:58:52 +08:00
parent 33d2231bed
commit e76a1dff71
2 changed files with 81 additions and 16 deletions

View File

@@ -7,25 +7,82 @@ class Vips {
Vips({this.vipsExecuteFile});
Future<File> generatePreview(String imgPath) async {
final imgOut =
"cache/preview/" + basename(imgPath).hashCode.toString() + ".webp";
/// 生成图片预览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 = "cache/preview/${baseName}${sizeSuffix}.webp";
final outFile = File(imgOut);
// 缓存命中:直接返回已存在的预览图
if (outFile.existsSync()) {
return outFile;
}
final result = await Process.run("vips", [
"webpsave",
imgPath,
imgOut,
"--Q",
"80",
"--smart-subsample",
"--strip",
]);
if (result.exitCode == 0) {
// 确保缓存目录存在
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!");
}
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}";
}
}