imgfunc
Version:
图片上传JS
162 lines (155 loc) • 5.2 kB
JavaScript
import { calcBASE64length } from "./lib";
import createImage from "./image";
import { COMPRESSERROR } from "./errorType";
import {STATIC_TIMEOUT, STATIC_RESPONSE_ERROR, STATIC_FILE_ERROR, STATIC_COMPRESS_ERROR, STATIC_EXCHANGE_ERROR} from './statusEnum'
// 默认最大质量
const defaultMaxQuality = 100;
// 默认最小的压缩质量
const defaultMinQuality = 0;
// 大图质量压成小图 差率 1kb ;比如规定最大2*1024*1024图片,3M的图片在向下压缩时允许最小2*1024*1024-1024
const defaultCompressDiff = 1024;
const CANVAS = document.createElement("canvas");
const CTX = CANVAS.getContext("2d");
/**
* 压缩图片
* @param {*} param0
*/
function imageTODataURL({ img, quality, fileType }) {
const width = (CANVAS.width = img.width);
const height = (CANVAS.height = img.height);
CTX.clearRect(0, 0, width, height);
CTX.drawImage(img, 0, 0, width, height);
const base64 = CANVAS.toDataURL(fileType, quality / 100);
CANVAS.width = 0;
CANVAS.height = 0;
return base64;
}
/**
* 图片压缩算法
* @param {*} param0
*/
const compressImage = ({
base64: base64Image,
maxSize,
fileType,
quality: defaultQuality
}) => {
let compressBase64 = base64Image;
// 最大的压缩率
let compressMaxQuality = defaultMaxQuality;
// 最小压缩率
let compressMinQuality = defaultMinQuality;
// 压缩得到最小的图片base64
let minCompressBase = null;
return new Promise((resolve, reject) => {
const compressRecursion = ({ base64, quality }) => {
try {
createImage(base64)
.then(image => {
// 将图片的类型统一转换 指定类型 默认 JPEG,
compressBase64 = imageTODataURL({
img: image,
quality,
fileType
});
const compressSize = calcBASE64length(compressBase64);
if (compressSize > maxSize) {
compressMaxQuality = quality;
const diffQuality = compressMaxQuality - compressMinQuality;
if (diffQuality <= 2) {
if (!minCompressBase) {
// TODO: 上传图片大小限制较小时,存在一轮压缩无法达到目的.这是考虑等比例压缩图片而非质量压缩
resolve({
result: true,
base64: compressBase64
});
} else {
resolve({
result: true,
base64: minCompressBase || compressBase64
});
}
} else {
const compressQuality = Math.ceil(
(compressMaxQuality + compressMinQuality) / 2
);
compressRecursion({
base64: compressBase64,
quality: compressQuality
});
}
} else {
minCompressBase = base64;
if (compressSize < maxSize) {
compressMaxQuality = 2 * quality > 100 ? 100 : 2 * quality;
compressMinQuality = quality;
const compressQuality = Math.ceil(
(compressMaxQuality + compressMinQuality) / 2
);
compressRecursion({
base64: compressBase64,
quality: compressQuality
});
} else {
resolve({ result: true, base64: compressBase64 });
}
}
})
.catch(error => {
reject({
errorMsg: error, // 给开发者看的
message: "图片压缩出错了",
errorType: COMPRESSERROR,
status:STATIC_COMPRESS_ERROR
});
});
} catch (err) {
reject({
errorMsg: err, // 给开发者看的
message: "图片压缩出错了",
errorType: COMPRESSERROR,
status:STATIC_COMPRESS_ERROR
});
}
};
compressRecursion({ base64: base64Image, quality: defaultQuality });
});
};
export default async ({ base64, maxSize, fileType }) => {
// 计算base64大小
const size = calcBASE64length(base64);
if (size > maxSize) {
// 执行压缩
const maxQuality = defaultMaxQuality;
const minQuality = defaultMinQuality;
const quality = Math.ceil((maxQuality + minQuality) / 2);
try {
const compressBase64 = await compressImage({
base64,
maxSize,
fileType,
quality
});
if (compressBase64.result) {
const { base64: compressImage } = compressBase64;
return { result: true, base64: compressImage };
} else {
return {
errorMsg: "代码错误", // 给开发者看的
message: "图片压缩出错了",
errorType: COMPRESSERROR,
status:STATIC_COMPRESS_ERROR
};
}
} catch (error) {
return {
errorMsg: error, // 给开发者看的
message: "图片压缩出错了",
errorType: COMPRESSERROR,
status:STATIC_COMPRESS_ERROR
};
}
} else {
return { result: true, base64: base64 };
}
};