Javascript - 如何将图像缩小到特定文件大小?

Raf*_*eis 4 javascript base64 png jpeg image

在将图像上传到服务器之前,我正在对图像进行 Base64 编码。我需要将它们的文件大小降低到特定大小 (500kB)。我试图获得原始文件大小和所需文件大小之间的比率,并相应地减少高度和宽度。但它不起作用。有什么帮助吗?

Sta*_*tan 5

我和你有同样的问题,我需要在上传到我的服务器之前调整图像的大小。所以我的第一个想法是计算像素数来确定字节数。但很快我注意到大多数图像格式都使用压缩。例如,只有白色像素的 1000x1000 图片将只是普通图像大小的一小部分。所以这就是为什么我认为很难将任何维度预先计算为字节数。所以我使用了二分搜索算法来尝试找到应该用来减少宽度和高度的百分比。图像将多次调整大小以找到完美的百分比,因此效率不高,但我想不出任何其他方式。

// 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});
            })
    );
}
Run Code Online (Sandbox Code Playgroud)

https://jsfiddle.net/qnhmytk4/3/


Jii*_*iiB -1

其他一些用户也有同样的问题。也许这对您有帮助:

JavaScript 使用基于 64 的编码代码减少图像的大小和质量

就我而言,没有办法使用 JavaScript 来减少客户端图像的文件大小。