问题
I am encoding my images in Base64 before uploading them to the server. I need to get their file sizes down to a specific size (500kB). I have tried to get the ratio between the original and the desired file size and reducing de height and width accordingly. But it does not work. Any help?
回答1:
Some other users had the same question. Maybe this helps you:
JavaScript reduce the size and quality of image with based64 encoded code
As far as i'm concerned, there is no way to reduce the filesize of an image on the client side using javascript.
回答2:
I had the same problem as you, I needed to resize an image before it was uploaded to my server. So my first thought was to calculate the number of pixels to determine the number of bytes. But very quickly I noticed that most image formats use compression. For example, a 1000x1000 picture with only white pixels will only be a fraction of the size of a normal image. So that’s why I think it’s hard to pre-calculate any dimensions into the number of bytes. So I used the binary search algorithm to try and find the percentage that should be used to reduce the width and height. The image will be resized multiple times to find the perfect percentage so it’s not very efficient but I couldn’t think of any other way.
// maxDeviation is the difference that is allowed default: 50kb
// Example: targetFileSizeKb = 500 then result will be between 450kb and 500kb
// increase the deviation to reduce the amount of iterations.
async function resizeImage(dataUrl, targetFileSizeKb, maxDeviation = 50) {
let originalFile = await urltoFile(dataUrl, 'test.png', 'image/png');
if (originalFile.size / 1000 < targetFileSizeKb)
return dataUrl; // File is already smaller
let low = 0.0;
let middle = 0.5;
let high = 1.0;
let result = dataUrl;
let file = originalFile;
while (Math.abs(file.size / 1000 - targetFileSizeKb) > maxDeviation) {
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
const img = document.createElement('img');
const promise = new Promise((resolve, reject) => {
img.onload = () => resolve();
img.onerror = reject;
});
img.src = dataUrl;
await promise;
canvas.width = Math.round(img.width * middle);
canvas.height = Math.round(img.height * middle);
context.scale(canvas.width / img.width, canvas.height / img.height);
context.drawImage(img, 0, 0);
file = await urltoFile(canvas.toDataURL(), 'test.png', 'image/png');
if (file.size / 1000 < (targetFileSizeKb - maxDeviation)) {
low = middle;
} else if (file.size / 1000 > targetFileSizeKb) {
high = middle;
}
middle = (low + high) / 2;
result = canvas.toDataURL();
}
return result;
}
function urltoFile(url, filename, mimeType) {
return (fetch(url)
.then(function (res) {
return res.arrayBuffer();
})
.then(function (buf) {
return new File([buf], filename, {type: mimeType});
})
);
}
https://jsfiddle.net/qnhmytk4/3/
来源:https://stackoverflow.com/questions/42092640/javascript-how-to-reduce-image-to-specific-file-size