【问题标题】:Image compressing/resizing very slow图像压缩/调整大小非常慢
【发布时间】:2018-01-18 11:05:31
【问题描述】:

我正在尝试调整移动设备上的图片大小。 (使用 ionic 2 框架,基于 angular 2)。

我的最大文件大小为 5MB,有些设备捕获的图像比这更大。所以我目前正在尝试使用canvas.toDataURL() 调整图像大小,但这非常慢。 (应用程序在 15-20 秒内没有响应)。

我目前的调整大小功能如下:

private resize(outputFormat, sourceImgObj, quality) {
    let mimeType = "image/jpeg";

    let cvs = document.createElement('canvas');
    cvs.width = sourceImgObj.naturalWidth;
    cvs.height = sourceImgObj.naturalHeight;
    let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0);

    let newImageData = cvs.toDataURL(mimeType, quality/100);
    return newImageData;
}

当时哪个(我相信)基于j-i-c,如果不一样的话。

这个功能确实有效。在浏览器中它很不错但仍然很慢(Chrome)。但是当在设备上运行此功能时,例如选择 8 MB 的图像,应用程序基本上会崩溃。

有什么方法可以更快地压缩/调整图像大小?


其他信息

我通过使用cordova-plugin-camera 获取文件本身,这是指向用户设备上文件的直接链接。所以这不是 base64 图像(但如果需要,我确实能够轻松获得)。

【问题讨论】:

  • 您是否尝试使用cvs.toBlob 而不是cvs.toDataURL?这可能会更好,因为 Blob 不需要新转换为(可能)base64 字符串。
  • 查看nodeca.github.io/pica/demo 希望对您有所帮助!
  • 您绝对需要保留图像的尺寸吗?我猜你的 8MB 图像相当大,如果它来自设备摄像头,压缩可能已经相当不错了。因此,当您在画布上绘制它时,您实际上是在生成一个新的原始图像(没有任何压缩),其像素数量与原始文件中的相同。这意味着您的画布本身将比原来的 8MB 内存大得多。当调用 toDataURL 时,它必须提取这些数据,处理它等等,消耗更多的内存。甚至不确定最后你会得到一个更轻的文件
  • 那么总而言之,与其试图降低质量,你是否可以先尝试降低这些图像的尺寸?
  • 没关系,只要保持纵横比不变

标签: javascript angular cordova ionic2


【解决方案1】:

你的 resize 函数的名字真的很糟糕。它所做的是改变 jpeg 有损算法的质量。它并没有真正调整你的图像大小,我猜你的 8MB 图像相当大,如果它来自设备相机,压缩可能已经相当不错了。

因此,当您在画布上绘制它时,您实际上是在生成一个新的原始图像(没有任何压缩),其像素数量与原始文件中的相同。

这意味着您的画布本身将比原来的 8MB 内存大得多。当调用 toDataURL 时,它必须提取这些数据,处理它等等,消耗更多的内存。

甚至不确定最后你会得到一个更轻的文件......

如果您可以真正调整图像大小(即更改图像尺寸),那么您的设备将更容易处理它:

function resize(sourceImgObj) {
    const mimeType = "image/jpeg"; // would probably be better to keep the one of the file...
    let quality = .92; // default;
    const cvs = document.createElement('canvas');
    const MAX_SIZE = 500; // in px for both height and width
    const w = sourceImgObj.naturalWidth;
    const h = sourceImgObj.naturalHeight;
    let ratio = MAX_SIZE / Math.max(w, h);
    if(ratio > 1){ // if it's smaller than our defined MAX_SIZE
      ratio = 1;
      quality = .5; // lower the jpeg quality
      }
    cvs.width = ratio * w;
    cvs.height = ratio * h;
    let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);

    // note : if it's not a problem to convert it to async then toBlob would be a better choice
    let newImageData = cvs.toDataURL(mimeType, quality);
    return newImageData;
}

inp.onchange = e => {
  const MAX_SIZE = 100000; // 100KB
  let img = new Image();
  img.src = URL.createObjectURL(inp.files[0]);
  img.onload = e => {
    // if it's not too big, return the image's current src
    let dataURL = (inp.files[0].size > MAX_SIZE) ?
    resize(img) : img.src;
    let out = new Image();
    out.src = dataURL;
    document.body.appendChild(out);
    };
  }
<input type="file" id="inp">

编辑 (ivaro18)

我只是想添加这个答案的修改版本。我不喜欢将质量参数降低到 50%,所以我保留了这个比例并对其进行了修改以满足我的需要。这会在 600 毫秒内将 8.1MB 图像的大小调整为 900kB。

resize(sourceImgObj, callback) {
   const mimeType = "image/jpeg";
   let quality = .92; // default;
   const cvs = document.createElement('canvas');
   const MAX_SIZE = 1024; // in px for both height and width
   const w = sourceImgObj.naturalWidth;
   const h = sourceImgObj.naturalHeight;
   let ratio = MAX_SIZE / Math.max(w, h);
   if(ratio > 1) {
       let percentage = (w >= h) ? ((w - MAX_SIZE) / w * 100) : ((h - MAX_SIZE) / h * 100);
       cvs.width = (percentage + 100)/100 * w;
       cvs.height = (percentage + 100)/100 * h;

   } else {
       cvs.width = w * ratio;
       cvs.height = h * ratio;
   }

   let ctx = cvs.getContext("2d").drawImage(sourceImgObj, 0, 0, cvs.width, cvs.height);

   let newImageData = cvs.toDataURL(mimeType, quality);
   callback(newImageData);
}

【讨论】:

    【解决方案2】:

    如果压缩的唯一目的是减小文件大小,那么您可以在拍照时在插件的配置中指定图像质量。

    您可以尝试几种不同的值,看看哪一种最适合您。

    https://github.com/apache/cordova-plugin-camera#cameracameraoptions--object

    【讨论】:

    • 但是我如何事先知道图像大小呢?如果图像超过 5MB,我只想缩小图像,下面的所有内容都将保持其原始质量。
    【解决方案3】:

    已经有一个库可以做到这一点,无需重新发明轮子

    https://www.npmjs.com/package/ngx-image-compress

    你可以在这里试试https://stackblitz.com/edit/ngx-compress-sample

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-10-23
      • 2012-07-30
      • 1970-01-01
      • 2018-02-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多