图像压缩压缩速度非常慢

问题描述 投票:4回答:3

我想在移动设备上调整一个图片的大小。使用ionic 2框架,基于angular 2)。

我的最大文件大小是5MB,而有些设备捕获的图像比这个大。所以,我目前正尝试使用以下方法来调整图片的大小 canvas.toDataURL() 但这是非常慢的。(App在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图像(但如果需要的话,我确实能够很容易地获得一个)。

javascript angular cordova ionic2
3个回答
2
投票

你的 调整大小 函数的名字真的很不好听。它的作用是改变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%,所以我保留了这个比例,并根据自己的需要进行了修改。这样可以在600ms内将一张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);
}

0
投票

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

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

https:/github.comapachecordova-plugin-camera#cameracameraoptions--object。


0
投票

已经有一个库来做这件事,不需要重新发明轮子。

https:/www.npmjs.compackagengx-image-compress

你可以在这里试试 https:/stackblitz.comeditngx-compress-sample。

© www.soinside.com 2019 - 2024. All rights reserved.