【问题标题】:Best way to access pixels of an image in JavaScript to do Image Processing?在 JavaScript 中访问图像像素以进行图像处理的最佳方法是什么?
【发布时间】:2011-09-13 21:23:14
【问题描述】:

我正在尝试使用 javascript 对图像执行简单的操作。为了获取图像的像素,我在画布上绘制图像,然后从画布中获取 ImageData。但是对于大图像,在画布上绘制它们需要很多时间。

有没有其他方法可以在不使用画布元素的情况下获取图像像素?

【问题讨论】:

  • 真的那么慢吗?如果您不将图像绘制到屏幕上,而仅绘制到画布上,也许会更快。
  • 我将它绘制到画布而不是屏幕上。但它仍然比大多数图像编辑工具慢很多。
  • 大部分图片编辑工具都是硬件加速的;并非所有浏览器都支持画布硬件加速。但是你测试的是什么浏览器?
  • $.getImageData 帮忙吗?
  • @Harmen,我正在使用 Firefox 和 Chrome 进行测试。

标签: javascript image html image-processing canvas


【解决方案1】:

下面的例子使用MarvinJ。它采用具有 2800x2053 分辨率的彩色图像,遍历每个像素计算灰度值并将其设置回来。画布上方有一个 div 用于打印处理时间。在我的机器上,它花了 115 毫秒,包括图片加载。

var time = new Date().getTime();

var canvas = document.getElementById("canvas");
image = new MarvinImage();
image.load("https://i.imgur.com/iuGXHFj.jpg", imageLoaded);

function imageLoaded(){
 
  for(var y=0; y<image.getHeight(); y++){
    for(var x=0; x<image.getWidth(); x++){
       var r = image.getIntComponent0(x,y);
       var g = image.getIntComponent1(x,y);
       var b = image.getIntComponent2(x,y);
       
       var gray = Math.floor(r * 0.21 + g * 0.72 + b * 0.07);
       
       image.setIntColor(x,y,255,gray,gray,gray);
     }
   }
   image.draw(canvas);
   
   $("#time").html("Processing time: "+(new Date().getTime()-time)+"ms");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://www.marvinj.org/releases/marvinj-0.7.js"></script>
<div id="time"></div>
<canvas id="canvas" width="2800" height="2053"></canvas>

【讨论】:

  • 获取图像数据需要时间。您在此操作后启动计时器。 jsfiddle.net/68vppz1u 对于像灰度这样的东西,您可以使用 globalCompositeOperations 更快地实现同样的效果:jsfiddle.net/68vppz1u/2
  • 我改变了答案。定时器在第一行js开始。
【解决方案2】:

我不确定,但是否可以将图像数据写入字符串,并操作字符串,然后在显示结果图像之前将其转换回图像?

这不需要在画布上绘图,只需将图像数据加载为字符串而不是图像。然而,这将涉及一些复杂且可能难以进行正确的字符串操作,以确保正确转换图像数据并更进一步地操作像素。

这也意味着对于较大的图像,字符串可能会很长,因此这可能会比画布占用更多的内存,并且可能需要拆分为多个字符串。作为交换,它可能比绘制到画布更快,尤其是在您只需要操作部分图像的情况下使用多个字符串。

我没有图像处理经验,但理论上没有理由不能将文件数据写入字符串。再次,它只是要制作一个非常长的字符串并因此可能对 RAM 产生影响,因为该字符串可能比图像文件本身占用更多的 RAM。但加载速度会更快,因为它不必像绘制到画布那样处理数据。

【讨论】:

    【解决方案3】:

    我对 Javascript 没有太多经验,但 Max Novakovic(@betamax) 编写了一个不错的小型 jQuery 插件,名为 $.getImageData,它可能会有所帮助。

    您可以在disturb blogplugin page 上阅读有关$.getImageData 的更多信息

    您应该能够通过context.getImageData(x, y, width, height).data 之类的方式访问像素。

    另外,您提到了硬件加速,这应该在 Firefox4 和 Chrome 中可用。 Shadertoy 在浏览器中使用 GLSL 着色器:

    【讨论】:

    • 正如我在上面也提到的,从我读过的关于插件的内容来看,它有助于获取给定 url 的图像对象。我们仍然需要通过在画布上绘制图像来获取像素
    【解决方案4】:

    我不认为你可以在带有硬件加速的 JavaScript 中进行图像处理,所以无论是画布还是其他技术,你都不会在 JavaScript 环境中获得太多边际收益。

    如果您希望您的代码进行硬件加速,您的代码必须被编译成在 GPU 中运行并且可以访问图形内存的东西。 Flash 和 Silverlight 的方法是引入 AGAL 和 HLSL 等着色语言。也许 JavaScript 将来会有这样的东西。

    所以我的建议是使用以下方法进行图像处理:

    1. 服务器端技术
    2. 带有着色语言的 Flash 和 Silverlight

    【讨论】:

    • 是的。谢谢提醒。 WebGL 不能进行像素操作,对吧?因此,像素级 JavaScript 似乎仍然无法编译为 GPU 加速代码。
    • 您可以使用 glsl 在 WebGL 图像上运行内核,但是您需要将图像缓冲区转换为一些字节数组,然后才能使用 js 读取它。但我上次这样做也是很久以前的事了……
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2010-11-15
    • 2020-09-07
    • 1970-01-01
    • 2020-11-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多