因为 手机重力感应 人们在拍照的时候,不同的重力,图片会有旋转
ios 没有统一 安卓 统一为 1 base64上传到oss
/*
* 裁剪图片- -base64 文件流 上传
* $base64_data 为以#号分割的字符串
*/
public function base64_img($base64_data){
ini_set('max_execution_time','300');
$img_str = '';
//判断是否是base64文件流
if(strpos($base64_data,'base64') !== false){
$img_arr = explode('#',$base64_data);
foreach ($img_arr as $key => $value){
if(strpos($value,'http://') !== false){
$img_arr[$key] = $value;
}else{
//图片类型
$type = $this->header_byte(substr($value,5,strpos($value,';')-5));
//文件流反转
$img_data_str = substr($value,strpos($value,',')+1);
//图片资源
$img_data = base64_decode($img_data_str);
//上传oss 拼接路径
$filename = "upload/images/base64/".date("Y/m/d",time());
$filename .= "/upload_".time().rand(1111,9999).".".$type;
Storage::put($filename, $img_data);
//校正 图片
if($type == 'jpg'){
//本地图片地址
$localName ="./upload/images/base64/tmp/wxupload_".time().rand(1111,9999).".jpg";
//调用
$new_filename = C('file_url').$filename;
$res = $this->imgReverse($new_filename,$localName);
if($res){
//校正成功 重新上传oss图片
$filename = "upload/images/base64/".date("Y/m/d",time());
$filename .= "/upload_".time().rand(1111,9999).".".$type;
Storage::put($filename,file_get_contents($localName));
}
}
$imgurl = C('file_url').$filename;
$img_arr[$key] = $imgurl;
}
}
$img_str = implode('#',$img_arr);
}else{
//不是文件流 直接返回
$img_str = $base64_data;
}
return $img_str;
}
/*
* ios 拍照上传 图片反转 矫正
* @param string
*/
public function imgReverse($image,$filename){
//从 JPEG 或 TIFF 文件中读取 EXIF 头信息 (数码相机元数据)
$exif = exif_read_data($image);
//从字符串中的图像流新建一图像
$data = imagecreatefromstring(file_get_contents($image));
//图片旋转
if(!empty($exif['Orientation'])) {
switch($exif['Orientation']) {
case 8:
$data = imagerotate($data, 90, 0);
break;
case 3:
$data = imagerotate($data, 180, 0);
break;
case 6:
$data = imagerotate($data, -90, 0);
break;
}
$dir = dirname($filename);
if(!is_dir($dir)){
mkdir($dir,0777,true);
}
//校正后的图片 返回资源
$res = imagejpeg($data,$filename);
if($res){
return true;
}else{
return false;
}
}else{
return false;
}
}
没有废话,直接代码,有点猛。。。。。。
修订(2019-04-08):因为后端校正图片,必须要获取 Orientation 属性,否则盲目的校正方向,必然会导致冤假错案,正常的图片也被处理为异常图片了。但是,某些图片在前端传给后端的时候,因不是原图,导致不存在该元素了。那么就绕过了校正操作,导致图片未处理。此时,需要前端校正处理。(如果前端OSS自传,更需要前端校正图片了,不要问我为什么)
function selectFileImage(fileObj) {
//图片方向角 added by lzk
var Orientation = null;
file = fileObj;
// var URL = URL || webkitURL;
//获取照片方向角属性,用户旋转控制
EXIF.getData(file, function() {
//alert(EXIF.pretty(this));
EXIF.getAllTags(this);
//alert(EXIF.getTag(this, 'Orientation'));
Orientation = EXIF.getTag(this, 'Orientation');
//return;
});
var oReader = new FileReader();
oReader.onload = function(e) {
//var blob = URL.createObjectURL(file);
//_compress(blob, file, basePath);
var image = new Image();
image.src = e.target.result;
image.onload = function() {
var expectWidth = this.naturalWidth;
var expectHeight = this.naturalHeight;
if (this.naturalWidth > this.naturalHeight && this.naturalWidth > 800) {
expectWidth = 800;
expectHeight = expectWidth * this.naturalHeight / this.naturalWidth;
} else if (this.naturalHeight > this.naturalWidth && this.naturalHeight > 1200) {
expectHeight = 1200;
expectWidth = expectHeight * this.naturalWidth / this.naturalHeight;
}
var canvas = document.createElement("canvas");
var ctx = canvas.getContext("2d");
canvas.width = expectWidth;
canvas.height = expectHeight;
ctx.drawImage(this, 0, 0, expectWidth, expectHeight);
var base64 = null;
//修复ios
if (navigator.userAgent.match(/iphone/i)) {
//console.log('iphone');
//alert(expectWidth + ',' + expectHeight);
//如果方向角不为1,都需要进行旋转 added by lzk
if(Orientation != "" && Orientation != 1){
//alert('旋转处理');
switch(Orientation){
case 6://需要顺时针(向左)90度旋转
//alert('需要顺时针(向左)90度旋转');
rotateImg(this,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
//alert('需要顺时针(向右)90度旋转');
rotateImg(this,'right',canvas);
break;
case 3://需要180度旋转
//alert('需要180度旋转');
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}
base64 = canvas.toDataURL("image/jpeg", 0.8);
}else{
//alert(Orientation);
if(Orientation != "" && Orientation != 1){
//alert('旋转处理');
switch(Orientation){
case 6://需要顺时针(向左)90度旋转
// alert('需要顺时针(向左)90度旋转');
rotateImg(this,'left',canvas);
break;
case 8://需要逆时针(向右)90度旋转
//alert('需要顺时针(向右)90度旋转');
rotateImg(this,'right',canvas);
break;
case 3://需要180度旋转
//alert('需要180度旋转');
rotateImg(this,'right',canvas);//转两次
rotateImg(this,'right',canvas);
break;
}
}
base64 = canvas.toDataURL("image/jpeg", 0.8);
//console.log(base64);
}
//uploadImage(base64);
//$("#myImage").attr("src", base64);
//return base64;
if(imgArr.length == 0){
imgArr[0] = 'http://static.img**.cn/image/microVoting/uploadBtn.png';
}
if(file.size/1024 > 200) {
smallImg(base64, function(newurl) {
imgArr.push(newurl);
change();
})
} else {
imgArr.push(base64);
change();
}
};
};
oReader.readAsDataURL(file);
}
//对图片旋转处理 added by lzk
function rotateImg(img, direction,canvas) {
//alert(img);
//最小与最大旋转方向,图片旋转4次后回到原方向
var min_step = 0;
var max_step = 3;
if (img == null)return;
//img的高度和宽度不能在img元素隐藏后获取,否则会出错
var height = img.height;
var width = img.width;
//var step = img.getAttribute('step');
var step = 2;
if (step == null) {
step = min_step;
}
if (direction == 'right') {
step++;
//旋转到原位置,即超过最大值
step > max_step && (step = min_step);
} else {
step--;
step < min_step && (step = max_step);
}
//旋转角度以弧度值为参数
var degree = step * 90 * Math.PI / 180;
var ctx = canvas.getContext('2d');
switch (step) {
case 0:
canvas.width = width;
canvas.height = height;
ctx.drawImage(img, 0, 0);
break;
case 1:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, 0, -height);
break;
case 2:
canvas.width = width;
canvas.height = height;
ctx.rotate(degree);
ctx.drawImage(img, -width, -height);
break;
case 3:
canvas.width = height;
canvas.height = width;
ctx.rotate(degree);
ctx.drawImage(img, -width, 0);
break;
}
}