前端图片压缩
一、图片压缩
前端图片压缩主要使用canvas将图片画到画布上,在图片绘制之前,先按照一定的宽高计算出要缩小的倍数,然后比较宽度和高度缩小的倍数,哪个倍数值比较大使用哪个进行压缩计算出最终的画布大小以及要绘制的图形大小;
以下是图片上传代码:
function clipImage(file, callback) {
const canvas = document.createElement('canvas')
const context = canvas.getContext('2d')
const image = new Image()
const objectUrl = getObjectURL(file)
image.src = objectUrl
image.onload = () => {
const wScale = image.width > 1920 ? image.width / 1920 : 1
const hScale = image.height > 1080 ? image.height / 1080 : 1
let w, h
if (wScale > hScale) {
w = image.width / wScale
h = image.height / wScale
} else {
w = image.width / hScale
h = image.height / hScale
}
canvas.width = w
canvas.height = h
context.drawImage(image, 0, 0, w, h)
}
}
function getObjectURL(file) {
let url = null
if (window.createObjectURL !== undefined) {
url = window.createObjectURL(file)
} else if (window.URL !== undefined) {
url = window.URL.createObjectURL(file)
} else if (window.webkitURL !== undefined) {
url = window.webkitURL.createObjectURL(file)
}
return url
}
function removeObjectUrl(url) {
if (window.revokeObjectURL !== undefined) {
window.revokeObjectURL(url)
} else if (window.URL !== undefined) {
window.URL.revokeObjectURL(url)
} else if (window.webkitURL !== undefined) {
window.webkitURL.revokeObjectURL(url)
}
}
## 二、移动端上传手机拍摄的照片时会出现不同方向的旋转;
在移动端使用相册里的图片上传时,会出现不同方向的旋转;如下图所示:
发生这种情况是因为,照片中包含很多属性来记录拍摄信息。
介绍下:EXIF:可交换图像文件格式(英语:Exchangeable image file format,官方简称Exif),是专门为数码相机的照片设定的,可以记录数码照片的属性信息和拍摄数据。
Exif所记录的数据信息非常丰富,包含了拍摄日期,摄器材,拍摄参数,图像处理参数,图像描述及版权信息,GPS定位数据,缩略图等;其中包含了拍摄角度,比如侧拍还是倒拍;
推荐使用exif.js查看需要的信息,角度(Orientation)就在0x0112;
接下来使用exif.js提供的方法getData 和 getTag获取图片的旋转值,一共会获取9个值,其中一个是undefined,代码如下:
function getPhotoOrientation(image, callback) {
const reader = new FileReader();
reader.readAsText(image);
let orient;
EXIF.getData(image, function () {
orient = EXIF.getTag(this, 'Orientation');
callback(orient);
})
}
## 三、修复不同角度的旋转
使用canvas的偏移旋转方法进行图片的修复,代码如下:
getPhotoOrientation(file, (orient) => {
switch (orient) {
case 2:
context.translate(w, 0)
context.scale(-1, 1)
context.drawImage(image, w, 0, w, h)
break
case 3:
context.rotate(180 * Math.PI / 180)
context.drawImage(image, -w, -h, w, h)
break
case 4:
context.translate(w, 0)
context.scale(-1, 1)
context.rotate(180 * Math.PI / 180)
context.drawImage(image, -w, -h, w, h)
break
case 5:
context.translate(w, 0)
context.scale(-1, 1)
context.rotate(90 * Math.PI / 180)
context.drawImage(image, 0, -w, h, w)
break
case 6:
canvas.width = h
canvas.height = w
context.rotate(90 * Math.PI / 180)
context.drawImage(image, 0, 0, w, -h)
break
case 7:
context.translate(w, 0)
context.scale(-1, 1)
context.rotate(270 * Math.PI / 180)
context.drawImage(image, -h, 0, h, w)
break
case 8:
context.rotate(270 * Math.PI / 180)
context.drawImage(image, -h, 0, h, w)
break
default:
context.drawImage(image, 0, 0, w, h)
}
})
这样就可以上传一个前端压缩的图片了。