在ble传入数据的时候对图片要一定的要求,比如:尺寸、文件大小等。 1、输入图片形状:长方形、正方形 2、目标大小 3、输入裁剪和压缩后的图片 4、代码如下
ini
/// 将图片裁剪为正方形并缩放到 [squareSize] x [squareSize],
/// 然后通过调整 JPEG 质量压缩至 [targetSize] 字节以内。
/// [imageBytes] : 原始图像字节数据
/// [squareSize] : 最终正方形的边长(像素),例如 360
/// [targetSize] : 目标文件大小(字节)
/// [minQuality] : 允许的最低 JPEG 质量(1-100),防止过度压缩
/// 返回压缩后的 JPEG 字节数据,如果解码失败则返回原图。
static Future<Uint8List> compressToSize(
Uint8List imageBytes,
int squareSize,
int targetSize, {
int minQuality = 85,
}) async {
final original = img.decodeImage(imageBytes);
if (original == null) return imageBytes; // 解码失败,返回原图
// 1. 裁剪为正方形(基于最小边居中裁剪)
img.Image squareImage;
final int srcWidth = original.width;
final int srcHeight = original.height;
if (srcWidth > srcHeight) {
// 宽度大于高度:以高度为边长,裁剪左右
final int cropX = (srcWidth - srcHeight) ~/ 2;
squareImage = img.copyCrop(
original,
x: cropX,
y: 0,
width: srcHeight,
height: srcHeight,
);
} else if (srcHeight > srcWidth) {
// 高度大于宽度:以宽度为边长,裁剪上下
final int cropY = (srcHeight - srcWidth) ~/ 2;
squareImage = img.copyCrop(
original,
x: 0,
y: cropY,
width: srcWidth,
height: srcWidth,
);
} else {
// 已是正方形,无需裁剪
squareImage = original;
}
// 2. 缩放到目标正方形尺寸
final resizedImage = img.copyResize(
squareImage,
width: squareSize,
height: squareSize,
);
// 3. 二分法调整 JPEG 质量
int low = 1;
int high = 100;
int bestQuality = 100;
Uint8List bestBytes = img.encodeJpg(resizedImage, quality: bestQuality);
// 如果最高质量已经小于目标,直接返回
if (bestBytes.length <= targetSize) {
return bestBytes;
}
const int maxIterations = 10;
for (int i = 0; i < maxIterations; i++) {
int mid = (low + high) ~/ 2;
if (mid < minQuality) break;
final compressedBytes = img.encodeJpg(resizedImage, quality: mid);
if (compressedBytes.length <= targetSize) {
// 满足要求,尝试更高质量
bestQuality = mid;
bestBytes = compressedBytes;
low = mid + 1;
} else {
high = mid - 1;
}
if (low > high) break;
}
return bestBytes;
}