可能な解決策の1つは、jpegの品質設定を変更することです。
多くの画質設定を繰り返すのではなく、画質設定の見積もりを作成しました。
イメージのファイルサイズが最良の品質で取得され、見積もりサイズを使用して、ファイルサイズの下にある品質設定を推測します。可能な限り近づくために、品質設定を上下に移動し、ファイルサイズを数回確認します。
ファイルサイズが必要なサイズより小さく、必要なサイズのしきい値パーセンテージより高い品質設定が見つかった場合、その品質設定が使用されるしきい値サイズがあります。
しきい値が見つからない場合は、合格した最高の品質設定を使用します。
品質設定が見つからない場合は、非常に低い設定になります。
品質設定がゼロの場合、失敗しました。
// testImage is the image to set quality of
// the image must be loaded
var imgC = image2Canvas(testImage); // convert image to a canvas
var qualitySetting = qualityForSize(imgC,244000); // find the image quality to be under file size 244000
// convert to data URL
var dataURL = imgC.toDataURL("image/jpeg",qualitySetting);
// the saved file will be under 244000
を使用する方法
// this function converts a image to a canvas image
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;
}
// warning try to limit calls to this function as it can cause problems on some systems
// as they try to keep up with GC
// This function gets the file size by counting the number of Base64 characters and
// calculating the number of bytes encoded.
function getImageFileSize(image,quality){ // image must be a canvas
return Math.floor(image.toDataURL("image/jpeg",quality).length * (3/4));
}
function qualityForSize(image,fileSize){
// These are approximations only
// and are the result of using a test image and finding the file size
// at quality setting 1 to 0.1 in 0.1 steps
const scalingFactors = [
5638850/5638850,
1706816/5638850,
1257233/5638850,
844268/5638850,
685253/5638850,
531014/5638850,
474293/5638850,
363686/5638850,
243578/5638850,
121475/5638850,
0, // this is added to catch the stuff ups.
]
var size = getImageFileSize(image,1); // get file size at best quality;
if(size <= fileSize){ // best quality is a pass
return 1;
}
// using size make a guess at the quality setting
var index = 0;
while(size * scalingFactors[index] > fileSize){ index += 1 }
if(index === 10){ // Could not find a quality setting
return 0; // this is bad and should not be used as a quality setting
}
var sizeUpper = size * scalingFactors[index-1]; // get estimated size at upper quality
var sizeLower = size * scalingFactors[index]; // get estimated size at lower quality
// estimate quality via linear interpolation
var quality = (1-(index/10)) + ((fileSize - sizeLower)/(sizeUpper-sizeLower)) * 0.1;
var qualityStep = 0.02; // the change in quality (this value gets smaller each try)
var numberTrys = 3; // number of trys to get as close as posible to the file size
var passThreshold = 0.90; // be within 90% of desiered file size
var passQualities = []; // array of quality settings that are under file size
while(numberTrys--){
var newSize = getImageFileSize(image,quality); // get the file size for quality guess
if(newSize <= fileSize && newSize/fileSize > passThreshold){ // does it pass?
return quality; // yes return quality
}
if(newSize > fileSize){ // file size too big
quality -= qualityStep; // try lower quality
qualityStep /= 2; // reduce the quality step for next try
}else{
passQualities.push(quality); // save this quality incase nothing get within the pass threashold
quality += qualityStep; // step the quality up.
qualityStep /= 2; // reduce the size of the next quality step
}
}
// could not find a quality setting so get the best we did find
if(passQualities.length > 0){ //check we did get a pass
passQualities.sort(); // sort to get best pass quality
return passQualities.pop(); // return best quality that passed
}
// still no good result so just default to next 0.1 step down
return 1-((index+1)/10);
}
必要
機能