随着科技发展的浪潮,手机上的摄像机的像素越来越高,成像的效果也越来越好。到现在一张手机拍摄的图片在 2M 左右是很正常的。在实际的应用场景中经常需要用户上传图片这样的人机交互方式。为了提高用户体验,上传图片之前要进行压缩。部分手机拍摄的图片会带有拍摄方向(如魅族,苹果),在上传之前就需要进行图片修正。案例中使用了 html5 的一些 API 对图片进行压缩; exif.js 的 EXIF.getDate(image, callback) API 获取图片的拍摄方向判断校正。
exif.js 相关资料:
https://github.com/exif-js/exif-js
http://code.ciaoca.com/javascript/exif-js/
html5 使用到的相关API
https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toDataURL
https://developer.mozilla.org/en-US/docs/Web/API/FileReader
https://developer.mozilla.org/zh-CN/docs/Web/API/CanvasRenderingContext2D/drawImage
https://developer.mozilla.org/zh-CN/docs/Web/API/Canvas_API/Tutorial/Using_images
1、添加 change 监听事件。当用户选择好图片后,使用 FileReader 读取图片文件。
2、获取到图片后使用 exif.js 的 EXIF.getDate(image, callback) API 获取图片的拍摄方向,根据拍摄方向进行不同角度的旋转
3、根据图片大小进行判断是否需要压缩
html DEMO:
<html lang="en">
<head>
<meta charset="UTF-8">
<title>testtitle>
<script src="jquery-3.1.0.min.js">script>
<script src="exif.js">script>
<script src="image.js">script>
head>
<body>
<form>
<input id="image" type="file" accept="*">
form>
<div id="show">div>
body>
<script>
$(function () {
var async = {};
//处理图片后进行的操作,如上传
async.do = function () {
var imageData = $('#show>img')[0].src;//获取base64格式的图片
var imageData = imageData.replace(/data:image\/jpeg;base64,/,'');//去掉"data:image/jpeg;base64,"
//上传图片
$.post('getImage.php',{image:imageData,lrj:'hhh'},function (data) {
console.log(data)
})
};
var source = $('#image');
var show = $('#show')
imageProcess(source, show, async)
})
script>
html>
图片质量对比
image.js:
/**
* Created by ROOT on 2016/12/14.
*/
/**
* @param source 图片源的表单
* @param show 要展示图片的div
* @param async 图片处理完成后要进行的操作,如ajax上传。等信息
*/
function imageProcess(source,show,async) {
//监听图片源表单的改变事件
source.change(function () {
var files = this.files;
if(files.length){
var isImage = checkFile(this.files);
if(!isImage){
show.html("请确保文件为图像类型");
}else{
var reader = new FileReader();
reader.onload = function(e){
var imageSize = e.total;//图片大小
var image = new Image();
image.src = e.target.result;
image.onload = function () {
// 旋转图片
var newImage = rotateImage(image)
// console.log(newImage)
//压缩图片
newImage = judgeCompress(newImage,imageSize);
newImage.setAttribute('width','100%');
show.html(newImage);
async.do();
}
}
reader.readAsDataURL(isImage);
}
}
})
}
/**
* 检查文件是否为图像类型
* @param files FileList
* @returns file File
*/
function checkFile(files){
console.log(files)
var file = files[0];
//使用正则表达式匹配判断
if(!/image\/\w+/.test(file.type)){
return false;
}
return file;
}
/**
* 判断图片是否需要压缩
* @param image HTMLImageElement
* @param imageSize int
* @returns {*} HTMLImageElement
*/
function judgeCompress(image,imageSize) {
//判断图片是否大于300000 bit
var threshold = 300000;//阈值,可根据实际情况调整
console.log('imageSize:'+imageSize)
if(imageSize>threshold){
var imageData = compress(image);
var newImage = new Image()
newImage.src = imageData
return newImage;
}else {
return image;
}
}
/**
*压缩图片
* @param image HTMLImageElement
* @returns {string} base64格式图像
*/
function compress(image) {
console.log('compress');
console.log(image)
var canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d');
var imageLength = image.src.length;
var width = image.width;
var height = image.height;
canvas.width = width;
canvas.height = height;
ctx.drawImage(image, 0, 0, width, height);
//压缩操作
var quality = 0.1;//图片质量 范围:0
var imageData = canvas.toDataURL("image/jpeg", quality);
console.log("压缩前:" + imageLength);
console.log("压缩后:" + imageData.length);
console.log("压缩率:" + ~~(100 * (imageLength - imageData.length) / imageLength) + "%");
return imageData;
}
/**
* 旋转图片
* @param image HTMLImageElement
* @returns newImage HTMLImageElement
*/
function rotateImage(image) {
console.log('rotateImage');
var width = image.width;
var height = image.height;
var canvas = document.createElement("canvas")
var ctx = canvas.getContext('2d');
var newImage = new Image();
//旋转图片操作
EXIF.getData(image,function () {
var orientation = EXIF.getTag(this,'Orientation');
// orientation = 6;//测试数据
console.log('orientation:'+orientation);
switch (orientation){
//正常状态
case 1:
console.log('旋转0°');
// canvas.height = height;
// canvas.width = width;
newImage = image;
break;
//旋转90度
case 6:
console.log('旋转90°');
canvas.height = width;
canvas.width = height;
ctx.rotate(Math.PI/2);
ctx.translate(0,-height);
ctx.drawImage(image,0,0)
imageDate = canvas.toDataURL('Image/jpeg',1)
newImage.src = imageDate;
break;
//旋转180°
case 3:
console.log('旋转180°');
canvas.height = height;
canvas.width = width;
ctx.rotate(Math.PI);
ctx.translate(-width,-height);
ctx.drawImage(image,0,0)
imageDate = canvas.toDataURL('Image/jpeg',1)
newImage.src = imageDate;
break;
//旋转270°
case 8:
console.log('旋转270°');
canvas.height = width;
canvas.width = height;
ctx.rotate(-Math.PI/2);
ctx.translate(-height,0);
ctx.drawImage(image,0,0)
imageDate = canvas.toDataURL('Image/jpeg',1)
newImage.src = imageDate;
break;
//undefined时不旋转
case undefined:
console.log('undefined 不旋转');
newImage = image;
break;
}
}
);
return newImage;
}
getImage.php:
/**
* Created by PhpStorm.
* User: 6500
* Date: 2017/4/5
* Time: 18:10
*/
$imagePath = './uploadPicture.jpg';//图片保存路径
$image = base64_decode($_POST['image']);
$newFile = fopen($imagePath,'w');
$fwriteRes = fwrite($newFile,$image);
fclose($newFile);
if ($fwriteRes){
echo 'success';
}