Flutter 裁剪图片

在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;
}
相关推荐
程序员黑豆1 小时前
Java类型推断完全指南:从var到菱形运算符,掌握使用限制与最佳实践
java·前端·ai编程
To_OC2 小时前
踩了个 TS 的坑之后,我终于把 type 和 interface 掰明白了
前端·react.js·typescript
GreenTea2 小时前
深度解读 Anthropic 多智能体报告:更强的模型 ≠ 更好的协调
前端·后端·算法
浮生望2 小时前
前端API工程化:用 Mock 数据与 Axios 配置实现独立于后端的并行开发
前端
万少3 小时前
给 DeepSeek Harness 装个"应用商店":一条命令,595 个插件随你逛
前端·javascript·后端
波波0073 小时前
C# 15 重磅新特性: 带标签 break 与 continue:重新定义嵌套循环控制流
服务器·前端·c#
Brown.alexis4 小时前
es6知识点1-自备使用
前端·ecmascript·es6
小爬的老粉丝5 小时前
JavaScript 纯前端预览 WPS:先识别容器,再路由解析器
前端·javascript·wps
计算机魔术师5 小时前
新兴多智能体系统的模式与问题
前端
用户059540174466 小时前
AI Agent 上下文污染踩坑实录:用 pytest + Redis 揪出 3 类记忆串号 bug,排查 6 小时
前端·css