最近在刚好遇到要压缩图片,网上随手搜了一下图片在线压缩,结果要么需要登录、要么要看广告,感觉很麻烦,于是乎,就在我的小程序“小白工具集”里撸了一个图片压缩的功能(写小程序纯属个人爱好)
图片大小必然遵循两个原则
1、相同格式下图片越清晰,文件越大
2、相同格式下图片尺寸越大,文件越大
所以我们压缩就只干两件事:可接受的范围内变的更模糊、变的更小
实现步骤
1、通过相册、相机或会话选择文件的api来拿到临时文件
2、识别设备类型,非ios设备直接使用微信官方的压缩api,然后over!
3、区分图片类型,JPG
图片同样直接使用微信官方的压缩api,然后over!
4、计算压缩、裁切后的图片大小,将图片绘制到画布上,然后导出为JPG
格式,最后同样是使用微信官方的压缩api,然后over!
but,坑来了,ios真机上高度或者宽度过大的图片画布在导出时抛canvasToTempFilePath:fail parse native buffer parameter error. native buffer exceed size limit
异常,没办法只能继续打补丁:先导出为base64然后再生成临时文件,再进行压缩...无语了...
小程序API列表
下面列举可能会用到的一些API,大家可以根据自己的需求选择使用
wx.chooseMedia
选择媒体文件。
设置mediaType:['image']
和sourceType:['album','camera']
,从相册、相机读取文件,拿到临时文件地址wx.chooseMessageFile
从会话选择聊天文件
设置type: 'image'
来过滤图片文件,可以很方便的从聊天会话或文件传输助手拿到文件wx.getFileSystemManager().getFileInfo
获取文件信息
根据临时文件路径拿到文件的大小wx.getImageInfo
获取图片信息
这里接口也支持下载网络图片,我们这里仅仅用它来根据临时文件路径获取图片的宽和高wx.compressImage
图片压缩接口
这个接口是微信提供的图片压缩API,可选压缩质量,很方便...但是吧,iOS端仅支持压缩JPG
格式图片😓,所以还得用其它方式来辅助完成压缩,大致思路是使用canvas
画布,通过画布来完成图片的重绘,实现其它格式转JPG
,进而实现继续使用wx.compressImage
来压缩wx.getDeviceInfo().system
获取设备系统信息
用于识别设备canvas
画布
负责图片绘制、压缩wx.canvasToTempFilePath
画布导出为临时文件wx.base64ToArrayBuffer
base64转bufferwx.getFileSystemManager().writeFile
写文件
关键代码
从相册选择图片
wx.chooseMedia({
count: 9,
mediaType: ['image'],
sizeType: ['original'],
sourceType: ['album'],
success: function (res) {
const images = res.tempFiles.map(i => {
console.log(i.tempFilePath, i.size);
});
},
fail: function (err) {
console.error('选择媒体文件失败:', err);
}
})
从相机拍照
wx.chooseMedia({
count: 1,
mediaType: ['image'],
sizeType: ['original'],
sourceType: ['camera'],
success: function (res) {
const images = res.tempFiles.map(i => {
console.log(i.tempFilePath, i.size);
});
},
fail: function (err) {
console.error('选择媒体文件失败:', err);
}
})
从会话选择图片
wx.chooseMessageFile({
count: 9,
type: 'image',
success: function (res) {
const images = res.tempFiles.map(i => {
console.log(i.path, i.size);
});
},
fail: function (err) {
console.error('选择媒体文件失败:', err);
}
})
加载图片大小
const fs = wx.getFileSystemManager();
fs.getFileInfo({
filePath: '文件路径',
success: (res) => {
console.log(res);
},
fail: (error) => {
console.error(error);
}
});
加载图片宽高
wx.getImageInfo({
src: '',
success: function (imageInfo) {
console.log(imageInfo);
},
fail: function (err) {
console.error('获取图片信息失败:', err);
}
});
微信api直接压缩
wx.compressImage({
src: '图片路径',
quality: 80, //压缩质量
compressedWidth: 900, //压缩后宽
compressedHeight: 900, //压缩后高
success(res) {
console.log(res.tempFilePath);
},
fail: (err) => {
console.error(err);
}
})
canvas重绘压缩
const query = this.createSelectorQuery()
let dom = query.select('#canvasId') //画布id
dom.fields({ node: true, size: true })
.exec((res: any) => {
const canvas = res[0].node
canvas.width = 900 //压缩后宽
canvas.height = 900 //压缩后高
const ctx = canvas.getContext('2d')
let img = canvas.createImage();
img.src = ''; //要压缩的图片路径
img.onload = function () {
// 将图片绘制到canvas
ctx.drawImage(img, 0, 0, canvas.width, canvas.height)
//大于4096的先转base64,再写入文件
if (canvas.width > 4096 || canvas.width > 4096) {
//转成base64图片后的质量和类型
const base64Data = canvas.toDataURL('image/jpeg', 0.8);
const base64 = base64Data.replace(/^data:image\/\w+;base64,/, '');
const buffer = wx.base64ToArrayBuffer(base64);
const filePath = `${wx.env.USER_DATA_PATH}/test.jpg`;
wx.getFileSystemManager().writeFile({
filePath,
data: buffer,
encoding: 'binary',
success() {
console.log("写入成功", filePath);
},
fail: (err) => {
console.error(err);
}
});
} else {
// 生成图片
wx.canvasToTempFilePath({
canvas,
destWidth: 900, //压缩后宽
destHeight: 900, //压缩后高
fileType: 'jpg',
quality: 0.8, //质量,可自定义
success(res) {
console.log(res.tempFilePath);
},
fail: (err) => {
console.error(err);
}
})
}
}
})
最后,给大家看下成品效果图