前言
在移动端领域,图片压缩基本是绕不过去的需求,尤其是微信分享对图片有大小限制。而高频使用图片压缩的原因无非以下几点原因:
1:性能优化,大尺寸图片导致内存占用飙升,易引发应用卡顿、闪退(尤其低端机型),压缩可降低渲染压力。
2:流量敏感,未压缩图片消耗用户超额流量,移动网络下加载缓慢,影响弱网用户体验。
3:存储限制,本地缓存大图快速占满手机存储空间,导致用户主动清理或卸载应用。
4:成本控制,服务器带宽和云存储费用与图片体积正相关,压缩可降低企业运营成本。
5:平台规则适配,社交媒体/文件上传接口普遍存在图片尺寸限制(如微信头像),压缩可规避上传失败。
6:响应速度提升,压缩后图片传输耗时减少50%以上,显著缩短用户等待时间。
7:视觉平衡需求,移动端屏幕物理尺寸有限,超高分辨率图片难以被肉眼感知,压缩可剔除冗余像素数据。
本质矛盾:移动端资源有限性(硬件/网络/存储)与高质量图片需求之间的冲突,压缩是技术妥协的最优解
而图片压缩又分2种1:质量压缩(不改变图片分辨率的情况下压缩图片文件大小)
2:分辨率压缩(改变图片分辨率,分辨率压缩时也会改变文件大小)
简单使用示例(支持文件大小和图片分辨率大小压缩)
public compress(context:Context){
// 此处换成实际的图片uri
const imageData = 'file://com.example.xxx/xxx.jpg'
// 支持fd、uri、沙箱路径、图片url、base64图片、ArrayBuffer数据
HMImage.compress(context)
.start([imageData])
.then((result: CompressResult) => {
// 本次压缩是否全部成功
const isAllSuccess = result.isAllSuccess
// 本次压缩成功的数据
const successData = result.successData
// 本次压缩失败的数据
const failData = result.failData
}).catch((error: BusinessError) => {
})
}
图片压缩实现方法介绍
1:质量压缩
const imagePacker: image.ImagePacker = image.createImagePacker()
// format:图片压缩后的目标格式
// quality:输出图片质量的参数,该参数仅对JPEG图片和HEIF图片生效。取值范围为0-100。
// 0质量最低,100质量最高,质量越高生成图片所占空间越大。WebP、PNG等图片均为无损编码
const packOpts: image.PackingOption = { format: 'image/webp', quality: 70 }
const imagePath = 'xxxx' //实际的图片沙箱路径
const imageSource = image.createImageSource(imagePath)
const result:ArrayBuffer = await imagePacker.packToData(imageSource, packOpts)
// 最后将压缩得到的ArrayBuffer类型的数据保存至本地,然后就完成了图片质量压缩
// 是不是很简单?其实就是官网提供的api,只负责调用就实现了
2:分辨率压缩
// 分辨率压缩的目标大小,比如500x500的图片,压缩成100X100的图片
let options: image.DecodingOptions = {
desiredSize: {
width: 100,
height: 100
}
}
const imagePath = 'xxxx' //实际的图片沙箱路径
const imageSource = image.createImageSource(imagePath)
// 这里进行分辨率压缩返回一个图像像素类PixelMap,
// 后续在通过packToData无损压缩返回ArrayBuffer数据
const pixelMap = imageSource.createPixelMapSync(options)
const imagePacker: image.ImagePacker = image.createImagePacker()
const packOpts: image.PackingOption = { format: 'image/webp', quality: 100 }
const result:ArrayBuffer = await imagePacker.packToData(pixelMap, packOpts)
// 最后将压缩得到的ArrayBuffer类型的数据保存至本地,然后就完成了图片分辨率压缩
// 是不是很简单?其实就是官网提供的api,只负责调用就实现了
ArrayBuffer数据保存至沙箱方法
// 需要保存文件的路径
const filePath="xxxx"
let fileFd =fileIo.openSync(filePath, fileIo.OpenMode.CREATE
| fileIo.OpenMode.WRITE_ONLY
| fileIo.OpenMode.TRUNC).fd
fileIo.writeSync(fileFd, arrayBuffer)
fileIo.closeSync(fileFd)
图片压缩库介绍(源码在文末)
支持的数据类型:fd,uri,图片沙箱路径,图片网络地址,base64图片,ArrayBuffer。
支持批量压缩,提供压缩进度监听。
HMImageUtils额外提供
1:fd转ArrayBuffer、UintArray方法
2:uri转ArrayBuffer、UintArray方法
3:沙箱路径转ArrayBuffer、UintArray方法
4:ArrayBuffer转UintArray方法
下载安装
ohpm install @zhongrui/hm_image
导入模块
import { HMImage, CompressImageOption, CompressResult } from "@zhongrui/hm_image";
图片压缩
public compress(context:Context){
// 此处换成实际的图片uri
const imageData = 'file://com.example.xxx/xxx.jpg'
// 支持fd、uri、沙箱路径、图片url、base64图片、ArrayBuffer数据
HMImage.compress(context)
// 打开调试模式,输出日志
.setDebug(true)
.setProgressListener((progress:number,total:number)=>{
//压缩进度,progress:压缩成功的数量,total:总数量
})
.start([imageData]).then((result: CompressResult) => {
// 本次压缩是否全部成功
const isAllSuccess = result.isAllSuccess
// 本次压缩成功的数据
const successData = result.successData
// 本次压缩失败的数据
const failData = result.failData
// 处理完业务操作之后,调用delete()方法可以删除本次压缩保存的沙箱图片
result.delete()
// 处理完业务操作之后,调用deleteAll()方法可以删除所有压缩保存在沙箱目录的图片,效果和HMImage.deleteAllCompressImage(context)一致
result.deleteAll()
}).catch((error: BusinessError) => {
const code = error.code
const message = error.message
console.info("compress err code:" + code + ",message:" + message)
})
}
compress
compress(context: Context, option?: CompressImageOption)
设置压缩参数
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
context | Context | 是 | 应用上下文 |
option | CompressImageOption | 否 | 图片压缩选项 |
CompressImageOption
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
maxWidth | number | 否 | 限制图片压缩后的最大宽度不超过maxWidth,单位:px |
maxHeight | number | 否 | 限制图片压缩后的最大高度不超过maxHeight,单位:px |
scale | number | 否 | 图片压缩时设置的分辨率缩放比例取值范围:(0,1] |
maxFileSize | number | 否 | 设置图片压缩后的文件大小不超过maxFileSize,单位:byte |
ignoreFileSize | number | 否 | 图片大小如果小于等于ignoreFileSize,则不压缩,单位:byte |
targetDir | string | 否 | 设置图片保存的目录 |
quality | number | 否 | 图片压缩的质量,取值范围:(0,100],默认值:70 |
qualityStep | number | 否 | 如果图片压缩后的文件大小超过maxFileSize,quality会依次减少qualityStep再进行压缩 |
compressNum | number | 否 | 同时压缩图片的多线程数量,默认值:8 |
imageFormat | CompressionImageFormat | 否 | 取值:JPEG,WEBP,PNG,HEIC,HEIF,默认值:CompressionImageFormat.WEBP |
start
start(image: ImageDataType[]): Promise< CompressResult >;
参数:
参数名 | 类型 | 是否必填 | 说明 |
---|---|---|---|
image | ImageDataType[] | 是 | 图片数据,支持string或number或ArrayBuffer类型,可以是fd,uri,url,沙箱路径,base64 |
返回值:
参数名 | 类型 | 说明 |
---|---|---|
isAllSuccess | boolean | 图片是否全部压缩成功 |
successData | CompressImageData[] | 压缩成功的图片数据 |
failData | CompressImageData[] | 压缩失败的图片数据 |
delete | function | 删除本次图片压缩文件的方法 |
deleteAll | function | 删除所有图片压缩文件的方法 |
CompressImageData
参数名 | 类型 | 说明 |
---|---|---|
code | number | 错误码 |
message | string | 错误提示信息 |
origin | ImageDataType | 原始图片数据 |
originSize | number | 原始图片文件大小,单位:byte |
fileName | string | 原始图片缓存到沙箱目录的文件名 |
filePath | string | 原始图片缓存到沙箱目录的文件路径 |
compressFileName | string | 压缩后的图片文件名 |
compressFilePath | string | 压缩后的图片文件路径 |
compressFileSize | number | 压缩后的图片文件大小,单位:byte |
CompressImageData.code错误码
错误码 | 说明 |
---|---|
1 | 成功 |
-1 | 内部错误 |
1001 | 参数错误 |
1002 | 原始图片复制到沙箱目录错误 |
1003 | 检查图片大小错误 |
1005 | 剩余空间不足 |
1006 | 创建imageSource失败 |
1007 | 分辨率压缩失败 |
1008 | 质量压缩失败 |
1009 | 保存和压缩过程错误 |
1010 | 网络图片地址为空 |
1011 | 获取网络图片大小错误 |
1012 | 下载网络地址错误 |
注意:start().then().catch((error: BusinessError) => {})中的BusinessError错误码需要另行处理,可参考官方文档
deleteAllCompressImage
删除所有图片压缩保存到本地的文件的方法
// 删除所有压缩保存在沙箱目录的图片
HMImage.deleteAllCompressImage(context)
let targetDir='/data/xxxx/haps/entry/files'
// 如果压缩图片时CompressImageOption参数有设置targetDir,这里可以传入otherDir一起删除
HMImage.deleteAllCompressImage(context,targetDir)
let otherDir=['/data/xxxx/haps/entry/files','/data/xxxx/haps/entry/cache']
// 除了删除默认缓存目录,还需要删除其他多个目录
HMImage.deleteAllCompressImage(context,...otherDir)
参数:
参数名 | 类型 | 是否必传 | 说明 |
---|---|---|---|
context | Context | 是 | 应用上下文 |
dirPath | …string[] | 否 | 其他目录 |
HMImageUtils
// fd、uri、沙箱路径文件转ArrayBuffer
HMImageUtils.fileToArrayBuffer(file: number | string)
// base64数据转ArrayBuffer
HMImageUtils.base64ToArrayBuffer(base64Image: string)
// fd、uri、沙箱路径、base64、ArrayBuffer数据转Uint8Array
HMImageUtils.fileToUint8Array(file: ImageDataType)
历史文章
HarmonyOS NEXT多环境+多渠道+自定义路径输出+自定义名称一键打app和hap包
HarmonyOS NEXT一行代码实现任意处弹窗
HarmonyOS NEXT数据列表加载更多(无需监听列表滑到最底部)
HarmonyOS NEXT下拉刷新+上拉加载(纵向横向都支持)(v1+v2装饰器)