如何在compressjs中动态查找质量参数

How to find quality parameter in compressjs dynamically

提问人:SA__ 提问时间:12/5/2021 更新时间:9/6/2022 访问量:169

问:

我的文件大小是 500kb(它会动态出现任何大小)。我的目标是 150kb。

由于某些原因,我只能选择质量

new Compressor(selectedFile1, {
            quality: targetRatio,

即,如果我将 targetRatio 传递给 0.7,它会将图像减少到 159kb~

为了动态地找到targetRatio,我所做的是

var targetRatio = fileSize / 150;

但是,我无法弄清楚如何找到 targetRatio 以获得确切的值,即减少到 150kb

这是测试的地方

javascript html jquery 数学 压缩

评论


答:

2赞 Christopher 12/5/2021 #1

达到 150kb 修改质量,并不适用于每个图像。

JPEG 压缩量通常以质量级别的百分比来衡量。100% 质量的图像(几乎)没有损失,而 1% 质量的图像质量非常低。一般来说,90%或更高的质量水平被认为是“高质量”,80%-90%是“中等质量”,70%-80%是低质量。

如果您使用 15.594 x 3.936 jpg(示例),根据存储的信息,其大小可能为 ~2.5mb,则 jpg 格式将无法达到 150kb。

因此,以 150kb 为目标将是 .150.000 / 2.500.000 = 0.06

enter image description here

从屏幕截图的结果大小可以看出,这是不可能的,您必须进行多次转换,并通过减小宽度和高度来测试结果大小是否准确或低于 150kb。但是使用 0.06 的质量压缩我示例中的原始图像将产生大约 800KB 的图像。

fetch('https://i.imgur.com/mw7BsYS.jpg')
  .then(response => response.blob())
  .then(async blob => {
    let {
      size
    } = blob;

    console.log("Startingsize", size, 'B');
    let img = document.createElement("img");
    img.src = URL.createObjectURL(blob);

    await new Promise((r) => img.onload = r);
    let {
      naturalWidth,
      naturalHeight
    } = img;
    
    console.log(naturalWidth, naturalHeight, size);
    const targetByte = 150 * 1024;
    // in case first picture is smaller than 150kb
    let compressed = { result: blob };
    // speeds up large pictures
    if (targetByte / size < 0.15) {
      naturalWidth *= 0.15;
      naturalHeight *= 0.15;
    } else if (targetByte / size < 0.25) {
      naturalWidth *= 0.25;
      naturalHeight *= 0.25;
    } else if (targetByte / size < 0.5) {
      naturalWidth *= 0.5;
      naturalHeight *= 0.5;
    } else if (targetByte / size < 0.75) {
      naturalWidth *= 0.75;
      naturalHeight *= 0.75;
    }

    // generate thumbnails
    while (size > targetByte) {
      if (blob.size > targetByte) {
        // the bigger the steps, the faster it will be.
        naturalWidth *= 0.99;
        naturalHeight *= 0.99;
      }
      let res = await new Promise((resolve, reject) => {
        const res = new Compressor(blob, {
          maxWidth: naturalWidth,
          maxHeight: naturalHeight,
          success(blob) {
            size = blob.size;
            console.log(naturalWidth, naturalHeight, size);
            compressed = res;
            resolve();
          },
          error: reject
        })
      });
    }

    // replace the compressed with the original image from above
    const original = img.src;
    img.onclick = () => { if (confirm("sure?")) img.src = original; };

    // compressed.result contains the final blob now
    img.src = URL.createObjectURL(compressed.result);

    await new Promise((r) => img.onload = r);
    console.log(compressed.result, img.naturalWidth, img.naturalHeight)

    document.body.append(img);
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/compressorjs/1.1.1/compressor.js"></script>

0赞 Noob and Nerd 9/6/2022 #2

要精确地达到一个尺寸几乎是不可能的。因素太多了。你可以粗略地用三分法则来确定它,或者从克里斯托夫那里获取信息。我会提前减小图像尺寸,您应该始终考虑质量。否则可以使用 .gif,但这仅支持 256 种颜色,但会更小。