【问题标题】:Grayscale in Fabric.js is slowFabric.js 中的灰度很慢
【发布时间】:2013-08-11 14:52:18
【问题描述】:

我不认为 Fabric.js 是这里的罪魁祸首,因为当我添加时间警报时,它只需要 2-3 秒。但是,这是它使用的代码:

 applyTo: function(canvasEl) {
    var context = canvasEl.getContext('2d'),
        imageData = context.getImageData(0, 0, canvasEl.width, canvasEl.height),
        data = imageData.data,
        len = imageData.width * imageData.height * 4,
        index = 0,
        average;

    while (index < len) {
      average = (data[index] + data[index + 1] + data[index + 2]) / 3;
      data[index]     = average;
      data[index + 1] = average;
      data[index + 2] = average;
      index += 4;
    }

    context.putImageData(imageData, 0, 0);
  },

所以如果不是冒犯者,那么冒犯者就是putImageData函数。

有什么方法可以增加/优化该功能,使其在 15 秒内处理 5000x5000 图像?

如果没有,有没有办法设置一个“工作”图标,只有在 putImageData 通过 jQuery 完成后才会被删除,因为目前,它会在 2 秒后被删除,因为 Fabric.js 代码完成得更快?

【问题讨论】:

  • 您是否需要为此使用 JS 和画布,或者 CSS approach 可以为您的应用程序工作?
  • 保存用户创建的图像以供将来使用甚至打印,所以我猜这是唯一的方法。我的选项和图像尺寸非常有限,所以只有特殊情况才会那么大。把它想象成一个打印传单。

标签: javascript jquery performance canvas fabricjs


【解决方案1】:

如果putImageData 占用的时间最多,您就无法提高它的速度,因为它是浏览器提供的低级功能。

您可以做的是逐步处理图像并将其显示给用户,而不会连续 15 秒阻塞浏览器。

提示:我建议使用 Chrome 开发人员工具,而不是使用 时间警报 来计时脚本的执行。他们为javascript 提供了一个很棒的分析工具,更具体地说,canvas drawing.

【讨论】:

    【解决方案2】:

    我对fabric.js 不是很熟悉,但是您对画布进行优化的选择非常有限。将您的变量一个接一个地放置,而不是创建一个平均变量,这将为您节省一点时间:

    data[index] = data[index+1] = data[index+2] = (data[index] + data[index + 1] + data[index + 2]) / 3;
    index+=4;
    

    您可能还想尝试将数据按行放在画布上。它不会加快速度,但如果你有这么大的画布,向用户展示一些进展会很好。在以下示例中,我这样做并将您的 while 循环更改为两个 for 循环,因为我更喜欢 for 循环:)

    for(var i=0;i<imageData.height;i++) {
        var row = context.getImageData(0, i, canvasEl.width, 1);
        for(var j=0;j<imageData.width*4;j+=4) {
            row.data[index] = row.data[index+1] = row.data[index+2] = (row.data[index] + row.data[index + 1] + row.data[index + 2]) / 3;
            context.putImageData(row, 0, i);
        }
    }
    

    【讨论】:

    • 1.不是一次获取/放置图像数据,而是多做 5000×5000 次,因此可能会进一步减慢速度。 2. Javascript 只会执行整个循环,然后然后 完全显示结果。为了做你想做的事,你需要使用 requestAnimationFrame 以块的形式在多个帧上详细/显示图像,有点像FastDom's defer method
    猜你喜欢
    • 2014-07-21
    • 1970-01-01
    • 1970-01-01
    • 2016-04-20
    • 2012-06-25
    • 2016-07-08
    • 1970-01-01
    • 2014-03-31
    • 1970-01-01
    相关资源
    最近更新 更多