更新记录

1.0.0(2026-10-09)

2026-10-09

  • 首个版本发布
  • Android 端:基于 BitmapFactory + Bitmap.compress 实现压缩,inJustDecodeBounds 只读尺寸、inSampleSize 降采样防 OOM
  • iOS 端:基于 UIGraphicsImageRenderer 重绘缩放 + UIImage.jpegData / pngData 编码
  • 鸿蒙端:基于 @kit.ImageKit 的 PixelMap + image.createImagePacker 编码
  • 提供 compress / compressToBase64 / resize / convertFormat / getImageInfo 五个接口
  • 返回压缩率与真实输出尺寸,便于业务侧判断是否需要二次压缩
  • web 与小程序端降级到 Canvas 重绘路径,并提供 compressAsync 异步接口
  • webp 在无编码能力的平台(iOS / 鸿蒙 / API<30 的 Android)自动降级为 jpg,并在返回值中回写真实格式

平台兼容性

uni-app(3.99)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
√ √ √ √ √ √ √ √ √
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
√ √ √ √ √ √ √ √ √ - √ ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
√ √ √ ×

图片压缩(czg-imgcomp)

原生图片压缩与格式转换。App 端走 uts 原生实现(Android Bitmap / iOS UIGraphicsImageRenderer /鸿蒙 PixelMap),大图先降采样再压缩,避免一次性读入内存导致 OOM;web 与小程序端自动降级到 Canvas 重绘路径。

为什么不用现成方案

方案 问题
uni.compressImage 只支持 jpg、不能指定质量、不返回压缩率、无法控制输出尺寸
引入 zopfli / mozjpeg wasm 包体积大,小程序端加载慢,且压缩前仍要自己解码
直接调 Bitmap.compress 直接对大图压缩极易 OOM;且缺采样、缺格式协商、缺结果度量

本插件的取舍:先按最长边降采样,再按目标质量重编码,与原生图片管线(Android decode→sample→encode)的做法一致,并额外返回压缩率与真实输出尺寸,方便业务侧判断是否需要二次压缩。

特性

  • 原生实现:App 端不经过 JS 引擎,大图处理不卡 UI
  • 降采样防OOM:Android 用 inSampleSize、鸿蒙用 desiredSize、iOS 用 UIGraphicsImageRenderer 重绘,均在解码阶段降分辨率
  • 只读尺寸不占内存:读取图片信息走 inJustDecodeBounds / getImageInfoSync,不分配像素缓冲
  • 真实结果度量:返回压缩后字节数、尺寸、压缩率,ratio 可直接用于判断是否需要再压
  • 格式协商:请求 webp 但平台无编码能力时(iOS、鸿蒙)自动降级为 jpg,并在返回值的 format 中回写真实格式,不静默产出错格式
  • 全端可用:App 端原生实现;web / 小程序降级到 Canvas,接口一致

安装

在插件市场搜索「图片压缩」或插件 ID czg-imgcomp,点击「使用 HBuilderX 导入插件」;或把 g-imgcomp 目录放入工程 uni_modules/ 下。

App 端需先用 HBuilderX 制作自定义基座,uts 插件才能运行。详见 uts 插件使用说明。

用法

import { compress, compressToBase64, resize, convertFormat, getImageInfo }
  from '@/uni_modules/g-imgcomp/index.native.js'

// 1. 读图片信息(不占内存,可安全用于列表预加载)
const info = getImageInfo('/path/to/photo.jpg')
console.log(info.width, info.height, info.size, info.format)

// 2. 压缩到文件(质量 70 + 最长边不超过 1080)
const r = compress('/path/to/photo.jpg', {
  quality: 70,
  format: 'jpg',
  maxEdge: 1080,
  outPath: '/path/to/photo_min.jpg'
})
console.log(r.size)   // 压缩后字节数
console.log(r.ratio)  // 压缩率,如 0.18 表示压到原来的 18%

// 3. 压缩成 base64(直接塞进 JSON 字段)
const b64 = compressToBase64('/path/to/photo.jpg', {
  quality: 60,
  maxEdge: 640
})

// 4. 仅缩放,不重编码(保画质)
const rz = resize('/path/to/photo.jpg', 1280, '/path/to/photo_1280.jpg')

// 5. 格式转换
const cv = convertFormat('/path/to/photo.png', 'jpg', '/path/to/photo.jpg')

web / 小程序端

Canvas 导出本身是异步接口,所以压缩统一走 Promise:

import { compressAsync } from '@/uni_modules/g-imgcomp/index.js'

const r = await compressAsync('/path/to/photo.jpg', {
  quality: 70,
  format: 'jpg',
  maxEdge: 1080
})
console.log(r.path)  // 压缩后临时文件路径

web / 小程序端调用同步的 compress() 会抛出错误并提示改用 compressAsync(), 这是刻意设计——同步接口在非App 端没有等价实现,返回假结果比报错更糟。

API 清单

方法 签名 返回
getImageInfo (path: string) => ImageInfo { width, height, size, format }
compress (path: string, options: CompressOptions \| null) => CompressResult { size, width, height, ratio, format, path }
compressToBase64 (path: string, options: CompressOptions \| null) => string base64 字符串(无 dataURL 前缀)
resize (path: string, maxEdge: number, outPath: string) => CompressResult 同 compress
convertFormat (path: string, format: string, outPath: string) => CompressResult 同 compress
compressAsync (path: string, options: CompressOptions \| null) => Promise<CompressResult> Promise,接口与 compress 一致

CompressOptions

字段 类型 默认 说明
quality number 80 质量 0~100;PNG 忽略此值
format string 'jpg' 'jpg' / 'png' / 'webp'
maxEdge number 0 目标最长边像素;0 表示不缩放,大于原图时不会放大
outPath string '' 输出路径;留空则自动生成 <原名>_min.<格式>
filter string 'high' 缩放插值,'high' 清晰 / 'low' 更快

平台支持与能力差异

平台 实现 格式支持
Android BitmapFactory + Bitmap.compress jpg / png / webp
iOS UIGraphicsImageRenderer + UIImage.jpegData jpg / png(无 webp 编码,请求 webp 自动降级为 jpg)
鸿蒙 @kit.ImageKit PixelMap + Packer jpg / png(无 webp 编码,请求 webp 自动降级为 jpg)
Web /小程序 Canvas 重绘 + canvasToTempFilePath jpg / png

Android 从 API 30 起原生支持 WebP 编码,低于 API 30 的设备请求 webp 时会回退为 jpg,返回值 format 为真实格式。若业务必须保证 webp,建议在 Android 端加最低版本约束:

"app-plus": { "android": { "minSdkVersion": 21 } }

错误码

码 含义 触发场景
40001 EMPTY_PATH 传入空路径或非字符串
40002 BAD_OPTION quality 越界、format 非法、maxEdge 为负、options 非对象;非 App 端调同步 compress
40003 FILE_NOT_FOUND 路径不存在、无权限、或不是有效图片(尺寸为 0)
50001 UNSUPPORTED 当前环境无 uni 对象且未注入原生实现
50002 COMPRESS_FAIL 解码或编码失败(文件损坏、格式不支持、磁盘写入失败)

注意事项

  • ratio > 1 表示压缩后反而变大了(典型场景:小图 +高 quality + PNG)。此时建议改小 quality 或不再压缩。
  • 二次压缩会累积画质损失。若目标是把 2MB 降到 200KB,一次把 quality 设到 50~60通常优于两次各压80。
  • PNG 无损,压缩只能靠缩小尺寸来减小体积。需要减小体积请用 jpg。
  • 输入路径为 App 本地文件路径(plus.io.convertLocalFileSystemURL 或 uni.saveFile 的返回值),不是网络 URL。

价格

授权类型 价格
普通授权(regular) ¥19.90
源码授权(sourcecode) ¥99.00

普通授权版由 DCloud 对 uts 源码加密保护,运行时经云端解密编译;源码授权版提供完整 uts 源码,可自行修改与扩展,同样享受后续版本升级。

隐私说明

本插件全部图片处理在本机完成,不联网、不采集、不上传任何图片或数据。插件不主动读取相册与存储目录,输入完全由调用方通过参数传入。隐私声明详见 package.json 的 dcloudext.declaration。

更新日志

见 changelog.md

开源协议

MIT

隐私、权限声明

1. 本插件需要申请的系统权限列表:

无。压缩输入为调用方主动传入的图片路径,插件不主动读取相册或存储。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

全部图片处理在本机完成,不联网、不采集、不上传任何图片或数据。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。