Files
loongyan/bin/util/vips.dart
lzw-723 2a6c9ba8c2
All checks were successful
Dart CI / build (push) Successful in 34s
格式化代码
2026-04-04 14:44:27 +08:00

84 lines
2.1 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:io';
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 = 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}";
}
}