import Exif from 'exif-js';
/* eslint-disable func-names */
function ImageProcess(file, callback) {
let Orientation;
// 去获取拍照时的信息,解决拍出来的照片旋转问题
Exif.getData(file, function () {
Orientation = Exif.getTag(this, 'Orientation');
});
// console.log("Orientation", Orientation);
// 看支持不支持FileReader
if (!file || !window.FileReader) return;
if (/^image/.test(file.type)) {
// 创建一个reader
const reader = new window.FileReader();
// 将图片2将转成 base64 格式
reader.readAsDataURL(file);
// 读取成功后的回调
reader.onloadend = function () {
const img = new window.Image();
img.src = this.result;
img.onload = function () {
// 压缩图片
const data = ImageCompress(img, Orientation);
// console.log(dataURItoBlob(data));
callback(data);
};
};
}
}
function ImageCompress(img, Orientation) {
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// 瓦片canvas
const tCanvas = document.createElement('canvas');
const tctx = tCanvas.getContext('2d');
let { width, height } = img;
// 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let ratio = (width * height) / 4000000;
if (ratio > 1) {
ratio = Math.sqrt(ratio);
width /= ratio;
height /= ratio;
} else {
ratio = 1;
}
canvas.width = width;
canvas.height = height;
// 铺底色
ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// 如果图片像素大于100万则使用瓦片绘制
let count = (width * height) / 1000000;
if (count > 1) {
// 计算要分成多少块瓦片
count = ~~(Math.sqrt(count) + 1);
// 计算每块瓦片的宽和高
const nw = ~~(width / count);
const nh = ~~(height / count);
tCanvas.width = nw;
tCanvas.height = nh;
for (let i = 0; i < count; i += 1) {
for (let j = 0; j < count; j += 1) {
tctx.drawImage(img, i * nw * ratio, j * nh * ratio, nw * ratio, nh * ratio, 0, 0, nw, nh);
ctx.drawImage(tCanvas, i * nw, j * nh, nw, nh);
}
}
} else {
ctx.drawImage(img, 0, 0, width, height);
}
// 修复ios上传图片的时候 被旋转的问题
if (Orientation && Orientation !== 1) {
switch (Orientation) {
case 6: // 需要顺时针(向左)90度旋转
rotateImg(img, 'left', canvas);
break;
case 8: // 需要逆时针(向右)90度旋转
rotateImg(img, 'right', canvas);
break;
case 3: // 需要180度旋转 转两次
rotateImg(img, 'right', canvas);
rotateImg(img, 'right', canvas);
break;
default: break;
}
}
// 进行最小压缩
const ndata = canvas.toDataURL('image/jpeg', 0.5);
// 清除canvas画布的宽高
tCanvas.width = 0;
tCanvas.height = 0;
canvas.width = 0;
canvas.height = 0;
// 打印压缩前后的大小,以及压缩比率
// const initSize = img.src.length;
// console.log('压缩前:' + initSize);
// console.log('压缩后:' + ndata.length);
// console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
// console.log(ndata);
return ndata;
}
function rotateImg(img, direction, cvs) {
const canvas = cvs;
// 最小与最大旋转方向,图片旋转4次后回到原方向
const minStep = 0;
const maxStep = 3;
if (img == null) return;
// img的高度和宽度不能在img元素隐藏后获取,否则会出错
const { width, height } = img;
let step = 2;
if (step == null) {
step = minStep;
}
if (direction === 'right') {
step += 1;
// 旋转到原位置,即超过最大值
if (step > maxStep) step = minStep;
} else {
step -= 1;
if (step < minStep) step = maxStep;
}
// 旋转角度以弧度值为参数
const degree = (step * 90 * Math.PI) / 180;
const 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;
default: break;
}
}
function dataURItoBlob(dataURI) {
const byteString = window.atob(dataURI.split(',')[1]);
const mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// const ab = new ArrayBuffer(byteString.length);
const ia = new Uint8Array(byteString.length);
for (let i = 0; i < byteString.length; i += 1) {
ia[i] = byteString.charCodeAt(i);
}
return new window.Blob([ia], { type: mimeString });
}
export default ImageProcess;
import
Exif
from
'exif-js';
/* eslint-disable func-names */
function
ImageProcess(
file,
callback) {
let
Orientation;
// 去获取拍照时的信息,解决拍出来的照片旋转问题
Exif.
getData(
file,
function () {
Orientation =
Exif.
getTag(
this,
'Orientation');
});
// console.log("Orientation", Orientation);
// 看支持不支持FileReader
if (!
file || !
window.
FileReader)
return;
if (
/
^
image/.
test(
file.
type)) {
// 创建一个reader
const
reader =
new
window.
FileReader();
// 将图片2将转成 base64 格式
reader.
readAsDataURL(
file);
// 读取成功后的回调
reader.
onloadend =
function () {
const
img =
new
window.
Image();
img.
src =
this.
result;
img.
onload =
function () {
// 压缩图片
const
data =
ImageCompress(
img,
Orientation);
// console.log(dataURItoBlob(data));
callback(
data);
};
};
}
}
function
ImageCompress(
img,
Orientation) {
const
canvas =
document.
createElement(
'canvas');
const
ctx =
canvas.
getContext(
'2d');
// 瓦片canvas
const
tCanvas =
document.
createElement(
'canvas');
const
tctx =
tCanvas.
getContext(
'2d');
let {
width,
height } =
img;
// 如果图片大于四百万像素,计算压缩比并将大小压至400万以下
let
ratio = (
width *
height) /
4000000;
if (
ratio >
1) {
ratio =
Math.
sqrt(
ratio);
width /=
ratio;
height /=
ratio;
}
else {
ratio =
1;
}
canvas.
width =
width;
canvas.
height =
height;
// 铺底色
ctx.
fillStyle =
'#fff';
ctx.
fillRect(
0,
0,
canvas.
width,
canvas.
height);
// 如果图片像素大于100万则使用瓦片绘制
let
count = (
width *
height) /
1000000;
if (
count >
1) {
// 计算要分成多少块瓦片
count = ~~(
Math.
sqrt(
count) +
1);
// 计算每块瓦片的宽和高
const
nw = ~~(
width /
count);
const
nh = ~~(
height /
count);
tCanvas.
width =
nw;
tCanvas.
height =
nh;
for (
let
i =
0;
i <
count;
i +=
1) {
for (
let
j =
0;
j <
count;
j +=
1) {
tctx.
drawImage(
img,
i *
nw *
ratio,
j *
nh *
ratio,
nw *
ratio,
nh *
ratio,
0,
0,
nw,
nh);
ctx.
drawImage(
tCanvas,
i *
nw,
j *
nh,
nw,
nh);
}
}
}
else {
ctx.
drawImage(
img,
0,
0,
width,
height);
}
// 修复ios上传图片的时候 被旋转的问题
if (
Orientation &&
Orientation !==
1) {
switch (
Orientation) {
case
6:
// 需要顺时针(向左)90度旋转
rotateImg(
img,
'left',
canvas);
break;
case
8:
// 需要逆时针(向右)90度旋转
rotateImg(
img,
'right',
canvas);
break;
case
3:
// 需要180度旋转 转两次
rotateImg(
img,
'right',
canvas);
rotateImg(
img,
'right',
canvas);
break;
default:
break;
}
}
// 进行最小压缩
const
ndata =
canvas.
toDataURL(
'image/jpeg',
0.5);
// 清除canvas画布的宽高
tCanvas.
width =
0;
tCanvas.
height =
0;
canvas.
width =
0;
canvas.
height =
0;
// 打印压缩前后的大小,以及压缩比率
// const initSize = img.src.length;
// console.log('压缩前:' + initSize);
// console.log('压缩后:' + ndata.length);
// console.log('压缩率:' + ~~(100 * (initSize - ndata.length) / initSize) + "%");
// console.log(ndata);
return
ndata;
}
function
rotateImg(
img,
direction,
cvs) {
const
canvas =
cvs;
// 最小与最大旋转方向,图片旋转4次后回到原方向
const
minStep =
0;
const
maxStep =
3;
if (
img ==
null)
return;
// img的高度和宽度不能在img元素隐藏后获取,否则会出错
const {
width,
height } =
img;
let
step =
2;
if (
step ==
null) {
step =
minStep;
}
if (
direction ===
'right') {
step +=
1;
// 旋转到原位置,即超过最大值
if (
step >
maxStep)
step =
minStep;
}
else {
step -=
1;
if (
step <
minStep)
step =
maxStep;
}
// 旋转角度以弧度值为参数
const
degree = (
step *
90 *
Math.PI) /
180;
const
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;
default:
break;
}
}
function
dataURItoBlob(
dataURI) {
const
byteString =
window.
atob(
dataURI.
split(
',')[
1]);
const
mimeString =
dataURI.
split(
',')[
0].
split(
':')[
1].
split(
';')[
0];
// const ab = new ArrayBuffer(byteString.length);
const
ia =
new
Uint8Array(
byteString.
length);
for (
let
i =
0;
i <
byteString.
length;
i +=
1) {
ia[
i] =
byteString.
charCodeAt(
i);
}
return
new
window.
Blob([
ia], {
type:
mimeString });
}
export
default
ImageProcess;