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;
}
相关推荐
天渺工作室4 小时前
实现一个adblock/adblock plus等浏览器广告拦截器检测插件
前端·javascript
阳光是sunny4 小时前
Vue 项目怎么做用户行为全链路监控?轻量插件方案详解
前端·面试·架构
ZhengEnCi4 小时前
Q04-Vite禁用CSS代码分割-解决生产环境样式加载顺序混乱问题
前端·vue.js·vite
九酒5 小时前
AI Agent 开发踩坑记:口播功能非得用 APP 原生实现吗?
前端·人工智能·agent
Jackson__5 小时前
做了一段时间的AI coding后,我终于搞清了 CLI 和 MCP 的区别
前端·agent·ai编程
IT_陈寒8 小时前
JavaScript项目实战经验分享
前端·人工智能·后端
用户47949283569159 小时前
6w star,GitHub 趋势第一的 Ponytail,这个agent插件到底在火什么
前端·后端
薛定喵的谔10 小时前
我开源了一个精致的 Next.js 博客模板:Skyplume
前端·前端框架·next.js
张龙68711 小时前
构建生产级 AI Agent:工具调用与记忆架构实战指南
前端
kyriewen12 小时前
2026 年了,还在用 Node.js?Bun 迁移实战:20 分钟搞定,附踩坑记录
前端·javascript·node.js