Javascript - How to reduce image to specific file size?

笑着哭i 提交于 2020-08-08 03:50:09

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!