一种可能的解决方案是更改jpeg质量设置。
我已经创建了一个图像大小估算的质量设置,而不是迭代许多质量设置。
我获取最佳质量下图像的文件大小,然后使用估算大小猜测要小于文件大小的质量设置。为了尽可能接近,我上下移动质量设置并检查文件大小几次。
如果找到了一个质量设置,它的文件大小在所需大小之下且高于阈值百分比,则使用该质量设置。
如果未找到阈值,则使用通过的最佳质量质量设置。
如果遇到难以找到质量设置,则只提供非常低的设置。
如果质量设置为零,则表示失败。
所需功能
function image2Canvas(image){
var canvas = document.createElement("canvas");
canvas.width = image.width;
canvas.height = image.height;
canvas.ctx = canvas.getContext("2d");
canvas.ctx.drawImage(image,0,0);
return canvas;
}
function getImageFileSize(image,quality){
return Math.floor(image.toDataURL("image/jpeg",quality).length * (3/4));
}
function qualityForSize(image,fileSize){
const scalingFactors = [
5638850/5638850,
1706816/5638850,
1257233/5638850,
844268/5638850,
685253/5638850,
531014/5638850,
474293/5638850,
363686/5638850,
243578/5638850,
121475/5638850,
0,
]
var size = getImageFileSize(image,1);
if(size <= fileSize){
return 1;
}
var index = 0;
while(size * scalingFactors[index] > fileSize){ index += 1 }
if(index === 10){
return 0;
}
var sizeUpper = size * scalingFactors[index-1];
var sizeLower = size * scalingFactors[index];
var quality = (1-(index/10)) + ((fileSize - sizeLower) / (sizeUpper-sizeLower)) * 0.1;
var qualityStep = 0.02;
var numberTrys = 3;
var passThreshold = 0.90;
var passQualities = [];
while(numberTrys--){
var newSize = getImageFileSize(image,quality);
if(newSize <= fileSize && newSize/fileSize > passThreshold ){
return quality;
}
if(newSize > fileSize){
quality -= qualityStep;
qualityStep /= 2;
}else{
passQualities.push(quality);
quality += qualityStep;
qualityStep /= 2;
}
}
if(passQualities.length > 0){
passQualities.sort();
return passQualities.pop();
}
return 1-((index+1)/10);
}
如何使用
var imgC = image2Canvas(testImage);
var qualitySetting = qualityForSize(imgC,244000);
var dataURL = imgC.toDataURL("image/jpeg",qualitySetting);