繁体   English   中英

在Web Worker中调整和压缩图像。 我可以用帆布吗?

[英]Resize & Compress Image in Web Worker. Can I use a canvas?

研究背景

我现在正在客户端选择图像。

我想对该图像执行两个操作,并输出base64编码的字符串。

  1. 如果图像尺寸的宽度或高度大于1000,请调整尺寸。
  2. 用质量为0.5的jpeg压缩图像。

所以现在我将在主脚本中执行以下操作:

 $(function() { $('#upload').change(function() { var URL = window.URL || window.webkitURL; var imgURL = URL.createObjectURL(this.files[0]); var img = new Image(); img.onload = function() { var canvas = document.createElement('canvas'); var ctx = canvas.getContext('2d'); var w0 = img.width; var h0 = img.height; var w1 = Math.min(w0, 1000); var h1 = h0 / w0 * w1; canvas.width = w1; canvas.height = h1; ctx.drawImage(img, 0, 0, w0, h0, 0, 0, canvas.width, canvas.height); // Here, the result is ready, var data_src = canvas.toDataURL('image/jpeg', 0.5); $('#img').attr('src', data_src); URL.revokeObjectURL(imgURL); }; img.src = imgURL; }); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <input id="upload" type="file" accept="image/*" /> <img id="img" /> 

问题

但是,我的代码仍然可以在移动设备上运行,上面的过程(调整大小和压缩)无法很快完成。 这会导致GUI停止响应一会儿。

我希望该程序使用Web Worker在另一个线程中工作。 因此它不会阻止UI,因此用户体验会更好。

现在出现了问题,似乎网络工作者无法处理画布,我该如何解决?

一些事件驱动的编码

遗憾的是,Web工作人员尚未准备好使用浏览器支持。

Web worker中对toDataURL有限支持意味着需要另一种解决方案。 请在页面中下方查看MDN网络工作者API(ImageData) ,目前仅适用于Firefox。

查看您的onload您会在一次onload阻塞调用中完成所有繁重的工作。 您将在创建新画布,获取上下文,缩放和toDataURL的过程中阻止UI(不知道revokeObjectURL作用)。 在发生这种情况时,您需要让UI接几个电话。 因此,一点点事件驱动的处理将有助于减少故障(即使不会引起注意)。

尝试如下重写onload函数。

// have added some debugging code that would be useful to know if
// this does not solve the problem. Uncomment it and use it to see where
// the big delay is.
img.onload = function () {
    var canvas, ctx, w, h, dataSrc, delay; // hosit vars just for readability as the following functions will close over them
                                    // Just for the uninitiated in closure.
    // var now, CPUProfile = [];  // debug code 
    delay = 10; // 0 could work just as well and save you 20-30ms
    function revokeObject() { // not sure what this does but playing it safe
        // as an event.
        // now = performance.now(); // debug code
        URL.revokeObjectURL(imgURL);
        //CPUProfile.push(performance.now()-now); // debug code
        // setTimeout( function () { CPUProfile.forEach ( time => console.log(time)), 0);
    }
    function decodeImage() {
        // now = performance.now(); // debug code
        $('#img').attr('src', dataSrc);
        setTimeout(revokeObject, delay); // gives the UI a second chance to get something done.
        //CPUProfile.push(performance.now()-now); // debug code
    }
    function encodeImage() {
        // now = performance.now(); // debug code
        dataSrc = canvas.toDataURL('image/jpeg', 0.5);
        setTimeout(decodeImage, delay); // gives the UI a second chance to get something done.
        //CPUProfile.push(performance.now()-now); // debug code
    }
    function scaleImage() {
        // now = performance.now(); // debug code
        ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
        setTimeout(encodeImage, delay); // gives the UI a second chance to get something done.
        //CPUProfile.push(performance.now()-now); // debug code
    }
    // now = performance.now(); // debug code
    canvas = document.createElement('canvas');
    ctx = canvas.getContext('2d');
    w = Math.min(img.width, 1000);
    h = img.height / img.width * w;
    canvas.width = w;
    canvas.height = h;
    setTimeout(scaleImage, delay); // gives the UI a chance to get something done.
    //CPUProfile.push(performance.now()-now); // debug code
};

setTimeout允许当前调用退出,释放调用堆栈,并允许UI在DOM上获得手套。 我给了10毫秒,我个人将从0毫秒开始,因为调用堆栈访问未被阻止,但是我正在安全地玩

运气好的话,这个问题将大大减少。 如果仍然不能接受,那么我可以查看一下CPU配置文件,看看是否无法通过解决瓶颈找到解决方案。 我的猜测是toDataURL是负载所在。 如果是这样,可能的解决方案是找到用javascript编写的JPG编码器,该编码器可以转换为事件驱动的编码器。

问题不是处理数据需要多长时间,而是您阻塞UI的时间。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM