热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Flutter问题系列第74篇】在Flutter中如何对Uint8List和File类型的图像数据进行压缩

这是【Flutter问题系列第74篇】,如果觉得有用的话,欢迎关注专栏。文章目录一:问题描述二:引入࿰

这是【Flutter 问题系列第 74 篇】,如果觉得有用的话,欢迎关注专栏。

文章目录

      • 一:问题描述
      • 二:引入,获取依赖
      • 三:根据数据类型指定压缩方式
        • 3-1:Uint8List → Uint8List
        • 3-2:File → File
        • 3-3:File → Uint8List
        • 3-4:Asset → Uint8List
        • 解释说明
      • 四:完整代码


一:问题描述

项目中用到了百度 OCR 图像识别的功能,如果上传的图片大于 4 兆的话,就会提示因图片过大识别失败。

所以需要对上传的图像进行压缩,在 Flutter 中如何对图像数据进行压缩呢?

二:引入,获取依赖

这里用到了 pub 上的第三方插件库 flutter_image_compress,同时支持在 Android 和 iOS 上运行。截止到发文最新版本是 1.1.0 。

在项目的配置文件 pubspec.yaml 中引入依赖,如下图所示

在这里插入图片描述

然后在终端执行 flutter pub get 命令获取依赖。

三:根据数据类型指定压缩方式

这里我根据官方文档指定的数据类型,封装了四种不同的图像数据转换的方法,

这里自定义一个压缩图片的工具类 CompressUtil,并指定其最小分辨率的高度和宽度。

如下代码所示

class CompressUtil {static int minHeight = 1920; // 指定最小分辨率的高度static int minWidth = 1080; // 指定最小分辨率的宽度
}

然后在当前工具类中,定义了如下四个压缩的方法,简单明了,不需要你对插件有了解,直接拿走使用就行。

3-1:Uint8List → Uint8List

第一种压缩方式的参数类型是 Uint8List ,返回值类型是 Future,如下代码所示

/// 压缩方式一 Uint8List -> Uint8Liststatic Future<Uint8List> u8ToU8(Uint8List list) async {int quality &#61; imageQuality(list.length);Uint8List result &#61; await FlutterImageCompress.compressWithList(list,minWidth: minWidth,minHeight: minHeight,quality: quality,);debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");return result;}

3-2&#xff1a;File → File

第二种压缩方式的参数类型是 File&#xff0c;返回值类型是 Future&#xff0c;如下代码所示

/// 压缩方式二 File -> Filestatic Future<File?> fileToFile(File file) async {// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);// 缓存路径Directory cache &#61; await getTemporaryDirectory();int time &#61; DateTime.now().millisecondsSinceEpoch;String savePath &#61; cache.path &#43; "/AllenSu_$time.jpg"; // 指定压缩后图片的路径File? result &#61; await FlutterImageCompress.compressAndGetFile(file.path,savePath,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.readAsBytesSync().length)}");}return result;}

获取文件路径这里用到了插件 path_provider&#xff0c;需要在 pubspec.yaml 文件中引入。

压缩后图片的路径你可以修改为自定义的路径。

3-3&#xff1a;File → Uint8List

第三种压缩方式的参数类型是 File&#xff0c;返回值类型是 Future&#xff0c;如下代码所示

/// 压缩方式三 File -> Uint8Liststatic Future<Uint8List?> fileToU8(File file) async {// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);Uint8List? result &#61; await FlutterImageCompress.compressWithFile(file.path,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");}return result;}

3-4&#xff1a;Asset → Uint8List

第三种压缩方式的参数类型是 String&#xff08;其实就是图片的路径 path&#xff09;&#xff0c;返回值类型是 Future&#xff0c;如下代码所示

/// 压缩方式四 Asset -> Uint8Liststatic Future<Uint8List?> assetToU8(String assetName) async {File file &#61; File(assetName);// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);Uint8List? result &#61; await FlutterImageCompress.compressAssetImage(assetName,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");}return result!;}

以上四种压缩图片的方式满足正常开发是没有问题的。

解释说明

代码中的方法 imageQuality(int length)size((int length)) 是我自己扩展的&#xff0c;原因如下

  • 对于方法 imageQuality&#xff0c;是为了根据传入的图片字节长度&#xff0c;返回指定的图片质量。如果你想固定压缩图片的质量&#xff0c;可以不用在意这个方法。
  • 对于方法 size&#xff0c;是为了方便查看图片的大小&#xff0c;因为图片的大小是字节数组的长度&#xff0c;看起来不太方便&#xff0c;所以进行了转换&#xff0c;如果图片小于 1 兆&#xff0c;则显示 KB&#xff0c;如果图片大于 1 兆&#xff0c;则显示 MB&#xff0c;并保留一位小数。

我并没有把代码中的注释去掉&#xff0c;因为我觉得你在调试的时候应该可以用得到。

四&#xff1a;完整代码

以上是对封装的工具类进行了拆分&#xff0c;对工具类的每个方法进行了解释说明。

但为方便大家复制&#xff0c;最后把完整的代码贴到这里&#xff0c;如下

import &#39;dart:io&#39;;
import &#39;dart:typed_data&#39;;
import &#39;package:flutter/widgets.dart&#39;;
import &#39;package:flutter_image_compress/flutter_image_compress.dart&#39;;
import &#39;package:path_provider/path_provider.dart&#39;;// ------------------------------------------------------
// author&#xff1a;Allen Su
// date &#xff1a;2022/7/9 00:08
// usage &#xff1a;图片压缩工具类
// ------------------------------------------------------class CompressUtil {static int minHeight &#61; 1920; // 指定最小分辨率的高度static int minWidth &#61; 1080; // 指定最小分辨率的宽度/// 压缩方式一 Uint8List -> Uint8Liststatic Future<Uint8List> u8ToU8(Uint8List list) async {int quality &#61; imageQuality(list.length);Uint8List result &#61; await FlutterImageCompress.compressWithList(list,minWidth: minWidth,minHeight: minHeight,quality: quality,);debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");return result;}/// 压缩方式二 File -> Filestatic Future<File?> fileToFile(File file) async {// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);// 缓存路径Directory cache &#61; await getTemporaryDirectory();int time &#61; DateTime.now().millisecondsSinceEpoch;String savePath &#61; cache.path &#43; "/AllenSu_$time.jpg";File? result &#61; await FlutterImageCompress.compressAndGetFile(file.path,savePath,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.readAsBytesSync().length)}");}return result;}/// 压缩方式三 File -> Uint8Liststatic Future<Uint8List?> fileToU8(File file) async {// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);Uint8List? result &#61; await FlutterImageCompress.compressWithFile(file.path,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");}return result;}/// 压缩方式四 Asset -> Uint8Liststatic Future<Uint8List?> assetToU8(String assetName) async {File file &#61; File(assetName);// 图片质量int quality &#61; imageQuality(file.readAsBytesSync().length);Uint8List? result &#61; await FlutterImageCompress.compressAssetImage(assetName,minWidth: minWidth,minHeight: minHeight,quality: quality,);if (result !&#61; null) {debugPrint("压缩后图片的大小&#xff1a;${size(result.length)}");}return result!;}/// 根据传入的图片字节长度&#xff0c;返回指定的图片质量static int imageQuality(int length) {debugPrint("压缩前图片的大小&#xff1a;${size(length)}");int quality &#61; 100; // 图片质量指数int m &#61; 1024 * 1024; // 1 兆if (length < 0.5 * m) {quality &#61; 70;debugPrint("图片小于 0.5 兆&#xff0c;质量设置为 70");} else if (length >&#61; 0.5 * m && length < 1 * m) {quality &#61; 60;debugPrint("图片大于 0.5 兆小于 1 兆&#xff0c;质量设置为 60");} else if (length >&#61; 1 * m && length < 2 * m) {quality &#61; 50;debugPrint("图片大于 1 兆小于 2 兆&#xff0c;质量设置为 50");} else if (length >&#61; 2 * m && length < 3 * m) {quality &#61; 40;debugPrint("图片大于 2 兆小于 3 兆&#xff0c;质量设置为 40");} else if (length >&#61; 3 * m && length < 4 * m) {quality &#61; 30;debugPrint("图片大于 3 兆小于 4 兆&#xff0c;质量设置为 30");} else {quality &#61; 20;debugPrint("图片大于 4 兆&#xff0c;质量设置为 20");}return quality;}/// 根据传入的字节长度&#xff0c;转换成相应的 M 和 KBstatic String size(int length) {String res &#61; "";final int unit &#61; 1024;final int m &#61; unit * unit; // 1M// 如果小于 1 兆&#xff0c;显示 KBif (length < 1 * m) {res &#61; (length / unit).toStringAsFixed(0) &#43; " KB";}// 如果大于 1 兆&#xff0c;显示 MB&#xff0c;并保留一位小数if (length >&#61; 1 * m) {res &#61; (length / m).toStringAsFixed(1) &#43; " MB";}return res;}
}

经测试&#xff0c;1 张 1.2 兆的图片&#xff0c;如果设置压缩质量为 50&#xff0c;压缩后大概在 50 - 100 kb 之间&#xff0c;图片虽然小了许多&#xff0c;但还是很清晰的&#xff0c;且 OCR 识别成功率几乎是 100 %。

至此&#xff0c;关于如何在 Flutter 中对图像数据进行压缩便介绍到这里。

你的问题得到解决了吗&#xff1f;欢迎在评论区留言。

赠人玫瑰&#xff0c;手有余香&#xff0c;如果觉得文章不错&#xff0c;希望可以给个一键三连&#xff0c;感谢。



结束语
Google 的 Flutter 越来越火&#xff0c;截止 2022年7月9日 GitHub 标星已达 142K&#xff0c;Flutter 毅然是一种趋势&#xff0c;所以作为前端开发者&#xff0c;没有理由不趁早去学习。

无论你是 Flutter 新手还是已经入门了&#xff0c;不妨先点个关注&#xff0c;后续我会将 Flutter 中的常用组件&#xff08;含有源码分析、组件的用法及注意事项&#xff09;以及可能遇到的问题写到 CSDN 博客中&#xff0c;希望自己学习的同时&#xff0c;也可以帮助更多的人。

推荐阅读
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • PHP图片截取方法及应用实例
    本文介绍了使用PHP动态切割JPEG图片的方法,并提供了应用实例,包括截取视频图、提取文章内容中的图片地址、裁切图片等问题。详细介绍了相关的PHP函数和参数的使用,以及图片切割的具体步骤。同时,还提供了一些注意事项和优化建议。通过本文的学习,读者可以掌握PHP图片截取的技巧,实现自己的需求。 ... [详细]
  • Redis底层数据结构之压缩列表的介绍及实现原理
    本文介绍了Redis底层数据结构之压缩列表的概念、实现原理以及使用场景。压缩列表是Redis为了节约内存而开发的一种顺序数据结构,由特殊编码的连续内存块组成。文章详细解释了压缩列表的构成和各个属性的含义,以及如何通过指针来计算表尾节点的地址。压缩列表适用于列表键和哈希键中只包含少量小整数值和短字符串的情况。通过使用压缩列表,可以有效减少内存占用,提升Redis的性能。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 本文介绍了Android中的assets目录和raw目录的共同点和区别,包括获取资源的方法、目录结构的限制以及列出资源的能力。同时,还解释了raw目录中资源文件生成的ID,并说明了这些目录的使用方法。 ... [详细]
  • Android自定义控件绘图篇之Paint函数大汇总
    本文介绍了Android自定义控件绘图篇中的Paint函数大汇总,包括重置画笔、设置颜色、设置透明度、设置样式、设置宽度、设置抗锯齿等功能。通过学习这些函数,可以更好地掌握Paint的用法。 ... [详细]
  • 开发笔记:加密&json&StringIO模块&BytesIO模块
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了加密&json&StringIO模块&BytesIO模块相关的知识,希望对你有一定的参考价值。一、加密加密 ... [详细]
  • Android中高级面试必知必会,积累总结
    本文介绍了Android中高级面试的必知必会内容,并总结了相关经验。文章指出,如今的Android市场对开发人员的要求更高,需要更专业的人才。同时,文章还给出了针对Android岗位的职责和要求,并提供了简历突出的建议。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文介绍了Redis的基础数据结构string的应用场景,并以面试的形式进行问答讲解,帮助读者更好地理解和应用Redis。同时,描述了一位面试者的心理状态和面试官的行为。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 本文讨论了在手机移动端如何使用HTML5和JavaScript实现视频上传并压缩视频质量,或者降低手机摄像头拍摄质量的问题。作者指出HTML5和JavaScript无法直接压缩视频,只能通过将视频传送到服务器端由后端进行压缩。对于控制相机拍摄质量,只有使用JAVA编写Android客户端才能实现压缩。此外,作者还解释了在交作业时使用zip格式压缩包导致CSS文件和图片音乐丢失的原因,并提供了解决方法。最后,作者还介绍了一个用于处理图片的类,可以实现图片剪裁处理和生成缩略图的功能。 ... [详细]
  • 一句话解决高并发的核心原则
    本文介绍了解决高并发的核心原则,即将用户访问请求尽量往前推,避免访问CDN、静态服务器、动态服务器、数据库和存储,从而实现高性能、高并发、高可扩展的网站架构。同时提到了Google的成功案例,以及适用于千万级别PV站和亿级PV网站的架构层次。 ... [详细]
  • 本文介绍了OkHttp3的基本使用和特性,包括支持HTTP/2、连接池、GZIP压缩、缓存等功能。同时还提到了OkHttp3的适用平台和源码阅读计划。文章还介绍了OkHttp3的请求/响应API的设计和使用方式,包括阻塞式的同步请求和带回调的异步请求。 ... [详细]
author-avatar
你我她啊
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有