最近在剛好遇到要壓縮圖片,網(wǎng)上隨手搜了一下圖片在線(xiàn)壓縮,結(jié)果要么需要登錄、要么要看廣告,感覺(jué)很麻煩,于是乎,就在我的小程序“小白工具集”里擼了一個(gè)圖片壓縮的功能(寫(xiě)小程序純屬個(gè)人愛(ài)好)
圖片大小必然遵循兩個(gè)原則
1、相同格式下圖片越清晰,文件越大
2、相同格式下圖片尺寸越大,文件越大
所以我們壓縮就只干兩件事:可接受的范圍內(nèi)變的更模糊、變的更小
實(shí)現(xiàn)步驟
1、通過(guò)相冊(cè)、相機(jī)或會(huì)話(huà)選擇文件的api來(lái)拿到臨時(shí)文件
2、識(shí)別設(shè)備類(lèi)型,非ios設(shè)備直接使用微信官方的壓縮api,然后over!
3、區(qū)分圖片類(lèi)型,JPG圖片同樣直接使用微信官方的壓縮api,然后over!
4、計(jì)算壓縮、裁切后的圖片大小,將圖片繪制到畫(huà)布上,然后導(dǎo)出為JPG格式,最后同樣是使用微信官方的壓縮api,然后over!
but,坑來(lái)了,ios真機(jī)上高度或者寬度過(guò)大的圖片畫(huà)布在導(dǎo)出時(shí)拋canvasToTempFilePath:fail parse native buffer parameter error. native buffer exceed size limit異常,沒(méi)辦法只能繼續(xù)打補(bǔ)?。合葘?dǎo)出為base64然后再生成臨時(shí)文件,再進(jìn)行壓縮...無(wú)語(yǔ)了...
小程序API列表
下面列舉可能會(huì)用到的一些API,大家可以根據(jù)自己的需求選擇使用
wx.chooseMedia選擇媒體文件。
設(shè)置mediaType:['image']和sourceType:['album','camera'],從相冊(cè)、相機(jī)讀取文件,拿到臨時(shí)文件地址wx.chooseMessageFile從會(huì)話(huà)選擇聊天文件
設(shè)置type: 'image'來(lái)過(guò)濾圖片文件,可以很方便的從聊天會(huì)話(huà)或文件傳輸助手拿到文件wx.getFileSystemManager().getFileInfo獲取文件信息
根據(jù)臨時(shí)文件路徑拿到文件的大小wx.getImageInfo獲取圖片信息
這里接口也支持下載網(wǎng)絡(luò)圖片,我們這里僅僅用它來(lái)根據(jù)臨時(shí)文件路徑獲取圖片的寬和高wx.compressImage圖片壓縮接口
這個(gè)接口是微信提供的圖片壓縮API,可選壓縮質(zhì)量,很方便...但是吧,iOS端僅支持壓縮JPG格式圖片??,所以還得用其它方式來(lái)輔助完成壓縮,大致思路是使用canvas畫(huà)布,通過(guò)畫(huà)布來(lái)完成圖片的重繪,實(shí)現(xiàn)其它格式轉(zhuǎn)JPG,進(jìn)而實(shí)現(xiàn)繼續(xù)使用wx.compressImage來(lái)壓縮wx.getDeviceInfo().system獲取設(shè)備系統(tǒng)信息
用于識(shí)別設(shè)備canvas畫(huà)布
負(fù)責(zé)圖片繪制、壓縮wx.canvasToTempFilePath畫(huà)布導(dǎo)出為臨時(shí)文件wx.base64ToArrayBufferbase64轉(zhuǎn)bufferwx.getFileSystemManager().writeFile寫(xiě)文件
關(guān)鍵代碼
從相冊(cè)選擇圖片
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);
}
})
從相機(jī)拍照
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);
}
})
從會(huì)話(huà)選擇圖片
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, //壓縮質(zhì)量
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') //畫(huà)布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的先轉(zhuǎn)base64,再寫(xiě)入文件
if (canvas.width > 4096 || canvas.width > 4096) {
//轉(zhuǎn)成base64圖片后的質(zhì)量和類(lèi)型
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("寫(xiě)入成功", filePath);
},
fail: (err) => {
console.error(err);
}
});
} else {
// 生成圖片
wx.canvasToTempFilePath({
canvas,
destWidth: 900, //壓縮后寬
destHeight: 900, //壓縮后高
fileType: 'jpg',
quality: 0.8, //質(zhì)量,可自定義
success(res) {
console.log(res.tempFilePath);
},
fail: (err) => {
console.error(err);
}
})
}
}
})
最后,給大家看下成品效果圖
